Skip to content

Commit 2668d32

Browse files
authored
Merge pull request #158 from OpenIPC/dev
This PR merges the latest dev branch changes into master
2 parents ab5a5cd + 9a77ec9 commit 2668d32

File tree

9 files changed

+212
-64
lines changed

9 files changed

+212
-64
lines changed

.github/workflows/gen-test-coverage-report.yml

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,6 @@ concurrency:
66

77
on:
88
workflow_dispatch:
9-
push:
10-
branches: ["master"]
11-
pull_request:
12-
branches: ["master"]
13-
release:
14-
types: [published]
159

1610
jobs:
1711
coverage:
@@ -38,11 +32,14 @@ jobs:
3832
run: dotnet workload restore
3933

4034
- name: Restore dependencies
41-
run: dotnet restore Companion.Desktop/Companion.Desktop.csproj
35+
run: dotnet restore
4236

4337
- name: Build project
4438
run: dotnet build Companion.Desktop/Companion.Desktop.csproj --configuration Release --no-restore
4539

40+
- name: Build tests
41+
run: dotnet build Companion.Tests/Companion.Tests.csproj --configuration Release --no-restore
42+
4643
- name: Run tests with coverage
4744
run: dotnet test Companion.Tests/Companion.Tests.csproj --configuration Release --no-build --verbosity normal --logger "trx" --collect:"XPlat Code Coverage"
4845

@@ -62,7 +59,7 @@ jobs:
6259
with:
6360
name: coverage
6461
path: ${{ github.workspace }}/Cobertura.xml
65-
retention-days: 3
62+
retention-days: 1
6663

6764
- name: Publish Code Coverage Report
6865
uses: irongut/CodeCoverageSummary@v1.3.0
@@ -90,7 +87,7 @@ jobs:
9087
with:
9188
name: test-results
9289
path: ${{ github.workspace }}/**/TestResults/**/*
93-
retention-days: 3
90+
retention-days: 1
9491

9592
- name: Publish Test Results
9693
if: always()
@@ -106,10 +103,3 @@ jobs:
106103
find "${{ github.workspace }}" -type f -name "*.trx" -delete || true
107104
find "${{ github.workspace }}" -type f -name "*.cobertura.xml" -delete || true
108105
rm -f "${{ github.workspace }}/Cobertura.xml" "${{ github.workspace }}/code-coverage-results.md" || true
109-
110-
- name: Prune Old Artifacts
111-
if: always() && github.event_name != 'pull_request'
112-
uses: c-hive/gha-remove-artifacts@v1
113-
with:
114-
age: '1 day'
115-
skip-recent: 2

Companion.Tests/ViewModels/FirmwareTabViewModelTests.cs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,39 @@ public void CanExecuteDownloadFirmware_ReturnsTrue_IfValidState()
143143
Assert.That(canExecute, Is.True);
144144
}
145145

