17 if (ssid.length() == 0)
19 return {
false,
"SSID не может быть пустым"};
21 if (ssid.length() > 32)
23 return {
false,
"SSID слишком длинный (максимум 32 символа)"};
30 if (password.length() > 0 && password.length() < 8)
32 return {
false,
"Пароль должен содержать минимум 8 символов"};
34 if (password.length() > 63)
36 return {
false,
"Пароль слишком длинный (максимум 63 символа)"};
43 if (server.length() == 0)
45 return {
false,
"MQTT сервер не может быть пустым"};
47 if (server.length() > 253)
49 return {
false,
"MQTT сервер слишком длинный"};
52 if (server.indexOf(
' ') >= 0)
54 return {
false,
"MQTT сервер содержит недопустимые символы"};
63 return {
false,
"MQTT порт должен быть в диапазоне 1-65535"};
70 if (apiKey.length() == 0)
72 return {
false,
"ThingSpeak API ключ не может быть пустым"};
74 if (apiKey.length() != 16)
76 return {
false,
"ThingSpeak API ключ должен содержать 16 символов"};
81 if (!isAlphaNumeric(c))
83 return {
false,
"ThingSpeak API ключ содержит недопустимые символы"};
92 if (interval < min_val || interval > max_val)
94 String message = String(name) +
" должен быть в диапазоне " + String(min_val) +
"-" + String(max_val) +
" мс";
95 return {
false, message};
117 return validateInterval(interval, 10000, 86400000,
"Интервал обновления NTP");
128 return {
false,
"Температура вне допустимого диапазона"};
137 return {
false,
"Влажность вне допустимого диапазона"};
146 return {
false,
"pH вне допустимого диапазона"};
155 return {
false,
"EC вне допустимого диапазона"};
164 String message = String(nutrient) +
" вне допустимого диапазона";
165 return {
false, message};
181 if (!ssidResult.isValid)
184 result.
errors.push_back({
"ssid", ssidResult.message});
189 if (!passwordResult.isValid)
192 result.
errors.push_back({
"password", passwordResult.message});
201 if (!mqttServerResult.isValid)
204 result.
errors.push_back({
"mqtt_server", mqttServerResult.message});
208 if (!mqttPortResult.isValid)
211 result.
errors.push_back({
"mqtt_port", mqttPortResult.message});
216 if (
config.thingSpeakEnabled)
219 if (!tsResult.isValid)
222 result.
errors.push_back({
"thingspeak_api_key", tsResult.message});
229 if (!sensorIntervalResult.isValid)
232 result.
errors.push_back({
"sensor_read_interval", sensorIntervalResult.message});
236 if (!mqttIntervalResult.isValid)
239 result.
errors.push_back({
"mqtt_publish_interval", mqttIntervalResult.message});
243 if (!tsIntervalResult.isValid)
246 result.
errors.push_back({
"thingspeak_interval", tsIntervalResult.message});
250 if (!ntpIntervalResult.isValid)
253 result.
errors.push_back({
"ntp_update_interval", ntpIntervalResult.message});
265 if (!tempResult.isValid)
268 result.
errors.push_back({
"temperature", tempResult.message});
272 if (!humResult.isValid)
275 result.
errors.push_back({
"humidity", humResult.message});
279 if (!phResult.isValid)
282 result.
errors.push_back({
"ph", phResult.message});
286 if (!ecResult.isValid)
289 result.
errors.push_back({
"ec", ecResult.message});
293 if (!nitrogenResult.isValid)
296 result.
errors.push_back({
"nitrogen", nitrogenResult.message});
300 if (!phosphorusResult.isValid)
303 result.
errors.push_back({
"phosphorus", phosphorusResult.message});
307 if (!potassiumResult.isValid)
310 result.
errors.push_back({
"potassium", potassiumResult.message});
325 for (
int i = 0; i <= ip.length(); i++)
327 if (i == ip.length() || ip.charAt(i) ==
'.')
329 if (i == start)
return false;
331 String part = ip.substring(start, i);
332 int value = part.toInt();
334 if (value < 0 || value > 255)
return false;
335 if (part != String(value))
return false;
347 if (hostname.length() == 0 || hostname.length() > 253)
return false;
349 for (
char c : hostname)
351 if (!isAlphaNumeric(c) && c !=
'.' && c !=
'-')
358 if (hostname.charAt(0) ==
'.' || hostname.charAt(0) ==
'-' || hostname.charAt(hostname.length() - 1) ==
'.' ||
359 hostname.charAt(hostname.length() - 1) ==
'-')
371 String formatted =
"Ошибки валидации:\n";
372 for (
const auto& error : result.
errors)
374 formatted +=
"• " + error.field +
": " + error.message +
"\n";
383 String formatted =
"Ошибки валидации датчика:\n";
384 for (
const auto& error : result.
errors)
386 formatted +=
"• " + error.field +
": " + error.message +
"\n";
399 logSuccess(
"Валидация %s прошла успешно", context);
403 logError(
"Валидация %s не пройдена:", context);
404 for (
const auto& error : result.
errors)
406 logError(
" %s: %s", error.field.c_str(), error.message.c_str());
415 logSuccess(
"Валидация датчика %s прошла успешно", context);
419 logWarn(
"Валидация датчика %s не пройдена:", context);
420 for (
const auto& error : result.
errors)
422 logWarn(
" %s: %s", error.field.c_str(), error.message.c_str());
Централизованные константы системы JXCT.
constexpr int CONFIG_MQTT_PORT_MAX
constexpr float SENSOR_TEMP_MAX
constexpr float SENSOR_PH_MAX
constexpr uint16_t SENSOR_EC_MAX
constexpr unsigned long CONFIG_THINGSPEAK_MIN
constexpr float SENSOR_HUMIDITY_MAX
constexpr uint16_t SENSOR_NPK_MAX
constexpr unsigned long CONFIG_INTERVAL_MIN
constexpr unsigned long CONFIG_INTERVAL_MAX
constexpr unsigned long CONFIG_THINGSPEAK_MAX
void logWarn(const char *format,...)
void logSuccess(const char *format,...)
void logError(const char *format,...)
Система логгирования с красивым форматированием
Результат валидации конфигурации
std::vector< ValidationError > errors
Результат валидации данных датчика
std::vector< ValidationError > errors
Результат валидации одного поля
bool isValidIPAddress(const String &ip)
Проверка валидности IP адреса
ValidationResult validateMQTTPublishInterval(unsigned long interval)
Валидация интервала публикации MQTT.
SensorValidationResult validateFullSensorData(const SensorData &data)
Полная валидация данных датчика
ValidationResult validateMQTTPort(int port)
Валидация MQTT порта
ValidationResult validateInterval(unsigned long interval, unsigned long min_val, unsigned long max_val, const char *name)
Валидация интервала (общая функция)
void logValidationResult(const ConfigValidationResult &result, const char *context)
Логирование результата валидации конфигурации
ValidationResult validateThingSpeakInterval(unsigned long interval)
Валидация интервала ThingSpeak.
ValidationResult validateNPK(float value, const char *nutrient)
Валидация NPK значений
ValidationResult validateHumidity(float humidity)
Валидация влажности
ValidationResult validateSensorReadInterval(unsigned long interval)
Валидация интервала чтения датчика
void logSensorValidationResult(const SensorValidationResult &result, const char *context)
Логирование результата валидации датчика
ValidationResult validatePH(float ph)
Валидация pH.
ValidationResult validatePassword(const String &password)
Валидация пароля WiFi.
ValidationResult validateMQTTServer(const String &server)
Валидация MQTT сервера
bool isValidHostname(const String &hostname)
Проверка валидности hostname.
ValidationResult validateEC(float ec)
Валидация электропроводности
String formatSensorValidationErrors(const SensorValidationResult &result)
Форматирование ошибок валидации датчика
ValidationResult validateThingSpeakAPIKey(const String &apiKey)
Валидация ThingSpeak API ключа
ConfigValidationResult validateFullConfig(const ConfigData &config, bool checkRequired)
Полная валидация конфигурации
String formatValidationErrors(const ConfigValidationResult &result)
Форматирование ошибок валидации конфигурации
ValidationResult validateSSID(const String &ssid)
Валидация SSID.
ValidationResult validateTemperature(float temperature)
Валидация температуры
ValidationResult validateNTPInterval(unsigned long interval)
Валидация интервала обновления NTP.
Заголовочный файл утилит валидации