Skip to content

Commit

Permalink
Merge pull request #303 from openppg/new-webusb
Browse files Browse the repository at this point in the history
New SP140 webusb sync commands
  • Loading branch information
zjwhitehead authored Dec 23, 2024
2 parents 260e5ff + f5544b0 commit 0caf543
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 37 deletions.
131 changes: 108 additions & 23 deletions assets/js/configurator/sp140.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

document.addEventListener('DOMContentLoaded', () => {
let connectButton = document.querySelector('#connect');
let syncButton = document.querySelector('#sync');
let statusDisplay = document.querySelector('#status');
let port;

Expand Down Expand Up @@ -66,10 +67,27 @@
let textDecoder = new TextDecoder();
var usb_input = textDecoder.decode(data);
if (usb_input.length < 5) { return }
var usb_parsed = JSON.parse(usb_input); // TODO figure out why empty data is sent
updateFormFromSync(usb_parsed);
Rollbar.info('Synced-SP140', usb_parsed);

// Split the input on newlines and process each valid JSON object
usb_input.split('\n').forEach(jsonStr => {
try {
if (jsonStr.trim().length > 0) {
var usb_parsed = JSON.parse(jsonStr);

// Update the form with the received data
updateFormFromSync(usb_parsed);

// Request the next chunk of data if available
requestNextChunk();

Rollbar.info('Synced-SP140', usb_parsed);
}
} catch (e) {
console.warn('Failed to parse JSON:', e, jsonStr);
}
});
};

port.onReceiveError = error => {
Rollbar.warn(error);
console.error(error);
Expand All @@ -83,30 +101,43 @@
// Update the page from received data
function updateFormFromSync(usb_parsed){
console.log('raw', usb_parsed);
if (usesNewMapping(usb_parsed)){
if (usesNewMapping(usb_parsed)) {
usb_parsed = migrateUsbData(usb_parsed);
console.log('parsed', usb_parsed);
}
else{
} else if (usb_parsed.major_v !== undefined && !usb_parsed.arch) {
// Only set SAMD21 as default during initial sync AND when no arch is specified
usb_parsed.arch = 'SAMD21';
}
usb_parsed = sanitizeUsbData(usb_parsed);
console.log('sanitized', usb_parsed);

$('#armedTime').text(displayTime(usb_parsed.armed_time));
$('#deviceId').text(usb_parsed.device_id);
$('#deviceArch').text(usb_parsed.arch);
$('#versionMajor').text(usb_parsed.major_v);
$('#versionMinor').text(usb_parsed.minor_v);
$('#deviceRev').text(usb_parsed.revision);
$('#orientation-lh').prop('checked', usb_parsed.screen_rot == 3);
$('#orientation-rh').prop('checked', usb_parsed.screen_rot == 1);
$('#units-alt').prop('checked', usb_parsed.metric_alt);
$('#seaPressureInput').val(usb_parsed.sea_pressure);
$('#performance-chill').prop('checked', usb_parsed.performance_mode == 0);
$('#performance-sport').prop('checked', usb_parsed.performance_mode == 1);
$('#theme-light').prop('checked', usb_parsed.theme == 0);
$('#theme-dark').prop('checked', usb_parsed.theme == 1);
// Version and architecture info (from initial sync)
if (usb_parsed.major_v !== undefined) $('#versionMajor').text(usb_parsed.major_v);
if (usb_parsed.minor_v !== undefined) $('#versionMinor').text(usb_parsed.minor_v);
if (usb_parsed.device_id !== undefined) $('#deviceId').text(usb_parsed.device_id);
if (usb_parsed.id !== undefined) $('#deviceId').text(usb_parsed.id);
if (usb_parsed.arch !== undefined) $('#deviceArch').text(usb_parsed.arch);

// Units settings
if (usb_parsed.metric_alt !== undefined) $('#units-alt').prop('checked', usb_parsed.metric_alt);
if (usb_parsed.sea_pressure !== undefined) $('#seaPressureInput').val(usb_parsed.sea_pressure);
if (usb_parsed.armed_time !== undefined) $('#armedTime').text(displayTime(usb_parsed.armed_time));

// Display settings
if (usb_parsed.screen_rot !== undefined) {
$('#orientation-lh').prop('checked', usb_parsed.screen_rot == 3);
$('#orientation-rh').prop('checked', usb_parsed.screen_rot == 1);
}
if (usb_parsed.theme !== undefined) {
$('#theme-light').prop('checked', usb_parsed.theme == 0);
$('#theme-dark').prop('checked', usb_parsed.theme == 1);
}

// Performance settings
if (usb_parsed.performance_mode !== undefined) {
$('#performance-chill').prop('checked', usb_parsed.performance_mode == 0);
$('#performance-sport').prop('checked', usb_parsed.performance_mode == 1);
}
}

// migrate new data to old mappings
Expand All @@ -133,9 +164,16 @@

// clean up string numbers to be numbers
function sanitizeUsbData(usb_parsed){
usb_parsed.screen_rot = parseInt(usb_parsed.screen_rot);
usb_parsed.performance_mode = parseInt(usb_parsed.performance_mode);
usb_parsed.theme = parseInt(usb_parsed.theme);
// Only sanitize values that exist
if (usb_parsed.screen_rot !== undefined) {
usb_parsed.screen_rot = parseInt(usb_parsed.screen_rot);
}
if (usb_parsed.performance_mode !== undefined) {
usb_parsed.performance_mode = parseInt(usb_parsed.performance_mode);
}
if (usb_parsed.theme !== undefined) {
usb_parsed.theme = parseInt(usb_parsed.theme);
}
return usb_parsed;
}

Expand Down Expand Up @@ -187,6 +225,7 @@
port.disconnect();
$('#frm-config :input').prop('disabled', true);
$('button#bl').prop('disabled', true);
syncButton.disabled = true;
connectButton.textContent = 'Connect';
statusDisplay.textContent = '';
port = null;
Expand All @@ -196,11 +235,57 @@
port.send(new TextEncoder('utf-8').encode(JSON.stringify(usb_json)));
}

let lastSyncTime = 0;
const SYNC_COOLDOWN = 2000; // 2 seconds in milliseconds

const DATA_CHUNKS = ['get_units', 'get_disp', 'get_perf', 'get_id'];
let currentChunkIndex = 0;

function sendSyncCommand() {
const now = Date.now();
if (now - lastSyncTime < SYNC_COOLDOWN) {
console.log('Sync cooldown active, please wait');
return;
}

// Reset the chunk index when starting a new sync
currentChunkIndex = 0;

// Start with basic sync command (gets version and arch)
let sync_command_json = { 'command': 'sync' };
console.log('sending', sync_command_json);
sendJSON(sync_command_json);
lastSyncTime = now;

// Visually disable the button
syncButton.disabled = true;
setTimeout(() => {
syncButton.disabled = false;
}, SYNC_COOLDOWN);
}

function requestNextChunk() {
if (currentChunkIndex < DATA_CHUNKS.length) {
let command_json = { 'command': DATA_CHUNKS[currentChunkIndex] };
console.log('sending chunk request', command_json);
sendJSON(command_json);
currentChunkIndex++;
}
}

function didConnect() {
statusDisplay.textContent = '';
connectButton.textContent = 'Disconnect';
$('#frm-config :input').prop('disabled', false);
$('button#bl').prop('disabled', false);
syncButton.disabled = false;

sendSyncCommand();
}

// Add sync button click handler
syncButton.addEventListener('click', function() {
sendSyncCommand();
});
});
})();
25 changes: 11 additions & 14 deletions content/configurators/sp140.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

