320 lines
8.3 KiB
C++
320 lines
8.3 KiB
C++
#include <Arduino.h>
|
||
#include "UI.h"
|
||
|
||
// Local UI control
|
||
static uint16_t portInput;
|
||
|
||
// -------------------------------
|
||
// Calibration UI helpers & callbacks
|
||
// -------------------------------
|
||
void refreshCalibrationUI() {
|
||
for (int i = 0; i < 5; i++) {
|
||
ESPUI.updateControlValue(calInputs[i], String(calibratedPoints[selectedCalChannel][i], 2));
|
||
}
|
||
}
|
||
|
||
void calChannelCallback(Control *sender, int type) {
|
||
// Turn override OFF when switching channels
|
||
for (int ch = 0; ch < NUM_CHANNELS; ch++) {
|
||
overrideActive[ch] = false;
|
||
}
|
||
ESPUI.updateControlValue(calOverrideSwitch, "0");
|
||
|
||
selectedCalChannel = sender->value.toInt();
|
||
Serial.print("Calibration channel changed to ");
|
||
Serial.println(selectedCalChannel);
|
||
|
||
refreshCalibrationUI();
|
||
}
|
||
|
||
void calPointCallback(Control *sender, int type) {
|
||
int index = sender->id - calInputs[0];
|
||
if (index >= 0 && index < 5) {
|
||
float val = sender->value.toFloat();
|
||
calibratedPoints[selectedCalChannel][index] = val;
|
||
Serial.printf("Cal[%d][%d] = %.2f\n", selectedCalChannel, index, val);
|
||
}
|
||
}
|
||
|
||
void calTestCallback(Control *sender, int type) {
|
||
if (!overrideActive[selectedCalChannel]) return;
|
||
|
||
float logical = sender->value.toFloat(); // 0–100 integer
|
||
|
||
if (logical < 0) logical = 0;
|
||
if (logical > 100) logical = 100;
|
||
|
||
float calibrated = applyCalibration(selectedCalChannel, logical);
|
||
int duty = (int)((calibrated / 100.0f) * ((1 << pwmResolution) - 1));
|
||
|
||
ledcWrite(pwmPins[selectedCalChannel], duty);
|
||
|
||
Serial.printf("Override update CH%d: logical=%.2f calibrated=%.2f duty=%d\n",
|
||
selectedCalChannel, logical, calibrated, duty);
|
||
}
|
||
|
||
void calSaveCallback(Control *sender, int type) {
|
||
Serial.printf("Saving calibration for CH%d...\n", selectedCalChannel);
|
||
|
||
for (int i = 0; i < 5; i++) {
|
||
String key = "cal_" + String(selectedCalChannel) + "_" + String(i);
|
||
prefs.putFloat(key.c_str(), calibratedPoints[selectedCalChannel][i]);
|
||
}
|
||
|
||
Serial.println("Calibration saved.");
|
||
}
|
||
|
||
void calOverrideSwitchCallback(Control *sender, int type) {
|
||
bool enabled = sender->value.toInt() == 1;
|
||
|
||
if (enabled) {
|
||
Serial.println("Override enabled.");
|
||
|
||
// Enable override only for the selected channel
|
||
for (int ch = 0; ch < NUM_CHANNELS; ch++) {
|
||
overrideActive[ch] = (ch == selectedCalChannel);
|
||
}
|
||
|
||
// Immediately apply the test value
|
||
float logical = ESPUI.getControl(calTestValueInput)->value.toFloat();
|
||
if (logical < 0) logical = 0;
|
||
if (logical > 100) logical = 100;
|
||
|
||
float calibrated = applyCalibration(selectedCalChannel, logical);
|
||
int duty = (int)((calibrated / 100.0f) * ((1 << pwmResolution) - 1));
|
||
ledcWrite(pwmPins[selectedCalChannel], duty);
|
||
|
||
Serial.printf("Override driving CH%d: logical=%.2f calibrated=%.2f duty=%d\n",
|
||
selectedCalChannel, logical, calibrated, duty);
|
||
|
||
} else {
|
||
Serial.println("Override disabled. Returning to UDP control.");
|
||
|
||
// Disable all overrides
|
||
for (int ch = 0; ch < NUM_CHANNELS; ch++) {
|
||
overrideActive[ch] = false;
|
||
}
|
||
}
|
||
}
|
||
|
||
// -------------------------------
|
||
// UI init
|
||
// -------------------------------
|
||
void uiInit(uint16_t& tabSettings, uint16_t& tabLighting, uint16_t& tabCalibration) {
|
||
|
||
// Create tabs
|
||
tabSettings = ESPUI.addControl(ControlType::Tab, "Settings", "Settings");
|
||
tabLighting = ESPUI.addControl(ControlType::Tab, "Lighting", "Lighting");
|
||
tabCalibration= ESPUI.addControl(ControlType::Tab, "Calibration", "Calibration");
|
||
|
||
// Restart button callback
|
||
auto restartCallback = [](Control *sender, int type) {
|
||
ESP.restart();
|
||
};
|
||
|
||
// Port input callback
|
||
auto portInputCallback = [](Control *sender, int type) {
|
||
Serial.print("Port input changed to: ");
|
||
Serial.println(sender->value);
|
||
};
|
||
|
||
// Save & Apply callback
|
||
auto savePortCallback = [](Control *sender, int type) {
|
||
if (type != B_UP) return; // Prevent double-trigger
|
||
|
||
Control* c = ESPUI.getControl(portInput);
|
||
int newPort = c->value.toInt();
|
||
|
||
if (newPort < 1024 || newPort > 65535) {
|
||
Serial.println("Invalid port (1024–65535)");
|
||
return;
|
||
}
|
||
|
||
prefs.putInt("udpPort", newPort);
|
||
udpPort = newPort;
|
||
|
||
udp.stop();
|
||
udp.begin(udpPort);
|
||
|
||
Serial.print("New UDP port applied: ");
|
||
Serial.println(udpPort);
|
||
|
||
ESPUI.updateControlValue(portInput, String(newPort));
|
||
};
|
||
|
||
// -------------------------------------------
|
||
// Connection Status section
|
||
// -------------------------------------------
|
||
ESPUI.addControl(
|
||
ControlType::Separator,
|
||
"Connection Status",
|
||
"",
|
||
ControlColor::None,
|
||
tabSettings
|
||
);
|
||
|
||
// Live-updating connection status label
|
||
connectionStatusLabel = ESPUI.addControl(
|
||
ControlType::Label,
|
||
"Status",
|
||
"Disconnected",
|
||
ControlColor::Wetasphalt,
|
||
tabSettings
|
||
);
|
||
|
||
// -------------------------------------------
|
||
// UDP Telemetry Connection Settings section
|
||
// -------------------------------------------
|
||
|
||
ESPUI.addControl(
|
||
ControlType::Separator,
|
||
"UDP Telemetry Connection Settings",
|
||
"",
|
||
ControlColor::None,
|
||
tabSettings
|
||
);
|
||
|
||
// UDP Port Number input
|
||
portInput = ESPUI.addControl(
|
||
ControlType::Number,
|
||
"UDP Port",
|
||
String(udpPort),
|
||
ControlColor::Peterriver,
|
||
tabSettings,
|
||
portInputCallback
|
||
);
|
||
|
||
// Save & Apply button
|
||
ESPUI.addControl(
|
||
ControlType::Button,
|
||
"UDP Port",
|
||
"Save & Apply",
|
||
ControlColor::Emerald,
|
||
tabSettings,
|
||
savePortCallback
|
||
);
|
||
|
||
// Existing separator (leave as-is)
|
||
ESPUI.addControl(
|
||
ControlType::Separator,
|
||
"",
|
||
"",
|
||
ControlColor::None,
|
||
tabSettings
|
||
);
|
||
|
||
// Restart button (unchanged)
|
||
ESPUI.addControl(
|
||
ControlType::Button,
|
||
"Restart ESP32",
|
||
"Restart",
|
||
ControlColor::Alizarin,
|
||
tabSettings,
|
||
restartCallback
|
||
);
|
||
|
||
// Lighting tab placeholder
|
||
ESPUI.addControl(
|
||
ControlType::Label,
|
||
"Lighting Placeholder",
|
||
"Coming soon...",
|
||
ControlColor::Emerald,
|
||
tabLighting
|
||
);
|
||
|
||
// -------------------------------
|
||
// Calibration tab UI
|
||
// -------------------------------
|
||
|
||
// Channel selector
|
||
calChannelDropdown = ESPUI.addControl(
|
||
ControlType::Select,
|
||
"Selected Channel",
|
||
"0",
|
||
ControlColor::Peterriver,
|
||
tabCalibration,
|
||
calChannelCallback
|
||
);
|
||
|
||
// Add options 0–7
|
||
for (int i = 0; i < NUM_CHANNELS; i++) {
|
||
char value[8];
|
||
snprintf(value, sizeof(value), "%d", i);
|
||
|
||
ESPUI.addControl(
|
||
ControlType::Option,
|
||
channelDropdownLabels[i], // static label
|
||
value, // static-ish value (OK)
|
||
ControlColor::None,
|
||
calChannelDropdown
|
||
);
|
||
}
|
||
|
||
ESPUI.addControl(
|
||
ControlType::Separator,
|
||
"",
|
||
"",
|
||
ControlColor::None,
|
||
tabCalibration
|
||
);
|
||
|
||
// Calibration inputs
|
||
const char* calNames[5] = {"0%", "25%", "50%", "75%", "100%"};
|
||
|
||
for (int i = 0; i < 5; i++) {
|
||
calInputs[i] = ESPUI.addControl(
|
||
ControlType::Number,
|
||
calNames[i],
|
||
String(calibratedPoints[0][i], 2),
|
||
ControlColor::Wetasphalt,
|
||
tabCalibration,
|
||
calPointCallback
|
||
);
|
||
}
|
||
|
||
ESPUI.addControl(
|
||
ControlType::Separator,
|
||
"",
|
||
"",
|
||
ControlColor::None,
|
||
tabCalibration
|
||
);
|
||
|
||
// Test value input
|
||
calTestValueInput = ESPUI.addControl(
|
||
ControlType::Slider,
|
||
"Test Value",
|
||
"50",
|
||
ControlColor::Carrot,
|
||
tabCalibration,
|
||
calTestCallback
|
||
);
|
||
|
||
calOverrideSwitch = ESPUI.addControl(
|
||
ControlType::Switcher,
|
||
"Override",
|
||
"0", // default OFF
|
||
ControlColor::Alizarin,
|
||
tabCalibration,
|
||
calOverrideSwitchCallback
|
||
);
|
||
|
||
ESPUI.addControl(
|
||
ControlType::Separator,
|
||
"",
|
||
"",
|
||
ControlColor::None,
|
||
tabCalibration
|
||
);
|
||
|
||
// Save button
|
||
calSaveButton = ESPUI.addControl(
|
||
ControlType::Button,
|
||
"Save Calibration",
|
||
"Save",
|
||
ControlColor::Emerald,
|
||
tabCalibration,
|
||
calSaveCallback
|
||
);
|
||
}
|