22 html +=
"<div class='container'>";
24 html +=
"<h1>⚙️ Калибровка датчика</h1>";
25 html +=
"<p>Здесь вы сможете выполнить калибровку датчика и настроить компенсацию показаний.";
26 html +=
" В этой версии доступен выбор профиля почвы и загрузка калибровочных таблиц (CSV).</p>";
29 html +=
"<form action='/calibration/save' method='post' enctype='multipart/form-data'>";
30 html +=
"<div class='section'><h2>Профиль почвы</h2>";
31 html +=
"<div class='form-group'><label for='soil_profile'>Тип почвы:</label><select id='soil_profile' name='soil_profile'>";
32 html +=
"<option value='sand'>Песок</option>";
33 html +=
"<option value='sandpeat'>Песчано-торфяной</option>";
34 html +=
"<option value='loam'>Суглинок</option>";
35 html +=
"<option value='peat'>Торф</option>";
36 html +=
"<option value='clay'>Глина</option>";
37 html +=
"</select></div></div>";
40 html +=
"<div class='section'><h2>Калибровочная таблица";
47 html +=
" <span style='font-size:14px;color:#888'>(";
48 html +=
"Песок:" + String(hasSand?
"✅":
"❌") +
", ";
49 html +=
"Песч.-торф:" + String(hasSandPeat?
"✅":
"❌") +
", ";
50 html +=
"Суглинок:" + String(hasLoam?
"✅":
"❌") +
", ";
51 html +=
"Глина:" + String(hasClay?
"✅":
"❌") +
", ";
52 html +=
"Торф:" + String(hasPeat?
"✅":
"❌") +
")</span></h2>";
53 html +=
"<div class='form-group'><label for='calibration_csv'>Файл CSV:</label><input type='file' id='calibration_csv' name='calibration_csv' accept='.csv' required></div></div>";
73 html.replace(
"<div class='container'>",
"<div class='container'><div class='msg msg-success'>✅ Калибровочная таблица сохранена</div>");
75 webServer.send(200,
"text/html; charset=utf-8", html);
85 if (upload.status == UPLOAD_FILE_START)
88 String profileStr =
webServer.arg(
"soil_profile");
100 logError(
"Не удалось создать файл %s", path);
103 else if (upload.status == UPLOAD_FILE_WRITE)
107 uploadFile.write(upload.buf, upload.currentSize);
110 else if (upload.status == UPLOAD_FILE_END)
115 logSuccess(
"Файл калибровки загружен (%u байт)", upload.totalSize);
117 webServer.sendHeader(
"Location",
"/calibration?ok=1",
true);
118 webServer.send(302,
"text/plain",
"Redirect");
128 logInfo(
"Маршруты калибровки инициализированы");
132 webServer.on(
"/calibration/save", HTTP_POST, []() {
String generateButton(ButtonType type, const char *icon, const char *text, const char *action)
#define UI_ICON_CALIBRATION
void logSuccess(const char *format,...)
void logError(const char *format,...)
void logInfo(const char *format,...)
Система логгирования с красивым форматированием
bool hasTable(SoilProfile profile)
const char * profileToFilename(SoilProfile)
static SoilProfile uploadProfile
static void handleCalibrationPage()
void setupCalibrationRoutes()
Настройка маршрутов калибровки (/calibration)
static void handleCalibrationUpload()
static String generateCalibrationPage()
Алгоритмы коррекции показаний датчиков
Заголовочный файл утилит валидации
String generatePageHeader(const String &title, const String &icon)
Генерация заголовка HTML страницы
String generatePageFooter()
Генерация футера HTML страницы