diff --git a/Source/v2/Meadow.CLI/Meadow.CLI.csproj b/Source/v2/Meadow.CLI/Meadow.CLI.csproj index 766ae353..40124bf4 100644 --- a/Source/v2/Meadow.CLI/Meadow.CLI.csproj +++ b/Source/v2/Meadow.CLI/Meadow.CLI.csproj @@ -11,7 +11,7 @@ Wilderness Labs, Inc Wilderness Labs, Inc true - 2.0.0.5 + 2.0.0.6 AnyCPU http://developer.wildernesslabs.co/Meadow/Meadow.Foundation/ icon.png diff --git a/Source/v2/Meadow.Cli/AppManager.cs b/Source/v2/Meadow.Cli/AppManager.cs index edebb7d5..994a8fac 100644 --- a/Source/v2/Meadow.Cli/AppManager.cs +++ b/Source/v2/Meadow.Cli/AppManager.cs @@ -77,9 +77,9 @@ public static async Task DeployApplication( .Except(localFiles.Keys .Select(f => Path.GetFileName(f))); - if (removeFiles.Count() == 0) + if (!removeFiles.Any()) { - logger.LogInformation($"No files to delete"); + logger?.LogInformation($"No files to delete"); } // delete those files @@ -105,7 +105,7 @@ public static async Task DeployApplication( send_file: - if (!await connection?.WriteFile(localFile.Key, null, cancellationToken)) + if (!await connection.WriteFile(localFile.Key, null, cancellationToken)) { logger?.LogWarning($"Error sending'{Path.GetFileName(localFile.Key)}'. Retrying."); await Task.Delay(100); diff --git a/Source/v2/Meadow.Cli/Commands/Current/App/AppDeployCommand.cs b/Source/v2/Meadow.Cli/Commands/Current/App/AppDeployCommand.cs index a7601165..a5928ba5 100644 --- a/Source/v2/Meadow.Cli/Commands/Current/App/AppDeployCommand.cs +++ b/Source/v2/Meadow.Cli/Commands/Current/App/AppDeployCommand.cs @@ -99,7 +99,7 @@ protected override async ValueTask ExecuteCommand() if (wasRuntimeEnabled) { // restore runtime state - Logger.LogInformation("Enabling runtime..."); + Logger?.LogInformation("Enabling runtime..."); await connection.RuntimeEnable(CancellationToken); } diff --git a/Source/v2/Meadow.Cli/Commands/Current/App/AppRunCommand.cs b/Source/v2/Meadow.Cli/Commands/Current/App/AppRunCommand.cs index b211797e..c70b137a 100644 --- a/Source/v2/Meadow.Cli/Commands/Current/App/AppRunCommand.cs +++ b/Source/v2/Meadow.Cli/Commands/Current/App/AppRunCommand.cs @@ -135,7 +135,7 @@ private async Task DeployApplication(IMeadowConnection connection, string Logger?.LogInformation($"Deploying app from {file.DirectoryName}..."); - await AppManager.DeployApplication(_packageManager, connection, file.DirectoryName, true, false, Logger, CancellationToken); + await AppManager.DeployApplication(_packageManager, connection, file.DirectoryName!, true, false, Logger, CancellationToken); connection.FileWriteProgress -= OnFileWriteProgress; diff --git a/Source/v2/Meadow.Cli/Commands/Current/Cloud/Package/CloudPackageUploadCommand.cs b/Source/v2/Meadow.Cli/Commands/Current/Cloud/Package/CloudPackageUploadCommand.cs index fbd9ca32..cc5f0946 100644 --- a/Source/v2/Meadow.Cli/Commands/Current/Cloud/Package/CloudPackageUploadCommand.cs +++ b/Source/v2/Meadow.Cli/Commands/Current/Cloud/Package/CloudPackageUploadCommand.cs @@ -51,7 +51,7 @@ protected override async ValueTask ExecuteCommand() { Logger?.LogInformation($"Uploading package {Path.GetFileName(MpakPath)}..."); - var package = await _packageService.UploadPackage(MpakPath, org.Id, Description, Host, CancellationToken); + var package = await _packageService.UploadPackage(MpakPath, org.Id, Description ?? string.Empty, Host, CancellationToken); Logger?.LogInformation($"Upload complete. Package Id: {package.Id}"); } catch (MeadowCloudException mex) diff --git a/Source/v2/Meadow.Cli/Commands/Current/Device/DeviceProvisionCommand.cs b/Source/v2/Meadow.Cli/Commands/Current/Device/DeviceProvisionCommand.cs index 441afceb..4bab3747 100644 --- a/Source/v2/Meadow.Cli/Commands/Current/Device/DeviceProvisionCommand.cs +++ b/Source/v2/Meadow.Cli/Commands/Current/Device/DeviceProvisionCommand.cs @@ -32,7 +32,7 @@ public DeviceProvisionCommand(DeviceService deviceService, MeadowConnectionManag protected override async ValueTask ExecuteCommand() { - UserOrg org; + UserOrg? org; try { @@ -44,6 +44,7 @@ protected override async ValueTask ExecuteCommand() Logger?.LogInformation("Retrieving your user and organization information..."); var userOrgs = await _userService.GetUserOrgs(Host, CancellationToken).ConfigureAwait(false); + if (userOrgs == null || !userOrgs.Any()) { Logger?.LogInformation($"Please visit {Host} to register your account."); @@ -60,6 +61,7 @@ protected override async ValueTask ExecuteCommand() } org = userOrgs.FirstOrDefault(o => o.Id == OrgId || o.Name == OrgId); + if (org == null) { Logger?.LogInformation($"Unable to find an organization with a Name or ID matching '{OrgId}'"); diff --git a/Source/v2/Meadow.Cli/MeadowConnectionManager.cs b/Source/v2/Meadow.Cli/MeadowConnectionManager.cs index f00084ce..0e392ddd 100644 --- a/Source/v2/Meadow.Cli/MeadowConnectionManager.cs +++ b/Source/v2/Meadow.Cli/MeadowConnectionManager.cs @@ -227,10 +227,12 @@ public static IList GetMeadowSerialPortsForWindows() foreach (ManagementObject moResult in searcher.Get()) { // Try Caption and if not Name, they both seems to contain the COM port - string portLongName = moResult["Caption"].ToString(); + string portLongName = $"{moResult["Caption"]}"; if (string.IsNullOrEmpty(portLongName)) - portLongName = moResult["Name"].ToString(); - string pnpDeviceId = moResult["PNPDeviceID"].ToString(); + { + portLongName = $"{moResult["Name"]}"; + } + string pnpDeviceId = $"{moResult["PNPDeviceID"]}"; // we could collect and return a fair bit of other info from the query: diff --git a/Source/v2/Meadow.Cli/Properties/AssemblyInfo.cs b/Source/v2/Meadow.Cli/Properties/AssemblyInfo.cs index 4600f0e0..e5fd00c5 100644 --- a/Source/v2/Meadow.Cli/Properties/AssemblyInfo.cs +++ b/Source/v2/Meadow.Cli/Properties/AssemblyInfo.cs @@ -6,6 +6,6 @@ namespace Meadow.CLI { public static class Constants { - public const string CLI_VERSION = "2.0.0.5"; + public const string CLI_VERSION = "2.0.0.6"; } } \ No newline at end of file diff --git a/Source/v2/Meadow.Cloud.Client/Identity/LibSecret.cs b/Source/v2/Meadow.Cloud.Client/Identity/LibSecret.cs index 7b6f40d0..73530971 100644 --- a/Source/v2/Meadow.Cloud.Client/Identity/LibSecret.cs +++ b/Source/v2/Meadow.Cloud.Client/Identity/LibSecret.cs @@ -45,13 +45,13 @@ public LibSecret(String service, String account) (int)AttributeType.STRING, IntPtr.Zero); } - public void SetSecret(String password) + public void SetSecret(string password) { _ = secret_password_store_sync(intPt, COLLECTION_SESSION, $"{Service}/{Account}", password, IntPtr.Zero, out IntPtr errorPtr, serviceLabel, Service, accountLabel, Account, IntPtr.Zero); HandleError(errorPtr, "An error was encountered while writing secret to keyring"); } - public string GetSecret() + public string? GetSecret() { IntPtr passwordPtr = secret_password_lookup_sync(intPt, IntPtr.Zero, out IntPtr errorPtr, serviceLabel, Service, accountLabel, Account, IntPtr.Zero); HandleError(errorPtr, "An error was encountered while reading secret from keyring"); diff --git a/Source/v2/Meadow.Cloud.Client/Services/PackageService.cs b/Source/v2/Meadow.Cloud.Client/Services/PackageService.cs index 02f3f260..8ee60027 100644 --- a/Source/v2/Meadow.Cloud.Client/Services/PackageService.cs +++ b/Source/v2/Meadow.Cloud.Client/Services/PackageService.cs @@ -9,7 +9,7 @@ namespace Meadow.Cloud; public class PackageService : CloudServiceBase { - private string _info_json = "info.json"; + private readonly string _info_json = "info.json"; public PackageService(IdentityManager identityManager) : base(identityManager) { @@ -86,7 +86,7 @@ private string GetPackageOsVersion(string packagePath) { var content = File.ReadAllText(tempInfoJson); var packageInfo = JsonSerializer.Deserialize(content); - result = packageInfo.OsVersion; + result = packageInfo?.OsVersion ?? string.Empty; File.Delete(tempInfoJson); } diff --git a/Source/v2/Meadow.Hcom/Connections/ConnectionBase.cs b/Source/v2/Meadow.Hcom/Connections/ConnectionBase.cs index f1119097..85b906cc 100644 --- a/Source/v2/Meadow.Hcom/Connections/ConnectionBase.cs +++ b/Source/v2/Meadow.Hcom/Connections/ConnectionBase.cs @@ -6,7 +6,7 @@ public abstract class ConnectionBase : IMeadowConnection, IDisposable { private bool _isDisposed; - public ConnectionState State { get; protected set; } + public virtual ConnectionState State { get; protected set; } public IMeadowDevice? Device { get; protected set; } public event EventHandler<(string message, string? source)> DeviceMessageReceived = default!; diff --git a/Source/v2/Meadow.Hcom/Connections/SerialConnection.cs b/Source/v2/Meadow.Hcom/Connections/SerialConnection.cs index 2ca4f621..fea79e9e 100644 --- a/Source/v2/Meadow.Hcom/Connections/SerialConnection.cs +++ b/Source/v2/Meadow.Hcom/Connections/SerialConnection.cs @@ -134,12 +134,12 @@ public void RemoveListener(IConnectionListener listener) // TODO: stop maintaining connection? } - public ConnectionState State + public override ConnectionState State { get => _state; - private set + protected set { - if (value == State) return; + if (value == State) { return; } var old = _state; _state = value; @@ -237,7 +237,7 @@ public override void Detach() } } - private async void CommandManager() + private void CommandManager() { while (!_isDisposed) { @@ -1203,25 +1203,23 @@ void OnFileDataReceived(object? sender, string data) public override async Task StartDebuggingSession(int port, ILogger? logger, CancellationToken cancellationToken) { - if (Device != null) + if (Device == null) { - logger?.LogDebug($"Start Debugging on port: {port}"); - await Device.StartDebugging(port, logger, cancellationToken); + throw new DeviceNotFoundException(); + } - /* TODO logger?.LogDebug("Reinitialize the device"); - await ReInitializeMeadow(cancellationToken); */ + logger?.LogDebug($"Start Debugging on port: {port}"); + await Device.StartDebugging(port, logger, cancellationToken); - var endpoint = new IPEndPoint(IPAddress.Loopback, port); - var debuggingServer = new DebuggingServer(Device, endpoint, logger); + /* TODO logger?.LogDebug("Reinitialize the device"); + await ReInitializeMeadow(cancellationToken); */ - logger?.LogDebug("Tell the Debugging Server to Start Listening"); - await debuggingServer.StartListening(cancellationToken); - return debuggingServer; - } - else - { - throw new DeviceNotFoundException(); - } + var endpoint = new IPEndPoint(IPAddress.Loopback, port); + var debuggingServer = new DebuggingServer(Device, endpoint, logger); + + logger?.LogDebug("Tell the Debugging Server to Start Listening"); + await debuggingServer.StartListening(cancellationToken); + return debuggingServer; } public override async Task StartDebugging(int port, ILogger? logger, CancellationToken? cancellationToken) diff --git a/Source/v2/Meadow.Hcom/Connections/TcpConnection.cs b/Source/v2/Meadow.Hcom/Connections/TcpConnection.cs index 207d6a4f..022011bc 100644 --- a/Source/v2/Meadow.Hcom/Connections/TcpConnection.cs +++ b/Source/v2/Meadow.Hcom/Connections/TcpConnection.cs @@ -16,7 +16,7 @@ public TcpConnection(string uri) _client = new HttpClient(); } - public override async Task Attach(CancellationToken? cancellationToken = null, int timeoutSeconds = 10) + public override Task Attach(CancellationToken? cancellationToken = null, int timeoutSeconds = 10) { /* var request = RequestBuilder.Build(); @@ -43,7 +43,9 @@ public TcpConnection(string uri) */ // TODO: is there a way to "attach"? ping result? device info? - return Device = new MeadowDevice(this); + Device = new MeadowDevice(this); + + return Task.FromResult(Device); // TODO: web socket for listen? } diff --git a/Source/v2/Meadow.Hcom/Debugging/DebuggingServer.cs b/Source/v2/Meadow.Hcom/Debugging/DebuggingServer.cs index 22e20cad..cddd4fd3 100644 --- a/Source/v2/Meadow.Hcom/Debugging/DebuggingServer.cs +++ b/Source/v2/Meadow.Hcom/Debugging/DebuggingServer.cs @@ -1,9 +1,9 @@ -using System.Buffers; +using Microsoft.Extensions.Logging; +using System.Buffers; using System.Diagnostics; using System.Net; using System.Net.Sockets; using System.Security.Cryptography; -using Microsoft.Extensions.Logging; namespace Meadow.Hcom; @@ -18,12 +18,12 @@ public class DebuggingServer : IDisposable public IPEndPoint LocalEndpoint { get; private set; } private readonly object _lck = new object(); - private CancellationTokenSource? _cancellationTokenSource; - private readonly ILogger _logger; + private CancellationTokenSource _cancellationTokenSource; + private readonly ILogger? _logger; private readonly IMeadowDevice _meadow; private ActiveClient? _activeClient; private int _activeClientCount = 0; - private TcpListener _listener; + private readonly TcpListener _listener; private Task? _listenerTask; private bool _isReady; public bool Disposed; @@ -35,7 +35,7 @@ public class DebuggingServer : IDisposable /// The to debug /// The to listen for incoming debugger connections /// The to logging state information - public DebuggingServer(IMeadowDevice meadow, IPEndPoint localEndpoint, ILogger logger) + public DebuggingServer(IMeadowDevice meadow, IPEndPoint localEndpoint, ILogger? logger) { LocalEndpoint = localEndpoint; _meadow = meadow; @@ -77,8 +77,7 @@ public async Task StopListening() { _listener?.Stop(); - if (_cancellationTokenSource != null) - _cancellationTokenSource?.Cancel(false); + _cancellationTokenSource?.Cancel(false); if (_listenerTask != null) { @@ -92,7 +91,7 @@ private async Task StartListener() { _listener.Start(); LocalEndpoint = (IPEndPoint)_listener.LocalEndpoint; - _logger.LogInformation($"Listening for Visual Studio to connect on {LocalEndpoint.Address}:{LocalEndpoint.Port}" + Environment.NewLine); + _logger?.LogInformation($"Listening for Visual Studio to connect on {LocalEndpoint.Address}:{LocalEndpoint.Port}" + Environment.NewLine); _isReady = true; // This call will wait for the client to connect, before continuing. We shouldn't need a loop. @@ -101,13 +100,13 @@ private async Task StartListener() } catch (SocketException soex) { - _logger.LogError("A Socket error occurred. The port may already be in use. Try rebooting to free up the port."); - _logger.LogError($"Error:\n{soex.Message} \nStack Trace:\n{soex.StackTrace}"); + _logger?.LogError("A Socket error occurred. The port may already be in use. Try rebooting to free up the port."); + _logger?.LogError($"Error:\n{soex.Message} \nStack Trace:\n{soex.StackTrace}"); } catch (Exception ex) { - _logger.LogError("An unhandled exception occurred while listening for debugging connections."); - _logger.LogError($"Error:\n{ex.Message} \nStack Trace:\n{ex.StackTrace}"); + _logger?.LogError("An unhandled exception occurred while listening for debugging connections."); + _logger?.LogError($"Error:\n{ex.Message} \nStack Trace:\n{ex.StackTrace}"); } } @@ -117,10 +116,10 @@ private void OnConnect(TcpClient tcpClient) { lock (_lck) { - _logger.LogInformation("Visual Studio has Connected" + Environment.NewLine); + _logger?.LogInformation("Visual Studio has Connected" + Environment.NewLine); if (_activeClientCount > 0 && _activeClient?.Disposed == false) { - _logger.LogDebug("Closing active client"); + _logger?.LogDebug("Closing active client"); Debug.Assert(_activeClientCount == 1); Debug.Assert(_activeClient != null); CloseActiveClient(); @@ -132,7 +131,7 @@ private void OnConnect(TcpClient tcpClient) } catch (Exception ex) { - _logger.LogError(ex, "An error occurred while connecting to Visual Studio"); + _logger?.LogError(ex, "An error occurred while connecting to Visual Studio"); } } @@ -147,8 +146,10 @@ public void Dispose() { lock (_lck) { - if (Disposed) - return; + if (Disposed) + { + return; + } _cancellationTokenSource?.Cancel(false); _activeClient?.Dispose(); _listenerTask?.Dispose(); @@ -166,18 +167,18 @@ private class ActiveClient : IDisposable private readonly CancellationTokenSource _cts; private readonly Task _receiveVsDebugDataTask; private readonly Task _receiveMeadowDebugDataTask; - private readonly ILogger _logger; + private readonly ILogger? _logger; public bool Disposed = false; // Constructor - internal ActiveClient(IMeadowDevice meadow, TcpClient tcpClient, ILogger logger, CancellationToken cancellationToken) + internal ActiveClient(IMeadowDevice meadow, TcpClient tcpClient, ILogger? logger, CancellationToken cancellationToken) { _cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); _logger = logger; _meadow = meadow; _tcpClient = tcpClient; _networkStream = tcpClient.GetStream(); - _logger.LogDebug("Starting receive task"); + _logger?.LogDebug("Starting receive task"); _receiveVsDebugDataTask = Task.Factory.StartNew(SendToMeadowAsync, TaskCreationOptions.LongRunning); _receiveMeadowDebugDataTask = Task.Factory.StartNew(SendToVisualStudio, TaskCreationOptions.LongRunning); } @@ -208,7 +209,7 @@ private async Task SendToMeadowAsync() Array.Copy(receiveBuffer, 0, meadowBuffer, destIndex, bytesRead); // Forward the RECIEVE_BUFFER_SIZE chunk to Meadow immediately - _logger.LogTrace("Received {count} bytes from VS, will forward to HCOM/Meadow. {hash}", + _logger?.LogTrace("Received {count} bytes from VS, will forward to HCOM/Meadow. {hash}", meadowBuffer.Length, BitConverter.ToString(md5.ComputeHash(meadowBuffer)) .Replace("-", string.Empty) @@ -223,31 +224,31 @@ private async Task SendToMeadowAsync() else { // User probably hit stop - _logger.LogInformation("Unable to Read Data from Visual Studio"); - _logger.LogTrace("Unable to Read Data from Visual Studio"); + _logger?.LogInformation("Unable to Read Data from Visual Studio"); + _logger?.LogTrace("Unable to Read Data from Visual Studio"); } } } catch (IOException ioe) { // VS client probably died - _logger.LogInformation("Visual Studio has Disconnected" + Environment.NewLine); - _logger.LogTrace(ioe, "Visual Studio has Disconnected"); + _logger?.LogInformation("Visual Studio has Disconnected" + Environment.NewLine); + _logger?.LogTrace(ioe, "Visual Studio has Disconnected"); } catch (ObjectDisposedException ode) { // User probably hit stop - _logger.LogInformation("Visual Studio has stopped debugging" + Environment.NewLine); - _logger.LogTrace(ode, "Visual Studio has stopped debugging"); + _logger?.LogInformation("Visual Studio has stopped debugging" + Environment.NewLine); + _logger?.LogTrace(ode, "Visual Studio has stopped debugging"); } catch (Exception ex) { - _logger.LogError($"Error receiving data from Visual Studio.{Environment.NewLine}Error: {ex.Message}{Environment.NewLine}StackTrace:{Environment.NewLine}{ex.StackTrace}"); + _logger?.LogError($"Error receiving data from Visual Studio.{Environment.NewLine}Error: {ex.Message}{Environment.NewLine}StackTrace:{Environment.NewLine}{ex.StackTrace}"); throw; } } - private async Task SendToVisualStudio() + private Task SendToVisualStudio() { try { @@ -258,22 +259,22 @@ private async Task SendToVisualStudio() /* TODO while (_meadow.DataProcessor.DebuggerMessages.Count > 0) { var byteData = _meadow.DataProcessor.DebuggerMessages.Take(_cts.Token); - _logger.LogTrace("Received {count} bytes from Meadow, will forward to VS", byteData.Length); + _logger?.LogTrace("Received {count} bytes from Meadow, will forward to VS", byteData.Length); if (!_tcpClient.Connected) { - _logger.LogDebug("Cannot forward data, Visual Studio is not connected"); + _logger?.LogDebug("Cannot forward data, Visual Studio is not connected"); return; } await _networkStream.WriteAsync(byteData, 0, byteData.Length, _cts.Token); - _logger.LogTrace("Forwarded {count} bytes to VS", byteData.Length); + _logger?.LogTrace("Forwarded {count} bytes to VS", byteData.Length); }*/ } else { // User probably hit stop - _logger.LogInformation("Unable to Write Data from Visual Studio"); - _logger.LogTrace("Unable to Write Data from Visual Studio"); + _logger?.LogInformation("Unable to Write Data from Visual Studio"); + _logger?.LogTrace("Unable to Write Data from Visual Studio"); } } } @@ -281,26 +282,31 @@ private async Task SendToVisualStudio() { // User probably hit stop; Removed logging as User doesn't need to see this // Keeping it as a TODO in case we find a side effect that needs logging. - // TODO _logger.LogInformation("Operation Cancelled"); - // TODO _logger.LogTrace(oce, "Operation Cancelled"); + // TODO _logger?.LogInformation("Operation Cancelled"); + // TODO _logger?.LogTrace(oce, "Operation Cancelled"); } catch (Exception ex) { - _logger.LogError($"Error sending data to Visual Studio.{Environment.NewLine}Error: {ex.Message}{Environment.NewLine}StackTrace:{Environment.NewLine}{ex.StackTrace}"); + _logger?.LogError($"Error sending data to Visual Studio.{Environment.NewLine}Error: {ex.Message}{Environment.NewLine}StackTrace:{Environment.NewLine}{ex.StackTrace}"); - if (_cts.IsCancellationRequested) - throw; + if (_cts.IsCancellationRequested) + { + throw; + } } + return Task.CompletedTask; } public void Dispose() { lock (_tcpClient) { - if (Disposed) - return; + if (Disposed) + { + return; + } - _logger.LogTrace("Disposing ActiveClient"); + _logger?.LogTrace("Disposing ActiveClient"); _cts.Cancel(false); _receiveVsDebugDataTask.Wait(TimeSpan.FromSeconds(10)); _receiveMeadowDebugDataTask.Wait(TimeSpan.FromSeconds(10)); diff --git a/Source/v2/Meadow.Hcom/Firmware/FirmwareManager.cs b/Source/v2/Meadow.Hcom/Firmware/FirmwareManager.cs index c0d6aaa0..63483930 100644 --- a/Source/v2/Meadow.Hcom/Firmware/FirmwareManager.cs +++ b/Source/v2/Meadow.Hcom/Firmware/FirmwareManager.cs @@ -38,7 +38,7 @@ public static async Task GetCloudLatestFirmwareVersion() { var json = await reader.ReadToEndAsync(); - if (json == null) return string.Empty; + if (json == null) { return string.Empty; } return JsonSerializerExtensions.DeserializeAnonymousType(json, new { version = string.Empty }).version; } diff --git a/Source/v2/Meadow.Hcom/Firmware/FirmwareUpdater.cs b/Source/v2/Meadow.Hcom/Firmware/FirmwareUpdater.cs index 5bf5aea1..c1aeeaba 100644 --- a/Source/v2/Meadow.Hcom/Firmware/FirmwareUpdater.cs +++ b/Source/v2/Meadow.Hcom/Firmware/FirmwareUpdater.cs @@ -6,7 +6,6 @@ namespace Meadow.Hcom; public class FirmwareUpdater { private readonly ILogger? _logger; - private readonly Task? _updateTask; private IMeadowConnection _connection; private UpdateState _state; @@ -45,7 +44,7 @@ private set if (value == _state) return; PreviousState = CurrentState; _state = value; - _logger.LogDebug($"Firmware Updater: {PreviousState}->{CurrentState}"); + _logger?.LogDebug($"Firmware Updater: {PreviousState}->{CurrentState}"); } } @@ -63,9 +62,9 @@ private async void StateMachine() try { // make sure we have a current device info - info = await _connection.Device.GetDeviceInfo(); + info = await _connection.Device!.GetDeviceInfo(); - if (info.OsVersion == RequestedVersion) + if (info?.OsVersion == RequestedVersion) { // no need to update, it's already there CurrentState = UpdateState.DFUCompleted; @@ -96,7 +95,7 @@ private async void StateMachine() ++tries; if (tries > 5) { - _logger.LogError($"Failed to enter DFU mode: {ex.Message}"); + _logger?.LogError($"Failed to enter DFU mode: {ex.Message}"); CurrentState = UpdateState.Error; // exit state machine @@ -137,10 +136,7 @@ private async void StateMachine() await _connection.WaitForMeadowAttach(); await Task.Delay(2000); // wait 2 seconds to allow full boot - if (info == null) - { - info = await _connection.Device.GetDeviceInfo(); - } + info ??= await _connection.Device!.GetDeviceInfo(); CurrentState = UpdateState.DisablingMonoForRuntime; } @@ -154,7 +150,7 @@ private async void StateMachine() case UpdateState.DisablingMonoForRuntime: try { - await _connection.Device.RuntimeDisable(); + await _connection.Device!.RuntimeDisable(); } catch (Exception ex) { @@ -165,7 +161,7 @@ private async void StateMachine() CurrentState = UpdateState.UpdatingRuntime; break; case UpdateState.UpdatingRuntime: - if (info.RuntimeVersion == RequestedVersion) + if (info?.RuntimeVersion == RequestedVersion) { // no need to update, it's already there } @@ -178,7 +174,7 @@ private async void StateMachine() if (info == null) { - info = await _connection.Device.GetDeviceInfo(); + info = await _connection.Device!.GetDeviceInfo(); } // await _connection.Device.FlashRuntime(RequestedVersion); @@ -195,7 +191,7 @@ private async void StateMachine() case UpdateState.DisablingMonoForCoprocessor: try { - await _connection.Device.RuntimeDisable(); + await _connection.Device!.RuntimeDisable(); CurrentState = UpdateState.UpdatingCoprocessor; } @@ -208,7 +204,7 @@ private async void StateMachine() CurrentState = UpdateState.UpdatingCoprocessor; break; case UpdateState.UpdatingCoprocessor: - if (info.CoprocessorOsVersion == RequestedVersion) + if (info?.CoprocessorOsVersion == RequestedVersion) { // no need to update, it's already there } @@ -224,7 +220,7 @@ private async void StateMachine() if (info == null) { Debug.WriteLine(">> query device info"); - info = await _connection.Device.GetDeviceInfo(); + info = await _connection.Device!.GetDeviceInfo(); } Debug.WriteLine(">> flashing ESP"); @@ -243,7 +239,7 @@ private async void StateMachine() case UpdateState.AllWritesComplete: try { - await _connection.Device.Reset(); + await _connection.Device!.Reset(); } catch (Exception ex) { @@ -252,27 +248,26 @@ private async void StateMachine() return; } break; - CurrentState = UpdateState.VerifySuccess; case UpdateState.VerifySuccess: try { await _connection.WaitForMeadowAttach(); await Task.Delay(2000); // wait 2 seconds to allow full boot - info = await _connection.Device.GetDeviceInfo(); - if (info.OsVersion != RequestedVersion) + info = await _connection.Device!.GetDeviceInfo(); + if (info?.OsVersion != RequestedVersion) { // this is a failure - _logger?.LogWarning($"OS version {info.OsVersion} does not match requested version {RequestedVersion}"); + _logger?.LogWarning($"OS version {info?.OsVersion} does not match requested version {RequestedVersion}"); } - if (info.RuntimeVersion != RequestedVersion) + if (info?.RuntimeVersion != RequestedVersion) { // this is a failure - _logger?.LogWarning($"Runtime version {info.RuntimeVersion} does not match requested version {RequestedVersion}"); + _logger?.LogWarning($"Runtime version {info?.RuntimeVersion} does not match requested version {RequestedVersion}"); } - if (info.CoprocessorOsVersion != RequestedVersion) + if (info?.CoprocessorOsVersion != RequestedVersion) { // not necessarily an error - _logger?.LogWarning($"Coprocessor version {info.CoprocessorOsVersion} does not match requested version {RequestedVersion}"); + _logger?.LogWarning($"Coprocessor version {info?.CoprocessorOsVersion} does not match requested version {RequestedVersion}"); } } catch (Exception ex) @@ -306,6 +301,7 @@ public Task Update(IMeadowConnection? connection, string? version = null) { // verify the version requested is valid var build = FirmwareManager.GetAllLocalFirmwareBuilds().FirstOrDefault(b => b.Version == version); + if (build == null) { throw new Exception($"Unknown build: '{version}'"); @@ -328,4 +324,4 @@ public Task Update(IMeadowConnection? connection, string? version = null) return Task.Run(StateMachine); } -} +} \ No newline at end of file diff --git a/Source/v2/Meadow.Hcom/SerialRequests/SetRtcTimeRequest.cs b/Source/v2/Meadow.Hcom/SerialRequests/SetRtcTimeRequest.cs index 96b14b50..41bb7400 100644 --- a/Source/v2/Meadow.Hcom/SerialRequests/SetRtcTimeRequest.cs +++ b/Source/v2/Meadow.Hcom/SerialRequests/SetRtcTimeRequest.cs @@ -10,13 +10,16 @@ public DateTimeOffset? Time { get { - if (Payload.Length == 0) { return null; } + if (Payload?.Length == 0) { return null; } return DateTimeOffset.Parse(Encoding.ASCII.GetString(Payload)); } set { - base.Payload = Encoding.ASCII.GetBytes(value.Value.ToUniversalTime().ToString("o")); + if (value != null) + { + base.Payload = Encoding.ASCII.GetBytes(value.Value.ToUniversalTime().ToString("o")); + } } } diff --git a/Source/v2/Meadow.SoftwareManager/F7FirmwarePackageCollection.cs b/Source/v2/Meadow.SoftwareManager/F7FirmwarePackageCollection.cs index ffac2127..d20eddbc 100644 --- a/Source/v2/Meadow.SoftwareManager/F7FirmwarePackageCollection.cs +++ b/Source/v2/Meadow.SoftwareManager/F7FirmwarePackageCollection.cs @@ -13,7 +13,7 @@ public class F7FirmwarePackageCollection : IFirmwarePackageCollection /// public event EventHandler DownloadProgress = default!; - public event EventHandler DefaultVersionChanged; + public event EventHandler DefaultVersionChanged = default!; public string PackageFileRoot { get; } @@ -74,7 +74,7 @@ private set return null; } - public Task DeletePackage(string version) + public async Task DeletePackage(string version) { var existing = _f7Packages.FirstOrDefault(p => p.Version == version); @@ -91,13 +91,11 @@ public Task DeletePackage(string version) } var newDefault = _f7Packages[i].Version; _f7Packages.Remove(DefaultPackage); - SetDefaultPackage(newDefault); + await SetDefaultPackage(newDefault); var path = Path.Combine(PackageFileRoot, version); Directory.Delete(path, true); - - return Task.CompletedTask; } public async Task SetDefaultPackage(string version)