146+
[Test]
147+
public void SelectedFirmwareSource_DefaultsToOpenIpcBuilder()
148+
{
149+
Assert.That(_viewModel.SelectedFirmwareSource, Is.EqualTo("OpenIPC Builder"));
150+
}
151+
152+
[Test]
153+
public void BuildFirmwareDownloadUrl_DefaultSource_UsesOpenIpcReleaseUrl()
154+
{
155+
var url = (string)InvokePrivateMethod(_viewModel, "BuildFirmwareDownloadUrl", "test-fw.tgz");
156+
Assert.That(url, Is.EqualTo("https://github.com/OpenIPC/builder/releases/download/latest/test-fw.tgz"));
157+
}
158+
159+
[Test]
160+
public void BuildFirmwareDownloadUrl_GregSource_UsesRawGithubUrl()
161+
{
162+
_viewModel.SelectedFirmwareSource = "Greg APFPV";
163+
164+
var url = (string)InvokePrivateMethod(_viewModel, "BuildFirmwareDownloadUrl", "test-fw.tgz");
165+
166+
Assert.That(url, Is.EqualTo("https://raw.githubusercontent.com/sickgreg/OpenIPC_sickgregFPV_apfpv/main/test-fw.tgz"));
167+
}
168+
169+
[Test]
170+
public void CanUseDropdowns_GregSource_ReturnsFalse()
171+
{
172+
_viewModel.CanConnect = true;
173+
_viewModel.IsConnected = true;
174+
_viewModel.SelectedFirmwareSource = "Greg APFPV";
175+
176+
Assert.That(_viewModel.CanUseDropdowns, Is.False);
177+
}
178+
146179
[Test]
147180
public void UpdateSysupgradeProgressFromLine_KernelWritingPercent_MapsToRange()
148181
{

Companion/App.axaml.cs

Lines changed: 7 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -147,29 +147,19 @@ private void UpdateExistingSettings(string configPath)
147147
existingSettings["UpdateChecker"] = new JObject(
148148
new JProperty("LatestJsonUrl", "https://github.com/OpenIPC/companion/releases/latest/download/latest.json")
149149
);
150-
150+
151151
hasChanges = true;
152-
Log.Information("Added Presets section to existing settings");
152+
Log.Information("Updated UpdateChecker settings in existing settings");
153153
}
154-
// Check if Presets section exists, add if missing
155-
if (existingSettings["Presets"] == null)
154+
else
156155
{
157-
existingSettings["Presets"] = new JObject(
158-
new JProperty("Repositories",
159-
new JArray(
160-
new JObject(
161-
new JProperty("Url", "https://github.com/OpenIPC/fpv-presets"),
162-
new JProperty("Branch", "master"),
163-
new JProperty("Description", "Official OpenIPC presets repository"),
164-
new JProperty("IsActive", true)
165-
)
166-
)
167-
)
156+
existingSettings["UpdateChecker"] = new JObject(
157+
new JProperty("LatestJsonUrl", "https://github.com/OpenIPC/companion/releases/latest/download/latest.json")
168158
);
159+
169160
hasChanges = true;
170-
Log.Information("Added Presets section to existing settings");
161+
Log.Information("Added UpdateChecker settings to existing settings");
171162
}
172-
173163
// Add more upgrade steps for other sections as needed
174164

175165
// Save changes if needed
@@ -419,20 +409,6 @@ private JObject createDefaultAppSettings()
419409
"https://github.com/OpenIPC/companion/releases/latest/download/latest.json")
420410
)
421411
),
422-
new JProperty("Presets",
423-
new JObject(
424-
new JProperty("Repositories",
425-
new JArray(
426-
new JObject(
427-
new JProperty("Url", "https://github.com/OpenIPC/fpv-presets"),
428-
new JProperty("Branch", "master"),
429-
new JProperty("Description", "Official OpenIPC presets repository"),
430-
new JProperty("IsActive", true)
431-
)
432-
)
433-
)
434-
)
435-
),
436412
new JProperty("Serilog",
437413
new JObject(
438414
new JProperty("Using", new JArray("Serilog.Sinks.Console", "Serilog.Sinks.File")),

Companion/Models/OpenIPC.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ public enum FileType
1919

2020
public const string OpenIPCBuilderGitHubApiUrl = "https://api.github.com/repos/OpenIPC/builder/releases/latest";
2121
public const string OpenIPCFirmwareGitHubApiUrl = "https://api.github.com/repos/OpenIPC/firmware/releases/latest";
22+
public const string GregApfpvContentsGitHubApiUrl =
23+
"https://api.github.com/repos/sickgreg/OpenIPC_sickgregFPV_apfpv/contents";
24+
public const string GregApfpvRawBaseUrl =
25+
"https://raw.githubusercontent.com/sickgreg/OpenIPC_sickgregFPV_apfpv/main/";
2226
public const string MajesticFileLoc = "/etc/majestic.yaml";
2327
public const string WfbConfFileLoc = "/etc/wfb.conf";
2428
public const string WfbYamlFileLoc = "/etc/wfb.yaml";

Companion/Services/UpdateChecker.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,18 @@ namespace Companion.Services;
99

1010
public class UpdateChecker
1111
{
12+
private const string DefaultLatestJsonUrl =
13+
"https://github.com/OpenIPC/companion/releases/latest/download/latest.json";
14+
1215
private readonly HttpClient _httpClient;
1316
private readonly string _latestJsonUrl;
1417

1518
public UpdateChecker(HttpClient httpClient, IConfiguration configuration)
1619
{
1720
_httpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient));
1821
_latestJsonUrl = configuration["UpdateChecker:LatestJsonUrl"];
22+
if (string.IsNullOrWhiteSpace(_latestJsonUrl))
23+
_latestJsonUrl = DefaultLatestJsonUrl;
1924
}
2025

2126

Companion/Services/WifiCardDetector.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@ public static string DetectWifiCard(string lsusbOutput)
6363
driver = "ar9271";
6464
Log.Information($"Read WiFi card: {card}, Driver: {driver}");
6565
break;
66+
case "0bda:c812":
67+
driver = "88x2cu";
68+
Log.Information($"Read WiFi card: {card}, Driver: {driver}");
69+
break;
6670
}
6771

