Skip to content

Commit

Permalink
Add configuration for Waveshare Lite Hardware
Browse files Browse the repository at this point in the history
Don't attempt to load HW whe not supported
Hardware pins are now directly loaded from the hw module
Added support for Waveshare L76B GPS module
Added support for Waveshare SX1262  module
GpsDecoder more robust against INF and NAN values
support for TWO SPI buses (but not at the same time)
PioSerial faster baudrate detection
  • Loading branch information
rvt committed Feb 7, 2025
1 parent d7fcbe8 commit ef6581b
Show file tree
Hide file tree
Showing 44 changed files with 2,568 additions and 2,348 deletions.
33 changes: 0 additions & 33 deletions OpenACE V0.0.2/OpenACE V0.0.2.kicad_pcb
Original file line number Diff line number Diff line change
Expand Up @@ -24557,39 +24557,6 @@
)
)
)
(dimension
(type aligned)
(layer "F.Cu")
(uuid "5e43da73-1987-4d03-9ce1-6dbfab2211bb")
(pts
(xy 130.429 36.195) (xy 49.53 36.195)
)
(height -8.636)
(gr_text "80.8990 mm"
(at 89.9795 43.031 0)
(layer "F.Cu")
(uuid "5e43da73-1987-4d03-9ce1-6dbfab2211bb")
(effects
(font
(size 1.5 1.5)
(thickness 0.3)
)
)
)
(format
(prefix "")
(suffix "")
(units 3)
(units_format 1)
(precision 4)
)
(style
(thickness 0.2)
(arrow_length 1.27)
(text_position_mode 0)
(extension_height 0.58642)
(extension_offset 0.5) keep_text_aligned)
)
(segment
(start 89.154 100.076)
(end 89.154 102.489)
Expand Down
5 changes: 4 additions & 1 deletion src/SystemGUI/src/components/aircraftsession.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ class AirCraftSession extends El {
let idx = e.currentTarget.selectedIndex;
let aircraftId = store.state.aircrafts[idx].callSign;
if (aircraftId === store.state.aircraftId) return;
this.changed(aircraftId);
// Call the assigned function to update the aircraft
if (aircraftId) {
this.changed(aircraftId);
}
}

render(html) {
Expand Down
85 changes: 75 additions & 10 deletions src/SystemGUI/src/components/modules.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ class OpenAceModules extends El {
selectedModule: 0,
enabled: [],
restartDlg: false,
changeHwDlg : false,
});

// All modules that can be monitored (Some time we should automated this by reading this from the Micocontroller)
this.monitorable = [
"ADSL",
Expand All @@ -26,6 +28,7 @@ class OpenAceModules extends El {
"Sx1262_0",
"Sx1262_1",
"UbloxM8N",
"L76B",
"ADSBDecoder",
"Dump1090Client",
"Bmp280",
Expand All @@ -35,7 +38,7 @@ class OpenAceModules extends El {
"DataPort",
"AirConnect",
"Bluetooth",
"Webserver"
"Webserver",
];
this.configurable = ["WifiService", "ADSBDecoder", "GDLoverUDP", "Dump1090Client", "Bmp280", "Sx1262_0", "Sx1262_1", "Bluetooth"];
this.enablers = [
Expand All @@ -51,11 +54,12 @@ class OpenAceModules extends El {
"Sx1262_1",
"Sx1262_0",
"UbloxM8N",
"L76B",
"RadioTunerRx",
"RadioTunerTx",
"DataPort",
"AirConnect",
"Bluetooth"
"Bluetooth",
];
this.info = {
WifiService: (html) =>
Expand All @@ -79,7 +83,8 @@ class OpenAceModules extends El {
AceSpi: (html) => html`Core module for controlling SPI access between different modules.`,
Config: (html) => html`Core module for receiving and storing configurations.`,
GpsDecoder: (html) => html`Core module for decoding GPS NMEA messages.`,
UbloxM8N: (html) => html`Configures uBlox8 or similar hardware devices.`,
UbloxM8N: (html) => html`Configures uBlox GPS devices`,
L76B: (html) => html`Configures L76B GPS devices`,
PicoRtc: (html) => html`Reads GPS messages and handles accurate time tracking for various protocols.`,
Sx1262_0: (html) => html`Radio module 1. Sends and receives ADS-L, OGN, and Flarm protocols.`,
Sx1262_1: (html) => html`Radio module 2. Sends and receives ADS-L, OGN, and Flarm protocols.`,
Expand All @@ -90,6 +95,7 @@ class OpenAceModules extends El {

mounted() {
this._running = false;
this._newHwIdx = 0;
this._fetchData();
}

Expand All @@ -109,8 +115,11 @@ class OpenAceModules extends El {
}

_restartButton(html) {
return html`<button class="btn xs" onclick=${() => (this.state.restartDlg = true)}>Restart</button>`;
return html`<button class="btn xs" onclick=${() => (this.state.restartDlg = true)}>Restart</button>
${this.state.restartDlg ? this._restartAreYouSureDlg(html) : ""} ${this.state.usbBootDlg ? this._usbBootDlgAreYouSureDlg(html) : ""}
`;
}

_usbBootButton(html) {
return html`<button class="btn xs" onclick=${() => (this.state.usbBootDlg = true)}>Upload Firmware</button>`;
}
Expand Down Expand Up @@ -165,6 +174,43 @@ class OpenAceModules extends El {
</div>`;
}

_changeHwButton(html) {
return html`<button class="btn xs" onclick=${() => (this.state.changeHwDlg = true)}>Change Board : ${store.state.hardwareName}</button>
${this.state.changeHwDlg === true ? this._changeHardwareDialog(html) : ""}
`;
}

_changeHardwareDialog(html) {
return html` <div class="modal show">
<div class="modal-content mw-400 rounded">
<article class="accent-light shadow">
<header>
<h4>Change hardware model?</h4>
</header>
<div class="overflow-auto accent-primary" style="color: black">
<!-- Quick hack to make text black on Safari Desktop -->
<p>
This will change the type of board that OpenAce is running on.
After changing the connection will be temporary disconnected.
Any unsaved data will be available after restart.<br />
</p>
<select onchange=${ e => this._selectedHwIndx = e.currentTarget.selectedIndex}>
${store.availableHardware.map(
(item) => html`<option ${item.hardware === store.state?.hardware?.type ? "selected" : ""} value="${item.hardware}">${item.name}</option>`,
)}
</select>
</div>
<footer class="px-2 jc-end">
<button type="button" class="btn btn-error sm ml-1 md-ml-3" onclick=${this._hardwareUpdatedConfirm}>Change</button>
<button type="button" class="btn btn-primary sm ml-1 md-ml-3" onclick=${() => (this.state.changeHwDlg = false)}>Cancel</button>
</footer>
</article>
</div>
</div>`;
}

_postConstructToString(value) {
const errorMap = {
0: "Never Loaded",
Expand All @@ -180,6 +226,7 @@ class OpenAceModules extends El {
10: "Configuration error",
11: "Timer error",
12: "Mutex error",
13: "Not Available",
};
return errorMap[value] || "Unknown error";
}
Expand Down Expand Up @@ -249,6 +296,17 @@ class OpenAceModules extends El {
`;
}

async _hardwareUpdatedConfirm(e)
{
if (this._selectedHwIndx > 0) {
this.state.changeHwDlg = true;
await store.updateHardware(this._selectedHwIndx);
this._selectedHwIndx = 0;
store.restart();
}
this.state.changeHwDlg = false;
}

_row(html, item) {
let monitorBtn =
item.poststatus == 1 && this.monitorable.includes(item.name)
Expand Down Expand Up @@ -288,11 +346,7 @@ class OpenAceModules extends El {
_showModuleOverview(html) {
let items = this._filteredItems();
return html`
<div class="grid md-columns-2 lg-columns-3 ">
<div>${this._restartButton(html)}</div>
<div>${this._usbBootButton(html)}</div>
</div>
${this.state.restartDlg ? this._restartAreYouSureDlg(html) : ""} ${this.state.usbBootDlg ? this._usbBootDlgAreYouSureDlg(html) : ""}
<div class="section">
<table>
<tbody>
Expand All @@ -303,11 +357,22 @@ class OpenAceModules extends El {
`;
}

_showHeader(html) {
let items = this._filteredItems();
return html`
<div class="row md-columns-2 lg-columns-3" style="margin-top: 5px">
<div>${this._restartButton(html)}</div>
<div>${this._usbBootButton(html)}</div>
<div>${this._changeHwButton(html)}</div>
</div>
`;
}

render(html) {
let pageContent;
switch (this.state.whatToShow) {
case "modules":
pageContent = this._showModuleOverview(html);
pageContent = this._showHeader(html) + this._showModuleOverview(html);
break;
case "monitor":
pageContent = this._showModuleStatus(html);
Expand Down
77 changes: 53 additions & 24 deletions src/SystemGUI/src/components/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@ import { El } from "@frameable/el";
let instance;

export class OpenAceStore {
availableHardware = [{name: "-", hardware:"-"}, {name: "OpenAce Board", hardware:"PICO_2RADIO"}, {name: "Waveshare Lite", hardware:"WAVESHARE_LITE"}];

constructor() {
if (instance) {
throw new Error("New instance cannot be created!!");
}


instance = this;

this.state = El.observable({
Expand All @@ -19,6 +22,8 @@ export class OpenAceStore {
aircrafts: [],
numberOfAircrafts: 0,
configModified: false,
hardware: {},
hardwareName: ""
});
}

Expand All @@ -42,29 +47,30 @@ export class OpenAceStore {
*
* @returns
*/
init() {
return this.fetch("/api/_Configuration/config.json")
.then((data) => {
this.state.aircraftId = data.aircraftId;
this.state.configModified = data._dirty;
return this.state.aircraftId;
})
.then((aircraftId) => {
this.fetch(`/api/_Configuration/aircraft.json`).then((data) => {
Object.assign(this.state.aircraftsObj, data);
this._updateAircraftArray();

// Validate if the configured aircraft exists in the array
if (data[this.state.aircraftId] === undefined) {
if (this.state.aircrafts.length > 0) {
return this.setDefaultAirCraftId(this.state.aircrafts[0].callSign);
} else {
this.state.aircraftId = "";
}
}
return data;
});
});
async init() {
// Fetch config.json
const configData = await this.fetch("/api/_Configuration/config.json");
this.state.aircraftId = configData.aircraftId;
this.state.configModified = configData._dirty;

// Fetch aircraft.json
const aircraftData = await this.fetch("/api/_Configuration/aircraft.json");
Object.assign(this.state.aircraftsObj, aircraftData);
this._updateAircraftArray();

// Validate if the configured aircraft exists
if (aircraftData[this.state.aircraftId] === undefined) {
if (this.state.aircrafts.length > 0) {
await this.setDefaultAirCraftId(this.state.aircrafts[0].callSign);
} else {
this.state.aircraftId = "";
}
}

// Fetch hardware.json
const hardwareData = await this.fetch("/api/_Configuration/hardware.json");
Object.assign(this.state.hardware, hardwareData);
this.state.hardwareName = this.availableHardware.find(d => d.hardware === hardwareData.type)?.name;
}

/**
Expand Down Expand Up @@ -108,6 +114,26 @@ export class OpenAceStore {
});
}

/**
* Update the type of board this is running on
* @param {*} type
* @returns
*/
updateHardware(typeIdx) {
const type = this.availableHardware[typeIdx].hardware;
this.state.hardwareName = this.availableHardware[typeIdx].name;
return this.fetch(`/api/_Configuration/hardware.json`, {
method: "POST",
headers: {
"X-Method": "POST",
},
body: JSON.stringify({type}),
}).then((data) => {
this.state.hardware.type = type;
return data;
});
}

/**
* Set the default aircraft ID in the config path
*
Expand Down Expand Up @@ -177,7 +203,7 @@ export class OpenAceStore {
fetch(path, requestOptions) {
return fetch(path, {
...requestOptions,
signal: AbortSignal.timeout(2500),
signal: AbortSignal.timeout(5500),
})
.then((response) => {
if (path.includes("SaveBR.json")) {
Expand All @@ -191,6 +217,9 @@ export class OpenAceStore {
this.state.connected = true;
return response.json();
})
.then((data) => {
return new Promise((resolve) => setTimeout(() => resolve(data), 10)); // Delay to not overload the PICO
})
.catch((e) => {
this.state.connected = false;
throw new Error(e);
Expand Down
2 changes: 1 addition & 1 deletion src/SystemGUI/src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
// Have to set this with a timeout or else the drop down does not appear on the right aircraft
setTimeout(() => {
// Default page to open
store.state.page = "session";
store.state.page = "modules";
}, 50);
});
}
Expand Down
2 changes: 1 addition & 1 deletion src/lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ add_subdirectory(aircrafttracker)
add_subdirectory(gpsdecoder)
add_subdirectory(rtc)
add_subdirectory(dump1090Client)
add_subdirectory(ubloxm8n)
add_subdirectory(gps)
add_subdirectory(serialadsb)
add_subdirectory(wifiservice)
add_subdirectory(webserver)
Expand Down
Loading

0 comments on commit ef6581b

Please sign in to comment.