diff --git a/.github/workflows/github-actions.yml b/.github/workflows/github-actions.yml
index d1275e5d..f1918459 100644
--- a/.github/workflows/github-actions.yml
+++ b/.github/workflows/github-actions.yml
@@ -115,14 +115,13 @@ jobs:
&& \
rm "./dependency_tracker_private_signing_key.ppk" "./dependency_tracker_api_key.ppk"
-# todo figure out why this is failing as of Oct 2024 -> https://github.com/EnricoMi/publish-unit-test-result-action/issues/633
-# - name: '📡 Publish Test Results' # https://github.com/marketplace/actions/publish-test-results
-# uses: 'EnricoMi/publish-unit-test-result-action/macos@v2'
-# if: always()
-# with:
-# files: |
-# TestResults/**/TEST-*.xml
-# TestResults/**/TEST-*.trx
+ - name: '📡 Publish Test Results' # https://github.com/marketplace/actions/publish-test-results
+ uses: 'EnricoMi/publish-unit-test-result-action/macos@master'
+ if: always()
+ with:
+ files: |
+ TestResults/**/TEST-*.xml
+ TestResults/**/TEST-*.trx
- name: '⬆️ Upload Artifacts' # to share with other workflows https://stackoverflow.com/a/77663335/863651
uses: 'actions/upload-artifact@v4'
diff --git a/Laerdal.McuMgr.Bindings.Android.Native/gradle.properties b/Laerdal.McuMgr.Bindings.Android.Native/gradle.properties
index ab4b134e..123e09cf 100644
--- a/Laerdal.McuMgr.Bindings.Android.Native/gradle.properties
+++ b/Laerdal.McuMgr.Bindings.Android.Native/gradle.properties
@@ -19,7 +19,9 @@ android.useAndroidX=true
# resources declared in the library itself and none from the library's dependencies,
# thereby reducing the size of the R class for that library
android.nonTransitiveRClass=true
-# in macos just comment this one out
+# as long as we use gradle 7.6 we will get warnings if we try to build against android 34 or above we suppress such warnings
+android.suppressUnsupportedCompileSdk=34
+# in macos just comment out the windows paths and keep the homebrew path
# org.gradle.java.home=C/://Program Files//Microsoft//jdk-11.0.15.10-hotspot
# org.gradle.java.home=C://Program Files//OpenJDK//jdk-17.0.2
org.gradle.java.home=/opt/homebrew/opt/openjdk@17
diff --git a/Laerdal.McuMgr.Bindings.Android.Native/mcumgr-laerdal-wrapper/src/main/java/no/laerdal/mcumgr_laerdal_wrapper/AndroidDeviceResetter.java b/Laerdal.McuMgr.Bindings.Android.Native/mcumgr-laerdal-wrapper/src/main/java/no/laerdal/mcumgr_laerdal_wrapper/AndroidDeviceResetter.java
index 9713ea59..3fe538fb 100644
--- a/Laerdal.McuMgr.Bindings.Android.Native/mcumgr-laerdal-wrapper/src/main/java/no/laerdal/mcumgr_laerdal_wrapper/AndroidDeviceResetter.java
+++ b/Laerdal.McuMgr.Bindings.Android.Native/mcumgr-laerdal-wrapper/src/main/java/no/laerdal/mcumgr_laerdal_wrapper/AndroidDeviceResetter.java
@@ -9,6 +9,7 @@
import io.runtime.mcumgr.exception.McuMgrException;
import io.runtime.mcumgr.managers.DefaultManager;
import io.runtime.mcumgr.response.dflt.McuMgrOsResponse;
+import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
@SuppressWarnings("unused")
@@ -65,7 +66,7 @@ public void onError(@NotNull final McuMgrException error) {
});
}
- public void disconnect() { //noinspection ConstantValue
+ public void disconnect() {
if (_manager == null)
return;
@@ -95,18 +96,21 @@ protected void onCleared() {
private String _lastFatalErrorMessage;
+ @Contract(pure = true)
public String getLastFatalErrorMessage() {
return _lastFatalErrorMessage;
}
public void fatalErrorOccurredAdvertisement(final String errorMessage) {
- _lastFatalErrorMessage = errorMessage; //this method is intentionally empty its meant to be overridden by csharp binding libraries to intercept updates
+ _lastFatalErrorMessage = errorMessage;
}
+ @Contract(pure = true)
public void logMessageAdvertisement(final String message, final String category, final String level) {
//this method is intentionally empty its meant to be overridden by csharp binding libraries to intercept updates
}
+ @Contract(pure = true)
public void stateChangedAdvertisement(final EAndroidDeviceResetterState oldState, final EAndroidDeviceResetterState currentState) {
//this method is intentionally empty its meant to be overridden by csharp binding libraries to intercept updates
}
diff --git a/Laerdal.McuMgr.Bindings.Android.Native/mcumgr-laerdal-wrapper/src/main/java/no/laerdal/mcumgr_laerdal_wrapper/AndroidFileDownloader.java b/Laerdal.McuMgr.Bindings.Android.Native/mcumgr-laerdal-wrapper/src/main/java/no/laerdal/mcumgr_laerdal_wrapper/AndroidFileDownloader.java
index a6fd0239..aa5860b9 100644
--- a/Laerdal.McuMgr.Bindings.Android.Native/mcumgr-laerdal-wrapper/src/main/java/no/laerdal/mcumgr_laerdal_wrapper/AndroidFileDownloader.java
+++ b/Laerdal.McuMgr.Bindings.Android.Native/mcumgr-laerdal-wrapper/src/main/java/no/laerdal/mcumgr_laerdal_wrapper/AndroidFileDownloader.java
@@ -5,29 +5,86 @@
import androidx.annotation.NonNull;
import io.runtime.mcumgr.McuMgrTransport;
import io.runtime.mcumgr.ble.McuMgrBleTransport;
+import io.runtime.mcumgr.exception.McuMgrErrorException;
import io.runtime.mcumgr.exception.McuMgrException;
import io.runtime.mcumgr.managers.FsManager;
import io.runtime.mcumgr.transfer.DownloadCallback;
import io.runtime.mcumgr.transfer.TransferController;
import no.nordicsemi.android.ble.ConnectionPriorityRequest;
+import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
@SuppressWarnings("unused")
public class AndroidFileDownloader
{
+ private Context _context;
+ private BluetoothDevice _bluetoothDevice;
+
private FsManager _fileSystemManager;
- @SuppressWarnings("FieldCanBeLocal")
- private final McuMgrBleTransport _transport;
+ private McuMgrBleTransport _transport;
private TransferController _downloadingController;
+ private FileDownloaderCallbackProxy _fileDownloaderCallbackProxy;
private int _initialBytes;
private long _downloadStartTimestamp;
private String _remoteFilePathSanitized = "";
private EAndroidFileDownloaderState _currentState = EAndroidFileDownloaderState.NONE;
+ public AndroidFileDownloader() //this flavour is meant to be used in conjunction with trySetBluetoothDevice() and trySetContext()
+ {
+ }
+
public AndroidFileDownloader(@NonNull final Context context, @NonNull final BluetoothDevice bluetoothDevice)
{
- _transport = new McuMgrBleTransport(context, bluetoothDevice);
+ _context = context;
+ _bluetoothDevice = bluetoothDevice;
+ }
+
+ public boolean trySetContext(@NonNull final Context context)
+ {
+ if (!IsIdleOrCold())
+ return false;
+
+ if (!tryInvalidateCachedTransport()) //order
+ return false;
+
+ _context = context;
+ return true;
+ }
+
+ public boolean trySetBluetoothDevice(@NonNull final BluetoothDevice bluetoothDevice)
+ {
+ if (!IsIdleOrCold()) {
+ logMessageAdvertisement("[AFD.TSBD.005] trySetBluetoothDevice() cannot proceed because the uploader is not cold", "FileUploader", "ERROR", _remoteFilePathSanitized);
+ return false;
+ }
+
+ if (!tryInvalidateCachedTransport()) //order
+ {
+ logMessageAdvertisement("[AFD.TSBD.020] Failed to invalidate the cached-transport instance", "FileUploader", "ERROR", _remoteFilePathSanitized);
+ return false;
+ }
+
+ _bluetoothDevice = bluetoothDevice; //order
+
+ logMessageAdvertisement("[AFD.TSBD.030] Successfully set the android-bluetooth-device to the given value", "FileUploader", "TRACE", _remoteFilePathSanitized);
+
+ return true;
+ }
+
+ public boolean tryInvalidateCachedTransport()
+ {
+ if (_transport == null) //already scrapped
+ return true;
+
+ if (!IsIdleOrCold()) //if the upload is already in progress we bail out
+ return false;
+
+ disposeFilesystemManager(); // order
+ disposeTransport(); // order
+ disposeCallbackProxy(); // order
+
+ return true;
}
/**
@@ -44,68 +101,65 @@ public EAndroidFileDownloaderVerdict beginDownload(
final String remoteFilePath,
final int initialMtuSize
// final int windowCapacity, //theoretically nordic firmwares at some point will support this for downloads but as of Q3 2024 there is no support for this
- // final int memoryAlignment //this doesnt make sense for downloading it only makes sense in uploading scenarios https://github.com/NordicSemiconductor/Android-nRF-Connect-Device-Manager/issues/188#issuecomment-2391146897
)
{
- if (_currentState != EAndroidFileDownloaderState.NONE //if the download is already in progress we bail out
- && _currentState != EAndroidFileDownloaderState.ERROR
- && _currentState != EAndroidFileDownloaderState.COMPLETE
- && _currentState != EAndroidFileDownloaderState.CANCELLED)
+ if (!IsCold()) //keep first
{
- logMessageAdvertisement("Cannot start a new download while another one is still in progress (state=" + _currentState.toString() + ")", "FileDownloader", "ERROR", remoteFilePath);
+ onError("Another download is already in progress");
return EAndroidFileDownloaderVerdict.FAILED__DOWNLOAD_ALREADY_IN_PROGRESS;
}
if (remoteFilePath == null || remoteFilePath.isEmpty()) {
- setState(EAndroidFileDownloaderState.ERROR);
- fatalErrorOccurredAdvertisement("", "Target-file provided is dud!");
+ onError("Target-file provided is dud!");
return EAndroidFileDownloaderVerdict.FAILED__INVALID_SETTINGS;
}
- final String remoteFilePathSanitized = remoteFilePath.trim();
- if (remoteFilePathSanitized.endsWith("/")) //the path must point to a file not a directory
+ _remoteFilePathSanitized = remoteFilePath.trim();
+ if (_remoteFilePathSanitized.endsWith("/")) //the path must point to a file not a directory
{
- setState(EAndroidFileDownloaderState.ERROR);
- fatalErrorOccurredAdvertisement(_remoteFilePathSanitized, "Provided target-path points to a directory not a file!");
+ onError("Provided target-path points to a directory not a file");
return EAndroidFileDownloaderVerdict.FAILED__INVALID_SETTINGS;
}
- if (!remoteFilePathSanitized.startsWith("/"))
+ if (!_remoteFilePathSanitized.startsWith("/"))
{
- setState(EAndroidFileDownloaderState.ERROR);
- fatalErrorOccurredAdvertisement(_remoteFilePathSanitized, "Provided target-path is not an absolute path!");
+ onError("Provided target-path is not an absolute path");
return EAndroidFileDownloaderVerdict.FAILED__INVALID_SETTINGS;
}
- if (initialMtuSize > 0)
- {
- _transport.setInitialMtu(initialMtuSize);
+ if (_context == null) {
+ onError("No context specified - call trySetContext() first");
+
+ return EAndroidFileDownloaderVerdict.FAILED__INVALID_SETTINGS;
}
- _fileSystemManager = new FsManager(_transport);
+ if (_bluetoothDevice == null) {
+ onError("No bluetooth-device specified - call trySetBluetoothDevice() first");
- setLoggingEnabled(false);
- requestHighConnectionPriority();
+ return EAndroidFileDownloaderVerdict.FAILED__INVALID_SETTINGS;
+ }
- setState(EAndroidFileDownloaderState.IDLE);
- busyStateChangedAdvertisement(true);
- fileDownloadProgressPercentageAndDataThroughputChangedAdvertisement(0, 0);
+ resetDownloadState(); //order must be called before ensureTransportIsInitializedExactlyOnce() because the environment might try to set the device via trySetBluetoothDevice()!!!
+ ensureTransportIsInitializedExactlyOnce(initialMtuSize); //order
- _initialBytes = 0;
- _remoteFilePathSanitized = remoteFilePathSanitized;
+ final EAndroidFileDownloaderVerdict verdict = ensureFilesystemManagerIsInitializedExactlyOnce(); //order
+ if (verdict != EAndroidFileDownloaderVerdict.SUCCESS)
+ return verdict;
+
+ ensureFileDownloaderCallbackProxyIsInitializedExactlyOnce(); //order
+ setLoggingEnabled(false);
try
{
- _downloadingController = _fileSystemManager.fileDownload(remoteFilePathSanitized, new FileDownloaderCallbackProxy());
+ _downloadingController = _fileSystemManager.fileDownload(_remoteFilePathSanitized, _fileDownloaderCallbackProxy);
}
catch (final Exception ex)
{
- setState(EAndroidFileDownloaderState.ERROR);
- fatalErrorOccurredAdvertisement(_remoteFilePathSanitized, ex.getMessage());
+ onError("Failed to initialize download", ex);
return EAndroidFileDownloaderVerdict.FAILED__ERROR_UPON_COMMENCING;
}
@@ -162,9 +216,62 @@ public void cancel()
transferController.cancel(); //order
}
- private void requestHighConnectionPriority()
+ private void resetDownloadState() {
+ _initialBytes = 0;
+ _downloadStartTimestamp = 0;
+
+ setState(EAndroidFileDownloaderState.IDLE);
+ busyStateChangedAdvertisement(true);
+ fileDownloadProgressPercentageAndDataThroughputChangedAdvertisement(0, 0);
+ }
+
+ private void ensureTransportIsInitializedExactlyOnce(int initialMtuSize)
{
- final McuMgrTransport mcuMgrTransporter = _fileSystemManager.getTransporter();
+ if (_transport != null)
+ return;
+
+ logMessageAdvertisement("[AFD.ETIIEO.010] (Re)Initializing transport: initial-mtu-size=" + initialMtuSize, "FileDownloader", "TRACE", _remoteFilePathSanitized);
+
+ _transport = new McuMgrBleTransport(_context, _bluetoothDevice);
+
+ if (initialMtuSize > 0)
+ {
+ _transport.setInitialMtu(initialMtuSize);
+ }
+ }
+
+ private void ensureFileDownloaderCallbackProxyIsInitializedExactlyOnce() {
+ if (_fileDownloaderCallbackProxy != null) //already initialized
+ return;
+
+ _fileDownloaderCallbackProxy = new FileDownloaderCallbackProxy();
+ }
+
+ private EAndroidFileDownloaderVerdict ensureFilesystemManagerIsInitializedExactlyOnce() {
+ if (_fileSystemManager != null) //already initialized
+ return EAndroidFileDownloaderVerdict.SUCCESS;
+
+ logMessageAdvertisement("[AFD.EFMIIEO.010] (Re)Initializing filesystem-manager", "FileDownloader", "TRACE", _remoteFilePathSanitized);
+
+ try
+ {
+ _fileSystemManager = new FsManager(_transport); //order
+
+ requestHighConnectionPriority(_fileSystemManager); //order
+ }
+ catch (final Exception ex)
+ {
+ onError(ex.getMessage(), ex);
+
+ return EAndroidFileDownloaderVerdict.FAILED__INVALID_SETTINGS;
+ }
+
+ return EAndroidFileDownloaderVerdict.SUCCESS;
+ }
+
+ private void requestHighConnectionPriority(FsManager fileSystemManager)
+ {
+ final McuMgrTransport mcuMgrTransporter = fileSystemManager.getTransporter();
if (!(mcuMgrTransporter instanceof McuMgrBleTransport))
return;
@@ -172,6 +279,39 @@ private void requestHighConnectionPriority()
bleTransporter.requestConnPriority(ConnectionPriorityRequest.CONNECTION_PRIORITY_HIGH);
}
+ private void disposeTransport()
+ {
+ if (_transport == null)
+ return;
+
+ try {
+ _transport.disconnect();
+ } catch (Exception ex) {
+ // ignore
+ }
+
+ _transport = null;
+ }
+
+ private void disposeFilesystemManager()
+ {
+ if (_fileSystemManager == null)
+ return;
+
+ try {
+ _fileSystemManager.closeAll();
+ } catch (McuMgrException e) {
+ // ignore
+ }
+
+ _fileSystemManager = null;
+ }
+
+ private void disposeCallbackProxy()
+ {
+ _fileDownloaderCallbackProxy = null;
+ }
+
private void setLoggingEnabled(final boolean enabled)
{
final McuMgrTransport mcuMgrTransporter = _fileSystemManager.getTransporter();
@@ -197,56 +337,107 @@ private void setState(final EAndroidFileDownloaderState newState)
//00 trivial hotfix to deal with the fact that the filedownload progress% doesnt fill up to 100%
}
+ @Contract(pure = true)
+ private boolean IsIdleOrCold()
+ {
+ return _currentState == EAndroidFileDownloaderState.IDLE || IsCold();
+ }
+
+ @Contract(pure = true)
+ private boolean IsCold()
+ {
+ return _currentState == EAndroidFileDownloaderState.NONE
+ || _currentState == EAndroidFileDownloaderState.ERROR
+ || _currentState == EAndroidFileDownloaderState.COMPLETE
+ || _currentState == EAndroidFileDownloaderState.CANCELLED;
+ }
+
private String _lastFatalErrorMessage;
+ @Contract(pure = true)
public String getLastFatalErrorMessage()
{
return _lastFatalErrorMessage;
}
- public void fatalErrorOccurredAdvertisement(final String resource, final String errorMessage)
+ public void onError(final String errorMessage)
+ {
+ onError(errorMessage, null);
+ }
+
+ //@Contract(pure = true) //dont
+ public void onError(final String errorMessage, final Exception exception)
+ {
+ setState(EAndroidFileDownloaderState.ERROR);
+
+ if (!(exception instanceof McuMgrErrorException))
+ {
+ fatalErrorOccurredAdvertisement(_remoteFilePathSanitized, errorMessage, -1, -1);
+ return;
+ }
+
+ McuMgrErrorException mcuMgrErrorException = (McuMgrErrorException) exception;
+ fatalErrorOccurredAdvertisement(
+ _remoteFilePathSanitized,
+ errorMessage,
+ mcuMgrErrorException.getCode().value(),
+ (mcuMgrErrorException.getGroupCode() != null ? mcuMgrErrorException.getGroupCode().group : -99)
+ );
+ }
+
+ public void fatalErrorOccurredAdvertisement(
+ final String remoteFilePath,
+ final String errorMessage,
+ final int mcuMgrErrorCode, // io.runtime.mcumgr.McuMgrErrorCode
+ final int fsManagerGroupReturnCode // io.runtime.mcumgr.managers.FsManager.ReturnCode
+ )
{
- //this method is meant to be overridden by csharp binding libraries to intercept updates
_lastFatalErrorMessage = errorMessage;
}
+ @Contract(pure = true)
public void busyStateChangedAdvertisement(boolean busyNotIdle)
{
//this method is intentionally empty its meant to be overridden by csharp binding libraries to intercept updates
}
+ @Contract(pure = true)
public void cancelledAdvertisement()
{
//this method is intentionally empty its meant to be overridden by csharp binding libraries to intercept updates
}
- //wrapper utility method so that we wont have to constantly pass remoteFilePathSanitized as the first argument currently unused but should be handy in the future
+ @Contract(pure = true) //wrapper utility method so that we wont have to constantly pass remoteFilePathSanitized as the first argument currently unused but should be handy in the future
public void stateChangedAdvertisement(final EAndroidFileDownloaderState oldState, final EAndroidFileDownloaderState newState)
{
stateChangedAdvertisement(_remoteFilePathSanitized, oldState, newState);
}
+ @Contract(pure = true)
public void stateChangedAdvertisement(final String resource, final EAndroidFileDownloaderState oldState, final EAndroidFileDownloaderState newState)
{
//this method is intentionally empty its meant to be overridden by csharp binding libraries to intercept updates
}
+ @Contract(pure = true)
public void fileDownloadProgressPercentageAndDataThroughputChangedAdvertisement(final int progressPercentage, final float averageThroughput)
{
//this method is intentionally empty its meant to be overridden by csharp binding libraries to intercept updates
}
+ @Contract(pure = true)
public void downloadCompletedAdvertisement(final String resource, final byte[] data)
{
//this method is intentionally empty its meant to be overridden by csharp binding libraries to intercept updates
}
- //wrapper utility method so that we wont have to constantly pass remoteFilePathSanitized as the fourth argument currently unused but should be handy in the future
+ @Contract(pure = true) //wrapper utility method so that we wont have to constantly pass remoteFilePathSanitized as the fourth argument currently unused but should be handy in the future
private void logMessageAdvertisement(final String message, final String category, final String level)
{
logMessageAdvertisement(message, category, level, _remoteFilePathSanitized);
}
+ @Contract(pure = true)
public void logMessageAdvertisement(final String message, final String category, final String level, final String resource) //wrapper method
{
//this method is intentionally empty its meant to be overridden by csharp binding libraries to intercept updates
@@ -283,13 +474,14 @@ public void onDownloadProgressChanged(final int bytesSent, final int fileSize, f
}
@Override
- public void onDownloadFailed(@NonNull final McuMgrException error)
+ public void onDownloadFailed(@NonNull final McuMgrException exception)
{
fileDownloadProgressPercentageAndDataThroughputChangedAdvertisement(0, 0);
- setState(EAndroidFileDownloaderState.ERROR);
- fatalErrorOccurredAdvertisement(_remoteFilePathSanitized, error.getMessage());
+ onError(exception.getMessage(), exception);
setLoggingEnabled(true);
busyStateChangedAdvertisement(false);
+
+ _downloadingController = null; //game over
}
@Override
@@ -300,6 +492,8 @@ public void onDownloadCanceled()
cancelledAdvertisement();
setLoggingEnabled(true);
busyStateChangedAdvertisement(false);
+
+ _downloadingController = null; //game over
}
@Override
@@ -312,6 +506,8 @@ public void onDownloadCompleted(byte @NotNull [] data)
setLoggingEnabled(true);
busyStateChangedAdvertisement(false);
+
+ _downloadingController = null; //game over
}
}
}
diff --git a/Laerdal.McuMgr.Bindings.Android.Native/mcumgr-laerdal-wrapper/src/main/java/no/laerdal/mcumgr_laerdal_wrapper/AndroidFileUploader.java b/Laerdal.McuMgr.Bindings.Android.Native/mcumgr-laerdal-wrapper/src/main/java/no/laerdal/mcumgr_laerdal_wrapper/AndroidFileUploader.java
index 3a4420c6..f3277a13 100644
--- a/Laerdal.McuMgr.Bindings.Android.Native/mcumgr-laerdal-wrapper/src/main/java/no/laerdal/mcumgr_laerdal_wrapper/AndroidFileUploader.java
+++ b/Laerdal.McuMgr.Bindings.Android.Native/mcumgr-laerdal-wrapper/src/main/java/no/laerdal/mcumgr_laerdal_wrapper/AndroidFileUploader.java
@@ -27,10 +27,10 @@ public class AndroidFileUploader
private int _initialBytes;
private long _uploadStartTimestamp;
- private String _remoteFilePathSanitized;
+ private String _remoteFilePathSanitized = "";
private EAndroidFileUploaderState _currentState = EAndroidFileUploaderState.NONE;
- public AndroidFileUploader()
+ public AndroidFileUploader() //this flavour is meant to be used in conjunction with trySetBluetoothDevice() and trySetContext()
{
}
@@ -54,23 +54,20 @@ public boolean trySetContext(@NonNull final Context context)
public boolean trySetBluetoothDevice(@NonNull final BluetoothDevice bluetoothDevice)
{
- logMessageAdvertisement("[AFU.TSBD.000] trySetBluetoothDevice() called", "FileUploader", "TRACE", _remoteFilePathSanitized);
-
if (!IsIdleOrCold()) {
- logMessageAdvertisement("[AFU.TSBD.005] trySetBluetoothDevice() cannot proceed because the uploader is not cold", "FileUploader", "TRACE", _remoteFilePathSanitized);
+ logMessageAdvertisement("[AFU.TSBD.005] trySetBluetoothDevice() cannot proceed because the uploader is not cold", "FileUploader", "ERROR", _remoteFilePathSanitized);
return false;
}
- logMessageAdvertisement("[AFU.TSBD.010]", "FileUploader", "TRACE", _remoteFilePathSanitized);
if (!tryInvalidateCachedTransport()) //order
{
- logMessageAdvertisement("[AFU.TSBD.020]", "FileUploader", "TRACE", _remoteFilePathSanitized);
+ logMessageAdvertisement("[AFU.TSBD.020] Failed to invalidate the cached-transport instance", "FileUploader", "ERROR", _remoteFilePathSanitized);
return false;
}
_bluetoothDevice = bluetoothDevice; //order
- logMessageAdvertisement("[AFU.TSBD.010] Native Bluetooth-Device set to a new instance", "FileUploader", "TRACE", _remoteFilePathSanitized);
+ logMessageAdvertisement("[AFU.TSBD.030] Successfully set the android-bluetooth-device to the given value", "FileUploader", "TRACE", _remoteFilePathSanitized);
return true;
}
@@ -111,54 +108,47 @@ public EAndroidFileUploaderVerdict beginUpload(
final int memoryAlignment
)
{
- if (!IsCold()) {
- setState(EAndroidFileUploaderState.ERROR);
- onError("N/A", "Another upload is already in progress", null);
+ if (!IsCold()) { //keep first
+ onError("Another upload is already in progress");
return EAndroidFileUploaderVerdict.FAILED__OTHER_UPLOAD_ALREADY_IN_PROGRESS;
}
- if (_context == null) {
- setState(EAndroidFileUploaderState.ERROR);
- onError("N/A", "No context specified - call trySetContext() first", null);
+ if (remoteFilePath == null || remoteFilePath.isEmpty()) {
+ onError("Provided target-path is empty", null);
return EAndroidFileUploaderVerdict.FAILED__INVALID_SETTINGS;
}
- if (_bluetoothDevice == null) {
- setState(EAndroidFileUploaderState.ERROR);
- onError("N/A", "No bluetooth-device specified - call trySetBluetoothDevice() first", null);
+ _remoteFilePathSanitized = remoteFilePath.trim();
+ if (_remoteFilePathSanitized.endsWith("/")) //the path must point to a file not a directory
+ {
+ onError("Provided target-path points to a directory not a file");
return EAndroidFileUploaderVerdict.FAILED__INVALID_SETTINGS;
}
- if (remoteFilePath == null || remoteFilePath.isEmpty()) {
- setState(EAndroidFileUploaderState.ERROR);
- onError("N/A", "Provided target-path is empty", null);
+ if (!_remoteFilePathSanitized.startsWith("/"))
+ {
+ onError("Provided target-path is not an absolute path");
return EAndroidFileUploaderVerdict.FAILED__INVALID_SETTINGS;
}
- _remoteFilePathSanitized = remoteFilePath.trim();
- if (_remoteFilePathSanitized.endsWith("/")) //the path must point to a file not a directory
- {
- setState(EAndroidFileUploaderState.ERROR);
- onError(_remoteFilePathSanitized, "Provided target-path points to a directory not a file", null);
+ if (_context == null) {
+ onError("No context specified - call trySetContext() first");
return EAndroidFileUploaderVerdict.FAILED__INVALID_SETTINGS;
}
- if (!_remoteFilePathSanitized.startsWith("/"))
- {
- setState(EAndroidFileUploaderState.ERROR);
- onError(_remoteFilePathSanitized, "Provided target-path is not an absolute path", null);
+ if (_bluetoothDevice == null) {
+ onError("No bluetooth-device specified - call trySetBluetoothDevice() first");
return EAndroidFileUploaderVerdict.FAILED__INVALID_SETTINGS;
}
if (data == null) { // data being null is not ok but data.length==0 is perfectly ok because we might want to create empty files
- setState(EAndroidFileUploaderState.ERROR);
- onError(_remoteFilePathSanitized, "Provided data is null", null);
+ onError("Provided data is null");
return EAndroidFileUploaderVerdict.FAILED__INVALID_DATA;
}
@@ -188,8 +178,7 @@ public EAndroidFileUploaderVerdict beginUpload(
}
catch (final Exception ex)
{
- setState(EAndroidFileUploaderState.ERROR);
- onError(_remoteFilePathSanitized, "Failed to initialize the upload", ex);
+ onError("Failed to initialize the upload", ex);
return EAndroidFileUploaderVerdict.FAILED__ERROR_UPON_COMMENCING;
}
@@ -245,8 +234,7 @@ private EAndroidFileUploaderVerdict ensureFilesystemManagerIsInitializedExactlyO
}
catch (final Exception ex)
{
- setState(EAndroidFileUploaderState.ERROR);
- onError(_remoteFilePathSanitized, ex.getMessage(), ex);
+ onError("[AFU.EFMIIEO.010] Failed to initialize the native file-system-manager", ex);
return EAndroidFileUploaderVerdict.FAILED__INVALID_SETTINGS;
}
@@ -391,26 +379,31 @@ private boolean IsCold()
private String _lastFatalErrorMessage;
+ @Contract(pure = true)
public String getLastFatalErrorMessage()
{
return _lastFatalErrorMessage;
}
- public void onError(
- final String remoteFilePath,
- final String errorMessage,
- final Exception exception
- )
+ private void onError(final String errorMessage)
+ {
+ onError(errorMessage, null);
+ }
+
+ //@Contract(pure = true) //dont
+ private void onError(final String errorMessage, final Exception exception)
{
+ setState(EAndroidFileUploaderState.ERROR); //keep first
+
if (!(exception instanceof McuMgrErrorException))
{
- fatalErrorOccurredAdvertisement(remoteFilePath, errorMessage, -1, -1);
+ fatalErrorOccurredAdvertisement(_remoteFilePathSanitized, errorMessage, -1, -1); // -1 values get mapped to the 'generic' error code
return;
}
McuMgrErrorException mcuMgrErrorException = (McuMgrErrorException) exception;
fatalErrorOccurredAdvertisement(
- remoteFilePath,
+ _remoteFilePathSanitized,
errorMessage,
mcuMgrErrorException.getCode().value(),
(mcuMgrErrorException.getGroupCode() != null ? mcuMgrErrorException.getGroupCode().group : -99)
@@ -427,36 +420,43 @@ public void fatalErrorOccurredAdvertisement(
_lastFatalErrorMessage = errorMessage; //this method is meant to be overridden by csharp binding libraries to intercept updates
}
+ @Contract(pure = true)
public void busyStateChangedAdvertisement(final boolean busyNotIdle)
{
//this method is intentionally empty its meant to be overridden by csharp binding libraries to intercept updates
}
+ @Contract(pure = true)
public void fileUploadedAdvertisement(final String remoteFilePath)
{
//this method is intentionally empty its meant to be overridden by csharp binding libraries to intercept updates
}
+ @Contract(pure = true)
public void cancellingAdvertisement(final String reason)
{
//this method is intentionally empty its meant to be overridden by csharp binding libraries to intercept updates
}
+ @Contract(pure = true)
public void cancelledAdvertisement(final String reason)
{
//this method is intentionally empty its meant to be overridden by csharp binding libraries to intercept updates
}
+ @Contract(pure = true)
public void stateChangedAdvertisement(final String remoteFilePath, final EAndroidFileUploaderState oldState, final EAndroidFileUploaderState newState) // (final EAndroidFileUploaderState oldState, final EAndroidFileUploaderState newState)
{
//this method is intentionally empty its meant to be overridden by csharp binding libraries to intercept updates
}
+ @Contract(pure = true)
public void fileUploadProgressPercentageAndDataThroughputChangedAdvertisement(final int progressPercentage, final float averageThroughput)
{
//this method is intentionally empty its meant to be overridden by csharp binding libraries to intercept updates
}
+ @Contract(pure = true)
public void logMessageAdvertisement(final String message, final String category, final String level, final String resource)
{
//this method is intentionally empty its meant to be overridden by csharp binding libraries to intercept updates
@@ -496,8 +496,7 @@ public void onUploadProgressChanged(final int bytesSent, final int fileSize, fin
public void onUploadFailed(@NonNull final McuMgrException error)
{
fileUploadProgressPercentageAndDataThroughputChangedAdvertisement(0, 0);
- setState(EAndroidFileUploaderState.ERROR);
- onError(_remoteFilePathSanitized, error.getMessage(), error);
+ onError(error.getMessage(), error);
setLoggingEnabled(true);
busyStateChangedAdvertisement(false);
diff --git a/Laerdal.McuMgr.Bindings.Android.Native/mcumgr-laerdal-wrapper/src/main/java/no/laerdal/mcumgr_laerdal_wrapper/AndroidFirmwareEraser.java b/Laerdal.McuMgr.Bindings.Android.Native/mcumgr-laerdal-wrapper/src/main/java/no/laerdal/mcumgr_laerdal_wrapper/AndroidFirmwareEraser.java
index 1f713b4e..e2b1a14a 100644
--- a/Laerdal.McuMgr.Bindings.Android.Native/mcumgr-laerdal-wrapper/src/main/java/no/laerdal/mcumgr_laerdal_wrapper/AndroidFirmwareEraser.java
+++ b/Laerdal.McuMgr.Bindings.Android.Native/mcumgr-laerdal-wrapper/src/main/java/no/laerdal/mcumgr_laerdal_wrapper/AndroidFirmwareEraser.java
@@ -10,6 +10,7 @@
import io.runtime.mcumgr.managers.ImageManager;
import io.runtime.mcumgr.response.img.McuMgrImageResponse;
import io.runtime.mcumgr.response.img.McuMgrImageStateResponse;
+import org.jetbrains.annotations.Contract;
@SuppressWarnings("unused")
public class AndroidFirmwareEraser {
@@ -79,12 +80,14 @@ private void setState(EAndroidFirmwareEraserState newState) {
stateChangedAdvertisement(oldState, newState); //order
}
+ @Contract(pure = true)
public void stateChangedAdvertisement(EAndroidFirmwareEraserState oldState, EAndroidFirmwareEraserState currentState) {
//this method is intentionally empty its meant to be overridden by csharp binding libraries to intercept updates
}
private String _lastFatalErrorMessage;
+ @Contract(pure = true)
public String getLastFatalErrorMessage() {
return _lastFatalErrorMessage;
}
@@ -93,10 +96,12 @@ public void fatalErrorOccurredAdvertisement(final String errorMessage) {
_lastFatalErrorMessage = errorMessage; //this method is meant to be overridden by csharp binding libraries to intercept updates
}
+ @Contract(pure = true)
public void logMessageAdvertisement(final String message, final String category, final String level) {
//this method is intentionally empty its meant to be overridden by csharp binding libraries to intercept updates
}
+ @Contract(pure = true)
public void busyStateChangedAdvertisement(final boolean busyNotIdle) {
//this method is intentionally empty its meant to be overridden by csharp binding libraries to intercept updates
}
diff --git a/Laerdal.McuMgr.Bindings.Android.Native/mcumgr-laerdal-wrapper/src/main/java/no/laerdal/mcumgr_laerdal_wrapper/AndroidFirmwareInstaller.java b/Laerdal.McuMgr.Bindings.Android.Native/mcumgr-laerdal-wrapper/src/main/java/no/laerdal/mcumgr_laerdal_wrapper/AndroidFirmwareInstaller.java
index eef36436..d637d03c 100644
--- a/Laerdal.McuMgr.Bindings.Android.Native/mcumgr-laerdal-wrapper/src/main/java/no/laerdal/mcumgr_laerdal_wrapper/AndroidFirmwareInstaller.java
+++ b/Laerdal.McuMgr.Bindings.Android.Native/mcumgr-laerdal-wrapper/src/main/java/no/laerdal/mcumgr_laerdal_wrapper/AndroidFirmwareInstaller.java
@@ -18,6 +18,7 @@
import io.runtime.mcumgr.exception.McuMgrException;
import io.runtime.mcumgr.exception.McuMgrTimeoutException;
import no.nordicsemi.android.ble.ConnectionPriorityRequest;
+import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
@SuppressWarnings("unused")
@@ -237,6 +238,7 @@ protected void onCleared()
private String _lastFatalErrorMessage;
+ @Contract(pure = true)
public String getLastFatalErrorMessage()
{
return _lastFatalErrorMessage;
@@ -258,26 +260,31 @@ public void fatalErrorOccurredAdvertisement(final EAndroidFirmwareInstallationSt
_lastFatalErrorMessage = errorMessage;
}
+ @Contract(pure = true)
public void logMessageAdvertisement(final String message, final String category, final String level)
{
//this method is intentionally empty its meant to be overridden by csharp binding libraries to intercept updates
}
+ @Contract(pure = true)
public void cancelledAdvertisement()
{
//this method is intentionally empty its meant to be overridden by csharp binding libraries to intercept updates
}
+ @Contract(pure = true)
public void busyStateChangedAdvertisement(final boolean busyNotIdle)
{
//this method is intentionally empty its meant to be overridden by csharp binding libraries to intercept updates
}
+ @Contract(pure = true)
public void stateChangedAdvertisement(final EAndroidFirmwareInstallationState oldState, final EAndroidFirmwareInstallationState currentState)
{
//this method is intentionally empty its meant to be overridden by csharp binding libraries to intercept updates
}
+ @Contract(pure = true)
public void firmwareUploadProgressPercentageAndDataThroughputChangedAdvertisement(final int progressPercentage, final float averageThroughput)
{
//this method is intentionally empty its meant to be overridden by csharp binding libraries to intercept updates
diff --git a/Laerdal.McuMgr.Bindings.Android/Laerdal.McuMgr.Bindings.Android.csproj b/Laerdal.McuMgr.Bindings.Android/Laerdal.McuMgr.Bindings.Android.csproj
index 691c6362..35d1227b 100644
--- a/Laerdal.McuMgr.Bindings.Android/Laerdal.McuMgr.Bindings.Android.csproj
+++ b/Laerdal.McuMgr.Bindings.Android/Laerdal.McuMgr.Bindings.Android.csproj
@@ -62,10 +62,10 @@
true
- 1.0.1168.0
- 1.0.1168.0
- 1.0.1168.0
- 1.0.1168.0
+ 1.0.1177.0
+ 1.0.1177.0
+ 1.0.1177.0
+ 1.0.1177.0
$(PackageId)
$(Authors)
diff --git a/Laerdal.McuMgr.Bindings.MacCatalyst/Laerdal.McuMgr.Bindings.MacCatalyst.csproj b/Laerdal.McuMgr.Bindings.MacCatalyst/Laerdal.McuMgr.Bindings.MacCatalyst.csproj
index f1f8fa61..0569bbac 100644
--- a/Laerdal.McuMgr.Bindings.MacCatalyst/Laerdal.McuMgr.Bindings.MacCatalyst.csproj
+++ b/Laerdal.McuMgr.Bindings.MacCatalyst/Laerdal.McuMgr.Bindings.MacCatalyst.csproj
@@ -73,10 +73,10 @@
$(AllowedReferenceRelatedFileExtensions);.pdb
- 1.0.1168.0
- 1.0.1168.0
- 1.0.1168.0
- 1.0.1168.0
+ 1.0.1177.0
+ 1.0.1177.0
+ 1.0.1177.0
+ 1.0.1177.0
$(PackageId)
McuMgr Bindings for MacCatalyst - MAUI ready
diff --git a/Laerdal.McuMgr.Bindings.MacCatalystAndIos.Native/McuMgrBindingsiOS/McuMgrBindingsiOS/IOSFileDownloader.swift b/Laerdal.McuMgr.Bindings.MacCatalystAndIos.Native/McuMgrBindingsiOS/McuMgrBindingsiOS/IOSFileDownloader.swift
index cc207b47..547bcc3f 100644
--- a/Laerdal.McuMgr.Bindings.MacCatalystAndIos.Native/McuMgrBindingsiOS/McuMgrBindingsiOS/IOSFileDownloader.swift
+++ b/Laerdal.McuMgr.Bindings.MacCatalystAndIos.Native/McuMgrBindingsiOS/McuMgrBindingsiOS/IOSFileDownloader.swift
@@ -6,68 +6,92 @@ public class IOSFileDownloader: NSObject {
private var _listener: IOSListenerForFileDownloader!
private var _transporter: McuMgrBleTransport!
- private var _currentState: EIOSFileDownloaderState
+ private var _cbPeripheral: CBPeripheral!
private var _fileSystemManager: FileSystemManager!
- private var _lastFatalErrorMessage: String
+ private var _currentState: EIOSFileDownloaderState = .none
private var _lastBytesSend: Int = -1
+ private var _lastFatalErrorMessage: String = ""
private var _lastBytesSendTimestamp: Date? = nil
- private var _remoteFilePathSanitized: String
+ private var _remoteFilePathSanitized: String = ""
+
+ @objc
+ public init(_ listener: IOSListenerForFileDownloader!) {
+ _listener = listener
+ }
@objc
public init(_ cbPeripheral: CBPeripheral!, _ listener: IOSListenerForFileDownloader!) {
_listener = listener
- _transporter = McuMgrBleTransport(cbPeripheral)
- _currentState = .none
- _lastFatalErrorMessage = ""
- _remoteFilePathSanitized = ""
+ _cbPeripheral = cbPeripheral
+ }
+
+ @objc
+ public func trySetBluetoothDevice(_ cbPeripheral: CBPeripheral!) -> Bool {
+ if !isIdleOrCold() {
+ return false
+ }
+
+ if !tryInvalidateCachedTransport() { //order
+ return false
+ }
+
+ _cbPeripheral = cbPeripheral //order
+ return true
+ }
+
+ @objc
+ public func tryInvalidateCachedTransport() -> Bool {
+ if _transporter == nil { //already scrapped
+ return true
+ }
+
+ if !isIdleOrCold() { //if the upload is already in progress we bail out
+ return false
+ }
+
+ disposeFilesystemManager() // order
+ disposeTransport() // order
+
+ return true;
}
@objc
public func beginDownload(_ remoteFilePath: String) -> EIOSFileDownloadingInitializationVerdict {
- if _currentState != .none
- && _currentState != .error
- && _currentState != .complete
- && _currentState != .cancelled { //if another download is already in progress we bail out
+
+ if !isCold() { //keep first if another download is already in progress we bail out
+ onError("Another download is already in progress")
+
return EIOSFileDownloadingInitializationVerdict.failedDownloadAlreadyInProgress
}
- _lastBytesSend = -1
- _lastBytesSendTimestamp = nil
-
- if remoteFilePath.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
- setState(EIOSFileDownloaderState.error)
- fatalErrorOccurredAdvertisement("", "Target-file provided is dud!")
+ _remoteFilePathSanitized = remoteFilePath.trimmingCharacters(in: .whitespacesAndNewlines)
+ if _remoteFilePathSanitized.isEmpty {
+ onError("Target-file provided is dud!")
return EIOSFileDownloadingInitializationVerdict.failedInvalidSettings
}
- if remoteFilePath.hasSuffix("/") {
- setState(EIOSFileDownloaderState.error)
- fatalErrorOccurredAdvertisement(_remoteFilePathSanitized, "Target-file points to a directory instead of a file")
+ if _remoteFilePathSanitized.hasSuffix("/") {
+ onError("Target-file points to a directory instead of a file")
return EIOSFileDownloadingInitializationVerdict.failedInvalidSettings
}
- if !remoteFilePath.hasPrefix("/") {
- setState(EIOSFileDownloaderState.error)
- fatalErrorOccurredAdvertisement(_remoteFilePathSanitized, "Target-path is not absolute!")
+ if !_remoteFilePathSanitized.hasPrefix("/") {
+ onError("Target-path is not absolute!")
return EIOSFileDownloadingInitializationVerdict.failedInvalidSettings
}
- _fileSystemManager = FileSystemManager(transport: _transporter) // the delegate aspect is implemented in the extension below
- _fileSystemManager.logDelegate = self
+ resetUploadState() //order
+ disposeFilesystemManager() //00 vital hack
+ ensureTransportIsInitializedExactlyOnce() //order
+ ensureFilesystemManagerIsInitializedExactlyOnce() //order
- setState(EIOSFileDownloaderState.idle)
- busyStateChangedAdvertisement(true)
- fileDownloadProgressPercentageAndDataThroughputChangedAdvertisement(0, 0)
-
- _remoteFilePathSanitized = remoteFilePath
- let success = _fileSystemManager.download(name: remoteFilePath, delegate: self)
+ let success = _fileSystemManager.download(name: _remoteFilePathSanitized, delegate: self)
if !success {
- setState(EIOSFileDownloaderState.error)
- fatalErrorOccurredAdvertisement(_remoteFilePathSanitized, "Failed to commence file-Downloading (check logs for details)")
+ onError("Failed to commence file-Downloading (check logs for details)")
return EIOSFileDownloadingInitializationVerdict.failedErrorUponCommencing
}
@@ -106,11 +130,102 @@ public class IOSFileDownloader: NSObject {
_transporter?.close()
}
+ private func isIdleOrCold() -> Bool {
+ return _currentState == EIOSFileDownloaderState.idle || isCold();
+ }
+
+ private func isCold() -> Bool {
+ return _currentState == EIOSFileDownloaderState.none
+ || _currentState == EIOSFileDownloaderState.error
+ || _currentState == EIOSFileDownloaderState.complete
+ || _currentState == EIOSFileDownloaderState.cancelled
+ }
+
+ private func resetUploadState() {
+ _lastBytesSend = -1
+ _lastBytesSendTimestamp = nil
+
+ setState(EIOSFileDownloaderState.idle)
+ busyStateChangedAdvertisement(true)
+ fileDownloadProgressPercentageAndDataThroughputChangedAdvertisement(0, 0)
+ }
+
+ private func ensureFilesystemManagerIsInitializedExactlyOnce() {
+ if _fileSystemManager != nil { //already initialized
+ return
+ }
+
+ _fileSystemManager = FileSystemManager(transport: _transporter) //00
+ _fileSystemManager.logDelegate = self //00
+
+ //00 this doesnt throw an error the log-delegate aspect is implemented in the extension below via IOSFileDownloader: McuMgrLogDelegate
+ }
+
+ private func ensureTransportIsInitializedExactlyOnce() {
+ if _transporter != nil {
+ return
+ }
+
+ _transporter = McuMgrBleTransport(_cbPeripheral)
+ }
+
+ private func disposeTransport() {
+ _transporter?.close()
+ _transporter = nil
+ }
+
+ private func disposeFilesystemManager() {
+ //_fileSystemManager?.cancelTransfer() dont
+ _fileSystemManager = nil
+ }
+
//@objc dont
- private func fatalErrorOccurredAdvertisement(_ resource: String, _ errorMessage: String) {
+ private func onError(_ errorMessage: String, _ error: Error? = nil) {
+ setState(EIOSFileDownloaderState.error) //keep first
+
_lastFatalErrorMessage = errorMessage
- _listener.fatalErrorOccurredAdvertisement(resource, errorMessage)
+ let (errorCode, _) = deduceErrorCode(errorMessage)
+
+ _listener.fatalErrorOccurredAdvertisement(
+ _remoteFilePathSanitized,
+ errorMessage,
+ errorCode
+ )
+ }
+
+ // unfortunately I couldnt figure out a way to deduce the error code from the error itself so I had to resort to string sniffing ugly but it works
+ private func deduceErrorCode(_ errorMessage: String) -> (Int, String?) {
+ let (matchesArray, possibleError) = matches(for: " [(]\\d+[)][.]?$", in: errorMessage) // "UNKNOWN (1)."
+ if possibleError != nil {
+ return (-99, possibleError)
+ }
+
+ let errorCode = matchesArray.isEmpty
+ ? -99
+ : (Int(matchesArray[0].trimmingCharacters(in: .whitespaces).trimmingCharacters(in: ["(", ")", "."]).trimmingCharacters(in: .whitespaces)) ?? 0)
+
+ return (errorCode, possibleError)
+ }
+
+ private func matches(for regex: String, in text: String) -> ([String], String?) { //00
+ do {
+ let regex = try NSRegularExpression(pattern: regex)
+ let results = regex.matches(in: text, range: NSRange(text.startIndex..., in: text))
+
+ return (
+ results.map {
+ String(text[Range($0.range, in: text)!])
+ },
+ nil
+ )
+ } catch let error {
+ print("invalid regex: \(error.localizedDescription)")
+
+ return ([], error.localizedDescription)
+ }
+
+ //00 https://stackoverflow.com/a/27880748/863651
}
//@objc dont
@@ -143,7 +258,7 @@ public class IOSFileDownloader: NSObject {
) {
_listener.fileDownloadProgressPercentageAndDataThroughputChangedAdvertisement(progressPercentage, averageThroughput)
}
-
+
//@objc dont
private func downloadCompletedAdvertisement(_ resource: String, _ data: [UInt8]) {
_listener.downloadCompletedAdvertisement(resource, data)
@@ -178,8 +293,8 @@ extension IOSFileDownloader: FileDownloadDelegate {
}
public func downloadDidFail(with error: Error) {
- setState(EIOSFileDownloaderState.error)
- fatalErrorOccurredAdvertisement(_remoteFilePathSanitized, error.localizedDescription)
+ onError(error.localizedDescription, error)
+
busyStateChangedAdvertisement(false)
}
diff --git a/Laerdal.McuMgr.Bindings.MacCatalystAndIos.Native/McuMgrBindingsiOS/McuMgrBindingsiOS/IOSFileUploader.swift b/Laerdal.McuMgr.Bindings.MacCatalystAndIos.Native/McuMgrBindingsiOS/McuMgrBindingsiOS/IOSFileUploader.swift
index cf710bb9..333269ba 100644
--- a/Laerdal.McuMgr.Bindings.MacCatalystAndIos.Native/McuMgrBindingsiOS/McuMgrBindingsiOS/IOSFileUploader.swift
+++ b/Laerdal.McuMgr.Bindings.MacCatalystAndIos.Native/McuMgrBindingsiOS/McuMgrBindingsiOS/IOSFileUploader.swift
@@ -7,14 +7,14 @@ public class IOSFileUploader: NSObject {
private let _listener: IOSListenerForFileUploader!
private var _transporter: McuMgrBleTransport!
private var _cbPeripheral: CBPeripheral!
- private var _currentState: EIOSFileUploaderState = .none
private var _fileSystemManager: FileSystemManager!
- private var _cancellationReason: String = ""
- private var _lastFatalErrorMessage: String = ""
- private var _remoteFilePathSanitized: String!
+ private var _currentState: EIOSFileUploaderState = .none
private var _lastBytesSend: Int = 0
+ private var _cancellationReason: String = ""
+ private var _lastFatalErrorMessage: String = ""
private var _lastBytesSendTimestamp: Date? = nil
+ private var _remoteFilePathSanitized: String!
@objc
public init(_ listener: IOSListenerForFileUploader!) {
@@ -29,7 +29,7 @@ public class IOSFileUploader: NSObject {
@objc
public func trySetBluetoothDevice(_ cbPeripheral: CBPeripheral!) -> Bool {
- if !IsCold() {
+ if !isIdleOrCold() {
return false
}
@@ -47,7 +47,7 @@ public class IOSFileUploader: NSObject {
return true
}
- if !IsCold() { //if the upload is already in progress we bail out
+ if !isIdleOrCold() { //if the upload is already in progress we bail out
return false
}
@@ -65,65 +65,60 @@ public class IOSFileUploader: NSObject {
_ byteAlignment: Int
) -> EIOSFileUploadingInitializationVerdict {
- if !IsCold() { //if another upload is already in progress we bail out
- setState(EIOSFileUploaderState.error)
+ if !isCold() { //keep first if another upload is already in progress we bail out
onError("Another upload is already in progress")
return EIOSFileUploadingInitializationVerdict.failedOtherUploadAlreadyInProgress
}
- if _cbPeripheral == nil {
- setState(EIOSFileUploaderState.error)
- onError("No bluetooth-device specified - call trySetBluetoothDevice() first");
-
- return EIOSFileUploadingInitializationVerdict.failedInvalidSettings;
- }
-
- if (pipelineDepth >= 2 && byteAlignment <= 1) {
- setState(EIOSFileUploaderState.error)
- onError("When pipeline-depth is set to 2 or above you must specify a byte-alignment >=2 (given byte-alignment is '\(byteAlignment)')")
-
- return .failedInvalidSettings
- }
-
- let byteAlignmentEnum = translateByteAlignmentMode(byteAlignment);
- if (byteAlignmentEnum == nil) {
- setState(EIOSFileUploaderState.error)
- onError("Invalid byte-alignment value '\(byteAlignment)': It must be a power of 2 up to 16")
-
- return .failedInvalidSettings
- }
-
_remoteFilePathSanitized = remoteFilePath.trimmingCharacters(in: .whitespacesAndNewlines)
if _remoteFilePathSanitized.isEmpty {
- setState(EIOSFileUploaderState.error)
onError("Target-file provided is dud")
return EIOSFileUploadingInitializationVerdict.failedInvalidSettings
}
if _remoteFilePathSanitized.hasSuffix("/") {
- setState(EIOSFileUploaderState.error)
onError("Target-file points to a directory instead of a file")
return EIOSFileUploadingInitializationVerdict.failedInvalidSettings
}
if !_remoteFilePathSanitized.hasPrefix("/") {
- setState(EIOSFileUploaderState.error)
onError("Target-path is not absolute!")
return EIOSFileUploadingInitializationVerdict.failedInvalidSettings
}
if data == nil { // data being nil is not ok btw data.length==0 is perfectly ok because we might want to create empty files
+ onError("The data provided are nil")
+
return EIOSFileUploadingInitializationVerdict.failedInvalidData
}
+ if _cbPeripheral == nil {
+ onError("No bluetooth-device specified - call trySetBluetoothDevice() first");
+
+ return EIOSFileUploadingInitializationVerdict.failedInvalidSettings;
+ }
+
+ if (pipelineDepth >= 2 && byteAlignment <= 1) {
+ onError("When pipeline-depth is set to 2 or above you must specify a byte-alignment >=2 (given byte-alignment is '\(byteAlignment)')")
+
+ return .failedInvalidSettings
+ }
+
+ let byteAlignmentEnum = translateByteAlignmentMode(byteAlignment);
+ if (byteAlignmentEnum == nil) {
+ onError("Invalid byte-alignment value '\(byteAlignment)': It must be a power of 2 up to 16")
+
+ return .failedInvalidSettings
+ }
+
+ resetUploadState() //order
disposeFilesystemManager() //00 vital hack
ensureTransportIsInitializedExactlyOnce() //order
ensureFilesystemManagerIsInitializedExactlyOnce() //order
- resetUploadState() //order
var configuration = FirmwareUpgradeConfiguration(byteAlignment: byteAlignmentEnum!)
if (pipelineDepth >= 0) {
@@ -137,7 +132,6 @@ public class IOSFileUploader: NSObject {
delegate: self
)
if !success {
- setState(EIOSFileUploaderState.error)
onError("Failed to commence file-uploading (check logs for details)")
return EIOSFileUploadingInitializationVerdict.failedErrorUponCommencing
@@ -239,7 +233,11 @@ public class IOSFileUploader: NSObject {
_fileSystemManager = nil
}
- private func IsCold() -> Bool {
+ private func isIdleOrCold() -> Bool {
+ return _currentState == EIOSFileUploaderState.idle || isCold();
+ }
+
+ private func isCold() -> Bool {
return _currentState == EIOSFileUploaderState.none
|| _currentState == EIOSFileUploaderState.error
|| _currentState == EIOSFileUploaderState.complete
@@ -248,6 +246,8 @@ public class IOSFileUploader: NSObject {
//@objc dont
private func onError(_ errorMessage: String, _ error: Error? = nil) {
+ setState(EIOSFileUploaderState.error) //keep first
+
_lastFatalErrorMessage = errorMessage
let (errorCode, _) = deduceErrorCode(errorMessage)
@@ -365,7 +365,6 @@ extension IOSFileUploader: FileUploadDelegate {
}
public func uploadDidFail(with error: Error) {
- setState(EIOSFileUploaderState.error)
onError(error.localizedDescription, error)
busyStateChangedAdvertisement(false)
}
diff --git a/Laerdal.McuMgr.Bindings.MacCatalystAndIos.Native/McuMgrBindingsiOS/McuMgrBindingsiOS/IOSListenerForFileDownloader.swift b/Laerdal.McuMgr.Bindings.MacCatalystAndIos.Native/McuMgrBindingsiOS/McuMgrBindingsiOS/IOSListenerForFileDownloader.swift
index 62d9ea0c..0275d8e9 100644
--- a/Laerdal.McuMgr.Bindings.MacCatalystAndIos.Native/McuMgrBindingsiOS/McuMgrBindingsiOS/IOSListenerForFileDownloader.swift
+++ b/Laerdal.McuMgr.Bindings.MacCatalystAndIos.Native/McuMgrBindingsiOS/McuMgrBindingsiOS/IOSListenerForFileDownloader.swift
@@ -3,9 +3,10 @@ import Foundation
@objc
public protocol IOSListenerForFileDownloader {
func logMessageAdvertisement(_ message: String, _ category: String, _ level: String, _ resource: String)
- func fatalErrorOccurredAdvertisement(_ resource: String, _ errorMessage: String)
+ func fatalErrorOccurredAdvertisement(_ resource: String, _ errorMessage: String, _ errorCode: Int)
func cancelledAdvertisement()
+
func stateChangedAdvertisement(_ resource: String, _ oldState: EIOSFileDownloaderState, _ newState: EIOSFileDownloaderState)
func busyStateChangedAdvertisement(_ busyNotIdle: Bool)
func downloadCompletedAdvertisement(_ resource: String, _ data: [UInt8])
diff --git a/Laerdal.McuMgr.Bindings.NetStandard/Laerdal.McuMgr.Bindings.NetStandard.csproj b/Laerdal.McuMgr.Bindings.NetStandard/Laerdal.McuMgr.Bindings.NetStandard.csproj
index ceb6eab9..f3e3ca9b 100644
--- a/Laerdal.McuMgr.Bindings.NetStandard/Laerdal.McuMgr.Bindings.NetStandard.csproj
+++ b/Laerdal.McuMgr.Bindings.NetStandard/Laerdal.McuMgr.Bindings.NetStandard.csproj
@@ -37,10 +37,10 @@
$(AllowedReferenceRelatedFileExtensions);.pdb
- 1.0.1168.0
- 1.0.1168.0
- 1.0.1168.0
- 1.0.1168.0
+ 1.0.1177.0
+ 1.0.1177.0
+ 1.0.1177.0
+ 1.0.1177.0
$(PackageId)
McuMgr C# Implementation (WIP)
diff --git a/Laerdal.McuMgr.Bindings.iOS/Laerdal.McuMgr.Bindings.iOS.csproj b/Laerdal.McuMgr.Bindings.iOS/Laerdal.McuMgr.Bindings.iOS.csproj
index 9bb84e46..87aa794c 100644
--- a/Laerdal.McuMgr.Bindings.iOS/Laerdal.McuMgr.Bindings.iOS.csproj
+++ b/Laerdal.McuMgr.Bindings.iOS/Laerdal.McuMgr.Bindings.iOS.csproj
@@ -73,10 +73,10 @@
$(AllowedReferenceRelatedFileExtensions);.pdb
- 1.0.1168.0
- 1.0.1168.0
- 1.0.1168.0
- 1.0.1168.0
+ 1.0.1177.0
+ 1.0.1177.0
+ 1.0.1177.0
+ 1.0.1177.0
$(PackageId)
McuMgr Bindings for iOS - MAUI ready
diff --git a/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.BeginDownload.ShouldThrowArgumentException_GivenInvalidRemoteFilePath.cs b/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.BeginDownload.ShouldThrowArgumentException_GivenInvalidRemoteFilePath.cs
index f93b1510..664f54ba 100644
--- a/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.BeginDownload.ShouldThrowArgumentException_GivenInvalidRemoteFilePath.cs
+++ b/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.BeginDownload.ShouldThrowArgumentException_GivenInvalidRemoteFilePath.cs
@@ -25,7 +25,12 @@ public void BeginDownload_ShouldThrowArgumentException_GivenInvalidRemoteFilePat
using var eventsMonitor = fileDownloader.Monitor();
// Act
- var work = new Func(() => fileDownloader.BeginDownload(remoteFilePath: remoteFilePath));
+ var work = new Func(() => fileDownloader.BeginDownload(
+ hostDeviceModel: "foobar",
+ hostDeviceManufacturer: "acme corp.",
+
+ remoteFilePath: remoteFilePath
+ ));
// Assert
work.Should().ThrowExactly();
diff --git a/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.MultipleFilesDownloadAsync.ShouldCompleteSuccessfully_GivenNoFilesToDownload.cs b/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.MultipleFilesDownloadAsync.ShouldCompleteSuccessfully_GivenNoFilesToDownload.cs
index b5ef7796..f303e8b4 100644
--- a/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.MultipleFilesDownloadAsync.ShouldCompleteSuccessfully_GivenNoFilesToDownload.cs
+++ b/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.MultipleFilesDownloadAsync.ShouldCompleteSuccessfully_GivenNoFilesToDownload.cs
@@ -20,7 +20,12 @@ public async Task MultipleFilesDownloadAsync_ShouldCompleteSuccessfully_GivenNoF
using var eventsMonitor = fileDownloader.Monitor();
// Act
- var work = new Func>>(async () => await fileDownloader.DownloadAsync([]));
+ var work = new Func>>(async () => await fileDownloader.DownloadAsync(
+ hostDeviceModel: "foobar",
+ hostDeviceManufacturer: "acme corp.",
+
+ remoteFilePaths: []
+ ));
// Assert
var results = (await work.Should().CompleteWithinAsync(500.Milliseconds())).Which;
diff --git a/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.MultipleFilesDownloadAsync.ShouldCompleteSuccessfully_GivenVariousFilesToDownload.cs b/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.MultipleFilesDownloadAsync.ShouldCompleteSuccessfully_GivenVariousFilesToDownload.cs
index e1cf813e..7bfa39c4 100644
--- a/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.MultipleFilesDownloadAsync.ShouldCompleteSuccessfully_GivenVariousFilesToDownload.cs
+++ b/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.MultipleFilesDownloadAsync.ShouldCompleteSuccessfully_GivenVariousFilesToDownload.cs
@@ -1,7 +1,9 @@
using FluentAssertions;
using FluentAssertions.Extensions;
+using Laerdal.McuMgr.Common.Enums;
using Laerdal.McuMgr.FileDownloader.Contracts.Enums;
using Laerdal.McuMgr.FileDownloader.Contracts.Native;
+using Laerdal.McuMgr.FileUploader.Contracts.Enums;
using GenericNativeFileDownloaderCallbacksProxy_ = Laerdal.McuMgr.FileDownloader.FileDownloader.GenericNativeFileDownloaderCallbacksProxy;
#pragma warning disable xUnit1026
@@ -46,6 +48,9 @@ public async Task MultipleFilesDownloadAsync_ShouldCompleteSuccessfully_GivenVar
// Act
var work = new Func>>(async () => await fileDownloader.DownloadAsync(
+ hostDeviceModel: "foobar",
+ hostDeviceManufacturer: "acme corp.",
+
remoteFilePaths: remoteFilePathsToTest,
maxRetriesPerDownload: 4
));
@@ -100,18 +105,18 @@ public override EFileDownloaderVerdict BeginDownload(string remoteFilePath, int?
if (remoteFilePathUppercase.Contains("some/file/that/exist/but/is/erroring/out/when/we/try/to/download/it.bin".ToUpperInvariant()))
{
StateChangedAdvertisement(remoteFilePath, oldState: EFileDownloaderState.Downloading, newState: EFileDownloaderState.Error);
- FatalErrorOccurredAdvertisement(remoteFilePath, "foobar");
+ FatalErrorOccurredAdvertisement(remoteFilePath, "foobar", EMcuMgrErrorCode.Unknown, EFileOperationGroupReturnCode.Unset);
}
else if (remoteFilePathUppercase.Contains("some/file/that/doesnt/exist.bin".ToUpperInvariant()))
{
StateChangedAdvertisement(remoteFilePath, oldState: EFileDownloaderState.Downloading, newState: EFileDownloaderState.Error);
- FatalErrorOccurredAdvertisement(remoteFilePath, "NO ENTRY (5)");
+ FatalErrorOccurredAdvertisement(remoteFilePath, "NO ENTRY (5)", EMcuMgrErrorCode.Unknown, EFileOperationGroupReturnCode.Unset);
}
else if (remoteFilePathUppercase.Contains("some/file/that/exist/and/completes/after/a/couple/of/attempts.bin".ToUpperInvariant())
&& _retryCountForProblematicFile++ < 3)
{
StateChangedAdvertisement(remoteFilePath, oldState: EFileDownloaderState.Downloading, newState: EFileDownloaderState.Error);
- FatalErrorOccurredAdvertisement(remoteFilePath, "ping pong");
+ FatalErrorOccurredAdvertisement(remoteFilePath, "ping pong", EMcuMgrErrorCode.Unknown, EFileOperationGroupReturnCode.Unset);
}
else
{
diff --git a/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.MultipleFilesDownloadAsync.ShouldThrowArgumentException_GivenPathCollectionWithErroneousFilesToDownload.cs b/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.MultipleFilesDownloadAsync.ShouldThrowArgumentException_GivenPathCollectionWithErroneousFilesToDownload.cs
index cf54bae9..a764b37f 100644
--- a/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.MultipleFilesDownloadAsync.ShouldThrowArgumentException_GivenPathCollectionWithErroneousFilesToDownload.cs
+++ b/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.MultipleFilesDownloadAsync.ShouldThrowArgumentException_GivenPathCollectionWithErroneousFilesToDownload.cs
@@ -29,7 +29,12 @@ public async Task MultipleFilesDownloadAsync_ShouldThrowArgumentException_GivenP
using var eventsMonitor = fileDownloader.Monitor();
// Act
- var work = new Func>>(async () => await fileDownloader.DownloadAsync(remoteFilePaths));
+ var work = new Func>>(async () => await fileDownloader.DownloadAsync(
+ hostDeviceModel: "foobar",
+ hostDeviceManufacturer: "acme corp.",
+
+ remoteFilePaths: remoteFilePaths
+ ));
// Assert
await work.Should().ThrowExactlyAsync().WithTimeoutInMs(500);
diff --git a/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.MultipleFilesDownloadAsync.ShouldThrowNullArgumentException_GivenNullForFilesToDownload.cs b/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.MultipleFilesDownloadAsync.ShouldThrowNullArgumentException_GivenNullForFilesToDownload.cs
index beb63324..bc9f6686 100644
--- a/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.MultipleFilesDownloadAsync.ShouldThrowNullArgumentException_GivenNullForFilesToDownload.cs
+++ b/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.MultipleFilesDownloadAsync.ShouldThrowNullArgumentException_GivenNullForFilesToDownload.cs
@@ -20,7 +20,12 @@ public async Task MultipleFilesDownloadAsync_ShouldThrowNullArgumentException_Gi
using var eventsMonitor = fileDownloader.Monitor();
// Act
- var work = new Func>>(async () => await fileDownloader.DownloadAsync(remoteFilePaths: null));
+ var work = new Func>>(async () => await fileDownloader.DownloadAsync(
+ hostDeviceModel: "foobar",
+ hostDeviceManufacturer: "acme corp.",
+
+ remoteFilePaths: null
+ ));
// Assert
await work.Should().ThrowExactlyAsync().WithTimeoutInMs(500);
diff --git a/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.SingleFileDownloadAsync.ShouldCompleteSuccessfullyByFallingBackToFailsafeSettings_GivenFlakyConnection.cs b/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.SingleFileDownloadAsync.ShouldCompleteSuccessfullyByFallingBackToFailsafeSettings_GivenFlakyConnection.cs
index 3716a16a..4ffa2559 100644
--- a/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.SingleFileDownloadAsync.ShouldCompleteSuccessfullyByFallingBackToFailsafeSettings_GivenFlakyConnection.cs
+++ b/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.SingleFileDownloadAsync.ShouldCompleteSuccessfullyByFallingBackToFailsafeSettings_GivenFlakyConnection.cs
@@ -6,6 +6,7 @@
using Laerdal.McuMgr.FileDownloader.Contracts.Enums;
using Laerdal.McuMgr.FileDownloader.Contracts.Events;
using Laerdal.McuMgr.FileDownloader.Contracts.Native;
+using Laerdal.McuMgr.FileUploader.Contracts.Enums;
using GenericNativeFileDownloaderCallbacksProxy_ = Laerdal.McuMgr.FileDownloader.FileDownloader.GenericNativeFileDownloaderCallbacksProxy;
#pragma warning disable xUnit1026
@@ -16,8 +17,8 @@ public partial class FileDownloaderTestbed
{
[Theory]
[InlineData("FDT.SFDA.SCSBFBTFS.GFBC.010", "/path/to/file.bin", 2)]
- [InlineData("FDT.SFDA.SCSBFBTFS.GFBC.020", "/path/to/file.bin", 3)]
- [InlineData("FDT.SFDA.SCSBFBTFS.GFBC.030", "/path/to/file.bin", 5)]
+ // [InlineData("FDT.SFDA.SCSBFBTFS.GFBC.020", "/path/to/file.bin", 3)]
+ // [InlineData("FDT.SFDA.SCSBFBTFS.GFBC.030", "/path/to/file.bin", 5)]
public async Task SingleFileDownloadAsync_ShouldCompleteSuccessfullyByFallingBackToFailsafeSettings_GivenFlakyBluetoothConnection(string testcaseNickname, string remoteFilePath, int maxTriesCount)
{
// Arrange
@@ -34,12 +35,15 @@ public async Task SingleFileDownloadAsync_ShouldCompleteSuccessfullyByFallingBac
// Act
var work = new Func(() => fileDownloader.DownloadAsync(
+ hostDeviceModel: "foobar",
+ hostDeviceManufacturer: "acme corp.",
+
maxTriesCount: maxTriesCount,
remoteFilePath: remoteFilePath
));
// Assert
- await work.Should().CompleteWithinAsync((maxTriesCount * 2).Seconds());
+ await work.Should().CompleteWithinAsync((maxTriesCount * 200).Seconds());
mockedNativeFileDownloaderProxy.BugDetected.Should().BeNull();
mockedNativeFileDownloaderProxy.CancelCalled.Should().BeFalse();
@@ -60,7 +64,7 @@ public async Task SingleFileDownloadAsync_ShouldCompleteSuccessfullyByFallingBac
.Where(x => x.EventName == nameof(fileDownloader.LogEmitted))
.SelectMany(x => x.Parameters)
.OfType()
- .Count(l => l is { Level: ELogLevel.Warning } && l.Message.Contains("GFCSICPTBU.010"))
+ .Count(l => l is { Level: ELogLevel.Warning } && l.Message.Contains("[FD.DA.010]"))
.Should()
.Be(1);
@@ -123,19 +127,19 @@ public override EFileDownloaderVerdict BeginDownload(
await Task.Delay(5);
FileDownloadProgressPercentageAndDataThroughputChangedAdvertisement(60, 10);
- if (_tryCounter == _maxTriesCount && initialMtuSize != AndroidTidbits.FailSafeBleConnectionSettings.InitialMtuSize)
+ if (_tryCounter == _maxTriesCount && initialMtuSize != AndroidTidbits.BleConnectionFailsafeSettings.ForDownloading.InitialMtuSize)
{
- BugDetected = $"[BUG DETECTED] The very last try should be with {nameof(initialMtuSize)} set to {AndroidTidbits.FailSafeBleConnectionSettings.InitialMtuSize} but it's set to {initialMtuSize?.ToString() ?? "(null)"} instead - something is wrong!";
- StateChangedAdvertisement(remoteFilePath, EFileDownloaderState.Downloading, EFileDownloaderState.Error); // order
- FatalErrorOccurredAdvertisement(remoteFilePath, BugDetected); // order
+ BugDetected = $"[BUG DETECTED] The very last try should be with {nameof(initialMtuSize)} set to {AndroidTidbits.BleConnectionFailsafeSettings.ForDownloading.InitialMtuSize} but it's set to {initialMtuSize?.ToString() ?? "(null)"} instead - something is wrong!";
+ StateChangedAdvertisement(remoteFilePath, EFileDownloaderState.Downloading, EFileDownloaderState.Error); // order
+ FatalErrorOccurredAdvertisement(remoteFilePath, BugDetected, EMcuMgrErrorCode.Unknown, EFileOperationGroupReturnCode.Unset); // order
return;
}
if (_tryCounter < _maxTriesCount)
{
await Task.Delay(20);
- StateChangedAdvertisement(remoteFilePath, EFileDownloaderState.Downloading, EFileDownloaderState.Error); // order
- FatalErrorOccurredAdvertisement(remoteFilePath, "fatal error occurred"); // order
+ StateChangedAdvertisement(remoteFilePath, EFileDownloaderState.Downloading, EFileDownloaderState.Error); // order
+ FatalErrorOccurredAdvertisement(remoteFilePath, "fatal error occurred", EMcuMgrErrorCode.Unknown, EFileOperationGroupReturnCode.Unset); // order
return;
}
diff --git a/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.SingleFileDownloadAsync.ShouldCompleteSuccessfully_GivenGreenNativeFileDownloader.cs b/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.SingleFileDownloadAsync.ShouldCompleteSuccessfully_GivenGreenNativeFileDownloader.cs
index 887c797f..429f5350 100644
--- a/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.SingleFileDownloadAsync.ShouldCompleteSuccessfully_GivenGreenNativeFileDownloader.cs
+++ b/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.SingleFileDownloadAsync.ShouldCompleteSuccessfully_GivenGreenNativeFileDownloader.cs
@@ -1,8 +1,10 @@
using FluentAssertions;
using FluentAssertions.Extensions;
+using Laerdal.McuMgr.Common.Enums;
using Laerdal.McuMgr.FileDownloader.Contracts.Enums;
using Laerdal.McuMgr.FileDownloader.Contracts.Events;
using Laerdal.McuMgr.FileDownloader.Contracts.Native;
+using Laerdal.McuMgr.FileUploader.Contracts.Enums;
using GenericNativeFileDownloaderCallbacksProxy_ = Laerdal.McuMgr.FileDownloader.FileDownloader.GenericNativeFileDownloaderCallbacksProxy;
#pragma warning disable xUnit1026
@@ -38,6 +40,9 @@ public async Task SingleFileDownloadAsync_ShouldCompleteSuccessfully_GivenGreenN
// Act
var work = new Func(() => fileDownloader.DownloadAsync(
+ hostDeviceModel: "foobar",
+ hostDeviceManufacturer: "acme corp.",
+
maxTriesCount: maxTriesCount,
remoteFilePath: remoteFilePath,
sleepTimeBetweenRetriesInMs: sleepTimeBetweenRetriesInMs
@@ -102,7 +107,7 @@ public override EFileDownloaderVerdict BeginDownload(string remoteFilePath, int?
if (_tryCount < _maxNumberOfTriesForSuccess)
{
StateChangedAdvertisement(remoteFilePath, EFileDownloaderState.Downloading, EFileDownloaderState.Error);
- FatalErrorOccurredAdvertisement(remoteFilePath, "fatal error occurred");
+ FatalErrorOccurredAdvertisement(remoteFilePath, "fatal error occurred", EMcuMgrErrorCode.Unknown, EFileOperationGroupReturnCode.Unset);
return;
}
diff --git a/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.SingleFileDownloadAsync.ShouldThrowAllDownloadAttemptsFailedException_GivenFatalErrorMidflight.cs b/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.SingleFileDownloadAsync.ShouldThrowAllDownloadAttemptsFailedException_GivenFatalErrorMidflight.cs
index 62d54476..52259579 100644
--- a/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.SingleFileDownloadAsync.ShouldThrowAllDownloadAttemptsFailedException_GivenFatalErrorMidflight.cs
+++ b/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.SingleFileDownloadAsync.ShouldThrowAllDownloadAttemptsFailedException_GivenFatalErrorMidflight.cs
@@ -1,11 +1,13 @@
using System.Diagnostics.CodeAnalysis;
using FluentAssertions;
using FluentAssertions.Extensions;
+using Laerdal.McuMgr.Common.Enums;
using Laerdal.McuMgr.Common.Helpers;
using Laerdal.McuMgr.FileDownloader.Contracts.Enums;
using Laerdal.McuMgr.FileDownloader.Contracts.Events;
using Laerdal.McuMgr.FileDownloader.Contracts.Exceptions;
using Laerdal.McuMgr.FileDownloader.Contracts.Native;
+using Laerdal.McuMgr.FileUploader.Contracts.Enums;
using GenericNativeFileDownloaderCallbacksProxy_ = Laerdal.McuMgr.FileDownloader.FileDownloader.GenericNativeFileDownloaderCallbacksProxy;
namespace Laerdal.McuMgr.Tests.FileDownloader
@@ -29,6 +31,9 @@ public async Task SingleFileDownloadAsync_ShouldThrowAllDownloadAttemptsFailedEx
// Act
var work = new Func(() => fileDownloader.DownloadAsync(
+ hostDeviceModel: "foobar",
+ hostDeviceManufacturer: "acme corp.",
+
maxTriesCount: maxTriesCount,
remoteFilePath: remoteFilePath
));
@@ -87,7 +92,7 @@ public override EFileDownloaderVerdict BeginDownload(string remoteFilePath, int?
await Task.Delay(2_000);
StateChangedAdvertisement(remoteFilePath, EFileDownloaderState.Downloading, EFileDownloaderState.Error);
- FatalErrorOccurredAdvertisement(remoteFilePath, "fatal error occurred");
+ FatalErrorOccurredAdvertisement(remoteFilePath, "fatal error occurred", EMcuMgrErrorCode.BadState, EFileOperationGroupReturnCode.Unset);
});
return verdict;
diff --git a/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.SingleFileDownloadAsync.ShouldThrowAllDownloadAttemptsFailedException_GivenRogueNativeErrorMessage.cs b/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.SingleFileDownloadAsync.ShouldThrowAllDownloadAttemptsFailedException_GivenRogueNativeErrorMessage.cs
index 742a7352..07e1a945 100644
--- a/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.SingleFileDownloadAsync.ShouldThrowAllDownloadAttemptsFailedException_GivenRogueNativeErrorMessage.cs
+++ b/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.SingleFileDownloadAsync.ShouldThrowAllDownloadAttemptsFailedException_GivenRogueNativeErrorMessage.cs
@@ -1,11 +1,13 @@
using System.Diagnostics.CodeAnalysis;
using FluentAssertions;
using FluentAssertions.Extensions;
+using Laerdal.McuMgr.Common.Enums;
using Laerdal.McuMgr.Common.Helpers;
using Laerdal.McuMgr.FileDownloader.Contracts.Enums;
using Laerdal.McuMgr.FileDownloader.Contracts.Events;
using Laerdal.McuMgr.FileDownloader.Contracts.Exceptions;
using Laerdal.McuMgr.FileDownloader.Contracts.Native;
+using Laerdal.McuMgr.FileUploader.Contracts.Enums;
using GenericNativeFileDownloaderCallbacksProxy_ = Laerdal.McuMgr.FileDownloader.FileDownloader.GenericNativeFileDownloaderCallbacksProxy;
namespace Laerdal.McuMgr.Tests.FileDownloader
@@ -33,6 +35,9 @@ public async Task SingleFileDownloadAsync_ShouldThrowAllDownloadAttemptsFailedEx
// Act
var work = new Func(() => fileDownloader.DownloadAsync(
+ hostDeviceModel: "foobar",
+ hostDeviceManufacturer: "acme corp.",
+
maxTriesCount: maxTriesCount, //doesnt really matter we just want to ensure that the method fails early and doesnt retry
remoteFilePath: remoteFilePath,
sleepTimeBetweenRetriesInMs: 10
@@ -98,7 +103,7 @@ public override EFileDownloaderVerdict BeginDownload(string remoteFilePath, int?
await Task.Delay(100);
StateChangedAdvertisement(remoteFilePath, EFileDownloaderState.Downloading, EFileDownloaderState.Error);
- FatalErrorOccurredAdvertisement(remoteFilePath, _nativeErrorMessageForFileNotFound);
+ FatalErrorOccurredAdvertisement(remoteFilePath, _nativeErrorMessageForFileNotFound, EMcuMgrErrorCode.Unknown, EFileOperationGroupReturnCode.Unset);
});
return verdict;
diff --git a/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.SingleFileDownloadAsync.ShouldThrowArgumentException_GivenEmptyRemoteFilePath.cs b/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.SingleFileDownloadAsync.ShouldThrowArgumentException_GivenEmptyRemoteFilePath.cs
index 19f92471..5a2ef7a1 100644
--- a/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.SingleFileDownloadAsync.ShouldThrowArgumentException_GivenEmptyRemoteFilePath.cs
+++ b/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.SingleFileDownloadAsync.ShouldThrowArgumentException_GivenEmptyRemoteFilePath.cs
@@ -21,7 +21,12 @@ public async Task SingleFileDownloadAsync_ShouldThrowArgumentException_GivenEmpt
using var eventsMonitor = fileDownloader.Monitor();
// Act
- var work = new Func(() => fileDownloader.DownloadAsync(remoteFilePath: remoteFilePath));
+ var work = new Func(() => fileDownloader.DownloadAsync(
+ hostDeviceModel: "foobar",
+ hostDeviceManufacturer: "acme corp.",
+
+ remoteFilePath: remoteFilePath
+ ));
// Assert
await work.Should().ThrowExactlyAsync().WithTimeoutInMs(500);
diff --git a/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.SingleFileDownloadAsync.ShouldThrowDownloadCancelledException_GivenCancellationRequestMidflight.cs b/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.SingleFileDownloadAsync.ShouldThrowDownloadCancelledException_GivenCancellationRequestMidflight.cs
index 1588a904..216db887 100644
--- a/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.SingleFileDownloadAsync.ShouldThrowDownloadCancelledException_GivenCancellationRequestMidflight.cs
+++ b/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.SingleFileDownloadAsync.ShouldThrowDownloadCancelledException_GivenCancellationRequestMidflight.cs
@@ -33,7 +33,12 @@ public async Task SingleFileUploadAsync_ShouldThrowUploadCancelledException_Give
fileDownloader.Cancel();
});
- var work = new Func(() => fileDownloader.DownloadAsync(remoteFilePath));
+ var work = new Func(() => fileDownloader.DownloadAsync(
+ hostDeviceModel: "foobar",
+ hostDeviceManufacturer: "acme corp.",
+
+ remoteFilePath: remoteFilePath
+ ));
// Assert
await work.Should().ThrowExactlyAsync().WithTimeoutInMs((int)5.Seconds().TotalMilliseconds);
diff --git a/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.SingleFileDownloadAsync.ShouldThrowDownloadInternalErrorException_GivenErroneousNativeFileDownloader.cs b/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.SingleFileDownloadAsync.ShouldThrowDownloadInternalErrorException_GivenErroneousNativeFileDownloader.cs
index 77f5b5ac..2a5e8be1 100644
--- a/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.SingleFileDownloadAsync.ShouldThrowDownloadInternalErrorException_GivenErroneousNativeFileDownloader.cs
+++ b/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.SingleFileDownloadAsync.ShouldThrowDownloadInternalErrorException_GivenErroneousNativeFileDownloader.cs
@@ -16,7 +16,12 @@ public async Task SingleFileDownloadAsync_ShouldThrowDownloadInternalErrorExcept
var fileDownloader = new McuMgr.FileDownloader.FileDownloader(mockedNativeFileDownloaderProxy);
// Act
- var work = new Func(() => fileDownloader.DownloadAsync(remoteFilePath: "/path/to/file.bin"));
+ var work = new Func(() => fileDownloader.DownloadAsync(
+ hostDeviceModel: "foobar",
+ hostDeviceManufacturer: "acme corp.",
+
+ remoteFilePath: "/path/to/file.bin"
+ ));
// Assert
(await work.Should().ThrowExactlyAsync()).WithInnerExceptionExactly("native symbols not loaded blah blah");
diff --git a/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.SingleFileDownloadAsync.ShouldThrowDownloadTimeoutException_GivenTooSmallTimeout.cs b/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.SingleFileDownloadAsync.ShouldThrowDownloadTimeoutException_GivenTooSmallTimeout.cs
index 94ba00a3..1752b3c1 100644
--- a/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.SingleFileDownloadAsync.ShouldThrowDownloadTimeoutException_GivenTooSmallTimeout.cs
+++ b/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.SingleFileDownloadAsync.ShouldThrowDownloadTimeoutException_GivenTooSmallTimeout.cs
@@ -23,7 +23,13 @@ public async Task SingleFileDownloadAsync_ShouldThrowDownloadTimeoutException_Gi
using var eventsMonitor = fileDownloader.Monitor();
// Act
- var work = new Func(() => fileDownloader.DownloadAsync(remoteFilePath: remoteFilePath, timeoutForDownloadInMs: 100));
+ var work = new Func(() => fileDownloader.DownloadAsync(
+ hostDeviceModel: "foobar",
+ hostDeviceManufacturer: "acme corp.",
+
+ remoteFilePath: remoteFilePath,
+ timeoutForDownloadInMs: 100
+ ));
// Assert
await work.Should().ThrowExactlyAsync().WithTimeoutInMs((int)5.Seconds().TotalMilliseconds);
diff --git a/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.SingleFileDownloadAsync.ShouldThrowRemoteFileNotFoundException_GivenNonExistentFilepath.cs b/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.SingleFileDownloadAsync.ShouldThrowRemoteFileNotFoundException_GivenNonExistentFilepath.cs
index b33545b6..567af537 100644
--- a/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.SingleFileDownloadAsync.ShouldThrowRemoteFileNotFoundException_GivenNonExistentFilepath.cs
+++ b/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.SingleFileDownloadAsync.ShouldThrowRemoteFileNotFoundException_GivenNonExistentFilepath.cs
@@ -1,11 +1,13 @@
using System.Diagnostics.CodeAnalysis;
using FluentAssertions;
using FluentAssertions.Extensions;
+using Laerdal.McuMgr.Common.Enums;
using Laerdal.McuMgr.Common.Helpers;
using Laerdal.McuMgr.FileDownloader.Contracts.Enums;
using Laerdal.McuMgr.FileDownloader.Contracts.Events;
using Laerdal.McuMgr.FileDownloader.Contracts.Exceptions;
using Laerdal.McuMgr.FileDownloader.Contracts.Native;
+using Laerdal.McuMgr.FileUploader.Contracts.Enums;
using GenericNativeFileDownloaderCallbacksProxy_ = Laerdal.McuMgr.FileDownloader.FileDownloader.GenericNativeFileDownloaderCallbacksProxy;
namespace Laerdal.McuMgr.Tests.FileDownloader
@@ -35,6 +37,9 @@ public async Task SingleFileDownloadAsync_ShouldThrowRemoteFileNotFoundException
// Act
var work = new Func(() => fileDownloader.DownloadAsync(
+ hostDeviceModel: "foobar",
+ hostDeviceManufacturer: "acme corp.",
+
maxTriesCount: maxTriesCount, //doesnt really matter we just want to ensure that the method fails early and doesnt retry
remoteFilePath: remoteFilePath,
sleepTimeBetweenRetriesInMs: 10
@@ -100,8 +105,8 @@ public override EFileDownloaderVerdict BeginDownload(string remoteFilePath, int?
await Task.Delay(100);
- StateChangedAdvertisement(remoteFilePath, EFileDownloaderState.Downloading, EFileDownloaderState.Error); // order simulates how the native code behaves
- FatalErrorOccurredAdvertisement(remoteFilePath, _nativeErrorMessageForFileNotFound); // order simulates how the csharp wrapper behaves
+ StateChangedAdvertisement(remoteFilePath, EFileDownloaderState.Downloading, EFileDownloaderState.Error); // order simulates how the native code behaves
+ FatalErrorOccurredAdvertisement(remoteFilePath, _nativeErrorMessageForFileNotFound, EMcuMgrErrorCode.NoEntry, EFileOperationGroupReturnCode.Unset); // order simulates how the csharp wrapper behaves
});
return verdict;
diff --git a/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.cs b/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.cs
index a5bc57ee..814ff867 100644
--- a/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.cs
+++ b/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.cs
@@ -2,6 +2,7 @@
using Laerdal.McuMgr.FileDownloader.Contracts;
using Laerdal.McuMgr.FileDownloader.Contracts.Enums;
using Laerdal.McuMgr.FileDownloader.Contracts.Native;
+using Laerdal.McuMgr.FileUploader.Contracts.Enums;
namespace Laerdal.McuMgr.Tests.FileDownloader
{
@@ -62,13 +63,17 @@ public void BusyStateChangedAdvertisement(bool busyNotIdle)
public void DownloadCompletedAdvertisement(string resource, byte[] data)
=> _downloaderCallbacksProxy.DownloadCompletedAdvertisement(resource, data); //raises the actual event
-
- public void FatalErrorOccurredAdvertisement(string resource, string errorMessage)
- => _downloaderCallbacksProxy.FatalErrorOccurredAdvertisement(resource, errorMessage); //raises the actual event
+
+ public void FatalErrorOccurredAdvertisement(string resource, string errorMessage, EMcuMgrErrorCode mcuMgrErrorCode, EFileOperationGroupReturnCode fileOperationGroupReturnCode)
+ => _downloaderCallbacksProxy.FatalErrorOccurredAdvertisement(resource, errorMessage, mcuMgrErrorCode, fileOperationGroupReturnCode); //raises the actual event
public void FileDownloadProgressPercentageAndDataThroughputChangedAdvertisement(int progressPercentage, float averageThroughput)
=> _downloaderCallbacksProxy.FileDownloadProgressPercentageAndDataThroughputChangedAdvertisement(progressPercentage, averageThroughput); //raises the actual event
+ public bool TrySetContext(object context) => throw new NotImplementedException();
+ public bool TrySetBluetoothDevice(object bluetoothDevice) => throw new NotImplementedException();
+ public bool TryInvalidateCachedTransport() => throw new NotImplementedException();
+
public void Dispose()
{
}
diff --git a/Laerdal.McuMgr.Tests/FileUploader/FileUploaderTestbed.MultipleFilesUploadAsync.ShouldCompleteSuccessfully_GivenVariousFilesToDownload.cs b/Laerdal.McuMgr.Tests/FileUploader/FileUploaderTestbed.MultipleFilesUploadAsync.ShouldCompleteSuccessfully_GivenVariousFilesToDownload.cs
index ace574db..06b77389 100644
--- a/Laerdal.McuMgr.Tests/FileUploader/FileUploaderTestbed.MultipleFilesUploadAsync.ShouldCompleteSuccessfully_GivenVariousFilesToDownload.cs
+++ b/Laerdal.McuMgr.Tests/FileUploader/FileUploaderTestbed.MultipleFilesUploadAsync.ShouldCompleteSuccessfully_GivenVariousFilesToDownload.cs
@@ -116,18 +116,18 @@ public override EFileUploaderVerdict BeginUpload(
if (remoteFilePathUppercase.Contains("some/file/to/a/folder/that/doesnt/exist.bin".ToUpperInvariant()))
{
StateChangedAdvertisement(remoteFilePath, EFileUploaderState.Uploading, EFileUploaderState.Error);
- FatalErrorOccurredAdvertisement(remoteFilePath, "UNKNOWN (1)", EMcuMgrErrorCode.Unknown, EFileUploaderGroupReturnCode.Unset);
+ FatalErrorOccurredAdvertisement(remoteFilePath, "UNKNOWN (1)", EMcuMgrErrorCode.Unknown, EFileOperationGroupReturnCode.Unset);
}
else if (remoteFilePathUppercase.Contains("some/file/that/succeeds/after/a/couple/of/attempts.bin".ToUpperInvariant())
&& _retryCountForProblematicFile++ < 3)
{
StateChangedAdvertisement(remoteFilePath, EFileUploaderState.Uploading, EFileUploaderState.Error);
- FatalErrorOccurredAdvertisement(remoteFilePath, "ping pong", EMcuMgrErrorCode.Busy, EFileUploaderGroupReturnCode.Unset);
+ FatalErrorOccurredAdvertisement(remoteFilePath, "ping pong", EMcuMgrErrorCode.Generic, EFileOperationGroupReturnCode.Unset);
}
else if (remoteFilePathUppercase.Contains("some/file/that/is/erroring/out/when/we/try/to/upload/it.bin".ToUpperInvariant()))
{
StateChangedAdvertisement(remoteFilePath, EFileUploaderState.Uploading, EFileUploaderState.Error);
- FatalErrorOccurredAdvertisement(remoteFilePath, "native symbols not loaded blah blah", EMcuMgrErrorCode.NotSupported, EFileUploaderGroupReturnCode.Unset);
+ FatalErrorOccurredAdvertisement(remoteFilePath, "native symbols not loaded blah blah", EMcuMgrErrorCode.Generic, EFileOperationGroupReturnCode.Unset);
}
else
{
diff --git a/Laerdal.McuMgr.Tests/FileUploader/FileUploaderTestbed.SingleFileUploadAsync.ShouldCompleteSuccessfullyByFallingBackToFailsafeSettingsRightAway_GivenProblematicDevices.cs b/Laerdal.McuMgr.Tests/FileUploader/FileUploaderTestbed.SingleFileUploadAsync.ShouldCompleteSuccessfullyByFallingBackToFailsafeSettingsRightAway_GivenProblematicDevices.cs
index acb638d9..8ae9b693 100644
--- a/Laerdal.McuMgr.Tests/FileUploader/FileUploaderTestbed.SingleFileUploadAsync.ShouldCompleteSuccessfullyByFallingBackToFailsafeSettingsRightAway_GivenProblematicDevices.cs
+++ b/Laerdal.McuMgr.Tests/FileUploader/FileUploaderTestbed.SingleFileUploadAsync.ShouldCompleteSuccessfullyByFallingBackToFailsafeSettingsRightAway_GivenProblematicDevices.cs
@@ -15,9 +15,9 @@ namespace Laerdal.McuMgr.Tests.FileUploader
public partial class FileUploaderTestbed
{
[Theory]
- [InlineData("FUT.SFUA.SCSBFBTFSRA.GPD.010", "samsung", "sm-x200", null, null, null, null, null, 1, 1, 23, 1, 1)]
- [InlineData("FUT.SFUA.SCSBFBTFSRA.GPD.020", " Samsung ", " SM-X200 ", null, null, null, null, null, 1, 1, 23, 1, 1)]
- [InlineData("FUT.SFUA.SCSBFBTFSRA.GPD.030", " Apple ", " iPhone 6 ", null, null, null, null, null, 1, 1, 23, 1, 1)]
+ [InlineData("FUT.SFUA.SCSBFBTFSRA.GPD.010", "samsung", "sm-x200", null, null, null, null, null, null, null, 23, 1, 1)]
+ [InlineData("FUT.SFUA.SCSBFBTFSRA.GPD.020", " Samsung ", " SM-X200 ", null, null, null, null, null, null, null, 23, 1, 1)]
+ [InlineData("FUT.SFUA.SCSBFBTFSRA.GPD.030", " Apple ", " iPhone 6 ", null, null, null, null, null, 1, 1, null, null, null)]
[InlineData("FUT.SFUA.SCSBFBTFSRA.GPD.040", " Apple ", " iPhone 6 ", 2, 4, null, null, null, 2, 4, null, null, null)]
[InlineData("FUT.SFUA.SCSBFBTFSRA.GPD.050", "AcmeCorp.", "foobar", null, null, null, null, null, null, null, null, null, null)]
public async Task SingleFileUploadAsync_ShouldCompleteSuccessfullyByFallingBackToFailsafeSettingsRightAway_GivenProblematicDevices(
diff --git a/Laerdal.McuMgr.Tests/FileUploader/FileUploaderTestbed.SingleFileUploadAsync.ShouldCompleteSuccessfullyByFallingBackToFailsafeSettings_GivenFlakyConnection.cs b/Laerdal.McuMgr.Tests/FileUploader/FileUploaderTestbed.SingleFileUploadAsync.ShouldCompleteSuccessfullyByFallingBackToFailsafeSettings_GivenFlakyConnection.cs
index a054d200..9dee7ea9 100644
--- a/Laerdal.McuMgr.Tests/FileUploader/FileUploaderTestbed.SingleFileUploadAsync.ShouldCompleteSuccessfullyByFallingBackToFailsafeSettings_GivenFlakyConnection.cs
+++ b/Laerdal.McuMgr.Tests/FileUploader/FileUploaderTestbed.SingleFileUploadAsync.ShouldCompleteSuccessfullyByFallingBackToFailsafeSettings_GivenFlakyConnection.cs
@@ -63,7 +63,7 @@ public async Task SingleFileUploadAsync_ShouldCompleteSuccessfullyByFallingBackT
.Where(x => x.EventName == nameof(fileUploader.LogEmitted))
.SelectMany(x => x.Parameters)
.OfType()
- .Count(l => l is { Level: ELogLevel.Warning } && l.Message.Contains("GFCSICPTBU.010"))
+ .Count(l => l is { Level: ELogLevel.Warning } && l.Message.Contains("[FU.UA.010]"))
.Should()
.Be(1);
@@ -136,51 +136,51 @@ public override EFileUploaderVerdict BeginUpload(
await Task.Delay(5);
FileUploadProgressPercentageAndDataThroughputChangedAdvertisement(60, 10);
- if (_tryCounter == _maxTriesCount && initialMtuSize != AndroidTidbits.FailSafeBleConnectionSettings.InitialMtuSize)
+ if (_tryCounter == _maxTriesCount && initialMtuSize != AndroidTidbits.BleConnectionFailsafeSettings.ForUploading.InitialMtuSize)
{
- BugDetected = $"[BUG DETECTED] The very last try should be with {nameof(initialMtuSize)} set to {AndroidTidbits.FailSafeBleConnectionSettings.InitialMtuSize} but it's set to {initialMtuSize?.ToString() ?? "(null)"} instead - something is wrong!";
- StateChangedAdvertisement(remoteFilePath, EFileUploaderState.Uploading, EFileUploaderState.Error); // order
- FatalErrorOccurredAdvertisement(remoteFilePath, BugDetected, EMcuMgrErrorCode.Unset, EFileUploaderGroupReturnCode.Unset); // order
+ BugDetected = $"[BUG DETECTED] The very last try should be with {nameof(initialMtuSize)} set to {AndroidTidbits.BleConnectionFailsafeSettings.ForUploading.InitialMtuSize} but it's set to {initialMtuSize?.ToString() ?? "(null)"} instead - something is wrong!";
+ StateChangedAdvertisement(remoteFilePath, EFileUploaderState.Uploading, EFileUploaderState.Error); // order
+ FatalErrorOccurredAdvertisement(remoteFilePath, BugDetected, EMcuMgrErrorCode.Generic, EFileOperationGroupReturnCode.Unset); // order
return;
}
- if (_tryCounter == _maxTriesCount && windowCapacity != AndroidTidbits.FailSafeBleConnectionSettings.WindowCapacity)
+ if (_tryCounter == _maxTriesCount && windowCapacity != AndroidTidbits.BleConnectionFailsafeSettings.ForUploading.WindowCapacity)
{
- BugDetected = $"[BUG DETECTED] The very last try should be with {nameof(windowCapacity)} set to {AndroidTidbits.FailSafeBleConnectionSettings.WindowCapacity} but it's set to {windowCapacity?.ToString() ?? "(null)"} instead - something is wrong!";
- StateChangedAdvertisement(remoteFilePath, EFileUploaderState.Uploading, EFileUploaderState.Error); // order
- FatalErrorOccurredAdvertisement(remoteFilePath, BugDetected, EMcuMgrErrorCode.Unset, EFileUploaderGroupReturnCode.Unset); // order
+ BugDetected = $"[BUG DETECTED] The very last try should be with {nameof(windowCapacity)} set to {AndroidTidbits.BleConnectionFailsafeSettings.ForUploading.WindowCapacity} but it's set to {windowCapacity?.ToString() ?? "(null)"} instead - something is wrong!";
+ StateChangedAdvertisement(remoteFilePath, EFileUploaderState.Uploading, EFileUploaderState.Error); // order
+ FatalErrorOccurredAdvertisement(remoteFilePath, BugDetected, EMcuMgrErrorCode.Generic, EFileOperationGroupReturnCode.Unset); // order
return;
}
- if (_tryCounter == _maxTriesCount && memoryAlignment != AndroidTidbits.FailSafeBleConnectionSettings.MemoryAlignment)
+ if (_tryCounter == _maxTriesCount && memoryAlignment != AndroidTidbits.BleConnectionFailsafeSettings.ForUploading.MemoryAlignment)
{
- BugDetected = $"[BUG DETECTED] The very last try should be with {nameof(memoryAlignment)} set to {AndroidTidbits.FailSafeBleConnectionSettings.MemoryAlignment} but it's set to {memoryAlignment?.ToString() ?? "(null)"} instead - something is wrong!";
- StateChangedAdvertisement(remoteFilePath, EFileUploaderState.Uploading, EFileUploaderState.Error); // order
- FatalErrorOccurredAdvertisement(remoteFilePath, BugDetected, EMcuMgrErrorCode.Unset, EFileUploaderGroupReturnCode.Unset); // order
+ BugDetected = $"[BUG DETECTED] The very last try should be with {nameof(memoryAlignment)} set to {AndroidTidbits.BleConnectionFailsafeSettings.ForUploading.MemoryAlignment} but it's set to {memoryAlignment?.ToString() ?? "(null)"} instead - something is wrong!";
+ StateChangedAdvertisement(remoteFilePath, EFileUploaderState.Uploading, EFileUploaderState.Error); // order
+ FatalErrorOccurredAdvertisement(remoteFilePath, BugDetected, EMcuMgrErrorCode.Generic, EFileOperationGroupReturnCode.Unset); // order
return;
}
- if (_tryCounter == _maxTriesCount && pipelineDepth != AppleTidbits.FailSafeBleConnectionSettings.PipelineDepth)
+ if (_tryCounter == _maxTriesCount && pipelineDepth != AppleTidbits.BleConnectionFailsafeSettings.ForUploading.PipelineDepth)
{
- BugDetected = $"[BUG DETECTED] The very last try should be with {nameof(pipelineDepth)} set to {AppleTidbits.FailSafeBleConnectionSettings.PipelineDepth} but it's set to {pipelineDepth?.ToString() ?? "(null)"} instead - something is wrong!";
- StateChangedAdvertisement(remoteFilePath, EFileUploaderState.Uploading, EFileUploaderState.Error); // order
- FatalErrorOccurredAdvertisement(remoteFilePath, BugDetected, EMcuMgrErrorCode.Unset, EFileUploaderGroupReturnCode.Unset); // order
+ BugDetected = $"[BUG DETECTED] The very last try should be with {nameof(pipelineDepth)} set to {AppleTidbits.BleConnectionFailsafeSettings.ForUploading.PipelineDepth} but it's set to {pipelineDepth?.ToString() ?? "(null)"} instead - something is wrong!";
+ StateChangedAdvertisement(remoteFilePath, EFileUploaderState.Uploading, EFileUploaderState.Error); // order
+ FatalErrorOccurredAdvertisement(remoteFilePath, BugDetected, EMcuMgrErrorCode.Generic, EFileOperationGroupReturnCode.Unset); // order
return;
}
- if (_tryCounter == _maxTriesCount && byteAlignment != AppleTidbits.FailSafeBleConnectionSettings.ByteAlignment)
+ if (_tryCounter == _maxTriesCount && byteAlignment != AppleTidbits.BleConnectionFailsafeSettings.ForUploading.ByteAlignment)
{
- BugDetected = $"[BUG DETECTED] The very last try should be with {nameof(byteAlignment)} set to {AppleTidbits.FailSafeBleConnectionSettings.ByteAlignment} but it's set to {byteAlignment?.ToString() ?? "(null)"} instead - something is wrong!";
- StateChangedAdvertisement(remoteFilePath, EFileUploaderState.Uploading, EFileUploaderState.Error); // order
- FatalErrorOccurredAdvertisement(remoteFilePath, BugDetected, EMcuMgrErrorCode.Unset, EFileUploaderGroupReturnCode.Unset); // order
+ BugDetected = $"[BUG DETECTED] The very last try should be with {nameof(byteAlignment)} set to {AppleTidbits.BleConnectionFailsafeSettings.ForUploading.ByteAlignment} but it's set to {byteAlignment?.ToString() ?? "(null)"} instead - something is wrong!";
+ StateChangedAdvertisement(remoteFilePath, EFileUploaderState.Uploading, EFileUploaderState.Error); // order
+ FatalErrorOccurredAdvertisement(remoteFilePath, BugDetected, EMcuMgrErrorCode.Generic, EFileOperationGroupReturnCode.Unset); // order
return;
}
if (_tryCounter < _maxTriesCount)
{
await Task.Delay(20);
- StateChangedAdvertisement(remoteFilePath, EFileUploaderState.Uploading, EFileUploaderState.Error); // order
- FatalErrorOccurredAdvertisement(remoteFilePath, "fatal error occurred", EMcuMgrErrorCode.Unset, EFileUploaderGroupReturnCode.Unset); // order
+ StateChangedAdvertisement(remoteFilePath, EFileUploaderState.Uploading, EFileUploaderState.Error); // order
+ FatalErrorOccurredAdvertisement(remoteFilePath, "fatal error occurred", EMcuMgrErrorCode.Generic, EFileOperationGroupReturnCode.Unset); // order
return;
}
diff --git a/Laerdal.McuMgr.Tests/FileUploader/FileUploaderTestbed.SingleFileUploadAsync.ShouldCompleteSuccessfully_GivenGreenNativeFileDownloader.cs b/Laerdal.McuMgr.Tests/FileUploader/FileUploaderTestbed.SingleFileUploadAsync.ShouldCompleteSuccessfully_GivenGreenNativeFileDownloader.cs
index 9ae50800..54c04013 100644
--- a/Laerdal.McuMgr.Tests/FileUploader/FileUploaderTestbed.SingleFileUploadAsync.ShouldCompleteSuccessfully_GivenGreenNativeFileDownloader.cs
+++ b/Laerdal.McuMgr.Tests/FileUploader/FileUploaderTestbed.SingleFileUploadAsync.ShouldCompleteSuccessfully_GivenGreenNativeFileDownloader.cs
@@ -123,7 +123,7 @@ public override EFileUploaderVerdict BeginUpload(
if (_tryCount < _maxNumberOfTriesForSuccess)
{
StateChangedAdvertisement(remoteFilePath, EFileUploaderState.Uploading, EFileUploaderState.Error);
- FatalErrorOccurredAdvertisement(remoteFilePath, "fatal error occurred", EMcuMgrErrorCode.Corrupt, EFileUploaderGroupReturnCode.Unset);
+ FatalErrorOccurredAdvertisement(remoteFilePath, "fatal error occurred", EMcuMgrErrorCode.Corrupt, EFileOperationGroupReturnCode.Unset);
return;
}
diff --git a/Laerdal.McuMgr.Tests/FileUploader/FileUploaderTestbed.SingleFileUploadAsync.ShouldCompleteSuccessfully_GivenGreenStream.cs b/Laerdal.McuMgr.Tests/FileUploader/FileUploaderTestbed.SingleFileUploadAsync.ShouldCompleteSuccessfully_GivenGreenStream.cs
index 6ff498ca..b354e372 100644
--- a/Laerdal.McuMgr.Tests/FileUploader/FileUploaderTestbed.SingleFileUploadAsync.ShouldCompleteSuccessfully_GivenGreenStream.cs
+++ b/Laerdal.McuMgr.Tests/FileUploader/FileUploaderTestbed.SingleFileUploadAsync.ShouldCompleteSuccessfully_GivenGreenStream.cs
@@ -137,7 +137,7 @@ public override EFileUploaderVerdict BeginUpload(
{
await Task.Delay(20);
StateChangedAdvertisement(remoteFilePath, EFileUploaderState.Uploading, EFileUploaderState.Error); // order
- FatalErrorOccurredAdvertisement(remoteFilePath, "fatal error occurred", EMcuMgrErrorCode.Unset, EFileUploaderGroupReturnCode.Unset); // order
+ FatalErrorOccurredAdvertisement(remoteFilePath, "fatal error occurred", EMcuMgrErrorCode.Corrupt, EFileOperationGroupReturnCode.Unset); // order
return;
}
diff --git a/Laerdal.McuMgr.Tests/FileUploader/FileUploaderTestbed.SingleFileUploadAsync.ShouldThrowAllUploadAttemptsFailedException_GivenFatalErrorMidflight.cs b/Laerdal.McuMgr.Tests/FileUploader/FileUploaderTestbed.SingleFileUploadAsync.ShouldThrowAllUploadAttemptsFailedException_GivenFatalErrorMidflight.cs
index 72a89d8b..1c6b109a 100644
--- a/Laerdal.McuMgr.Tests/FileUploader/FileUploaderTestbed.SingleFileUploadAsync.ShouldThrowAllUploadAttemptsFailedException_GivenFatalErrorMidflight.cs
+++ b/Laerdal.McuMgr.Tests/FileUploader/FileUploaderTestbed.SingleFileUploadAsync.ShouldThrowAllUploadAttemptsFailedException_GivenFatalErrorMidflight.cs
@@ -106,7 +106,7 @@ public override EFileUploaderVerdict BeginUpload(
await Task.Delay(2_000);
StateChangedAdvertisement(remoteFilePath, EFileUploaderState.Uploading, EFileUploaderState.Error); // order
- FatalErrorOccurredAdvertisement(remoteFilePath, "fatal error occurred", EMcuMgrErrorCode.Corrupt, EFileUploaderGroupReturnCode.Unset); // order
+ FatalErrorOccurredAdvertisement(remoteFilePath, "fatal error occurred", EMcuMgrErrorCode.Corrupt, EFileOperationGroupReturnCode.Unset); // order
});
return verdict;
diff --git a/Laerdal.McuMgr.Tests/FileUploader/FileUploaderTestbed.SingleFileUploadAsync.ShouldThrowAllUploadAttemptsFailedException_GivenRogueNativeErrorMessage.cs b/Laerdal.McuMgr.Tests/FileUploader/FileUploaderTestbed.SingleFileUploadAsync.ShouldThrowAllUploadAttemptsFailedException_GivenRogueNativeErrorMessage.cs
index b8254c52..b201aaa2 100644
--- a/Laerdal.McuMgr.Tests/FileUploader/FileUploaderTestbed.SingleFileUploadAsync.ShouldThrowAllUploadAttemptsFailedException_GivenRogueNativeErrorMessage.cs
+++ b/Laerdal.McuMgr.Tests/FileUploader/FileUploaderTestbed.SingleFileUploadAsync.ShouldThrowAllUploadAttemptsFailedException_GivenRogueNativeErrorMessage.cs
@@ -116,7 +116,7 @@ public override EFileUploaderVerdict BeginUpload(
await Task.Delay(100);
StateChangedAdvertisement(remoteFilePath, EFileUploaderState.Uploading, EFileUploaderState.Error); // order
- FatalErrorOccurredAdvertisement(remoteFilePath, _nativeErrorMessageForFileNotFound, EMcuMgrErrorCode.Corrupt, EFileUploaderGroupReturnCode.Unset); // order
+ FatalErrorOccurredAdvertisement(remoteFilePath, _nativeErrorMessageForFileNotFound, EMcuMgrErrorCode.Corrupt, EFileOperationGroupReturnCode.Unset); // order
});
return verdict;
diff --git a/Laerdal.McuMgr.Tests/FileUploader/FileUploaderTestbed.SingleFileUploadAsync.ShouldThrowRemoteFolderNotFoundException_GivenNonExistentFilepath.cs b/Laerdal.McuMgr.Tests/FileUploader/FileUploaderTestbed.SingleFileUploadAsync.ShouldThrowRemoteFolderNotFoundException_GivenNonExistentFilepath.cs
index 0e86a2bb..e5efc73d 100644
--- a/Laerdal.McuMgr.Tests/FileUploader/FileUploaderTestbed.SingleFileUploadAsync.ShouldThrowRemoteFolderNotFoundException_GivenNonExistentFilepath.cs
+++ b/Laerdal.McuMgr.Tests/FileUploader/FileUploaderTestbed.SingleFileUploadAsync.ShouldThrowRemoteFolderNotFoundException_GivenNonExistentFilepath.cs
@@ -133,7 +133,7 @@ public override EFileUploaderVerdict BeginUpload(
await Task.Delay(100);
StateChangedAdvertisement(remoteFilePath, EFileUploaderState.Uploading, EFileUploaderState.Error); // order
- FatalErrorOccurredAdvertisement(remoteFilePath, _nativeErrorMessageForFileNotFound, _mcuMgrErrorCode, EFileUploaderGroupReturnCode.Unset); // order
+ FatalErrorOccurredAdvertisement(remoteFilePath, _nativeErrorMessageForFileNotFound, _mcuMgrErrorCode, EFileOperationGroupReturnCode.Unset); // order
});
return verdict;
diff --git a/Laerdal.McuMgr.Tests/FileUploader/FileUploaderTestbed.SingleFileUploadAsync.ShouldThrowUnauthorizedErrorException_GivenAccessDeniedNativeErrorMessage.cs b/Laerdal.McuMgr.Tests/FileUploader/FileUploaderTestbed.SingleFileUploadAsync.ShouldThrowUnauthorizedErrorException_GivenAccessDeniedNativeErrorMessage.cs
index f547707f..3a2dbc05 100644
--- a/Laerdal.McuMgr.Tests/FileUploader/FileUploaderTestbed.SingleFileUploadAsync.ShouldThrowUnauthorizedErrorException_GivenAccessDeniedNativeErrorMessage.cs
+++ b/Laerdal.McuMgr.Tests/FileUploader/FileUploaderTestbed.SingleFileUploadAsync.ShouldThrowUnauthorizedErrorException_GivenAccessDeniedNativeErrorMessage.cs
@@ -74,7 +74,7 @@ public override EFileUploaderVerdict BeginUpload(
await Task.Delay(100);
StateChangedAdvertisement(remoteFilePath, EFileUploaderState.Uploading, EFileUploaderState.Error); // order
- FatalErrorOccurredAdvertisement(remoteFilePath, "blah blah", EMcuMgrErrorCode.AccessDenied, EFileUploaderGroupReturnCode.Unset); // order
+ FatalErrorOccurredAdvertisement(remoteFilePath, "blah blah", EMcuMgrErrorCode.AccessDenied, EFileOperationGroupReturnCode.Unset); // order
});
return verdict;
diff --git a/Laerdal.McuMgr.Tests/FileUploader/FileUploaderTestbed.cs b/Laerdal.McuMgr.Tests/FileUploader/FileUploaderTestbed.cs
index 5a82caa9..cadda09c 100644
--- a/Laerdal.McuMgr.Tests/FileUploader/FileUploaderTestbed.cs
+++ b/Laerdal.McuMgr.Tests/FileUploader/FileUploaderTestbed.cs
@@ -77,7 +77,7 @@ public void FatalErrorOccurredAdvertisement(
string resource,
string errorMessage,
EMcuMgrErrorCode errorCode,
- EFileUploaderGroupReturnCode fileUploaderGroupReturnCode
+ EFileOperationGroupReturnCode fileUploaderGroupReturnCode
) => _uploaderCallbacksProxy.FatalErrorOccurredAdvertisement(resource, errorMessage, errorCode, fileUploaderGroupReturnCode); //raises the actual event
public void FileUploadProgressPercentageAndDataThroughputChangedAdvertisement(int progressPercentage, float averageThroughput)
diff --git a/Laerdal.McuMgr.Tests/FirmwareInstaller/FirmwareInstallerTestbed.InstallAsync.ShouldCompleteSuccessfullyWithLastDitchAttemptUsingLowerInitialMtu_GivenFlakyConnectionForFileUploading.cs b/Laerdal.McuMgr.Tests/FirmwareInstaller/FirmwareInstallerTestbed.InstallAsync.ShouldCompleteSuccessfullyWithLastDitchAttemptUsingLowerInitialMtu_GivenFlakyConnectionForFileUploading.cs
index 7dcca6c9..a86a4906 100644
--- a/Laerdal.McuMgr.Tests/FirmwareInstaller/FirmwareInstallerTestbed.InstallAsync.ShouldCompleteSuccessfullyWithLastDitchAttemptUsingLowerInitialMtu_GivenFlakyConnectionForFileUploading.cs
+++ b/Laerdal.McuMgr.Tests/FirmwareInstaller/FirmwareInstallerTestbed.InstallAsync.ShouldCompleteSuccessfullyWithLastDitchAttemptUsingLowerInitialMtu_GivenFlakyConnectionForFileUploading.cs
@@ -124,41 +124,41 @@ public override EFirmwareInstallationVerdict BeginInstallation(
Task.Run(function: async () => //00 vital
{
- if (_tryCounter == 1 && initialMtuSize == AndroidTidbits.FailSafeBleConnectionSettings.InitialMtuSize)
+ if (_tryCounter == 1 && initialMtuSize == AndroidTidbits.BleConnectionFailsafeSettings.ForUploading.InitialMtuSize)
{
- BugDetected = $"[BUG DETECTED] The very first try should not be with {nameof(initialMtuSize)} set to the fail-safe value of {AndroidTidbits.FailSafeBleConnectionSettings.InitialMtuSize} right off the bat - something is wrong!";
+ BugDetected = $"[BUG DETECTED] The very first try should not be with {nameof(initialMtuSize)} set to the fail-safe value of {AndroidTidbits.BleConnectionFailsafeSettings.ForUploading.InitialMtuSize} right off the bat - something is wrong!";
StateChangedAdvertisement(oldState: EFirmwareInstallationState.Uploading, newState: EFirmwareInstallationState.Error);
FatalErrorOccurredAdvertisement(EFirmwareInstallationState.Uploading, EFirmwareInstallerFatalErrorType.FirmwareUploadingErroredOut, BugDetected);
return;
}
- if (_tryCounter == 1 && windowCapacity == AndroidTidbits.FailSafeBleConnectionSettings.WindowCapacity)
+ if (_tryCounter == 1 && windowCapacity == AndroidTidbits.BleConnectionFailsafeSettings.ForUploading.WindowCapacity)
{
- BugDetected = $"[BUG DETECTED] The very first try should not be with {nameof(windowCapacity)} set to the fail-safe value of {AndroidTidbits.FailSafeBleConnectionSettings.WindowCapacity} right off the bat - something is wrong!";
+ BugDetected = $"[BUG DETECTED] The very first try should not be with {nameof(windowCapacity)} set to the fail-safe value of {AndroidTidbits.BleConnectionFailsafeSettings.ForUploading.WindowCapacity} right off the bat - something is wrong!";
StateChangedAdvertisement(oldState: EFirmwareInstallationState.Uploading, newState: EFirmwareInstallationState.Error);
FatalErrorOccurredAdvertisement(EFirmwareInstallationState.Uploading, EFirmwareInstallerFatalErrorType.FirmwareUploadingErroredOut, BugDetected);
return;
}
- if (_tryCounter == 1 && memoryAlignment == AndroidTidbits.FailSafeBleConnectionSettings.MemoryAlignment)
+ if (_tryCounter == 1 && memoryAlignment == AndroidTidbits.BleConnectionFailsafeSettings.ForUploading.MemoryAlignment)
{
- BugDetected = $"[BUG DETECTED] The very first try should not be with {nameof(memoryAlignment)} set to the fail-safe value of {AndroidTidbits.FailSafeBleConnectionSettings.MemoryAlignment} right off the bat - something is wrong!";
+ BugDetected = $"[BUG DETECTED] The very first try should not be with {nameof(memoryAlignment)} set to the fail-safe value of {AndroidTidbits.BleConnectionFailsafeSettings.ForUploading.MemoryAlignment} right off the bat - something is wrong!";
StateChangedAdvertisement(oldState: EFirmwareInstallationState.Uploading, newState: EFirmwareInstallationState.Error);
FatalErrorOccurredAdvertisement(EFirmwareInstallationState.Uploading, EFirmwareInstallerFatalErrorType.FirmwareUploadingErroredOut, BugDetected);
return;
}
- if (_tryCounter == 1 && pipelineDepth == AppleTidbits.FailSafeBleConnectionSettings.PipelineDepth)
+ if (_tryCounter == 1 && pipelineDepth == AppleTidbits.BleConnectionFailsafeSettings.ForUploading.PipelineDepth)
{
- BugDetected = $"[BUG DETECTED] The very first try should not be with {nameof(pipelineDepth)} set to the fail-safe value of {AppleTidbits.FailSafeBleConnectionSettings.PipelineDepth} right off the bat - something is wrong!";
+ BugDetected = $"[BUG DETECTED] The very first try should not be with {nameof(pipelineDepth)} set to the fail-safe value of {AppleTidbits.BleConnectionFailsafeSettings.ForUploading.PipelineDepth} right off the bat - something is wrong!";
StateChangedAdvertisement(oldState: EFirmwareInstallationState.Uploading, newState: EFirmwareInstallationState.Error);
FatalErrorOccurredAdvertisement(EFirmwareInstallationState.Uploading, EFirmwareInstallerFatalErrorType.FirmwareUploadingErroredOut, BugDetected);
return;
}
- if (_tryCounter == 1 && byteAlignment == AppleTidbits.FailSafeBleConnectionSettings.ByteAlignment)
+ if (_tryCounter == 1 && byteAlignment == AppleTidbits.BleConnectionFailsafeSettings.ForUploading.ByteAlignment)
{
- BugDetected = $"[BUG DETECTED] The very first try should not be with {nameof(byteAlignment)} set to the fail-safe value of {AppleTidbits.FailSafeBleConnectionSettings.ByteAlignment} right off the bat - something is wrong!";
+ BugDetected = $"[BUG DETECTED] The very first try should not be with {nameof(byteAlignment)} set to the fail-safe value of {AppleTidbits.BleConnectionFailsafeSettings.ForUploading.ByteAlignment} right off the bat - something is wrong!";
StateChangedAdvertisement(oldState: EFirmwareInstallationState.Uploading, newState: EFirmwareInstallationState.Error);
FatalErrorOccurredAdvertisement(EFirmwareInstallationState.Uploading, EFirmwareInstallerFatalErrorType.FirmwareUploadingErroredOut, BugDetected);
return;
@@ -177,41 +177,41 @@ public override EFirmwareInstallationVerdict BeginInstallation(
FirmwareUploadProgressPercentageAndDataThroughputChangedAdvertisement(progressPercentage: 00, averageThroughput: 00);
await Task.Delay(10);
- if (_tryCounter == _maxTriesCount && initialMtuSize != AndroidTidbits.FailSafeBleConnectionSettings.InitialMtuSize)
+ if (_tryCounter == _maxTriesCount && initialMtuSize != AndroidTidbits.BleConnectionFailsafeSettings.ForUploading.InitialMtuSize)
{
- BugDetected = $"[BUG DETECTED] The very last try should be with {nameof(initialMtuSize)} set to {AndroidTidbits.FailSafeBleConnectionSettings.InitialMtuSize} but it's set to {initialMtuSize?.ToString() ?? "(null)"} instead - something is wrong!";
+ BugDetected = $"[BUG DETECTED] The very last try should be with {nameof(initialMtuSize)} set to {AndroidTidbits.BleConnectionFailsafeSettings.ForUploading.InitialMtuSize} but it's set to {initialMtuSize?.ToString() ?? "(null)"} instead - something is wrong!";
StateChangedAdvertisement(oldState: EFirmwareInstallationState.Uploading, newState: EFirmwareInstallationState.Error);
FatalErrorOccurredAdvertisement(EFirmwareInstallationState.Uploading, EFirmwareInstallerFatalErrorType.FirmwareUploadingErroredOut, BugDetected);
return;
}
- if (_tryCounter == _maxTriesCount && windowCapacity != AndroidTidbits.FailSafeBleConnectionSettings.WindowCapacity)
+ if (_tryCounter == _maxTriesCount && windowCapacity != AndroidTidbits.BleConnectionFailsafeSettings.ForUploading.WindowCapacity)
{
- BugDetected = $"[BUG DETECTED] The very last try should be with {nameof(windowCapacity)} set to {AndroidTidbits.FailSafeBleConnectionSettings.WindowCapacity} but it's set to {windowCapacity?.ToString() ?? "(null)"} instead - something is wrong!";
+ BugDetected = $"[BUG DETECTED] The very last try should be with {nameof(windowCapacity)} set to {AndroidTidbits.BleConnectionFailsafeSettings.ForUploading.WindowCapacity} but it's set to {windowCapacity?.ToString() ?? "(null)"} instead - something is wrong!";
StateChangedAdvertisement(oldState: EFirmwareInstallationState.Uploading, newState: EFirmwareInstallationState.Error);
FatalErrorOccurredAdvertisement(EFirmwareInstallationState.Uploading, EFirmwareInstallerFatalErrorType.FirmwareUploadingErroredOut, BugDetected);
return;
}
- if (_tryCounter == _maxTriesCount && memoryAlignment != AndroidTidbits.FailSafeBleConnectionSettings.MemoryAlignment)
+ if (_tryCounter == _maxTriesCount && memoryAlignment != AndroidTidbits.BleConnectionFailsafeSettings.ForUploading.MemoryAlignment)
{
- BugDetected = $"[BUG DETECTED] The very last try should be with {nameof(memoryAlignment)} set to {AndroidTidbits.FailSafeBleConnectionSettings.MemoryAlignment} but it's set to {memoryAlignment?.ToString() ?? "(null)"} instead - something is wrong!";
+ BugDetected = $"[BUG DETECTED] The very last try should be with {nameof(memoryAlignment)} set to {AndroidTidbits.BleConnectionFailsafeSettings.ForUploading.MemoryAlignment} but it's set to {memoryAlignment?.ToString() ?? "(null)"} instead - something is wrong!";
StateChangedAdvertisement(oldState: EFirmwareInstallationState.Uploading, newState: EFirmwareInstallationState.Error);
FatalErrorOccurredAdvertisement(EFirmwareInstallationState.Uploading, EFirmwareInstallerFatalErrorType.FirmwareUploadingErroredOut, BugDetected);
return;
}
- if (_tryCounter == _maxTriesCount && pipelineDepth != AppleTidbits.FailSafeBleConnectionSettings.PipelineDepth)
+ if (_tryCounter == _maxTriesCount && pipelineDepth != AppleTidbits.BleConnectionFailsafeSettings.ForUploading.PipelineDepth)
{
- BugDetected = $"[BUG DETECTED] The very last try should be with {nameof(pipelineDepth)} set to {AppleTidbits.FailSafeBleConnectionSettings.PipelineDepth} but it's set to {pipelineDepth?.ToString() ?? "(null)"} instead - something is wrong!";
+ BugDetected = $"[BUG DETECTED] The very last try should be with {nameof(pipelineDepth)} set to {AppleTidbits.BleConnectionFailsafeSettings.ForUploading.PipelineDepth} but it's set to {pipelineDepth?.ToString() ?? "(null)"} instead - something is wrong!";
StateChangedAdvertisement(oldState: EFirmwareInstallationState.Uploading, newState: EFirmwareInstallationState.Error);
FatalErrorOccurredAdvertisement(EFirmwareInstallationState.Uploading, EFirmwareInstallerFatalErrorType.FirmwareUploadingErroredOut, BugDetected);
return;
}
- if (_tryCounter == _maxTriesCount && byteAlignment != AppleTidbits.FailSafeBleConnectionSettings.ByteAlignment)
+ if (_tryCounter == _maxTriesCount && byteAlignment != AppleTidbits.BleConnectionFailsafeSettings.ForUploading.ByteAlignment)
{
- BugDetected = $"[BUG DETECTED] The very last try should be with {nameof(byteAlignment)} set to {AppleTidbits.FailSafeBleConnectionSettings.ByteAlignment} but it's set to {byteAlignment?.ToString() ?? "(null)"} instead - something is wrong!";
+ BugDetected = $"[BUG DETECTED] The very last try should be with {nameof(byteAlignment)} set to {AppleTidbits.BleConnectionFailsafeSettings.ForUploading.ByteAlignment} but it's set to {byteAlignment?.ToString() ?? "(null)"} instead - something is wrong!";
StateChangedAdvertisement(oldState: EFirmwareInstallationState.Uploading, newState: EFirmwareInstallationState.Error);
FatalErrorOccurredAdvertisement(EFirmwareInstallationState.Uploading, EFirmwareInstallerFatalErrorType.FirmwareUploadingErroredOut, BugDetected);
return;
diff --git a/Laerdal.McuMgr.sln b/Laerdal.McuMgr.sln
deleted file mode 100644
index 1b1732cf..00000000
--- a/Laerdal.McuMgr.sln
+++ /dev/null
@@ -1,69 +0,0 @@
-Microsoft Visual Studio Solution File, Format Version 12.00
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "_Misc", "_Misc", "{2459FC0F-B6EC-4C2C-BEA0-8534D539E124}"
- ProjectSection(SolutionItems) = preProject
- README.md = README.md
- LICENSE = LICENSE
- .gitignore = .gitignore
- azure-pipelines.yml = azure-pipelines.yml
- Laerdal.CreateNewReleaseInGithub.sh = Laerdal.Scripts\Laerdal.CreateNewReleaseInGithub.sh
- Laerdal.Builder.targets = Laerdal.Scripts\Laerdal.Builder.targets
- Laerdal.Version.sh = Laerdal.Scripts\Laerdal.Version.sh
- global.json = global.json
- Laerdal.SetupBuildEnvironment.sh = Laerdal.Scripts\Laerdal.SetupBuildEnvironment.sh
- .github\workflows\github-actions.yml = .github\workflows\github-actions.yml
- Laerdal.Scripts\Laerdal.GenerateSignAndUploadSbom.sh = Laerdal.Scripts\Laerdal.GenerateSignAndUploadSbom.sh
- EndProjectSection
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Laerdal.McuMgr", "Laerdal.McuMgr\Laerdal.McuMgr.csproj", "{4E2952A5-394E-4184-8E12-F2D5342A43B2}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Laerdal.McuMgr.Tests", "Laerdal.McuMgr.Tests\Laerdal.McuMgr.Tests.csproj", "{2112FF63-2823-428B-80EE-0ECEE476BA46}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "_Tests", "_Tests", "{0D581C9E-E80B-4663-86A0-672A5B9843A8}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Laerdal.McuMgr.Bindings.NetStandard", "Laerdal.McuMgr.Bindings.NetStandard\Laerdal.McuMgr.Bindings.NetStandard.csproj", "{84EEAAFB-5ED5-4697-9757-622FF332F44D}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Laerdal.McuMgr.Bindings.Android", "Laerdal.McuMgr.Bindings.Android\Laerdal.McuMgr.Bindings.Android.csproj", "{C6A768F6-E649-4621-A9A8-099A7887BBBF}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Laerdal.McuMgr.Bindings.iOS", "Laerdal.McuMgr.Bindings.iOS\Laerdal.McuMgr.Bindings.iOS.csproj", "{84273F19-16F7-4956-A4F6-74DF3F044F45}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Laerdal.McuMgr.Bindings.MacCatalyst", "Laerdal.McuMgr.Bindings.MacCatalyst\Laerdal.McuMgr.Bindings.MacCatalyst.csproj", "{DBB42900-156A-4233-9CBD-EF2D5D23278B}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {4E2952A5-394E-4184-8E12-F2D5342A43B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {4E2952A5-394E-4184-8E12-F2D5342A43B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {4E2952A5-394E-4184-8E12-F2D5342A43B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {4E2952A5-394E-4184-8E12-F2D5342A43B2}.Release|Any CPU.Build.0 = Release|Any CPU
- {E3C9ADE4-FF77-4615-984E-5C914537A350}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {E3C9ADE4-FF77-4615-984E-5C914537A350}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {E3C9ADE4-FF77-4615-984E-5C914537A350}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {E3C9ADE4-FF77-4615-984E-5C914537A350}.Release|Any CPU.Build.0 = Release|Any CPU
- {2112FF63-2823-428B-80EE-0ECEE476BA46}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {2112FF63-2823-428B-80EE-0ECEE476BA46}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {2112FF63-2823-428B-80EE-0ECEE476BA46}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {2112FF63-2823-428B-80EE-0ECEE476BA46}.Release|Any CPU.Build.0 = Release|Any CPU
- {84EEAAFB-5ED5-4697-9757-622FF332F44D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {84EEAAFB-5ED5-4697-9757-622FF332F44D}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {84EEAAFB-5ED5-4697-9757-622FF332F44D}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {84EEAAFB-5ED5-4697-9757-622FF332F44D}.Release|Any CPU.Build.0 = Release|Any CPU
- {C6A768F6-E649-4621-A9A8-099A7887BBBF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {C6A768F6-E649-4621-A9A8-099A7887BBBF}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {C6A768F6-E649-4621-A9A8-099A7887BBBF}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {C6A768F6-E649-4621-A9A8-099A7887BBBF}.Release|Any CPU.Build.0 = Release|Any CPU
- {84273F19-16F7-4956-A4F6-74DF3F044F45}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {84273F19-16F7-4956-A4F6-74DF3F044F45}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {84273F19-16F7-4956-A4F6-74DF3F044F45}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {84273F19-16F7-4956-A4F6-74DF3F044F45}.Release|Any CPU.Build.0 = Release|Any CPU
- {DBB42900-156A-4233-9CBD-EF2D5D23278B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {DBB42900-156A-4233-9CBD-EF2D5D23278B}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {DBB42900-156A-4233-9CBD-EF2D5D23278B}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {DBB42900-156A-4233-9CBD-EF2D5D23278B}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(NestedProjects) = preSolution
- {2112FF63-2823-428B-80EE-0ECEE476BA46} = {0D581C9E-E80B-4663-86A0-672A5B9843A8}
- EndGlobalSection
-EndGlobal
diff --git a/Laerdal.McuMgr.sln.DotSettings b/Laerdal.McuMgr.sln.DotSettings
deleted file mode 100644
index cf6cbeed..00000000
--- a/Laerdal.McuMgr.sln.DotSettings
+++ /dev/null
@@ -1,77 +0,0 @@
-
- Named
- True
- Required
- False
- ExpressionBody
- static public private protected internal file new abstract virtual sealed readonly override extern unsafe volatile async required
- Remove
- BaseClass
- False
- 1
- 0
- 1
- ALWAYS
- ALWAYS
- ALWAYS
- NEVER
- True
- CHOP_IF_LONG
- True
- 999999
- CHOP_IF_LONG
- CHOP_ALWAYS
- /usr/local/share/dotnet/sdk/7.0.404/MSBuild.dll
- /usr/local/share/dotnet/dotnet
- 1048576
- 1
- /Applications/Xcode_14_2.app
- NuGetPluginsThenRider
- True
- True
- True
- True
- True
- True
- True
- True
- True
- True
- True
- True
- True
- True
- True
- True
- True
- True
- True
- True
- True
- True
- True
- True
- True
- True
- True
- True
- True
- True
- True
- True
- True
- True
- True
- True
- True
- True
- True
- True
- True
- True
- True
- True
- True
- True
- True
- True
\ No newline at end of file
diff --git a/Laerdal.McuMgr.slnx b/Laerdal.McuMgr.slnx
new file mode 100644
index 00000000..c366a772
--- /dev/null
+++ b/Laerdal.McuMgr.slnx
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Laerdal.McuMgr.slnx.DotSettings.user b/Laerdal.McuMgr.slnx.DotSettings.user
new file mode 100644
index 00000000..6c4ad9fb
--- /dev/null
+++ b/Laerdal.McuMgr.slnx.DotSettings.user
@@ -0,0 +1,85 @@
+
+ <SessionState ContinuousTestingMode="0" IsActive="True" Name="All tests from Solution" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session">
+ <Solution />
+</SessionState>
+
+ True
+ True
+ True
+ Named
+ True
+ Required
+ False
+ ExpressionBody
+ static public private protected internal file new abstract virtual sealed readonly override extern unsafe volatile async required
+ Remove
+ BaseClass
+ False
+ 1
+ 0
+ 1
+ ALWAYS
+ ALWAYS
+ ALWAYS
+ NEVER
+ True
+ CHOP_IF_LONG
+ True
+ 999999
+ CHOP_IF_LONG
+ CHOP_ALWAYS
+ /usr/local/share/dotnet/sdk/7.0.404/MSBuild.dll
+ /usr/local/share/dotnet/dotnet
+ 1048576
+ 1
+ /Applications/Xcode_14_2.app
+ NuGetPluginsThenRider
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+
\ No newline at end of file
diff --git a/Laerdal.McuMgr/Droid/FileDownloader/FileDownloader.cs b/Laerdal.McuMgr/Droid/FileDownloader/FileDownloader.cs
index 6be5ff28..b1c1abab 100644
--- a/Laerdal.McuMgr/Droid/FileDownloader/FileDownloader.cs
+++ b/Laerdal.McuMgr/Droid/FileDownloader/FileDownloader.cs
@@ -12,6 +12,7 @@
using Laerdal.McuMgr.FileDownloader.Contracts;
using Laerdal.McuMgr.FileDownloader.Contracts.Enums;
using Laerdal.McuMgr.FileDownloader.Contracts.Native;
+using Laerdal.McuMgr.FileUploader.Contracts.Enums;
namespace Laerdal.McuMgr.FileDownloader
{
@@ -103,16 +104,45 @@ public EFileDownloaderVerdict BeginDownload(
));
}
+ public bool TrySetContext(object context) //the parameter must be of type 'object' so that it wont cause problems in platforms other than android
+ {
+ var androidContext = context as Context ?? throw new ArgumentException($"Expected {nameof(Context)} to be an AndroidContext but got '{context?.GetType().Name ?? "null"}' instead", nameof(context));
+
+ return base.TrySetContext(androidContext);
+ }
+
+ public bool TrySetBluetoothDevice(object bluetoothDevice)
+ {
+ var androidBluetoothDevice = bluetoothDevice as BluetoothDevice ?? throw new ArgumentException($"Expected {nameof(BluetoothDevice)} to be an AndroidBluetoothDevice but got '{bluetoothDevice?.GetType().Name ?? "null"}' instead", nameof(bluetoothDevice));
+
+ return base.TrySetBluetoothDevice(androidBluetoothDevice);
+ }
+
+ public new bool TryInvalidateCachedTransport()
+ {
+ return base.TryInvalidateCachedTransport();
+ }
+
#endregion commands
#region android callbacks -> csharp event emitters
-
- public override void FatalErrorOccurredAdvertisement(string resource, string errorMessage)
+
+ public override void FatalErrorOccurredAdvertisement(string resource, string errorMessage, int mcuMgrErrorCode, int fileOperationGroupReturnCode)
{
- base.FatalErrorOccurredAdvertisement(resource, errorMessage);
+ base.FatalErrorOccurredAdvertisement(resource, errorMessage, mcuMgrErrorCode, fileOperationGroupReturnCode); //just in case
- _fileDownloaderCallbacksProxy?.FatalErrorOccurredAdvertisement(resource, errorMessage);
+ FatalErrorOccurredAdvertisement(resource, errorMessage, (EMcuMgrErrorCode) mcuMgrErrorCode, (EFileOperationGroupReturnCode) fileOperationGroupReturnCode);
+ }
+
+ public void FatalErrorOccurredAdvertisement(string resource, string errorMessage, EMcuMgrErrorCode mcuMgrErrorCode, EFileOperationGroupReturnCode fileUploaderGroupReturnCode)
+ {
+ _fileDownloaderCallbacksProxy?.FatalErrorOccurredAdvertisement(
+ resource,
+ errorMessage,
+ mcuMgrErrorCode,
+ fileUploaderGroupReturnCode
+ );
}
public override void LogMessageAdvertisement(string message, string category, string level, string resource)
diff --git a/Laerdal.McuMgr/Droid/FileUploader/FileUploader.cs b/Laerdal.McuMgr/Droid/FileUploader/FileUploader.cs
index 920446f7..2b1908e6 100644
--- a/Laerdal.McuMgr/Droid/FileUploader/FileUploader.cs
+++ b/Laerdal.McuMgr/Droid/FileUploader/FileUploader.cs
@@ -152,10 +152,10 @@ public override void FatalErrorOccurredAdvertisement(string resource, string err
{
base.FatalErrorOccurredAdvertisement(resource, errorMessage, mcuMgrErrorCode, fileUploaderGroupReturnCode); //just in case
- FatalErrorOccurredAdvertisement(resource, errorMessage, (EMcuMgrErrorCode) mcuMgrErrorCode, (EFileUploaderGroupReturnCode) fileUploaderGroupReturnCode);
+ FatalErrorOccurredAdvertisement(resource, errorMessage, (EMcuMgrErrorCode) mcuMgrErrorCode, (EFileOperationGroupReturnCode) fileUploaderGroupReturnCode);
}
- public void FatalErrorOccurredAdvertisement(string resource, string errorMessage, EMcuMgrErrorCode mcuMgrErrorCode, EFileUploaderGroupReturnCode fileUploaderGroupReturnCode)
+ public void FatalErrorOccurredAdvertisement(string resource, string errorMessage, EMcuMgrErrorCode mcuMgrErrorCode, EFileOperationGroupReturnCode fileUploaderGroupReturnCode)
{
_fileUploaderCallbacksProxy?.FatalErrorOccurredAdvertisement(
resource,
diff --git a/Laerdal.McuMgr/Laerdal.McuMgr.csproj b/Laerdal.McuMgr/Laerdal.McuMgr.csproj
index 62ccbc65..0d24ba5a 100644
--- a/Laerdal.McuMgr/Laerdal.McuMgr.csproj
+++ b/Laerdal.McuMgr/Laerdal.McuMgr.csproj
@@ -71,10 +71,10 @@
$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb
- 1.0.1079.0
- 1.0.1079.0
- 1.0.1079.0
- 1.0.1079.0
+ 1.0.1177.0
+ 1.0.1177.0
+ 1.0.1177.0
+ 1.0.1177.0
$(PackageId)
$(Authors)
@@ -113,29 +113,29 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -150,7 +150,6 @@
armeabi-v7a;arm64-v8a
-
@@ -168,21 +167,21 @@
-
+
-
+
-
+
-
+
diff --git a/Laerdal.McuMgr/Shared/Common/Constants/Android.FailSafeBleConnectionSettings.cs b/Laerdal.McuMgr/Shared/Common/Constants/Android.FailSafeBleConnectionSettings.cs
index 48a79446..dea5de3e 100644
--- a/Laerdal.McuMgr/Shared/Common/Constants/Android.FailSafeBleConnectionSettings.cs
+++ b/Laerdal.McuMgr/Shared/Common/Constants/Android.FailSafeBleConnectionSettings.cs
@@ -43,11 +43,25 @@ public readonly struct AndroidTidbits
/// downloading files. These settings are enforced automagically when the ble connection turns out to be unstable and unreliable during the aforementioned operations.
/// The settings are editable can be adjusted to fit future needs.
///
- public readonly struct FailSafeBleConnectionSettings
+ public readonly struct BleConnectionFailsafeSettings
{
- static public int InitialMtuSize { get; set; } = 23; // applies to android only
- static public int WindowCapacity { get; set; } = 1; // applies to android only
- static public int MemoryAlignment { get; set; } = 1; // applies to android only
+ public readonly struct ForUploading
+ {
+ static public int InitialMtuSize { get; set; } = 23;
+ static public int WindowCapacity { get; set; } = 1;
+ static public int MemoryAlignment { get; set; } = 1;
+ }
+
+ public readonly struct ForDownloading
+ {
+ static public int InitialMtuSize { get; set; } = 50; //00
+ //static public int WindowCapacity { get; set; }= 1; //10
+
+ //00 oddly enough when it comes to downloading using a value of 23 is not supported even by healthy devices so we have to use a greater value it is worth noting
+ // however that even among healthy devices the lowest value supported varies some can go as low as 25 while others only as low as 30 go figure
+ //
+ //10 window capacity could be supported in the future currently its not support though https://github.com/NordicSemiconductor/Android-nRF-Connect-Device-Manager/issues/188#issuecomment-2391146897
+ }
}
}
}
diff --git a/Laerdal.McuMgr/Shared/Common/Constants/Apple.FailSafeBleConnectionSettings.cs b/Laerdal.McuMgr/Shared/Common/Constants/Apple.FailSafeBleConnectionSettings.cs
index f522daa9..0f27961c 100644
--- a/Laerdal.McuMgr/Shared/Common/Constants/Apple.FailSafeBleConnectionSettings.cs
+++ b/Laerdal.McuMgr/Shared/Common/Constants/Apple.FailSafeBleConnectionSettings.cs
@@ -21,10 +21,19 @@ public readonly struct AppleTidbits
/// erasing firmwares, uploading files, downloading files. These settings are enforced automagically when the ble connection turns out to be unstable and unreliable
/// during the aforementioned operations. The settings are editable can be adjusted to fit future needs.
///
- public readonly struct FailSafeBleConnectionSettings
+ public readonly struct BleConnectionFailsafeSettings
{
- static public int PipelineDepth { get; set; } = 1;
- static public int ByteAlignment { get; set; } = 1;
+ public readonly struct ForUploading
+ {
+ static public int PipelineDepth { get; set; } = 1;
+ static public int ByteAlignment { get; set; } = 1;
+ }
+
+ // public readonly struct ForDownloading //there are currently no apple devices that have issues with BLE connection stability when downloading
+ // {
+ // // static public int PipelineDepth { get; set; } = null; //not applicable to downloads
+ // // static public int ByteAlignment { get; set; } = 1; //not applicable to downloads
+ // }
}
}
}
\ No newline at end of file
diff --git a/Laerdal.McuMgr/Shared/Common/Helpers/ConnectionSettingsHelpers.cs b/Laerdal.McuMgr/Shared/Common/Helpers/ConnectionSettingsHelpers.cs
new file mode 100644
index 00000000..57105286
--- /dev/null
+++ b/Laerdal.McuMgr/Shared/Common/Helpers/ConnectionSettingsHelpers.cs
@@ -0,0 +1,95 @@
+using Laerdal.McuMgr.Common.Constants;
+
+namespace Laerdal.McuMgr.Common.Helpers
+{
+ static internal class ConnectionSettingsHelpers
+ {
+ static public (int? byteAlignment, int? pipelineDepth, int? initialMtuSize, int? windowCapacity, int? memoryAlignment)? GetFailsafeConnectionSettingsIfConnectionProvedToBeUnstable(
+ bool uploadingNotDownloading,
+ int triesCount,
+ int maxTriesCount,
+ int suspiciousTransportFailuresCount
+ )
+ {
+ var isConnectionTooUnstableForUploading = triesCount >= 2 && (triesCount == maxTriesCount || triesCount >= 3 && suspiciousTransportFailuresCount >= 2);
+ if (!isConnectionTooUnstableForUploading)
+ return null;
+
+ var byteAlignment = uploadingNotDownloading // ios + maccatalyst
+ ? AppleTidbits.BleConnectionFailsafeSettings.ForUploading.ByteAlignment
+ : (int?)null; //byteAlignment is not applicable for downloads
+ var pipelineDepth = uploadingNotDownloading // ios + maccatalyst
+ ? AppleTidbits.BleConnectionFailsafeSettings.ForUploading.PipelineDepth
+ : (int?)null; //pipelineDepth is not applicable for downloads
+
+ var initialMtuSize = uploadingNotDownloading //android when noticing persistent failures when uploading/downloading we
+ ? AndroidTidbits.BleConnectionFailsafeSettings.ForUploading.InitialMtuSize // resort to forcing the most failsafe settings we know of just in case
+ : AndroidTidbits.BleConnectionFailsafeSettings.ForDownloading.InitialMtuSize; // we manage to salvage this situation (works with SamsungA8 android tablets)
+ var windowCapacity = uploadingNotDownloading
+ ? AndroidTidbits.BleConnectionFailsafeSettings.ForUploading.WindowCapacity
+ : (int?)null; //window-capacity is not applicable for downloads
+ var memoryAlignment = uploadingNotDownloading
+ ? AndroidTidbits.BleConnectionFailsafeSettings.ForUploading.MemoryAlignment
+ : (int?)null; //memory-alignment is not applicable for downloads
+
+ return (byteAlignment: byteAlignment, pipelineDepth: pipelineDepth, initialMtuSize: initialMtuSize, windowCapacity: windowCapacity, memoryAlignment: memoryAlignment);
+ }
+
+ static public (int? byteAlignment, int? pipelineDepth, int? initialMtuSize, int? windowCapacity, int? memoryAlignment)? GetFailSafeConnectionSettingsIfHostDeviceIsProblematic(
+ bool uploadingNotDownloading,
+ string hostDeviceManufacturer,
+ string hostDeviceModel,
+ int? pipelineDepth = null,
+ int? byteAlignment = null,
+ int? initialMtuSize = null,
+ int? windowCapacity = null,
+ int? memoryAlignment = null
+ )
+ {
+ hostDeviceModel = (hostDeviceModel ?? "").Trim().ToLowerInvariant();
+ hostDeviceManufacturer = (hostDeviceManufacturer ?? "").Trim().ToLowerInvariant();
+
+ var isUsingDefaultAppleSettings = pipelineDepth == null && byteAlignment == null;
+ if (isUsingDefaultAppleSettings && AppleTidbits.KnownProblematicDevices.Contains((hostDeviceManufacturer, hostDeviceModel)))
+ {
+ return uploadingNotDownloading
+ ? (
+ byteAlignment: AppleTidbits.BleConnectionFailsafeSettings.ForUploading.ByteAlignment,
+ pipelineDepth: AppleTidbits.BleConnectionFailsafeSettings.ForUploading.PipelineDepth,
+ initialMtuSize: null, //only applies to android
+ windowCapacity: null, //only applies to android
+ memoryAlignment: null //only applies to android
+ )
+ : (
+ byteAlignment: null, //placeholder value currently there are no known apple devices that have issues with BLE connection stability
+ pipelineDepth: null, //placeholder value currently there are no known apple devices that have issues with BLE connection stability
+ initialMtuSize: null, //only applies to android
+ windowCapacity: null, //only applies to android
+ memoryAlignment: null //only applies to android
+ );
+ }
+
+ var isUsingDefaultAndroidSettings = initialMtuSize == null && windowCapacity == null && memoryAlignment == null;
+ if (isUsingDefaultAndroidSettings && AndroidTidbits.KnownProblematicDevices.Contains((hostDeviceManufacturer, hostDeviceModel)))
+ {
+ return uploadingNotDownloading
+ ? (
+ byteAlignment: null, //only applies to apple
+ pipelineDepth: null, //only applies to apple
+ initialMtuSize: AndroidTidbits.BleConnectionFailsafeSettings.ForUploading.InitialMtuSize,
+ windowCapacity: AndroidTidbits.BleConnectionFailsafeSettings.ForUploading.WindowCapacity,
+ memoryAlignment: AndroidTidbits.BleConnectionFailsafeSettings.ForUploading.MemoryAlignment
+ )
+ : (
+ byteAlignment: null, //only applies to apple
+ pipelineDepth: null, //only applies to apple
+ initialMtuSize: AndroidTidbits.BleConnectionFailsafeSettings.ForDownloading.InitialMtuSize,
+ windowCapacity: null, // currently it doesnt apply to android downloads but nordic might consider adding it in the future
+ memoryAlignment: null // doesnt apply to android downloads
+ );
+ }
+
+ return null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Laerdal.McuMgr/Shared/FileDownloader/Contracts/Events/FatalErrorOccurredEventArgs.cs b/Laerdal.McuMgr/Shared/FileDownloader/Contracts/Events/FatalErrorOccurredEventArgs.cs
index a3932b55..d9377fa9 100644
--- a/Laerdal.McuMgr/Shared/FileDownloader/Contracts/Events/FatalErrorOccurredEventArgs.cs
+++ b/Laerdal.McuMgr/Shared/FileDownloader/Contracts/Events/FatalErrorOccurredEventArgs.cs
@@ -1,7 +1,9 @@
// ReSharper disable MemberCanBePrivate.Global
// ReSharper disable ClassNeverInstantiated.Global
+using Laerdal.McuMgr.Common.Enums;
using Laerdal.McuMgr.Common.Events;
+using Laerdal.McuMgr.FileUploader.Contracts.Enums;
namespace Laerdal.McuMgr.FileDownloader.Contracts.Events
{
@@ -9,11 +11,15 @@ namespace Laerdal.McuMgr.FileDownloader.Contracts.Events
{
public string Resource { get; }
public string ErrorMessage { get; }
-
- public FatalErrorOccurredEventArgs(string resource, string errorMessage)
+ public EMcuMgrErrorCode McuMgrErrorCode { get; }
+ public EFileOperationGroupReturnCode FileOperationGroupReturnCode { get; }
+
+ public FatalErrorOccurredEventArgs(string resource, string errorMessage, EMcuMgrErrorCode mcuMgrErrorCode, EFileOperationGroupReturnCode fileOperationGroupReturnCode)
{
Resource = resource;
ErrorMessage = errorMessage;
+ McuMgrErrorCode = mcuMgrErrorCode;
+ FileOperationGroupReturnCode = fileOperationGroupReturnCode;
}
}
}
diff --git a/Laerdal.McuMgr/Shared/FileDownloader/Contracts/IFileDownloaderCommandable.cs b/Laerdal.McuMgr/Shared/FileDownloader/Contracts/IFileDownloaderCommandable.cs
index ae9d71d2..ef6281b8 100644
--- a/Laerdal.McuMgr/Shared/FileDownloader/Contracts/IFileDownloaderCommandable.cs
+++ b/Laerdal.McuMgr/Shared/FileDownloader/Contracts/IFileDownloaderCommandable.cs
@@ -11,6 +11,8 @@ public interface IFileDownloaderCommandable
/// Begins the file-downloading process on multiple files. Files that cannot be downloaded due to errors will have a null entry in the returned dictionary. To really know when the upgrade process has been completed you have to register to the events emitted by the downloader.
///
/// The remote files to download.
+ ///
+ ///
/// The amount of time to wait for each download to complete before skipping it.
/// The maximum amount of tries per download before skipping and moving over to the next download.
/// The amount of time to sleep between retries.
@@ -29,6 +31,8 @@ public interface IFileDownloaderCommandable
/// A dictionary containing the bytes of each remote file that got fetched over.
Task> DownloadAsync(
IEnumerable remoteFilePaths,
+ string hostDeviceManufacturer,
+ string hostDeviceModel,
int timeoutPerDownloadInMs = -1,
int maxRetriesPerDownload = 10,
int sleepTimeBetweenRetriesInMs = 0,
@@ -41,6 +45,7 @@ Task> DownloadAsync(
/// Begins the file-downloading process. To really know when the upgrade process has been completed you have to register to the events emitted by the downloader.
///
/// The remote file to download.
+ ///
/// The amount of time to wait for the operation to complete before bailing out.
/// The maximum amount of tries before bailing out with .
/// The amount of time to sleep between retries.
@@ -60,6 +65,8 @@ Task> DownloadAsync(
/// The bytes of the remote file that got fetched over.
Task DownloadAsync(
string remoteFilePath,
+ string hostDeviceManufacturer,
+ string hostDeviceModel,
int timeoutForDownloadInMs = -1,
int maxTriesCount = 10,
int sleepTimeBetweenRetriesInMs = 1_000,
@@ -73,6 +80,8 @@ Task DownloadAsync(
/// Begins the file-downloading process. To really know when the upgrade process has been completed you have to register to the events emitted by the downloader.
///
/// The remote file to download.
+ ///
+ ///
/// (Android only) Set the initial MTU size for the connection employed by the firmware-installation
/// (useful for some problematic devices such as Samsung A8 tablets). Acceptable custom values must lay within the range [23, 517].
/// If null, zero or negative it will default to 498. Note that in quirky devices like Samsung Galaxy A8 the only value that works is 23 - anything else fails.
@@ -87,6 +96,8 @@ Task DownloadAsync(
/// (Android only) Set the selected memory alignment. Defaults to 4 to match Nordic devices.
EFileDownloaderVerdict BeginDownload(
string remoteFilePath,
+ string hostDeviceManufacturer,
+ string hostDeviceModel,
int? initialMtuSize = null,
int? windowCapacity = null,
int? memoryAlignment = null
diff --git a/Laerdal.McuMgr/Shared/FileDownloader/Contracts/Native/INativeFileDownloaderCallbacksProxy.cs b/Laerdal.McuMgr/Shared/FileDownloader/Contracts/Native/INativeFileDownloaderCallbacksProxy.cs
index db7156e6..e0cc4182 100644
--- a/Laerdal.McuMgr/Shared/FileDownloader/Contracts/Native/INativeFileDownloaderCallbacksProxy.cs
+++ b/Laerdal.McuMgr/Shared/FileDownloader/Contracts/Native/INativeFileDownloaderCallbacksProxy.cs
@@ -1,5 +1,6 @@
using Laerdal.McuMgr.Common.Enums;
using Laerdal.McuMgr.FileDownloader.Contracts.Enums;
+using Laerdal.McuMgr.FileUploader.Contracts.Enums;
namespace Laerdal.McuMgr.FileDownloader.Contracts.Native
{
@@ -12,7 +13,7 @@ internal interface INativeFileDownloaderCallbacksProxy
void StateChangedAdvertisement(string resource, EFileDownloaderState oldState, EFileDownloaderState newState);
void BusyStateChangedAdvertisement(bool busyNotIdle);
void DownloadCompletedAdvertisement(string resource, byte[] data);
- void FatalErrorOccurredAdvertisement(string resource, string errorMessage);
+ void FatalErrorOccurredAdvertisement(string resource, string errorMessage, EMcuMgrErrorCode mcuMgrErrorCode, EFileOperationGroupReturnCode fileOperationGroupReturnCode);
void FileDownloadProgressPercentageAndDataThroughputChangedAdvertisement(int progressPercentage, float averageThroughput);
}
}
\ No newline at end of file
diff --git a/Laerdal.McuMgr/Shared/FileDownloader/Contracts/Native/INativeFileDownloaderCommandableProxy.cs b/Laerdal.McuMgr/Shared/FileDownloader/Contracts/Native/INativeFileDownloaderCommandableProxy.cs
index 8d0ebba2..73e29c4a 100644
--- a/Laerdal.McuMgr/Shared/FileDownloader/Contracts/Native/INativeFileDownloaderCommandableProxy.cs
+++ b/Laerdal.McuMgr/Shared/FileDownloader/Contracts/Native/INativeFileDownloaderCommandableProxy.cs
@@ -7,5 +7,9 @@ internal interface INativeFileDownloaderCommandableProxy
void Cancel();
void Disconnect();
EFileDownloaderVerdict BeginDownload(string remoteFilePath, int? initialMtuSize = null);
+
+ bool TrySetContext(object context);
+ bool TrySetBluetoothDevice(object bluetoothDevice);
+ bool TryInvalidateCachedTransport();
}
}
\ No newline at end of file
diff --git a/Laerdal.McuMgr/Shared/FileDownloader/FileDownloader.cs b/Laerdal.McuMgr/Shared/FileDownloader/FileDownloader.cs
index 94e7f683..1977ac35 100644
--- a/Laerdal.McuMgr/Shared/FileDownloader/FileDownloader.cs
+++ b/Laerdal.McuMgr/Shared/FileDownloader/FileDownloader.cs
@@ -15,6 +15,7 @@
using Laerdal.McuMgr.FileDownloader.Contracts.Events;
using Laerdal.McuMgr.FileDownloader.Contracts.Exceptions;
using Laerdal.McuMgr.FileDownloader.Contracts.Native;
+using Laerdal.McuMgr.FileUploader.Contracts.Enums;
namespace Laerdal.McuMgr.FileDownloader
{
@@ -41,14 +42,37 @@ public void Dispose()
public EFileDownloaderVerdict BeginDownload(
string remoteFilePath,
+ string hostDeviceManufacturer,
+ string hostDeviceModel,
int? initialMtuSize = null,
- int? windowCapacity = null,
- int? memoryAlignment = null
+ int? windowCapacity = null, //not applicable currently but nordic considers these for future use
+ int? memoryAlignment = null //not applicable currently but nordic considers these for future use
)
{
RemoteFilePathHelpers.ValidateRemoteFilePath(remoteFilePath); // order
remoteFilePath = RemoteFilePathHelpers.SanitizeRemoteFilePath(remoteFilePath); // order
+ var failsafeConnectionSettings = ConnectionSettingsHelpers.GetFailSafeConnectionSettingsIfHostDeviceIsProblematic(
+ initialMtuSize: initialMtuSize,
+ hostDeviceModel: hostDeviceModel,
+ hostDeviceManufacturer: hostDeviceManufacturer,
+ uploadingNotDownloading: false
+ );
+ if (failsafeConnectionSettings != null)
+ {
+ initialMtuSize = failsafeConnectionSettings.Value.initialMtuSize;
+ // windowCapacity = connectionSettings.Value.windowCapacity;
+ // memoryAlignment = connectionSettings.Value.memoryAlignment;
+
+ OnLogEmitted(new LogEmittedEventArgs(
+ level: ELogLevel.Warning,
+ message: $"[FD.BD.010] Host device '{hostDeviceModel} (made by {hostDeviceManufacturer})' is known to be problematic. Resorting to using failsafe settings " +
+ $"(initialMtuSize={initialMtuSize})",
+ resource: "File",
+ category: "FileDownloader"
+ ));
+ }
+
var verdict = _nativeFileDownloaderProxy.BeginDownload(
remoteFilePath: remoteFilePath,
initialMtuSize: initialMtuSize
@@ -140,6 +164,8 @@ public event EventHandler> DownloadAsync(
IEnumerable remoteFilePaths,
+ string hostDeviceManufacturer,
+ string hostDeviceModel,
int timeoutPerDownloadInMs = -1,
int maxRetriesPerDownload = 10,
int sleepTimeBetweenRetriesInMs = 0,
@@ -162,6 +188,8 @@ public async Task> DownloadAsync(
{
var data = await DownloadAsync(
remoteFilePath: path,
+ hostDeviceModel: hostDeviceModel,
+ hostDeviceManufacturer: hostDeviceManufacturer,
maxTriesCount: maxRetriesPerDownload,
timeoutForDownloadInMs: timeoutPerDownloadInMs,
@@ -190,10 +218,12 @@ public async Task> DownloadAsync(
private const int DefaultGracefulCancellationTimeoutInMs = 2_500;
public async Task DownloadAsync(
string remoteFilePath,
+ string hostDeviceManufacturer,
+ string hostDeviceModel,
int timeoutForDownloadInMs = -1,
int maxTriesCount = 10,
int sleepTimeBetweenRetriesInMs = 1_000,
- int gracefulCancellationTimeoutInMs = DefaultGracefulCancellationTimeoutInMs,
+ int gracefulCancellationTimeoutInMs = 2_500,
int? initialMtuSize = null,
int? windowCapacity = null,
int? memoryAlignment = null
@@ -223,22 +253,35 @@ public async Task DownloadAsync(
FatalErrorOccurred += FileDownloader_FatalErrorOccurred_;
FileDownloadProgressPercentageAndDataThroughputChanged += FileDownloader_FileDownloadProgressPercentageAndDataThroughputChanged_;
- var failSafeSettingsToApply = GetFailsafeConnectionSettingsIfConnectionProvedToBeUnstable_(
- triesCount_: triesCount,
- maxTriesCount_: maxTriesCount,
- suspiciousTransportFailuresCount_: suspiciousTransportFailuresCount,
- emitWarningAboutUnstableConnection_: !didWarnOnceAboutUnstableConnection
+ var failSafeSettingsToApply = ConnectionSettingsHelpers.GetFailsafeConnectionSettingsIfConnectionProvedToBeUnstable(
+ uploadingNotDownloading: false,
+ triesCount: triesCount,
+ maxTriesCount: maxTriesCount,
+ suspiciousTransportFailuresCount: suspiciousTransportFailuresCount
);
if (failSafeSettingsToApply != null)
{
- didWarnOnceAboutUnstableConnection = true;
initialMtuSize = failSafeSettingsToApply.Value.initialMtuSize;
windowCapacity = failSafeSettingsToApply.Value.windowCapacity;
memoryAlignment = failSafeSettingsToApply.Value.memoryAlignment;
+
+ if (!didWarnOnceAboutUnstableConnection)
+ {
+ didWarnOnceAboutUnstableConnection = true;
+ OnLogEmitted(new LogEmittedEventArgs(
+ level: ELogLevel.Warning,
+ message: $"[FD.DA.010] Attempt#{triesCount}: Connection is too unstable for downloading assets from the target device. Subsequent tries will use failsafe parameters on the connection " +
+ $"just in case it helps (initialMtuSize={failSafeSettingsToApply.Value.initialMtuSize}, windowCapacity={failSafeSettingsToApply.Value.windowCapacity}, memoryAlignment={failSafeSettingsToApply.Value.memoryAlignment})",
+ resource: "File",
+ category: "FileDownloader"
+ ));
+ }
}
var verdict = BeginDownload( //00 dont use task.run here for now
remoteFilePath: remoteFilePath,
+ hostDeviceModel: hostDeviceModel,
+ hostDeviceManufacturer: hostDeviceManufacturer,
initialMtuSize: initialMtuSize,
windowCapacity: windowCapacity,
@@ -398,35 +441,6 @@ void FileDownloader_FatalErrorOccurred_(object sender_, FatalErrorOccurredEventA
throw new DownloadCancelledException(); //20
return result;
-
- (int? initialMtuSize, int? windowCapacity, int? memoryAlignment)? GetFailsafeConnectionSettingsIfConnectionProvedToBeUnstable_(
- int triesCount_,
- int maxTriesCount_,
- int suspiciousTransportFailuresCount_,
- bool emitWarningAboutUnstableConnection_
- )
- {
- var isConnectionTooUnstableForDownloading_ = triesCount_ >= 2 && (triesCount_ == maxTriesCount_ || triesCount_ >= 3 && suspiciousTransportFailuresCount_ >= 2);
- if (!isConnectionTooUnstableForDownloading_)
- return null;
-
- var initialMtuSize_ = AndroidTidbits.FailSafeBleConnectionSettings.InitialMtuSize; // android when noticing persistent failures when uploading we resort
- var windowCapacity_ = AndroidTidbits.FailSafeBleConnectionSettings.WindowCapacity; // android to forcing the most failsafe settings we know of just in case
- var memoryAlignment_ = AndroidTidbits.FailSafeBleConnectionSettings.MemoryAlignment; // android we manage to salvage this situation (works with SamsungA8 android tablets)
-
- if (emitWarningAboutUnstableConnection_)
- {
- OnLogEmitted(new LogEmittedEventArgs(
- level: ELogLevel.Warning,
- message: $"[FD.DA.GFCSICPTBU.010] Attempt#{triesCount_}: Connection is too unstable for uploading assets to the target device. Subsequent tries will use failsafe parameters on the connection " +
- $"just in case it helps (initialMtuSize={initialMtuSize_}, windowCapacity={windowCapacity_}, memoryAlignment={memoryAlignment_})",
- resource: "File",
- category: "FileDownloader"
- ));
- }
-
- return (initialMtuSize: initialMtuSize_, windowCapacity: windowCapacity_, memoryAlignment: memoryAlignment_);
- }
//00 we are aware that in order to be 100% accurate about timeouts we should use task.run() here without await and then await the
// taskcompletionsource right after but if we went down this path we would also have to account for exceptions thus complicating
@@ -487,8 +501,8 @@ public void BusyStateChangedAdvertisement(bool busyNotIdle)
public void DownloadCompletedAdvertisement(string resource, byte[] data)
=> FileDownloader?.OnDownloadCompleted(new DownloadCompletedEventArgs(resource, data));
- public void FatalErrorOccurredAdvertisement(string resource, string errorMessage)
- => FileDownloader?.OnFatalErrorOccurred(new FatalErrorOccurredEventArgs(resource, errorMessage));
+ public void FatalErrorOccurredAdvertisement(string resource, string errorMessage, EMcuMgrErrorCode mcuMgrErrorCode, EFileOperationGroupReturnCode fileOperationGroupReturnCode)
+ => FileDownloader?.OnFatalErrorOccurred(new FatalErrorOccurredEventArgs(resource, errorMessage, mcuMgrErrorCode, fileOperationGroupReturnCode));
public void FileDownloadProgressPercentageAndDataThroughputChangedAdvertisement(int progressPercentage, float averageThroughput)
=> FileDownloader?.OnFileDownloadProgressPercentageAndDataThroughputChanged(new FileDownloadProgressPercentageAndDataThroughputChangedEventArgs(
diff --git a/Laerdal.McuMgr/Shared/FileUploader/Contracts/Enums/EFileUploaderGroupReturnCode.cs b/Laerdal.McuMgr/Shared/FileUploader/Contracts/Enums/EFileOperationGroupReturnCode.cs
similarity index 92%
rename from Laerdal.McuMgr/Shared/FileUploader/Contracts/Enums/EFileUploaderGroupReturnCode.cs
rename to Laerdal.McuMgr/Shared/FileUploader/Contracts/Enums/EFileOperationGroupReturnCode.cs
index a5da93c9..faf95cb4 100644
--- a/Laerdal.McuMgr/Shared/FileUploader/Contracts/Enums/EFileUploaderGroupReturnCode.cs
+++ b/Laerdal.McuMgr/Shared/FileUploader/Contracts/Enums/EFileOperationGroupReturnCode.cs
@@ -1,6 +1,6 @@
namespace Laerdal.McuMgr.FileUploader.Contracts.Enums
{
- public enum EFileUploaderGroupReturnCode //@formatter:off
+ public enum EFileOperationGroupReturnCode //@formatter:off
{
Unset = -99,
Ok = 00,
diff --git a/Laerdal.McuMgr/Shared/FileUploader/Contracts/Events/FatalErrorOccurredEventArgs.cs b/Laerdal.McuMgr/Shared/FileUploader/Contracts/Events/FatalErrorOccurredEventArgs.cs
index 3ce54b59..8075bec3 100644
--- a/Laerdal.McuMgr/Shared/FileUploader/Contracts/Events/FatalErrorOccurredEventArgs.cs
+++ b/Laerdal.McuMgr/Shared/FileUploader/Contracts/Events/FatalErrorOccurredEventArgs.cs
@@ -13,9 +13,9 @@ namespace Laerdal.McuMgr.FileUploader.Contracts.Events
public string RemoteFilePath { get; }
public EMcuMgrErrorCode ErrorCode { get; }
- public EFileUploaderGroupReturnCode GroupReturnCode { get; }
+ public EFileOperationGroupReturnCode GroupReturnCode { get; }
- public FatalErrorOccurredEventArgs(string remoteFilePath, string errorMessage, EMcuMgrErrorCode errorCode, EFileUploaderGroupReturnCode groupReturnCode)
+ public FatalErrorOccurredEventArgs(string remoteFilePath, string errorMessage, EMcuMgrErrorCode errorCode, EFileOperationGroupReturnCode groupReturnCode)
{
ErrorCode = errorCode;
ErrorMessage = errorMessage;
diff --git a/Laerdal.McuMgr/Shared/FileUploader/Contracts/Exceptions/UploadErroredOutException.cs b/Laerdal.McuMgr/Shared/FileUploader/Contracts/Exceptions/UploadErroredOutException.cs
index 6bfb2e4c..f891cdb1 100644
--- a/Laerdal.McuMgr/Shared/FileUploader/Contracts/Exceptions/UploadErroredOutException.cs
+++ b/Laerdal.McuMgr/Shared/FileUploader/Contracts/Exceptions/UploadErroredOutException.cs
@@ -9,7 +9,7 @@ public class UploadErroredOutException : Exception, IUploadException
public string RemoteFilePath { get; }
public EMcuMgrErrorCode McuMgrErrorCode { get; } = EMcuMgrErrorCode.Unset;
- public EFileUploaderGroupReturnCode GroupReturnCode { get; } = EFileUploaderGroupReturnCode.Unset;
+ public EFileOperationGroupReturnCode GroupReturnCode { get; } = EFileOperationGroupReturnCode.Unset;
protected UploadErroredOutException(string remoteFilePath, string errorMessage, Exception innerException = null)
: base($"An error occurred while uploading over to '{remoteFilePath}': '{errorMessage}'", innerException)
@@ -21,7 +21,7 @@ public UploadErroredOutException(
string nativeErrorMessage,
string remoteFilePath,
EMcuMgrErrorCode mcuMgrErrorCode,
- EFileUploaderGroupReturnCode groupReturnCode,
+ EFileOperationGroupReturnCode groupReturnCode,
Exception innerException = null
) : base($"An error occurred while uploading '{remoteFilePath}': '{nativeErrorMessage}' (mcuMgrErrorCode={mcuMgrErrorCode}, groupReturnCode={groupReturnCode})", innerException)
{
diff --git a/Laerdal.McuMgr/Shared/FileUploader/Contracts/Exceptions/UploadErroredOutRemoteFolderNotFoundException.cs b/Laerdal.McuMgr/Shared/FileUploader/Contracts/Exceptions/UploadErroredOutRemoteFolderNotFoundException.cs
index 5e81cfcf..fa739cd9 100644
--- a/Laerdal.McuMgr/Shared/FileUploader/Contracts/Exceptions/UploadErroredOutRemoteFolderNotFoundException.cs
+++ b/Laerdal.McuMgr/Shared/FileUploader/Contracts/Exceptions/UploadErroredOutRemoteFolderNotFoundException.cs
@@ -11,7 +11,7 @@ public UploadErroredOutRemoteFolderNotFoundException(
string nativeErrorMessage,
string remoteFilePath,
EMcuMgrErrorCode mcuMgrErrorCode,
- EFileUploaderGroupReturnCode groupReturnCode
+ EFileOperationGroupReturnCode groupReturnCode
) : base(
nativeErrorMessage: nativeErrorMessage,
remoteFilePath: remoteFilePath,
diff --git a/Laerdal.McuMgr/Shared/FileUploader/Contracts/Exceptions/UploadUnauthorizedException.cs b/Laerdal.McuMgr/Shared/FileUploader/Contracts/Exceptions/UploadUnauthorizedException.cs
index 3d789cf0..1243df45 100644
--- a/Laerdal.McuMgr/Shared/FileUploader/Contracts/Exceptions/UploadUnauthorizedException.cs
+++ b/Laerdal.McuMgr/Shared/FileUploader/Contracts/Exceptions/UploadUnauthorizedException.cs
@@ -9,9 +9,9 @@ public class UploadUnauthorizedException : UploadErroredOutException, IMcuMgrExc
public string RemoteFilePath { get; }
public EMcuMgrErrorCode McuMgrErrorCode { get; }
- public EFileUploaderGroupReturnCode GroupReturnCode { get; }
+ public EFileOperationGroupReturnCode GroupReturnCode { get; }
- public UploadUnauthorizedException(string nativeErrorMessage, string remoteFilePath, EMcuMgrErrorCode mcuMgrErrorCode, EFileUploaderGroupReturnCode groupReturnCode)
+ public UploadUnauthorizedException(string nativeErrorMessage, string remoteFilePath, EMcuMgrErrorCode mcuMgrErrorCode, EFileOperationGroupReturnCode groupReturnCode)
: base(remoteFilePath, $"{nativeErrorMessage} (McuMgrErrorCode={mcuMgrErrorCode}, GroupReturnCode={groupReturnCode})")
{
RemoteFilePath = remoteFilePath;
diff --git a/Laerdal.McuMgr/Shared/FileUploader/Contracts/Native/INativeFileUploaderCallbacksProxy.cs b/Laerdal.McuMgr/Shared/FileUploader/Contracts/Native/INativeFileUploaderCallbacksProxy.cs
index c27bfb09..16858c7d 100644
--- a/Laerdal.McuMgr/Shared/FileUploader/Contracts/Native/INativeFileUploaderCallbacksProxy.cs
+++ b/Laerdal.McuMgr/Shared/FileUploader/Contracts/Native/INativeFileUploaderCallbacksProxy.cs
@@ -14,7 +14,7 @@ internal interface INativeFileUploaderCallbacksProxy
void StateChangedAdvertisement(string resource, EFileUploaderState oldState, EFileUploaderState newState);
void BusyStateChangedAdvertisement(bool busyNotIdle);
void FileUploadedAdvertisement(string resource);
- void FatalErrorOccurredAdvertisement(string resource, string errorMessage, EMcuMgrErrorCode mcuMgrErrorCode, EFileUploaderGroupReturnCode fileUploaderGroupReturnCode);
+ void FatalErrorOccurredAdvertisement(string resource, string errorMessage, EMcuMgrErrorCode mcuMgrErrorCode, EFileOperationGroupReturnCode fileUploaderGroupReturnCode);
void FileUploadProgressPercentageAndDataThroughputChangedAdvertisement(int progressPercentage, float averageThroughput);
}
}
\ No newline at end of file
diff --git a/Laerdal.McuMgr/Shared/FileUploader/FileUploader.cs b/Laerdal.McuMgr/Shared/FileUploader/FileUploader.cs
index 658a967b..6c2678a6 100644
--- a/Laerdal.McuMgr/Shared/FileUploader/FileUploader.cs
+++ b/Laerdal.McuMgr/Shared/FileUploader/FileUploader.cs
@@ -62,76 +62,47 @@ public EFileUploaderVerdict BeginUpload(
RemoteFilePathHelpers.ValidateRemoteFilePath(remoteFilePath); // order
remoteFilePath = RemoteFilePathHelpers.SanitizeRemoteFilePath(remoteFilePath); // order
- var connectionSettings = GetFailSafeConnectionSettingsIfHostDeviceIsProblematic_(
- hostDeviceModel_: hostDeviceModel,
- hostDeviceManufacturer_: hostDeviceManufacturer,
-
- pipelineDepth_: pipelineDepth,
- byteAlignment_: byteAlignment,
- initialMtuSize_: initialMtuSize,
- windowCapacity_: windowCapacity,
- memoryAlignment_: memoryAlignment
- );
+ var failsafeConnectionSettings = ConnectionSettingsHelpers.GetFailSafeConnectionSettingsIfHostDeviceIsProblematic(
+ hostDeviceModel: hostDeviceModel,
+ hostDeviceManufacturer: hostDeviceManufacturer,
+
+ pipelineDepth: pipelineDepth,
+ byteAlignment: byteAlignment,
+ initialMtuSize: initialMtuSize,
+ windowCapacity: windowCapacity,
+ memoryAlignment: memoryAlignment,
+ uploadingNotDownloading: true
+ );
+ if (failsafeConnectionSettings != null)
+ {
+ pipelineDepth = failsafeConnectionSettings.Value.pipelineDepth;
+ byteAlignment = failsafeConnectionSettings.Value.byteAlignment;
+ initialMtuSize = failsafeConnectionSettings.Value.initialMtuSize;
+ windowCapacity = failsafeConnectionSettings.Value.windowCapacity;
+ memoryAlignment = failsafeConnectionSettings.Value.memoryAlignment;
+
+ OnLogEmitted(new LogEmittedEventArgs(
+ level: ELogLevel.Warning,
+ message: $"[FU.BU.010] Host device '{hostDeviceModel} (made by {hostDeviceManufacturer})' is known to be problematic. Resorting to using failsafe settings " +
+ $"(pipelineDepth={pipelineDepth}, byteAlignment={byteAlignment}, initialMtuSize={initialMtuSize}, windowCapacity={windowCapacity}, memoryAlignment={memoryAlignment})",
+ resource: "File",
+ category: "FileDownloader"
+ ));
+ }
var verdict = _nativeFileUploaderProxy.BeginUpload(
data: data,
remoteFilePath: remoteFilePath,
- pipelineDepth: connectionSettings.pipelineDepth,
- byteAlignment: connectionSettings.byteAlignment,
+ pipelineDepth: pipelineDepth,
+ byteAlignment: byteAlignment,
- initialMtuSize: connectionSettings.initialMtuSize,
- windowCapacity: connectionSettings.windowCapacity,
- memoryAlignment: connectionSettings.memoryAlignment
+ initialMtuSize: initialMtuSize,
+ windowCapacity: windowCapacity,
+ memoryAlignment: memoryAlignment
);
return verdict;
-
- (int? byteAlignment, int? pipelineDepth, int? initialMtuSize, int? windowCapacity, int? memoryAlignment) GetFailSafeConnectionSettingsIfHostDeviceIsProblematic_(
- string hostDeviceManufacturer_,
- string hostDeviceModel_,
- int? pipelineDepth_,
- int? byteAlignment_,
- int? initialMtuSize_,
- int? windowCapacity_,
- int? memoryAlignment_
- )
- {
- hostDeviceModel_ = (hostDeviceModel_ ?? "").Trim().ToLowerInvariant();
- hostDeviceManufacturer_ = (hostDeviceManufacturer_ ?? "").Trim().ToLowerInvariant();
-
- if (AppleTidbits.KnownProblematicDevices.Contains((hostDeviceManufacturer_, hostDeviceModel_))
- && (pipelineDepth_ ?? 1) == 1
- && (byteAlignment_ ?? 1) == 1)
- {
- return (
- byteAlignment: AppleTidbits.FailSafeBleConnectionSettings.ByteAlignment,
- pipelineDepth: AppleTidbits.FailSafeBleConnectionSettings.PipelineDepth,
- initialMtuSize: AndroidTidbits.FailSafeBleConnectionSettings.InitialMtuSize,
- windowCapacity: AndroidTidbits.FailSafeBleConnectionSettings.WindowCapacity,
- memoryAlignment: AndroidTidbits.FailSafeBleConnectionSettings.MemoryAlignment
- );
- }
-
- if (AndroidTidbits.KnownProblematicDevices.Contains((hostDeviceManufacturer_, hostDeviceModel_))
- && initialMtuSize_ == null
- && (windowCapacity_ ?? 1) == 1
- && (memoryAlignment_ ?? 1) == 1)
- {
- return (
- byteAlignment: AppleTidbits.FailSafeBleConnectionSettings.ByteAlignment,
- pipelineDepth: AppleTidbits.FailSafeBleConnectionSettings.PipelineDepth,
- initialMtuSize: AndroidTidbits.FailSafeBleConnectionSettings.InitialMtuSize,
- windowCapacity: AndroidTidbits.FailSafeBleConnectionSettings.WindowCapacity,
- memoryAlignment: AndroidTidbits.FailSafeBleConnectionSettings.MemoryAlignment
- );
- }
-
- return (
- byteAlignment: byteAlignment, pipelineDepth: pipelineDepth,
- initialMtuSize: initialMtuSize, windowCapacity: windowCapacity, memoryAlignment: memoryAlignment
- );
- }
}
public void Cancel(string reason = "") => _nativeFileUploaderProxy?.Cancel(reason);
@@ -338,32 +309,42 @@ public async Task UploadAsync(
FatalErrorOccurred += FileUploader_FatalErrorOccurred_;
FileUploadProgressPercentageAndDataThroughputChanged += FileUploader_FileUploadProgressPercentageAndDataThroughputChanged_;
- var failSafeSettingsToApply = GetFailsafeConnectionSettingsIfConnectionProvedToBeUnstable_(
- triesCount_: triesCount,
- maxTriesCount_: maxTriesCount,
- suspiciousTransportFailuresCount_: suspiciousTransportFailuresCount,
- emitWarningAboutUnstableConnection_: !didWarnOnceAboutUnstableConnection
+ var failSafeSettingsToApply = ConnectionSettingsHelpers.GetFailsafeConnectionSettingsIfConnectionProvedToBeUnstable(
+ uploadingNotDownloading: true,
+ triesCount: triesCount,
+ maxTriesCount: maxTriesCount,
+ suspiciousTransportFailuresCount: suspiciousTransportFailuresCount
);
if (failSafeSettingsToApply != null)
{
- didWarnOnceAboutUnstableConnection = true;
byteAlignment = failSafeSettingsToApply.Value.byteAlignment;
pipelineDepth = failSafeSettingsToApply.Value.pipelineDepth;
initialMtuSize = failSafeSettingsToApply.Value.initialMtuSize;
windowCapacity = failSafeSettingsToApply.Value.windowCapacity;
memoryAlignment = failSafeSettingsToApply.Value.memoryAlignment;
+
+ if (!didWarnOnceAboutUnstableConnection)
+ {
+ didWarnOnceAboutUnstableConnection = true;
+ OnLogEmitted(new LogEmittedEventArgs(
+ level: ELogLevel.Warning,
+ message: $"[FU.UA.010] Attempt#{triesCount}: Connection is too unstable for uploading assets to the target device. Subsequent tries will use failsafe parameters on the connection " +
+ $"just in case it helps (byteAlignment={failSafeSettingsToApply.Value.byteAlignment}, pipelineDepth={failSafeSettingsToApply.Value.pipelineDepth}, initialMtuSize={failSafeSettingsToApply.Value.initialMtuSize}, windowCapacity={failSafeSettingsToApply.Value.windowCapacity}, memoryAlignment={failSafeSettingsToApply.Value.memoryAlignment})",
+ resource: "File",
+ category: "FileUploader"
+ ));
+ }
}
var verdict = BeginUpload( //00 dont use task.run here for now
remoteFilePath: remoteFilePath,
-
hostDeviceModel: hostDeviceModel,
hostDeviceManufacturer: hostDeviceManufacturer,
- data: dataArray, // ios only
+ data: dataArray, // ios only
pipelineDepth: pipelineDepth, // ios only
- byteAlignment: byteAlignment, // android only
+ byteAlignment: byteAlignment, // android only
initialMtuSize: initialMtuSize, // android only
windowCapacity: windowCapacity,
memoryAlignment: memoryAlignment // android only
@@ -525,37 +506,6 @@ void FileUploader_FatalErrorOccurred_(object sender, FatalErrorOccurredEventArgs
throw new UploadCancelledException(cancellationReason); //20
return;
-
- (int? byteAlignment, int? pipelineDepth, int? initialMtuSize, int? windowCapacity, int? memoryAlignment)? GetFailsafeConnectionSettingsIfConnectionProvedToBeUnstable_(
- int triesCount_,
- int maxTriesCount_,
- int suspiciousTransportFailuresCount_,
- bool emitWarningAboutUnstableConnection_
- )
- {
- var isConnectionTooUnstableForUploading_ = triesCount_ >= 2 && (triesCount_ == maxTriesCount_ || triesCount_ >= 3 && suspiciousTransportFailuresCount_ >= 2);
- if (!isConnectionTooUnstableForUploading_)
- return null;
-
- var byteAlignment_ = AppleTidbits.FailSafeBleConnectionSettings.ByteAlignment; // ios + maccatalyst
- var pipelineDepth_ = AppleTidbits.FailSafeBleConnectionSettings.PipelineDepth; // ios + maccatalyst
- var initialMtuSize_ = AndroidTidbits.FailSafeBleConnectionSettings.InitialMtuSize; // android when noticing persistent failures when uploading we resort
- var windowCapacity_ = AndroidTidbits.FailSafeBleConnectionSettings.WindowCapacity; // android to forcing the most failsafe settings we know of just in case
- var memoryAlignment_ = AndroidTidbits.FailSafeBleConnectionSettings.MemoryAlignment; // android we manage to salvage this situation (works with SamsungA8 android tablets)
-
- if (emitWarningAboutUnstableConnection_)
- {
- OnLogEmitted(new LogEmittedEventArgs(
- level: ELogLevel.Warning,
- message: $"[FU.UA.GFCSICPTBU.010] Attempt#{triesCount_}: Connection is too unstable for uploading assets to the target device. Subsequent tries will use failsafe parameters on the connection " +
- $"just in case it helps (byteAlignment={byteAlignment_}, pipelineDepth={pipelineDepth_}, initialMtuSize={initialMtuSize_}, windowCapacity={windowCapacity_}, memoryAlignment={memoryAlignment_})",
- resource: "File",
- category: "FileUploader"
- ));
- }
-
- return (byteAlignment: byteAlignment_, pipelineDepth: pipelineDepth_, initialMtuSize: initialMtuSize_, windowCapacity: windowCapacity_, memoryAlignment: memoryAlignment_);
- }
//00 we are aware that in order to be 100% accurate about timeouts we should use task.run() here without await and then await the
// taskcompletionsource right after but if we went down this path we would also have to account for exceptions thus complicating
@@ -638,7 +588,7 @@ public void FatalErrorOccurredAdvertisement(
string resource,
string errorMessage,
EMcuMgrErrorCode mcuMgrErrorCode,
- EFileUploaderGroupReturnCode fileUploaderGroupReturnCode
+ EFileOperationGroupReturnCode fileUploaderGroupReturnCode
) => FileUploader?.OnFatalErrorOccurred(new FatalErrorOccurredEventArgs(
resource,
errorMessage,
diff --git a/Laerdal.McuMgr/Shared/FirmwareInstaller/Contracts/IFirmwareInstallerCommandable.cs b/Laerdal.McuMgr/Shared/FirmwareInstaller/Contracts/IFirmwareInstallerCommandable.cs
index 0768069f..e7d8d4b2 100644
--- a/Laerdal.McuMgr/Shared/FirmwareInstaller/Contracts/IFirmwareInstallerCommandable.cs
+++ b/Laerdal.McuMgr/Shared/FirmwareInstaller/Contracts/IFirmwareInstallerCommandable.cs
@@ -12,8 +12,8 @@ public interface IFirmwareInstallerCommandable
///
///
/// When 'maxTriesCount' is greater than or equal to 2 the connection will be monitored in terms of how stable and reliable it is during the firmware-uploading stage and if
- /// the uploading phase fails from the third attempt onwards then in the subsequent attempts the fail-safe settings in
- /// and will be enforced to try to upload the firmware.
+ /// the uploading phase fails from the third attempt onwards then in the subsequent attempts the fail-safe settings in
+ /// and will be enforced to try to upload the firmware.
///
/// The firmware bytes. If zipped then the archive must contain the .bin file and not a directory.
/// The firmware upgrade mode. Best to leave this to the default value 'TestAndConfirm'.
diff --git a/Laerdal.McuMgr/Shared/FirmwareInstaller/FirmwareInstaller.cs b/Laerdal.McuMgr/Shared/FirmwareInstaller/FirmwareInstaller.cs
index bc22da01..7ce90b0e 100644
--- a/Laerdal.McuMgr/Shared/FirmwareInstaller/FirmwareInstaller.cs
+++ b/Laerdal.McuMgr/Shared/FirmwareInstaller/FirmwareInstaller.cs
@@ -353,11 +353,11 @@ bool emitWarningAboutUnstableConnection_
if (!isConnectionTooUnstableForUploading_)
return null;
- var byteAlignment_ = AppleTidbits.FailSafeBleConnectionSettings.ByteAlignment; // ios + maccatalyst
- var pipelineDepth_ = AppleTidbits.FailSafeBleConnectionSettings.PipelineDepth; // ios + maccatalyst
- var initialMtuSize_ = AndroidTidbits.FailSafeBleConnectionSettings.InitialMtuSize; // android when noticing persistent failures when uploading we resort
- var windowCapacity_ = AndroidTidbits.FailSafeBleConnectionSettings.WindowCapacity; // android to forcing the most failsafe settings we know of just in case
- var memoryAlignment_ = AndroidTidbits.FailSafeBleConnectionSettings.MemoryAlignment; // android we manage to salvage this situation (works with SamsungA8 android tablets)
+ var byteAlignment_ = AppleTidbits.BleConnectionFailsafeSettings.ForUploading.ByteAlignment; // ios + maccatalyst
+ var pipelineDepth_ = AppleTidbits.BleConnectionFailsafeSettings.ForUploading.PipelineDepth; // ios + maccatalyst
+ var initialMtuSize_ = AndroidTidbits.BleConnectionFailsafeSettings.ForUploading.InitialMtuSize; // android when noticing persistent failures when uploading we resort
+ var windowCapacity_ = AndroidTidbits.BleConnectionFailsafeSettings.ForUploading.WindowCapacity; // android to forcing the most failsafe settings we know of just in case
+ var memoryAlignment_ = AndroidTidbits.BleConnectionFailsafeSettings.ForUploading.MemoryAlignment; // android we manage to salvage this situation (works with SamsungA8 android tablets)
if (emitWarningAboutUnstableConnection_)
{
diff --git a/Laerdal.McuMgr/iOS/FileDownloader/FileDownloader.cs b/Laerdal.McuMgr/iOS/FileDownloader/FileDownloader.cs
index f7e2bc46..8bc269ca 100644
--- a/Laerdal.McuMgr/iOS/FileDownloader/FileDownloader.cs
+++ b/Laerdal.McuMgr/iOS/FileDownloader/FileDownloader.cs
@@ -9,6 +9,7 @@
using Laerdal.McuMgr.FileDownloader.Contracts;
using Laerdal.McuMgr.FileDownloader.Contracts.Enums;
using Laerdal.McuMgr.FileDownloader.Contracts.Native;
+using Laerdal.McuMgr.FileUploader.Contracts.Enums;
using McuMgrBindingsiOS;
namespace Laerdal.McuMgr.FileDownloader
@@ -80,6 +81,23 @@ private void CleanupInfrastructure()
_nativeFileDownloader?.Dispose();
_nativeFileDownloader = null;
}
+
+ public bool TrySetContext(object context)
+ {
+ return true; //nothing to do in ios only android needs this and supports it
+ }
+
+ public bool TrySetBluetoothDevice(object bluetoothDevice)
+ {
+ var iosBluetoothDevice = bluetoothDevice as CBPeripheral ?? throw new ArgumentException($"Expected {nameof(bluetoothDevice)} to be of type {nameof(CBPeripheral)}", nameof(bluetoothDevice));
+
+ return _nativeFileDownloader?.TrySetBluetoothDevice(iosBluetoothDevice) ?? false;
+ }
+
+ public bool TryInvalidateCachedTransport()
+ {
+ return _nativeFileDownloader?.TryInvalidateCachedTransport() ?? false;
+ }
#region commands
@@ -156,8 +174,19 @@ public override void DownloadCompletedAdvertisement(string resource, NSNumber[]
public void DownloadCompletedAdvertisement(string resource, byte[] data) //conformance to the interface
=> _nativeFileDownloaderCallbacksProxy?.DownloadCompletedAdvertisement(resource, data);
- public override void FatalErrorOccurredAdvertisement(string resource, string errorMessage)
- => _nativeFileDownloaderCallbacksProxy?.FatalErrorOccurredAdvertisement(resource, errorMessage);
+ public override void FatalErrorOccurredAdvertisement(
+ string resource,
+ string errorMessage,
+ nint mcuMgrErrorCode
+ ) => FatalErrorOccurredAdvertisement(
+ resource,
+ errorMessage,
+ (EMcuMgrErrorCode)(int)mcuMgrErrorCode,
+ EFileOperationGroupReturnCode.Unset
+ );
+
+ public void FatalErrorOccurredAdvertisement(string resource, string errorMessage, EMcuMgrErrorCode mcuMgrErrorCode, EFileOperationGroupReturnCode fileOperationGroupReturnCode)
+ => _nativeFileDownloaderCallbacksProxy?.FatalErrorOccurredAdvertisement(resource, errorMessage, mcuMgrErrorCode, fileOperationGroupReturnCode);
public override void FileDownloadProgressPercentageAndDataThroughputChangedAdvertisement(nint progressPercentage, float averageThroughput)
=> FileDownloadProgressPercentageAndDataThroughputChangedAdvertisement(
diff --git a/Laerdal.McuMgr/iOS/FileUploader/FileUploader.cs b/Laerdal.McuMgr/iOS/FileUploader/FileUploader.cs
index 94de7804..a592ec77 100644
--- a/Laerdal.McuMgr/iOS/FileUploader/FileUploader.cs
+++ b/Laerdal.McuMgr/iOS/FileUploader/FileUploader.cs
@@ -209,13 +209,13 @@ nint mcuMgrErrorCode
resource,
errorMessage,
(EMcuMgrErrorCode)(int)mcuMgrErrorCode,
- EFileUploaderGroupReturnCode.Unset
+ EFileOperationGroupReturnCode.Unset
);
public void FatalErrorOccurredAdvertisement( //conformance to the interface
string resource,
string errorMessage, // ReSharper disable once MethodOverloadWithOptionalParameter
EMcuMgrErrorCode mcuMgrErrorCode,
- EFileUploaderGroupReturnCode fileUploaderGroupReturnCode
+ EFileOperationGroupReturnCode fileUploaderGroupReturnCode
) => _nativeFileUploaderCallbacksProxy?.FatalErrorOccurredAdvertisement(
resource,
errorMessage,
diff --git a/Laerdal.Scripts/Laerdal.Builder.targets b/Laerdal.Scripts/Laerdal.Builder.targets
index e9ab547b..5ecd54b9 100644
--- a/Laerdal.Scripts/Laerdal.Builder.targets
+++ b/Laerdal.Scripts/Laerdal.Builder.targets
@@ -243,17 +243,17 @@
-
-
+
+
-
-
+
+