6872
if (driver != null) break; //Stop at the first match (mimics the bash script behavior)

Companion/ViewModels/FirmwareTabViewModel.cs

Lines changed: 86 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ private enum SysupgradePhase
7979
private static readonly Regex MtdLineRegex =
8080
new(@"^(?<dev>mtd\d+):\s+(?<size>[0-9a-fA-F]+)\s+(?<erasesize>[0-9a-fA-F]+)\s+""(?<name>[^""]+)""",
8181
RegexOptions.Compiled);
82+
private const string OpenIpcFirmwareSource = "OpenIPC Builder";
83+
private const string GregApfpvFirmwareSource = "Greg APFPV";
8284
#endregion
8385

8486
#region Observable Properties
@@ -106,6 +108,7 @@ private enum SysupgradePhase
106108
[ObservableProperty] private bool _firmwareUpgradeInProgress;
107109
[ObservableProperty] private bool _isFirmwareExpanded = true;
108110
[ObservableProperty] private bool _isBootloaderExpanded;
111+
[ObservableProperty] private string _selectedFirmwareSource;
109112

110113
#endregion
111114

@@ -114,7 +117,7 @@ private enum SysupgradePhase
114117
/// <summary>
115118
/// Gets whether dropdowns should be enabled based on connection and firmware selection state
116119
/// </summary>
117-
public bool CanUseDropdowns => IsConnected;
120+
public bool CanUseDropdowns => IsConnected && !IsGregApfpvSourceSelected();
118121

119122
/// <summary>
120123
/// Gets whether soc dropdowns should be enabled based on connection and firmware selection state
@@ -147,6 +150,11 @@ private enum SysupgradePhase
147150
/// </summary>
148151
public ObservableCollection<string> FirmwareBySoc { get; set; } = new();
149152
public ObservableCollection<string> Bootloaders { get; set; } = new();
153+
public ObservableCollection<string> FirmwareSources { get; } = new()
154+
{
155+
OpenIpcFirmwareSource,
156+
GregApfpvFirmwareSource
157+
};
150158

151159
#endregion
152160

@@ -201,6 +209,7 @@ private void InitializeProperties()
201209
FirmwareUpgradeInProgress = false;
202210
IsFirmwareExpanded = true;
203211
IsBootloaderExpanded = false;
212+
SelectedFirmwareSource = OpenIpcFirmwareSource;
204213
}
205214

206215
partial void OnIsFirmwareExpandedChanged(bool value)
@@ -299,6 +308,15 @@ partial void OnSelectedFirmwareBySocChanged(string value)
299308
_bRecursionSelectGuard = false;
300309
UpdateCanExecuteCommands();
301310
}
311+
312+
partial void OnSelectedFirmwareSourceChanged(string value)
313+
{
314+
if (string.IsNullOrWhiteSpace(value) || _bRecursionSelectGuard)
315+
return;
316+
317+
ClearFirmwareSelectionsAndCollections();
318+
_ = LoadManufacturersAsync();
319+
}
302320

303321
partial void OnSelectedManufacturerChanged(string value)
304322
{
@@ -593,6 +611,30 @@ private void ClearForm()
593611
UpdateCanExecuteCommands();
594612
}
595613

