JXCT Soil Sensor 7-in-1 v3.4.9 (June 2025)
Professional IoT soil monitoring system with ESP32, Modbus RTU, MQTT, and advanced compensation algorithms
Загрузка...
Поиск...
Не найдено
config.cpp
См. документацию.
1
6#include <WiFi.h>
7#include "version.h" // ✅ Централизованное управление версией
8#include "jxct_device_info.h"
9#include "jxct_config_vars.h"
10#include "debug.h" // ✅ Добавляем систему условной компиляции
11#include "logger.h"
12
13// Firmware version definition - теперь берется из централизованного файла version.h
14// const char* FIRMWARE_VERSION уже определена в version.h
15
17{
18 uint8_t mac[6];
19 WiFi.macAddress(mac);
20 char buf[32];
21 snprintf(buf, sizeof(buf), "%s_%02X%02X%02X", DEVICE_MODEL, mac[3], mac[4], mac[5]);
22 return String(buf);
23}
24
26{
27 uint8_t mac[6];
28 WiFi.macAddress(mac);
29 char buf[32];
30 snprintf(buf, sizeof(buf), "jxct_%02X%02X%02X", mac[3], mac[4], mac[5]);
31 return String(buf);
32}
33
34Config config;
35Preferences preferences;
36
37#define KEY_NTP_INTERVAL "ntpIntvl" // ≤15 bytes, иначе NVS выдаёт KEY_TOO_LONG
38
40{
41 preferences.begin("jxct-sensor", false);
42
43 // WiFi настройки
44 preferences.getString("ssid", config.ssid, sizeof(config.ssid));
45 preferences.getString("password", config.password, sizeof(config.password));
46
47 // MQTT настройки
48 preferences.getString("mqttServer", config.mqttServer, sizeof(config.mqttServer));
49 config.mqttPort = preferences.getUShort("mqttPort", 1883);
50 preferences.getString("mqttUser", config.mqttUser, sizeof(config.mqttUser));
51 preferences.getString("mqttPassword", config.mqttPassword, sizeof(config.mqttPassword));
52 preferences.getString("mqttTopicPrefix", config.mqttTopicPrefix, sizeof(config.mqttTopicPrefix));
53 preferences.getString("mqttDeviceName", config.mqttDeviceName, sizeof(config.mqttDeviceName));
54 // Битовые поля boolean флагов
55 config.flags.hassEnabled = preferences.getBool("hassEnabled", false);
56 config.flags.useRealSensor = preferences.getBool("useRealSensor", false);
57 config.flags.mqttEnabled = preferences.getBool("mqttEnabled", false);
58 config.flags.thingSpeakEnabled = preferences.getBool("tsEnabled", false);
59 config.flags.calibrationEnabled = preferences.getBool("calEnabled", false);
60
61 config.mqttQos = preferences.getUChar("mqttQos", 0);
62 config.thingspeakInterval = preferences.getUShort("tsInterval", 60);
63 preferences.getString("manufacturer", config.manufacturer, sizeof(config.manufacturer));
64 preferences.getString("model", config.model, sizeof(config.model));
65 preferences.getString("swVersion", config.swVersion, sizeof(config.swVersion));
66
67 // ThingSpeak настройки
68 preferences.getString("tsApiKey", config.thingSpeakApiKey, sizeof(config.thingSpeakApiKey));
69 preferences.getString("tsChannelId", config.thingSpeakChannelId, sizeof(config.thingSpeakChannelId));
70
71 // Настройка датчика
72 config.modbusId = preferences.getUChar("modbusId", JXCT_MODBUS_ID);
73
74 config.webPassword[0] = '\0';
75
76 // NTP настройки
77 String ntpServer = preferences.getString("ntpServer", "pool.ntp.org");
78 ntpServer.toCharArray(config.ntpServer, sizeof(config.ntpServer));
79 config.ntpUpdateInterval = preferences.getUInt(KEY_NTP_INTERVAL, 60000);
80
81 // v2.3.0: Настраиваемые интервалы (с дефолтными значениями из v2.2.1)
82 config.sensorReadInterval = preferences.getUInt("sensorInterval", SENSOR_READ_INTERVAL);
83 config.mqttPublishInterval = preferences.getUInt("mqttInterval", MQTT_PUBLISH_INTERVAL);
84 config.thingSpeakInterval = preferences.getUInt("tsInterval", THINGSPEAK_INTERVAL);
85 config.webUpdateInterval = preferences.getUInt("webInterval", WEB_UPDATE_INTERVAL);
86
87 // v2.3.0: Настраиваемые пороги дельта-фильтра
88 config.deltaTemperature = preferences.getFloat("deltaTemp", DELTA_TEMPERATURE);
89 config.deltaHumidity = preferences.getFloat("deltaHum", DELTA_HUMIDITY);
90 config.deltaPh = preferences.getFloat("deltaPh", DELTA_PH);
91 config.deltaEc = preferences.getFloat("deltaEc", DELTA_EC);
92 config.deltaNpk = preferences.getFloat("deltaNpk", DELTA_NPK);
93
94 // v2.3.0: Настройки скользящего среднего (МИНИМАЛЬНАЯ ФИЛЬТРАЦИЯ)
95 config.movingAverageWindow = preferences.getUChar("avgWindow", 5); // минимальное окно
96 config.forcePublishCycles = preferences.getUChar("forceCycles", FORCE_PUBLISH_CYCLES);
97 config.filterAlgorithm = preferences.getUChar("filterAlgo", 0); // 0=среднее
98 config.outlierFilterEnabled = preferences.getUChar("outlierFilter", 0); // отключен для минимальной фильтрации
99
100 // Soil profile и агро-поля
101 config.soilProfile = preferences.getUChar("soilProfile", 0);
102 config.latitude = preferences.getFloat("lat", 0.0f);
103 config.longitude = preferences.getFloat("lon", 0.0f);
104 preferences.getString("cropId", config.cropId, sizeof(config.cropId));
105 config.flags.isGreenhouse = preferences.getBool("greenhouse", false);
106 config.irrigationSpikeThreshold = preferences.getFloat("irrigTh", 8.0f);
107 config.irrigationHoldMinutes = preferences.getUShort("irrigHold", 5);
108
109 // v2.6.1: сезонные коэффициенты и тип среды
110 config.environmentType = preferences.getUChar("envType", 0); // 0=outdoor по умолчанию
111 config.flags.seasonalAdjustEnabled = preferences.getBool("seasonAdj", true);
112 config.flags.autoOtaEnabled = preferences.getBool("autoOTA", false);
113
114 preferences.end();
115 // Значения по умолчанию для новых полей
116 if (strlen(config.mqttDeviceName) == 0)
117 strlcpy(config.mqttDeviceName, getDeviceId().c_str(), sizeof(config.mqttDeviceName));
118 if (strlen(config.thingSpeakChannelId) == 0)
119 strlcpy(config.thingSpeakChannelId, "", sizeof(config.thingSpeakChannelId));
120 if (strlen(config.mqttTopicPrefix) == 0)
121 strlcpy(config.mqttTopicPrefix, getDefaultTopic().c_str(), sizeof(config.mqttTopicPrefix));
122
123 logSuccess("Конфигурация загружена");
124 logDebug("SSID: %s, MQTT: %s:%d, ThingSpeak: %s", config.ssid, config.mqttServer, config.mqttPort,
125 config.flags.thingSpeakEnabled ? "включен" : "выключен");
126}
127
129{
130 preferences.begin("jxct-sensor", false);
131
132 // WiFi настройки
133 preferences.putString("ssid", config.ssid);
134 preferences.putString("password", config.password);
135
136 // MQTT настройки
137 preferences.putString("mqttServer", config.mqttServer);
138 preferences.putUShort("mqttPort", config.mqttPort);
139 preferences.putString("mqttUser", config.mqttUser);
140 preferences.putString("mqttPassword", config.mqttPassword);
141 preferences.putString("mqttTopicPrefix", config.mqttTopicPrefix);
142 preferences.putString("mqttDeviceName", config.mqttDeviceName);
143
144 // Битовые поля boolean флагов
145 preferences.putBool("hassEnabled", config.flags.hassEnabled);
146 preferences.putBool("useRealSensor", config.flags.useRealSensor);
147 preferences.putBool("mqttEnabled", config.flags.mqttEnabled);
148 preferences.putBool("tsEnabled", config.flags.thingSpeakEnabled);
149 preferences.putBool("calEnabled", config.flags.calibrationEnabled);
150
151 preferences.putUChar("mqttQos", config.mqttQos);
152 preferences.putUShort("tsInterval", config.thingspeakInterval);
153 preferences.putString("manufacturer", config.manufacturer);
154 preferences.putString("model", config.model);
155 preferences.putString("swVersion", config.swVersion);
156
157 // ThingSpeak настройки
158 preferences.putString("tsApiKey", config.thingSpeakApiKey);
159 preferences.putString("tsChannelId", config.thingSpeakChannelId);
160
161 // Настройка датчика
162 preferences.putUChar("modbusId", config.modbusId);
163
164 preferences.putString("webPassword", "");
165
166 // NTP настройки
167 preferences.putString("ntpServer", config.ntpServer);
168 preferences.putUInt(KEY_NTP_INTERVAL, config.ntpUpdateInterval);
169
170 // v2.3.0: Настраиваемые интервалы
171 preferences.putUInt("sensorInterval", config.sensorReadInterval);
172 preferences.putUInt("mqttInterval", config.mqttPublishInterval);
173 preferences.putUInt("tsInterval", config.thingSpeakInterval);
174 preferences.putUInt("webInterval", config.webUpdateInterval);
175
176 // v2.3.0: Настраиваемые пороги дельта-фильтра
177 preferences.putFloat("deltaTemp", config.deltaTemperature);
178 preferences.putFloat("deltaHum", config.deltaHumidity);
179 preferences.putFloat("deltaPh", config.deltaPh);
180 preferences.putFloat("deltaEc", config.deltaEc);
181 preferences.putFloat("deltaNpk", config.deltaNpk);
182
183 // v2.3.0: Настройки скользящего среднего
184 preferences.putUChar("avgWindow", config.movingAverageWindow);
185 preferences.putUChar("forceCycles", config.forcePublishCycles);
186 preferences.putUChar("filterAlgo", config.filterAlgorithm);
187 preferences.putUChar("outlierFilter", config.outlierFilterEnabled);
188
189 // Soil profile и агро-поля
190 preferences.putUChar("soilProfile", config.soilProfile);
191 preferences.putFloat("lat", config.latitude);
192 preferences.putFloat("lon", config.longitude);
193 preferences.putString("cropId", config.cropId);
194 preferences.putBool("greenhouse", config.flags.isGreenhouse);
195 preferences.putFloat("irrigTh", config.irrigationSpikeThreshold);
196 preferences.putUShort("irrigHold", config.irrigationHoldMinutes);
197
198 // v2.6.1: сохранение новых полей
199 preferences.putUChar("envType", config.environmentType);
200 preferences.putBool("seasonAdj", config.flags.seasonalAdjustEnabled);
201 preferences.putBool("autoOTA", config.flags.autoOtaEnabled);
202
203 preferences.end();
204
205 // ✅ Инвалидируем кэш MQTT конфигураций при изменении настроек
206 extern void invalidateHAConfigCache();
208
209 logSuccess("Конфигурация сохранена");
210}
211
213{
214 logWarn("Сброс конфигурации...");
215 preferences.begin("jxct-sensor", false);
216 preferences.clear();
217 preferences.end();
218 // ✅ Безопасный сброс структуры config без memset для упакованных структур
219 // Wi-Fi
220 config.ssid[0] = '\0';
221 config.password[0] = '\0';
222 // MQTT
223 config.mqttPort = 1883;
224 config.modbusId = JXCT_MODBUS_ID;
225 strlcpy(config.mqttTopicPrefix, getDefaultTopic().c_str(), sizeof(config.mqttTopicPrefix));
226 strlcpy(config.mqttDeviceName, getDeviceId().c_str(), sizeof(config.mqttDeviceName));
227
228 // ✅ Явный сброс битовых полей
229 config.flags.mqttEnabled = 0;
230 config.flags.thingSpeakEnabled = 0;
231 config.flags.hassEnabled = 0;
232 config.flags.useRealSensor = 0;
233 config.flags.calibrationEnabled = 0;
234
235 // ✅ Очистка всех строковых полей
236 strlcpy(config.thingSpeakChannelId, "", sizeof(config.thingSpeakChannelId));
237 strlcpy(config.mqttServer, "", sizeof(config.mqttServer));
238 strlcpy(config.mqttUser, "", sizeof(config.mqttUser));
239 strlcpy(config.mqttPassword, "", sizeof(config.mqttPassword));
240 strlcpy(config.thingSpeakApiKey, "", sizeof(config.thingSpeakApiKey));
241 strlcpy(config.manufacturer, "", sizeof(config.manufacturer));
242 strlcpy(config.model, "", sizeof(config.model));
243 strlcpy(config.swVersion, "", sizeof(config.swVersion));
244
245 // ✅ Сброс числовых полей
246 config.mqttQos = 0;
247 config.thingspeakInterval = 60;
248
249 // ✅ Безопасность веб-интерфейса
250 strlcpy(config.webPassword, "", sizeof(config.webPassword));
251
252 // NTP
253 strlcpy(config.ntpServer, "pool.ntp.org", sizeof(config.ntpServer));
254 config.ntpUpdateInterval = 60000;
255
256 // v2.3.0: Сброс настраиваемых интервалов к оптимизированным значениям v2.2.1
257 config.sensorReadInterval = SENSOR_READ_INTERVAL;
258 config.mqttPublishInterval = MQTT_PUBLISH_INTERVAL;
259 config.thingSpeakInterval = THINGSPEAK_INTERVAL;
260 config.webUpdateInterval = WEB_UPDATE_INTERVAL;
261
262 // v2.3.0: Сброс порогов дельта-фильтра
263 config.deltaTemperature = DELTA_TEMPERATURE;
264 config.deltaHumidity = DELTA_HUMIDITY;
265 config.deltaPh = DELTA_PH;
266 config.deltaEc = DELTA_EC;
267 config.deltaNpk = DELTA_NPK;
268
269 // v2.3.0: Сброс настроек скользящего среднего (МИНИМАЛЬНАЯ ФИЛЬТРАЦИЯ)
270 config.movingAverageWindow = 5; // минимальное окно
271 config.forcePublishCycles = FORCE_PUBLISH_CYCLES;
272 config.filterAlgorithm = 0; // среднее
273 config.outlierFilterEnabled = 0; // отключен для минимальной фильтрации
274
275 // Soil profile и агро-поля
276 config.soilProfile = 0;
277 config.latitude = 0.0f;
278 config.longitude = 0.0f;
279 strlcpy(config.cropId, "", sizeof(config.cropId));
280 config.flags.isGreenhouse = false;
281 config.irrigationSpikeThreshold = 8.0f;
282 config.irrigationHoldMinutes = 5;
283
284 // v2.6.1: сезонные коэффициенты и тип среды
285 config.environmentType = 0; // 0=outdoor по умолчанию
286 config.flags.seasonalAdjustEnabled = 0;
287 config.flags.autoOtaEnabled = 0;
288
289 logSuccess("Все настройки сброшены к значениям по умолчанию");
290 DEBUG_PRINT("[resetConfig] config.thingspeakInterval: ");
291 DEBUG_PRINTLN(config.thingspeakInterval);
292 DEBUG_PRINT("[resetConfig] config.manufacturer: ");
293 DEBUG_PRINTLN(config.manufacturer);
294 DEBUG_PRINT("[resetConfig] config.model: ");
295 DEBUG_PRINTLN(config.model);
296 DEBUG_PRINT("[resetConfig] config.swVersion: ");
297 DEBUG_PRINTLN(config.swVersion);
298 DEBUG_PRINT("[resetConfig] config.ntpServer: ");
299 DEBUG_PRINTLN(config.ntpServer);
300 DEBUG_PRINT("[resetConfig] config.ntpUpdateInterval: ");
301 DEBUG_PRINTLN(config.ntpUpdateInterval);
302}
303
305{
306 // Проверяем минимально необходимые настройки
307 if (strlen(config.ssid) == 0)
308 {
309 return false;
310 }
311
312 // Если MQTT включен, проверяем настройки MQTT
313 if (config.flags.mqttEnabled && strlen(config.mqttServer) == 0)
314 {
315 return false;
316 }
317
318 // Если ThingSpeak включен, проверяем API ключ
319 if (config.flags.thingSpeakEnabled && strlen(config.thingSpeakApiKey) == 0)
320 {
321 return false;
322 }
323
324 return true;
325}
Config config
Определения config.cpp:34
void saveConfig()
Определения config.cpp:128
Preferences preferences
Определения config.cpp:35
void resetConfig()
Определения config.cpp:212
String getDefaultTopic()
Определения config.cpp:25
#define KEY_NTP_INTERVAL
Определения config.cpp:37
String getDeviceId()
Определения config.cpp:16
void loadConfig()
Определения config.cpp:39
bool isConfigValid()
Определения config.cpp:304
#define DEBUG_PRINTLN(x)
Определения debug.h:18
#define DEBUG_PRINT(x)
Определения debug.h:17
#define WEB_UPDATE_INTERVAL
Определения jxct_config_vars.h:12
#define MQTT_PUBLISH_INTERVAL
Определения jxct_config_vars.h:10
#define DELTA_EC
Определения jxct_config_vars.h:30
#define FORCE_PUBLISH_CYCLES
Определения jxct_config_vars.h:32
#define SENSOR_READ_INTERVAL
Определения jxct_config_vars.h:9
#define JXCT_MODBUS_ID
Определения jxct_config_vars.h:35
#define DELTA_NPK
Определения jxct_config_vars.h:31
#define DELTA_PH
Определения jxct_config_vars.h:29
#define DELTA_HUMIDITY
Определения jxct_config_vars.h:28
#define DELTA_TEMPERATURE
Определения jxct_config_vars.h:27
#define THINGSPEAK_INTERVAL
Определения jxct_config_vars.h:11
void logDebug(const char *format,...)
Определения logger.cpp:112
void logWarn(const char *format,...)
Определения logger.cpp:78
void logSuccess(const char *format,...)
Определения logger.cpp:129
Система логгирования с красивым форматированием
void invalidateHAConfigCache()
Определения mqtt_client.cpp:734
static const char DEVICE_MODEL[]
Определения version.h:15