Alles verbessert

This commit is contained in:
2026-05-21 19:30:33 +02:00
parent 5dccc8985e
commit 33b71416ff
19 changed files with 855 additions and 229 deletions
+84 -65
View File
@@ -138,7 +138,7 @@
</div>
<p class="admin_copy motor_test_neutral_copy">
Das entspricht [config_drive_motor_neutral.py]: ein gemeinsamer `drive_pwm_neutral`-Wert für alle Fahrmotoren. Mit `-` und `+` sendest du den Stillstands-PWM direkt an alle Antriebe, bis wirklich alles steht.
Mit `-` und `+` stellst du den Stillstands-PWM jetzt pro Fahrmotor einzeln ein. `Speichern` schreibt alle sechs Werte dauerhaft in die `exomy.yaml`.
</p>
<div class="motor_test_neutral_toolbar">
@@ -146,22 +146,7 @@
<button id="drive_neutral_save_button" class="button buttonA" onclick="saveDriveNeutralValue()">Speichern</button>
</div>
<article class="drive_neutral_card" id="drive_neutral_card">
<div class="steering_neutral_card_header">
<span class="info_label">Drive PWM Neutral</span>
<strong>Alle Fahrmotoren</strong>
</div>
<div class="steering_neutral_value_row drive_neutral_value_row">
<button class="button buttonWarm steering_neutral_adjust" onclick="adjustDriveNeutralValue(-5)">-</button>
<strong id="drive_neutral_value" class="steering_neutral_value">-</strong>
<button class="button buttonA steering_neutral_adjust" onclick="adjustDriveNeutralValue(5)">+</button>
</div>
<div class="steering_neutral_meta">
<span id="drive_neutral_pins">Pins: -</span>
</div>
</article>
<div id="drive_neutral_grid" class="steering_neutral_grid"></div>
</div>
</section>
</div>
@@ -188,9 +173,8 @@
var activeMotorTestTab = 'impulse';
var steeringNeutralValues = {};
var steeringNeutralSavedValues = {};
var driveNeutralValue = null;
var driveNeutralSavedValue = null;
var driveNeutralPins = {};
var driveNeutralValues = {};
var driveNeutralSavedValues = {};
var STEERING_NEUTRAL_STEP = 5;
var WHEEL_ORDER = ['fl', 'fr', 'cl', 'cr', 'rl', 'rr'];
@@ -288,7 +272,7 @@
loadSteeringNeutralValues();
}
if (isDriveNeutral && driveNeutralValue === null) {
if (isDriveNeutral && !Object.keys(driveNeutralValues).length) {
loadDriveNeutralValue();
}
}
@@ -348,38 +332,59 @@
button.disabled = isNeutralLoading || isNeutralPreviewRunning || isNeutralSaving || !hasUnsavedNeutralChanges();
}
function renderDriveNeutralCard() {
var valueNode = document.getElementById('drive_neutral_value');
var pinsNode = document.getElementById('drive_neutral_pins');
var card = document.getElementById('drive_neutral_card');
if (valueNode) {
valueNode.textContent = driveNeutralValue === null ? '-' : String(driveNeutralValue);
function renderDriveNeutralCards() {
var grid = document.getElementById('drive_neutral_grid');
if (!grid) {
return;
}
if (pinsNode) {
var pinValues = WHEEL_ORDER
.filter(function (wheel) { return Object.prototype.hasOwnProperty.call(driveNeutralPins, wheel); })
.map(function (wheel) { return wheel.toUpperCase() + ':' + driveNeutralPins[wheel]; });
pinsNode.textContent = pinValues.length ? 'Pins: ' + pinValues.join(' ') : 'Pins: -';
}
var html = [];
WHEEL_ORDER.forEach(function (wheel) {
var entry = driveNeutralValues[wheel];
if (!entry) {
return;
}
if (card) {
var isDirty = driveNeutralValue !== null && driveNeutralSavedValue !== null && Number(driveNeutralValue) !== Number(driveNeutralSavedValue);
card.classList.toggle('is_dirty', isDirty);
}
var savedEntry = driveNeutralSavedValues[wheel];
var isDirty = !savedEntry || Number(savedEntry.value) !== Number(entry.value);
html.push(
'<article class="steering_neutral_card steering_neutral_card_compact' + (isDirty ? ' is_dirty' : '') + '">' +
'<div class="steering_neutral_compact_row">' +
'<div class="steering_neutral_card_header steering_neutral_card_header_compact">' +
'<strong class="steering_neutral_title">' + entry.wheel_label + '</strong>' +
'</div>' +
'<div class="steering_neutral_value_row steering_neutral_value_row_compact">' +
'<button class="button buttonWarm steering_neutral_adjust" onclick="adjustDriveNeutralValue(\'' + wheel + '\', -' + STEERING_NEUTRAL_STEP + ')">-</button>' +
'<strong class="steering_neutral_value">' + entry.value + '</strong>' +
'<button class="button buttonA steering_neutral_adjust" onclick="adjustDriveNeutralValue(\'' + wheel + '\', ' + STEERING_NEUTRAL_STEP + ')">+</button>' +
'</div>' +
'</div>' +
'</article>'
);
});
grid.innerHTML = html.join('');
updateDriveNeutralSaveButton();
}
function hasUnsavedDriveNeutralChanges() {
return WHEEL_ORDER.some(function (wheel) {
var currentEntry = driveNeutralValues[wheel];
var savedEntry = driveNeutralSavedValues[wheel];
if (!currentEntry || !savedEntry) {
return false;
}
return Number(currentEntry.value) !== Number(savedEntry.value);
});
}
function updateDriveNeutralSaveButton() {
var button = document.getElementById('drive_neutral_save_button');
if (!button) {
return;
}
var hasChanges = driveNeutralValue !== null && driveNeutralSavedValue !== null && Number(driveNeutralValue) !== Number(driveNeutralSavedValue);
button.disabled = isDriveNeutralLoading || isDriveNeutralPreviewRunning || isDriveNeutralSaving || !hasChanges;
button.disabled = isDriveNeutralLoading || isDriveNeutralPreviewRunning || isDriveNeutralSaving || !hasUnsavedDriveNeutralChanges();
}
async function fetchMotorTestStatus() {
@@ -606,7 +611,7 @@
isDriveNeutralLoading = true;
updateDriveNeutralSaveButton();
setMotorTestStatus('Lade Fahr-Neutralwert...');
setMotorTestStatus('Lade Fahr-Neutralwerte...');
try {
var response = await fetch(adminApiBase + '/api/motor-test/drive-neutral');
@@ -616,37 +621,44 @@
throw new Error(data.status || ('status ' + response.status));
}
driveNeutralValue = Number(data.drive_neutral && data.drive_neutral.value);
driveNeutralSavedValue = driveNeutralValue;
driveNeutralPins = data.drive_neutral && data.drive_neutral.pins ? data.drive_neutral.pins : {};
renderDriveNeutralCard();
driveNeutralValues = data.drive_neutral && data.drive_neutral.values ? data.drive_neutral.values : {};
driveNeutralSavedValues = JSON.parse(JSON.stringify(driveNeutralValues));
renderDriveNeutralCards();
renderContainerStatus(data);
setMotorTestStatus(data.status || 'Fahr-Neutralwert geladen');
setMotorTestStatus(data.status || 'Fahr-Neutralwerte geladen');
} catch (error) {
console.error(error);
setMotorTestStatus('Fehler');
alert(error.message || 'Der Fahr-Neutralwert konnte nicht geladen werden.');
alert(error.message || 'Die Fahr-Neutralwerte konnten nicht geladen werden.');
} finally {
isDriveNeutralLoading = false;
updateDriveNeutralSaveButton();
}
}
async function adjustDriveNeutralValue(delta) {
async function adjustDriveNeutralValue(wheel, delta) {
if (isContainerActionRunning || isMotorTestRunning || isNeutralLoading || isNeutralPreviewRunning || isNeutralSaving || isDriveNeutralLoading || isDriveNeutralPreviewRunning || isDriveNeutralSaving) {
return;
}
if (driveNeutralValue === null) {
var entry = driveNeutralValues[wheel];
if (!entry) {
return;
}
driveNeutralValue = Math.max(0, Math.min(4095, Number(driveNeutralValue) + Number(delta)));
renderDriveNeutralCard();
entry.value = Math.max(0, Math.min(4095, Number(entry.value) + Number(delta)));
renderDriveNeutralCards();
isDriveNeutralPreviewRunning = true;
updateDriveNeutralSaveButton();
setMotorTestStatus('Fahre Fahr-Neutralwert an...');
setMotorTestStatus('Fahre Fahr-Neutralwerte an...');
var values = {};
WHEEL_ORDER.forEach(function (wheelKey) {
if (driveNeutralValues[wheelKey]) {
values[wheelKey] = Number(driveNeutralValues[wheelKey].value);
}
});
try {
var response = await fetch(adminApiBase + '/api/motor-test/drive-neutral/preview', {
@@ -655,7 +667,7 @@
'Content-Type': 'application/json'
},
body: JSON.stringify({
value: driveNeutralValue
values: values
})
});
var data = await response.json();
@@ -664,10 +676,10 @@
throw new Error(data.status || ('status ' + response.status));
}
driveNeutralPins = data.drive_neutral && data.drive_neutral.pins ? data.drive_neutral.pins : driveNeutralPins;
renderDriveNeutralCard();
driveNeutralValues = data.drive_neutral && data.drive_neutral.values ? data.drive_neutral.values : driveNeutralValues;
renderDriveNeutralCards();
renderContainerStatus(data);
setMotorTestStatus(data.status || 'Fahr-Neutralwert angefahren');
setMotorTestStatus(data.status || 'Fahr-Neutralwerte angefahren');
} catch (error) {
console.error(error);
setMotorTestStatus('Fehler');
@@ -683,13 +695,21 @@
return;
}
if (driveNeutralValue === null || driveNeutralSavedValue === null || Number(driveNeutralValue) === Number(driveNeutralSavedValue)) {
if (!hasUnsavedDriveNeutralChanges()) {
return;
}
isDriveNeutralSaving = true;
updateDriveNeutralSaveButton();
setMotorTestStatus('Speichere Fahr-Neutralwert...');
setMotorTestStatus('Speichere Fahr-Neutralwerte...');
var values = {};
WHEEL_ORDER.forEach(function (wheel) {
var entry = driveNeutralValues[wheel];
if (entry) {
values[entry.key] = Number(entry.value);
}
});
try {
var response = await fetch(adminApiBase + '/api/motor-test/drive-neutral/save', {
@@ -698,7 +718,7 @@
'Content-Type': 'application/json'
},
body: JSON.stringify({
value: driveNeutralValue
values: values
})
});
var data = await response.json();
@@ -707,16 +727,15 @@
throw new Error(data.status || ('status ' + response.status));
}
driveNeutralValue = Number(data.drive_neutral && data.drive_neutral.value);
driveNeutralSavedValue = driveNeutralValue;
driveNeutralPins = data.drive_neutral && data.drive_neutral.pins ? data.drive_neutral.pins : driveNeutralPins;
renderDriveNeutralCard();
driveNeutralValues = data.drive_neutral && data.drive_neutral.values ? data.drive_neutral.values : driveNeutralValues;
driveNeutralSavedValues = JSON.parse(JSON.stringify(driveNeutralValues));
renderDriveNeutralCards();
renderContainerStatus(data);
setMotorTestStatus(data.status || 'Fahr-Neutralwert gespeichert');
setMotorTestStatus(data.status || 'Fahr-Neutralwerte gespeichert');
} catch (error) {
console.error(error);
setMotorTestStatus('Fehler');
alert(error.message || 'Der Fahr-Neutralwert konnte nicht gespeichert werden.');
alert(error.message || 'Die Fahr-Neutralwerte konnten nicht gespeichert werden.');
} finally {
isDriveNeutralSaving = false;
updateDriveNeutralSaveButton();