614+
private void ClearFirmwareSelectionsAndCollections()
615+
{
616+
_bRecursionSelectGuard = true;
617+
618+
SelectedManufacturer = string.Empty;
619+
SelectedDevice = string.Empty;
620+
SelectedFirmware = string.Empty;
621+
SelectedFirmwareBySoc = string.Empty;
622+
ManualLocalFirmwarePackageFile = string.Empty;
623+
624+
IsLocalFirmwarePackageSelected = false;
625+
IsManufacturerDeviceFirmwareComboSelected = false;
626+
IsManualUpdateEnabled = true;
627+
IsFirmwareBySocSelected = false;
628+
629+
Manufacturers.Clear();
630+
Devices.Clear();
631+
Firmwares.Clear();
632+
FirmwareBySoc.Clear();
633+
634+
_bRecursionSelectGuard = false;
635+
UpdateCanExecuteCommands();
636+
}
637+
596638
private bool CanExecuteDownloadFirmware()
597639
{
598640
return CanConnect &&
@@ -646,7 +688,9 @@ private async Task<FirmwareData> FetchFirmwareListAsync()
646688

647689
Logger.Information($"Fetched {filenames.Count()} firmware files.");
648690

649-
FirmwareData firmwareData = ProcessFilenames(filenames);
691+
FirmwareData firmwareData = IsGregApfpvSourceSelected()
692+
? new FirmwareData { Manufacturers = new ObservableCollection<Manufacturer>() }
693+
: ProcessFilenames(filenames);
650694

651695
// Populate FirmwareBySoc
652696
PopulateFirmwareBySoc(filenames); // Calling populate method here
@@ -696,11 +740,31 @@ private void PopulateFirmwareBySoc(IEnumerable<string> filenames)
696740

697741
private async Task<IEnumerable<string>> GetFilenamesAsync()
698742
{
699-
var response = await _gitHubService.GetGitHubDataAsync(OpenIPC.OpenIPCBuilderGitHubApiUrl);
700-
var releaseData = JObject.Parse(response.ToString());
701-
var assets = releaseData["assets"];
702-
return assets?.Select(asset => asset["name"]?.ToString()).Where(name => !string.IsNullOrEmpty(name)) ??
703-
Enumerable.Empty<string>();
743+
if (IsGregApfpvSourceSelected())
744+
{
745+
var response = await _gitHubService.GetGitHubDataAsync(OpenIPC.GregApfpvContentsGitHubApiUrl);
746+
if (string.IsNullOrEmpty(response))
747+
return Enumerable.Empty<string>();
748+
749+
var items = JArray.Parse(response);
750+
return items
751+
.Where(item => item["type"]?.ToString() == "file")
752+
.Select(item => item["name"]?.ToString())
753+
.Where(name => !string.IsNullOrEmpty(name))
754+
.Select(name => name!)
755+
.Where(name => name.EndsWith(".tgz", StringComparison.OrdinalIgnoreCase));
756+
}
757+
else
758+
{
759+
var response = await _gitHubService.GetGitHubDataAsync(OpenIPC.OpenIPCBuilderGitHubApiUrl);
760+
if (string.IsNullOrEmpty(response))
761+
return Enumerable.Empty<string>();
762+
763+
var releaseData = JObject.Parse(response);
764+
var assets = releaseData["assets"];
765+
return assets?.Select(asset => asset["name"]?.ToString()).Where(name => !string.IsNullOrEmpty(name)) ??
766+
Enumerable.Empty<string>();
767+
}
704768
}
705769

706770
private async Task<IEnumerable<string>> GetBootloaderFilenamesAsync()
@@ -1385,7 +1449,7 @@ private async Task PerformFirmwareUpgradeFromSocAsync()
13851449
if (!string.IsNullOrEmpty(firmwwareFile))
13861450
{
13871451
filename = firmwwareFile;
1388-
downloadUrl = $"https://github.com/OpenIPC/builder/releases/download/latest/{firmwwareFile}";
1452+
downloadUrl = BuildFirmwareDownloadUrl(firmwwareFile);
13891453
}
13901454

13911455
else
@@ -1441,7 +1505,7 @@ private async Task PerformFirmwareUpgradeFromDropdownAsync()
14411505
!string.IsNullOrEmpty(firmware?.Name))
14421506
{
14431507
filename = firmware.PackageFile;
1444-
downloadUrl = $"https://github.com/OpenIPC/builder/releases/download/latest/{filename}";
1508+
downloadUrl = BuildFirmwareDownloadUrl(filename);
14451509
}
14461510

14471511
else
@@ -1727,6 +1791,19 @@ public async Task SelectLocalFirmwarePackage(Window window)
17271791
}
17281792
}
17291793

1794+
private bool IsGregApfpvSourceSelected()
1795+
{
1796+
return string.Equals(SelectedFirmwareSource, GregApfpvFirmwareSource, StringComparison.OrdinalIgnoreCase);
1797+
}
1798+
1799+
private string BuildFirmwareDownloadUrl(string firmwareFilename)
1800+
{
1801+
if (IsGregApfpvSourceSelected())
1802+
return $"{OpenIPC.GregApfpvRawBaseUrl}{firmwareFilename}";
1803+
1804+
return $"https://github.com/OpenIPC/builder/releases/download/latest/{firmwareFilename}";
1805+
}
1806+
17301807
#endregion
17311808
}
17321809

0 commit comments

Comments
 (0)