<div class="connect-container">
<button id="connect" class="btn btn-primary btn-lg">Connect</button>
<button id="sync" class="btn btn-secondary btn-lg" disabled>Refresh</button>
<span id="status"></span>
</div>

Expand Down Expand Up @@ -112,16 +113,12 @@ <h5>Performance Mode</h5>
<code><span id="deviceId"></span></code>
</p>

<p class="mb-1">
<strong>Device Architecture: </strong>
<code><span id="deviceArch"></span></code>
</p>

<p class="mb-1">
<strong>Hardware Revision: </strong>
<code><span id="deviceRev"></span></code>
</p>

<!--
<p class="mb-1">
<strong>Hardware Revision: </strong>
<code><span id="deviceRev"></span></code>
</p>
-->
<p class="mb-1">
<strong>Firmware Version: </strong>
<code><span id="versionMajor"></span>.<span id="versionMinor"></span></code>
Expand All @@ -135,13 +132,13 @@ <h5>Performance Mode</h5>
<div class="card card-body bg-light">
<h4 class="card-title mt-0">Upgrades </h4>
<small class="text-muted">New firmware can add features and improve functionality.</small>
<h5>Latest SP140 firmware (6.4)</h5>
<span><a href="https://github.com/openppg/eppg-controller/releases/tag/v6.4" target="_blank">Release notes <i class="fas fa-info-circle"></i></a></span>
<h5>Latest SP140 firmware (6.5)</h5>
<span><a href="https://github.com/openppg/eppg-controller/releases/tag/v6.5" target="_blank">Release notes <i class="fas fa-info-circle"></i></a></span>
<div class="row mb-4">
<div class="col-md-5 mb-2">
RP2040 <br />
<a href="https://github.com/openppg/eppg-controller/releases/download/v6.4/OpenPPG-CRP2040-SP140.uf2" target="_blank">
<i class="fas fa-download"></i> (6.4R)
<a href="https://github.com/openppg/eppg-controller/releases/download/v6.5/OpenPPG-CRP2040-SP140.uf2" target="_blank">
<i class="fas fa-download"></i> (6.5R)
</a>
</div>
<div class="col-md-5 mb-2">
Expand Down

0 comments on commit 0caf543

Please sign in to comment.