diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 5292157..c121811 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,6 +1,6 @@ name: VSCode Extension env: - IDE_TOOLS_RELEASE_VERSION: 1.9.7 + IDE_TOOLS_RELEASE_VERSION: 2.0.0 on: push: @@ -18,14 +18,14 @@ jobs: steps: - name: Checkout current repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: path: main submodules: true - if: ${{ github.ref == 'refs/heads/main' }} name: Checkout Meadow.CLI.Core side-by-side - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: WildernessLabs/Meadow.CLI path: Meadow.CLI @@ -33,31 +33,43 @@ jobs: - if: ${{ github.ref != 'refs/heads/main' }} name: Checkout Meadow.CLI.Core side-by-side - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: WildernessLabs/Meadow.CLI path: Meadow.CLI ref: develop + - name: Checkout Meadow.Contracts side-by-side + uses: actions/checkout@v4 + with: + repository: WildernessLabs/Meadow.Contracts + path: Meadow.Contracts + ref: main + - name: Setup .NET 8.0.x - uses: actions/setup-dotnet@v3 + uses: actions/setup-dotnet@v4 with: dotnet-version: | 8.0.x - name: Setup Nuget - uses: Nuget/setup-nuget@v1.0.5 + uses: Nuget/setup-nuget@v2 - - name: Setup Node.js 16 - uses: actions/setup-node@v3 + - name: Setup Node.js 20 + uses: actions/setup-node@v4 with: - node-version: 16 + node-version: 20 - name: Install vsce run: | npm i -g @vscode/vsce npm i -g @vscode/debugprotocol + - name: Install FallBack Sources + run: | + nuget install Microsoft.SymbolStore -Version 1.0.411401 -FallbackSource "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json" + # May not be needed for now, but keeping it around nuget install Microsoft.FileFormats -Version 1.0.411401 -FallbackSource "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json" + - if: ${{ github.event_name == 'workflow_dispatch' }} name: Update VSCode Version Numbers run: | @@ -93,14 +105,14 @@ jobs: vsce package - name: Upload VSIX Artifacts - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: VSCodeMeadow.vsix.${{ ENV.IDE_TOOLS_RELEASE_VERSION }} path: 'main/*.vsix' - name: Upload Binlog Artifacts if: always() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: BinLogs path: '**/*.binlog' diff --git a/README.md b/README.md index 4b51921..66d64ff 100644 --- a/README.md +++ b/README.md @@ -129,6 +129,7 @@ You can also use the following short-cut on: ### Prerequisites +- Install Python - Install NPM Then run the following commands on the command line, once NPM is installed diff --git a/externals/debugger-libs b/externals/debugger-libs index 3ce6fbb..4462650 160000 --- a/externals/debugger-libs +++ b/externals/debugger-libs @@ -1 +1 @@ -Subproject commit 3ce6fbb1be8c3dc3de42fd16ef87b8a8c7ed2561 +Subproject commit 44626505d5235aa899fa4df3cf3f1d4256f5ca79 diff --git a/package-lock.json b/package-lock.json index af5a04a..c92e1ce 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "meadow", - "version": "1.9.7", + "version": "2.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "meadow", - "version": "1.9.7", + "version": "2.0.0", "license": "LICENSE", "dependencies": { "@types/execa": "^2.0.0", @@ -34,8 +34,9 @@ "ts-loader": "^9.4.2", "typescript": "^4.2.2", "vscode-nls-dev": "^4.0.3", - "webpack": "^5.76.0", - "webpack-cli": "^5.0.0" + "webpack": ">=5.94.0", + "webpack-cli": "^5.0.0", + "braces": ">=3.0.3" }, "engines": { "node": "^6.3.0", @@ -1360,7 +1361,7 @@ ], "dependencies": { "anymatch": "~3.1.2", - "braces": "~3.0.2", + "braces": ">=3.0.3", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", @@ -1874,7 +1875,7 @@ "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", "dependencies": { - "cross-spawn": "^7.0.3", + "cross-spawn": ">=7.0.5", "get-stream": "^6.0.0", "human-signals": "^2.1.0", "is-stream": "^2.0.0", @@ -1992,7 +1993,7 @@ "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", "dev": true, "dependencies": { - "cross-spawn": "^7.0.0", + "cross-spawn": ">=7.0.5", "signal-exit": "^4.0.1" }, "engines": { @@ -2749,7 +2750,7 @@ "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", "dev": true, "dependencies": { - "braces": "^3.0.2", + "braces": ">=3.0.3", "picomatch": "^2.3.1" }, "engines": { @@ -3965,7 +3966,7 @@ "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "webpack": "^5.76.0" + "webpack": "5.x.x" }, "peerDependenciesMeta": { "@swc/core": { @@ -4031,7 +4032,7 @@ }, "peerDependencies": { "typescript": "*", - "webpack": "^5.76.0" + "webpack": "5.x.x" } }, "node_modules/tslib": { @@ -4299,7 +4300,7 @@ "@webpack-cli/serve": "^2.0.1", "colorette": "^2.0.14", "commander": "^9.4.1", - "cross-spawn": "^7.0.3", + "cross-spawn": ">=7.0.5", "envinfo": "^7.7.3", "fastest-levenshtein": "^1.0.12", "import-local": "^3.0.2", diff --git a/package.json b/package.json index ee0b16c..a526303 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "meadow", "displayName": "VSCode Tools For Meadow", - "version": "1.9.7", + "version": "2.0.0", "publisher": "WildernessLabs", "description": "Build, Debug and Deploy Meadow applications", "icon": "meadow.png", @@ -56,14 +56,13 @@ "ts-loader": "^9.4.2", "typescript": "^4.2.2", "vscode-nls-dev": "^4.0.3", - "webpack": "^5.76.0", + "webpack": ">=5.94.0", "webpack-cli": "^5.0.0" }, "main": "./dist/extension", "activationEvents": [ "onStartupFinished", "onDebug", - "onCommand:extension.meadow.configureExceptions", "onCommand:extension.meadow.startSession" ], "contributes": { diff --git a/src/VSCodeMeadow.sln b/src/VSCodeMeadow.sln index 5560097..590114c 100644 --- a/src/VSCodeMeadow.sln +++ b/src/VSCodeMeadow.sln @@ -6,10 +6,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "debugger", "debugger", "{DD EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Meadow", "Meadow", "{639FE3D4-9D7F-4823-9911-48FE49C6998F}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Meadow.Hcom.6.0.0", "..\..\Meadow.CLI\Meadow.Hcom\Meadow.Hcom.6.0.0.csproj", "{5F0219BE-F626-4C90-89B0-202850AE43C5}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Meadow.CLI.Core.6.0.0", "..\..\Meadow.CLI\Meadow.CLI.Core\Meadow.CLI.Core.6.0.0.csproj", "{21E7E61E-D9CE-48E2-B1DA-52B5FC12015A}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VSCodeMeadow", "csharp\VSCodeMeadow.csproj", "{D46A8779-DAE7-4B90-ACBA-08893A504193}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mono.Debugging", "..\externals\debugger-libs\Mono.Debugging\Mono.Debugging.csproj", "{CD6FED13-1984-4491-97AB-1A4361E1F582}" @@ -18,20 +14,22 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mono.Debugger.Soft", "..\ex EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mono.Debugging.Soft", "..\externals\debugger-libs\Mono.Debugging.Soft\Mono.Debugging.Soft.csproj", "{7592E68B-CE43-4433-8B5A-F7890BAA2ABC}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Meadow.HCom", "..\..\Meadow.CLI\Source\v2\Meadow.HCom\Meadow.HCom.csproj", "{7F1115C6-5081-4997-AC0F-789D95B5092C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Meadow.Tooling.Core", "..\..\Meadow.CLI\Source\v2\Meadow.Tooling.Core\Meadow.Tooling.Core.csproj", "{AF35343B-B97C-4300-9EB4-DE753CADDC13}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Meadow.Linker", "..\..\Meadow.CLI\Source\v2\Meadow.Linker\Meadow.Linker.csproj", "{B11B8D26-FE98-4BD7-875E-D5A0801D3415}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Meadow.SoftwareManager", "..\..\Meadow.CLI\Source\v2\Meadow.SoftwareManager\Meadow.SoftwareManager.csproj", "{CC5D6AA6-F58A-4B8B-A514-988BCAEA21EE}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Meadow.Cloud.Client", "..\..\Meadow.CLI\Source\v2\Meadow.Cloud.Client\Meadow.Cloud.Client.csproj", "{7820644F-8B87-4864-81B4-A8CB5859A71C}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {5F0219BE-F626-4C90-89B0-202850AE43C5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {5F0219BE-F626-4C90-89B0-202850AE43C5}.Debug|Any CPU.Build.0 = Debug|Any CPU - {5F0219BE-F626-4C90-89B0-202850AE43C5}.Release|Any CPU.ActiveCfg = Release|Any CPU - {5F0219BE-F626-4C90-89B0-202850AE43C5}.Release|Any CPU.Build.0 = Release|Any CPU - {21E7E61E-D9CE-48E2-B1DA-52B5FC12015A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {21E7E61E-D9CE-48E2-B1DA-52B5FC12015A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {21E7E61E-D9CE-48E2-B1DA-52B5FC12015A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {21E7E61E-D9CE-48E2-B1DA-52B5FC12015A}.Release|Any CPU.Build.0 = Release|Any CPU {D46A8779-DAE7-4B90-ACBA-08893A504193}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D46A8779-DAE7-4B90-ACBA-08893A504193}.Debug|Any CPU.Build.0 = Debug|Any CPU {D46A8779-DAE7-4B90-ACBA-08893A504193}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -48,16 +46,39 @@ Global {7592E68B-CE43-4433-8B5A-F7890BAA2ABC}.Debug|Any CPU.Build.0 = Debug|Any CPU {7592E68B-CE43-4433-8B5A-F7890BAA2ABC}.Release|Any CPU.ActiveCfg = Release|Any CPU {7592E68B-CE43-4433-8B5A-F7890BAA2ABC}.Release|Any CPU.Build.0 = Release|Any CPU + {7F1115C6-5081-4997-AC0F-789D95B5092C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7F1115C6-5081-4997-AC0F-789D95B5092C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7F1115C6-5081-4997-AC0F-789D95B5092C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7F1115C6-5081-4997-AC0F-789D95B5092C}.Release|Any CPU.Build.0 = Release|Any CPU + {AF35343B-B97C-4300-9EB4-DE753CADDC13}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AF35343B-B97C-4300-9EB4-DE753CADDC13}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AF35343B-B97C-4300-9EB4-DE753CADDC13}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AF35343B-B97C-4300-9EB4-DE753CADDC13}.Release|Any CPU.Build.0 = Release|Any CPU + {B11B8D26-FE98-4BD7-875E-D5A0801D3415}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B11B8D26-FE98-4BD7-875E-D5A0801D3415}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B11B8D26-FE98-4BD7-875E-D5A0801D3415}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B11B8D26-FE98-4BD7-875E-D5A0801D3415}.Release|Any CPU.Build.0 = Release|Any CPU + {CC5D6AA6-F58A-4B8B-A514-988BCAEA21EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CC5D6AA6-F58A-4B8B-A514-988BCAEA21EE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CC5D6AA6-F58A-4B8B-A514-988BCAEA21EE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CC5D6AA6-F58A-4B8B-A514-988BCAEA21EE}.Release|Any CPU.Build.0 = Release|Any CPU + {7820644F-8B87-4864-81B4-A8CB5859A71C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7820644F-8B87-4864-81B4-A8CB5859A71C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7820644F-8B87-4864-81B4-A8CB5859A71C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7820644F-8B87-4864-81B4-A8CB5859A71C}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution - {5F0219BE-F626-4C90-89B0-202850AE43C5} = {639FE3D4-9D7F-4823-9911-48FE49C6998F} - {21E7E61E-D9CE-48E2-B1DA-52B5FC12015A} = {639FE3D4-9D7F-4823-9911-48FE49C6998F} {CD6FED13-1984-4491-97AB-1A4361E1F582} = {DD5D7FCB-5097-433E-8399-BB037883FB2F} {8D8752AF-06C6-40CE-AA55-B454DD6808E1} = {DD5D7FCB-5097-433E-8399-BB037883FB2F} {7592E68B-CE43-4433-8B5A-F7890BAA2ABC} = {DD5D7FCB-5097-433E-8399-BB037883FB2F} + {7F1115C6-5081-4997-AC0F-789D95B5092C} = {639FE3D4-9D7F-4823-9911-48FE49C6998F} + {AF35343B-B97C-4300-9EB4-DE753CADDC13} = {639FE3D4-9D7F-4823-9911-48FE49C6998F} + {B11B8D26-FE98-4BD7-875E-D5A0801D3415} = {639FE3D4-9D7F-4823-9911-48FE49C6998F} + {CC5D6AA6-F58A-4B8B-A514-988BCAEA21EE} = {639FE3D4-9D7F-4823-9911-48FE49C6998F} + {7820644F-8B87-4864-81B4-A8CB5859A71C} = {639FE3D4-9D7F-4823-9911-48FE49C6998F} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {C0062C7F-7F87-41DC-9A63-BE15C14E7A43} diff --git a/src/csharp/DebugSession.cs b/src/csharp/DebugSession.cs index 75ffccc..c3652bc 100644 --- a/src/csharp/DebugSession.cs +++ b/src/csharp/DebugSession.cs @@ -181,6 +181,16 @@ public MeadowOutputEvent(string outpt) { } } + public class UpdateProgressBarEvent : Event + { + public UpdateProgressBarEvent(string fileName, uint percent) + : base("updateProgressBar", new { + filename = fileName, + percentage = percent + }) + { + } + } // ---- Response ------------------------------------------------------------------------- public class Capabilities : ResponseBody { diff --git a/src/csharp/Meadow/DebugSessionLogger.cs b/src/csharp/Meadow/DebugSessionLogger.cs index bd36311..fba79d7 100644 --- a/src/csharp/Meadow/DebugSessionLogger.cs +++ b/src/csharp/Meadow/DebugSessionLogger.cs @@ -1,10 +1,14 @@ using System; +using System.Threading.Tasks; using Microsoft.Extensions.Logging; namespace VsCodeMeadowUtil { public class DebugSessionLogger : ILogger { + string previousFileName = string.Empty; + uint previousPercentage = 0; + public DebugSessionLogger(Action callback) { Callback = callback; @@ -20,13 +24,35 @@ public bool IsEnabled(LogLevel logLevel) if (System.Diagnostics.Debugger.IsAttached) return true; - return logLevel == LogLevel.Information; + return logLevel >= LogLevel.Information; } public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) { - if (logLevel == LogLevel.Information || logLevel == LogLevel.Error || logLevel == LogLevel.Warning) - Callback?.Invoke(formatter(state, exception)?.Trim()); + if (IsEnabled(logLevel)) + { + Callback?.Invoke(formatter(state, exception)); + } + } + + internal async Task ReportDeviceMessage(string source, string message) + { + this.LogInformation($"{source}: {message}"); + } + + internal async Task ReportFileProgress(string fileName, uint percentage) + { + if (percentage > 0 + && percentage > 99) + { + if (!previousFileName.Equals(fileName) + || !previousPercentage.Equals(percentage)) + { + this.LogInformation($"{percentage}% of '{fileName}' Sent"); + previousFileName = fileName; + previousPercentage = percentage; + } + } } } -} +} \ No newline at end of file diff --git a/src/csharp/Meadow/MeadowDeployer.cs b/src/csharp/Meadow/MeadowDeployer.cs index b3853a7..0a955a0 100644 --- a/src/csharp/Meadow/MeadowDeployer.cs +++ b/src/csharp/Meadow/MeadowDeployer.cs @@ -1,97 +1,136 @@ using System; -using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; -using Meadow.CLI.Core; -using Meadow.CLI.Core.DeviceManagement; -using Meadow.CLI.Core.Devices; -using Meadow.CLI.Core.Internals.MeadowCommunication.ReceiveClasses; +using Meadow; +using Meadow.CLI; +using Meadow.CLI.Commands.DeviceManagement; +using Meadow.Cloud.Client; +using Meadow.Hcom; +using Meadow.Package; +using Meadow.Software; using Microsoft.Extensions.Logging; +using VSCodeDebug; namespace VsCodeMeadowUtil { public class MeadowDeployer : IDisposable { - public MeadowDeployer(ILogger logger, string serial, CancellationToken cancellationToken) + public ILogger Logger { get; private set; } + public string PortName { get; private set; } + public CancellationToken CancelToken { get; private set; } + + public MonoDebugSession DebugSession { get; private set; } + + private readonly SettingsManager settingsManager = new SettingsManager(); + private readonly MeadowConnectionManager connectionManager = null; + + IMeadowConnection meadowConnection = null; + + public MeadowDeployer(MonoDebugSession monoDebugSession, ILogger logger, string portName, CancellationToken cancellationToken) { Logger = logger; - Serial = serial; + PortName = portName; CancelToken = cancellationToken; + DebugSession = monoDebugSession; + this.connectionManager = new MeadowConnectionManager(settingsManager); } - public ILogger Logger { get; private set; } - public string Serial { get; private set; } - public CancellationToken CancelToken { get; private set; } - - MeadowDeviceHelper meadow = null; - public async void Dispose() { try { - if (meadow != null) - { - await meadow.MonoDisable(true, CancelToken); - - meadow.Dispose(); - } + await meadowConnection?.RuntimeDisable(CancelToken); } catch { - } finally { - meadow = null; + meadowConnection = null; } } - public async Task Deploy(string folder, int debugPort = -1) - { - var isDebugging = debugPort > 1000; - try - { - if (meadow == null) + public async Task Deploy(string folder, bool isDebugging) + { + if (meadowConnection != null) { - var m = await MeadowDeviceManager.GetMeadowForSerialPort(Serial, logger: Logger); - if (m == null) - throw new InvalidOperationException("Meadow device not found"); + meadowConnection.FileWriteProgress -= MeadowConnection_DeploymentProgress; + meadowConnection.DeviceMessageReceived -= MeadowConnection_DeviceMessageReceived; + meadowConnection = null; + } + + meadowConnection = connectionManager.GetConnectionForRoute(PortName); + + meadowConnection.FileWriteProgress += MeadowConnection_DeploymentProgress; + meadowConnection.DeviceMessageReceived += MeadowConnection_DeviceMessageReceived; + + await meadowConnection.WaitForMeadowAttach(); - meadow = new MeadowDeviceHelper(m, Logger); + if (await meadowConnection.IsRuntimeEnabled() == true) + { + await meadowConnection.RuntimeDisable(); } - var appPathDll = Path.Combine(folder, "App.dll"); + var deviceInfo = await meadowConnection?.GetDeviceInfo(CancelToken); + string osVersion = deviceInfo?.OsVersion; + + var fileManager = new FileManager(null); + await fileManager.Refresh(); + + var collection = fileManager.Firmware["Meadow F7"]; //wrap this is a try/catch so it doesn't crash if the developer is offline try { - string osVersion = await meadow.GetOSVersion(TimeSpan.FromSeconds(30), CancelToken); - - await new DownloadManager(Logger).DownloadOsBinaries(osVersion); + // TODO Download OS once we have a valie MeadowCloudClient } catch (Exception e) { - Logger.LogInformation($"OS download failed, make sure you have an active internet connection.{Environment.NewLine}{e.Message}"); + Logger?.LogInformation($"OS download failed, make sure you have an active internet connection.{Environment.NewLine}{e.Message}"); } - await meadow.DeployApp(appPathDll, isDebugging, CancelToken); - } - finally - { - var running = await meadow.GetMonoRunState(CancelToken); - if (!running) + try + { + var packageManager = new PackageManager(fileManager); + + Logger.LogInformation("Trimming application binaries..."); + await packageManager.TrimApplication(new FileInfo(Path.Combine(folder, "App.dll")), osVersion, isDebugging, cancellationToken: CancelToken); + + Logger.LogInformation("Deploying application..."); + await AppManager.DeployApplication(packageManager, meadowConnection, osVersion, folder, isDebugging, false, Logger, CancelToken); + + //FIXME: without this delay, the debugger will fail to connect + await Task.Delay(1500); + + await meadowConnection.RuntimeEnable(); + } + finally { - await meadow?.MonoEnable(true, CancelToken); + meadowConnection.FileWriteProgress -= MeadowConnection_DeploymentProgress; } + return meadowConnection; + } + + private async void MeadowConnection_DeviceMessageReceived(object sender, (string message, string source) e) + { + if (Logger is DebugSessionLogger logger) + { + await logger.ReportDeviceMessage(e.source, e.message); } + } - // Debugger only returns when session is done - if (isDebugging) - return await meadow.StartDebuggingSession(debugPort, CancelToken); + private async void MeadowConnection_DeploymentProgress(object sender, (string fileName, long completed, long total) e) + { + var p = (uint)((e.completed / (double)e.total) * 100d); - return null; + if (Logger is DebugSessionLogger logger) + { + await logger.ReportFileProgress(e.fileName, p); + } + + // TODO DebugSession.SendEvent(new UpdateProgressBarEvent(e.fileName, p)); } } } \ No newline at end of file diff --git a/src/csharp/Meadow/UtilRunner.cs b/src/csharp/Meadow/UtilRunner.cs index 6530a7e..aa7e968 100644 --- a/src/csharp/Meadow/UtilRunner.cs +++ b/src/csharp/Meadow/UtilRunner.cs @@ -1,19 +1,13 @@ -using Mono.Options; +using Meadow.CLI.Commands.DeviceManagement; +using Mono.Options; using System; -using System.Collections; using System.Collections.Generic; -using System.Diagnostics; -using System.IO; using System.Linq; -using System.Linq.Expressions; using System.Threading.Tasks; -using VSCodeDebug; -using Meadow.CLI.Core.DeviceManagement; -using Meadow.CLI.Core.Devices; namespace VsCodeMeadowUtil { - class UtilRunner + class UtilRunner { const string helpCommand = "help"; @@ -83,9 +77,7 @@ static object Version() static async Task> AllDevices() { - var devices = new List(); - - var ports = await MeadowDeviceManager.GetSerialPorts() ?? new List(); + var ports = await MeadowConnectionManager.GetSerialPorts() ?? new List(); return ports.Select(p => new DeviceData { Name = p, Serial = p }); } diff --git a/src/csharp/MonoDebugSession.cs b/src/csharp/MonoDebugSession.cs index fd3e296..9ce5dfd 100644 --- a/src/csharp/MonoDebugSession.cs +++ b/src/csharp/MonoDebugSession.cs @@ -10,14 +10,11 @@ using System.Net; using VsCodeMeadowUtil; using Mono.Debugging.Client; -using System.Threading.Tasks; -using Meadow.CLI.Core.DeviceManagement; -using Meadow.CLI.Core.Devices; -using Meadow.CLI.Core.Internals.MeadowCommunication.ReceiveClasses; +using Meadow.Hcom; namespace VSCodeDebug { - public class MonoDebugSession : DebugSession + public class MonoDebugSession : DebugSession { private const string MONO = "mono"; private readonly string[] MONO_EXTENSIONS = new String[] { @@ -51,6 +48,10 @@ public class MonoDebugSession : DebugSession private bool _terminated = false; private bool _stderrEOF = true; private bool _stdoutEOF = true; + CancellationTokenSource ctsDeployMeadow; + MeadowDeployer meadowDeployer; + DebuggingServer meadowDebuggingServer; + string previousLogMessage = string.Empty; public MonoDebugSession() : base() { @@ -185,10 +186,6 @@ public override void Initialize(Response response, dynamic args) SendEvent(new InitializedEvent()); } - CancellationTokenSource ctsDeployMeadow; - MeadowDeployer meadowDeployer; - DebuggingServer meadowDebuggingServer; - public override async void Launch(Response response, dynamic args) { _attachMode = false; @@ -217,25 +214,28 @@ public override async void Launch(Response response, dynamic args) var fullOutputPath = Utilities.FixPathSeparators(launchOptions.GetBuildProperty("OutputPath")); - Log("Starting to Deploy to Meadow..."); - var errorMsg = string.Empty; try { var logger = new DebugSessionLogger(l => Log(l)); + + var isDebugging = launchOptions.DebugPort > 1024; // DEPLOY - meadowDeployer = new MeadowDeployer(logger, launchOptions.Serial, ctsDeployMeadow.Token); + meadowDeployer = new MeadowDeployer(this, logger, launchOptions.Serial, ctsDeployMeadow.Token); - meadowDebuggingServer = await meadowDeployer.Deploy(fullOutputPath, launchOptions.DebugPort); + var meadowConnection = await meadowDeployer.Deploy(fullOutputPath, isDebugging); - if (meadowDebuggingServer != null) + if (isDebugging) { + var meadowDebuggingServerTask = meadowConnection.StartDebuggingSession(launchOptions.DebugPort, logger, ctsDeployMeadow.Token); + _attachMode = true; Log($"Connecting to debugger: {address}:{launchOptions.DebugPort}"); Connect(IPAddress.Loopback, launchOptions.DebugPort); + await meadowDebuggingServerTask; } SendResponse(response); @@ -250,24 +250,37 @@ public override async void Launch(Response response, dynamic args) Disconnect(response, null); Terminate("Deploy failed."); - } void Log(string message) { - Console.WriteLine(message); - - if(message.Contains("StdOut") || message.Contains("StdInfo")) - { - // This appears in the "Meadow" tab - SendEvent(new MeadowOutputEvent(message.Substring(15) + Environment.NewLine)); - } - else - { - // This appears in the "Console" tab - SendEvent(new ConsoleOutputEvent(message + Environment.NewLine)); - } - + if (previousLogMessage != message) + { + Console.WriteLine(message); + + if (message.StartsWith("stdout") || message.StartsWith("info")) + { + // This appears in blue as it is from "Meadow" + var spliter = message.Split(':'); + if (spliter.Length > 1) + { + string output = string.Empty; + + for (int i = 1; i < spliter.Length; i++) + { + output += spliter[i]; + } + SendEvent(new MeadowOutputEvent(output + Environment.NewLine)); + } + } + else + { + // This appears in yellow as it's is comming from VS + SendEvent(new ConsoleOutputEvent(message + Environment.NewLine)); + } + + previousLogMessage = message; + } } private void Connect (LaunchData options, IPAddress address, int port) @@ -904,7 +917,7 @@ private void DebuggerKill() lock (_lock) { if (_session != null) { - _debuggeeExecuting = true; + _debuggeeExecuting = false; if (!_session.HasExited) _session.Exit(); @@ -915,4 +928,4 @@ private void DebuggerKill() } } } -} +} \ No newline at end of file diff --git a/src/csharp/Program.cs b/src/csharp/Program.cs index a83a10a..1f0d109 100644 --- a/src/csharp/Program.cs +++ b/src/csharp/Program.cs @@ -130,25 +130,48 @@ private static async Task RunSession(Stream inputStream, Stream outputStream) { logFile = null; } } - private static async Task RunServer(int port) { - var serverSocket = new TcpListener(IPAddress.Parse("127.0.0.1"), port); - serverSocket.Start(); - while (true) { - var clientSocket = await serverSocket.AcceptSocketAsync(); - if (clientSocket != null) { - Program.Log(">> accepted connection from client"); + private static async Task RunServer(int port) + { + using var serverSocket = new TcpListener(IPAddress.Loopback, port); + serverSocket.Start(); - using (var networkStream = new NetworkStream(clientSocket)) { - try { - await RunSession(networkStream, networkStream); - } catch (Exception e) { - Console.Error.WriteLine("Exception: " + e); + while (true) + { + try + { + var clientSocket = await serverSocket.AcceptSocketAsync(); + if (clientSocket != null) + { + Program.Log(">> Accepted connection from client"); + + try + { + using (var networkStream = new NetworkStream(clientSocket)) + { + await RunSession(networkStream, networkStream); + } + } + catch (Exception e) + { + Console.Error.WriteLine("Exception during session:", e); + // Any other logging here? + } + finally + { + if (clientSocket.Connected) + { + clientSocket.Shutdown(SocketShutdown.Both); + } + clientSocket.Close(); + Program.Log(">> Client connection closed"); } } - - clientSocket.Close(); - Program.Log(">> client connection closed"); + } + catch (Exception e) + { + Console.Error.WriteLine("Exception in server loop:", e); + // Could handle server loop exceptions as needed (e.g., retry, log, terminate gracefully) } } } diff --git a/src/csharp/VSCodeMeadow.csproj b/src/csharp/VSCodeMeadow.csproj index ad879ce..a8af000 100644 --- a/src/csharp/VSCodeMeadow.csproj +++ b/src/csharp/VSCodeMeadow.csproj @@ -2,7 +2,7 @@ net8.0 - 8.0 + 10.0 Exe vscode-meadow @@ -13,10 +13,9 @@ - - + diff --git a/src/typescript/extension.ts b/src/typescript/extension.ts index 9ec75a4..7f2b890 100644 --- a/src/typescript/extension.ts +++ b/src/typescript/extension.ts @@ -25,25 +25,26 @@ export const isMacOS = process.platform == "darwin"; export const isLinux = process.platform == "linux"; export function activate(context: vscode.ExtensionContext) { - meadowOutputChannel = vscode.window.createOutputChannel("Meadow"); - meadowProgressBar = vscode.window.withProgress({ - location: vscode.ProgressLocation.Notification, - title:"File Transferring", - cancellable: false - }, async (progress) => { - progress.report({increment:10}); - } - ); - this.MeadowProjectManager = new MeadowProjectManager(context); this.meadowBuildTaskProvider = vscode.tasks.registerTaskProvider(MeadowBuildTaskProvider.MeadowBuildScriptType, new MeadowBuildTaskProvider(context)); - context.subscriptions.push(vscode.commands.registerCommand('extension.meadow.configureExceptions', () => configureExceptions())); + //context.subscriptions.push(vscode.commands.registerCommand('extension.meadow.configureExceptions', () => configureExceptions())); context.subscriptions.push(vscode.commands.registerCommand('extension.meadow.startSession', config => startSession(config))); + context.subscriptions.push(vscode.commands.registerCommand('updateProgressBar', (fileName: string, percent: number) => { + console.log(`updateProgressBar`); + meadowProgressBar = vscode.window.withProgress({ + location: vscode.ProgressLocation.Notification, + title: "File Transferring", + cancellable: false + }, async (progress) => { + progress.report({ increment: percent, message: `Transferring ${fileName}` }); + }); + })); + const provider = new MeadowConfigurationProvider(context); context.subscriptions.push(vscode.debug.registerDebugConfigurationProvider('meadow', provider, vscode.DebugConfigurationProviderTriggerKind.Initial | vscode.DebugConfigurationProviderTriggerKind.Dynamic)); @@ -142,7 +143,7 @@ function getModel(): ExceptionConfigurations { return model; } -function configureExceptions(): void { +/*function configureExceptions(): void { const options: vscode.QuickPickOptions = { placeHolder: localize('select.exception', "First Select Exception"), @@ -180,7 +181,7 @@ function configureExceptions(): void { }); } }); -} +}*/ function setExceptionBreakpoints(model: ExceptionConfigurations): Thenable { diff --git a/src/typescript/meadow-configuration.ts b/src/typescript/meadow-configuration.ts index e78c8dc..f103f3a 100644 --- a/src/typescript/meadow-configuration.ts +++ b/src/typescript/meadow-configuration.ts @@ -61,7 +61,7 @@ export class MeadowConfigurationProvider implements vscode.DebugConfigurationPro return undefined; } - startupInfo = MeadowProjectManager.Shared.StartupInfo; + // TODO startupInfo = MeadowProjectManager.Shared.StartupInfo; if (project) { if (!config['msbuildPropertyFile']) @@ -78,7 +78,7 @@ export class MeadowConfigurationProvider implements vscode.DebugConfigurationPro if (currentBuildConfiguration.toLowerCase() === 'debug') config['debugPort'] = startupInfo.DebugPort; - var device = startupInfo.Device; + var device = config['deviceInfo']; if (!device) { @@ -87,7 +87,7 @@ export class MeadowConfigurationProvider implements vscode.DebugConfigurationPro } if (!device) { - vscode.window.showErrorMessage("Device not selected!"); + vscode.window.showErrorMessage("Device not selected or attached!"); return undefined; } diff --git a/src/typescript/meadow-project-manager.ts b/src/typescript/meadow-project-manager.ts index d495a4e..95b48c0 100644 --- a/src/typescript/meadow-project-manager.ts +++ b/src/typescript/meadow-project-manager.ts @@ -346,6 +346,7 @@ export class MeadowProjectManager { "type": "meadow", "request": "launch", "preLaunchTask": "meadow: Build", + "deviceInfo": item }); } });