JXCT Soil Sensor 7-in-1 3.10.1
IoT система мониторинга почвы на базе ESP32
Загрузка...
Поиск...
Не найдено
calibration_data.h
См. документацию.
1#pragma once
2
3#include <Arduino.h>
4#include <vector>
5#include <ArduinoJson.h>
6
13// ========== БАЗОВЫЕ СТРУКТУРЫ ==========
14
19 float expected; // Эталонное значение (буферный раствор)
20 float measured; // Показание датчика
21 uint32_t timestamp; // Время добавления точки
22
24 ModernCalibrationPoint(float exp, float meas) : expected(exp), measured(meas), timestamp(millis()) {}
25};
26
31 float slope; // Коэффициент наклона (a)
32 float intercept; // Смещение (b)
33 float r_squared; // Коэффициент детерминации R²
34 bool is_valid; // Флаг валидности коэффициентов
35
36 LinearCoefficients() : slope(1.0f), intercept(0.0f), r_squared(0.0f), is_valid(false) {}
37};
38
43 float offset; // Смещение: calibrated = raw + offset
44 bool is_valid; // Флаг валидности
45 uint32_t timestamp; // Время последнего обновления
46
47 OffsetCalibration() : offset(0.0f), is_valid(false), timestamp(0) {}
48};
49
50// ========== СПЕЦИАЛИЗИРОВАННЫЕ КАЛИБРОВКИ ==========
51
56 std::vector<ModernCalibrationPoint> points;
58
59 bool hasPoints() const { return !points.empty(); }
60 size_t getPointCount() const { return points.size(); }
61 bool isReady() const { return coefficients.is_valid && points.size() >= 2; }
62};
63
68 std::vector<ModernCalibrationPoint> points;
70
71 bool hasPoints() const { return !points.empty(); }
72 size_t getPointCount() const { return points.size(); }
73 bool isReady() const { return coefficients.is_valid && points.size() >= 2; }
74};
75
83 uint32_t last_calibration; // Время последней калибровки
84
86
87 bool isReady() const {
89 }
90
91 void setZeroPoint(float n_measured, float p_measured, float k_measured) {
92 nitrogen.offset = 0.0f - n_measured;
93 nitrogen.is_valid = true;
94 nitrogen.timestamp = millis();
95
96 phosphorus.offset = 0.0f - p_measured;
97 phosphorus.is_valid = true;
98 phosphorus.timestamp = millis();
99
100 potassium.offset = 0.0f - k_measured;
101 potassium.is_valid = true;
102 potassium.timestamp = millis();
103
104 last_calibration = millis();
105 }
106};
107
108// ========== ОСНОВНАЯ СТРУКТУРА КАЛИБРОВКИ ==========
109
114 // Offset калибровки
117
118 // Многоточечные калибровки
121
122 // NPK калибровка
124
125 // Метаданные
126 String device_id;
127 uint32_t created_at;
128 uint32_t updated_at;
129
130 SensorCalibrationData() : created_at(millis()), updated_at(millis()) {}
131
135 bool isComplete() const {
137 ph.isReady() && ec.isReady() && npk.isReady();
138 }
139
143 void touch() {
144 updated_at = millis();
145 }
146
150 void reset() {
153 ph = PHCalibration();
154 ec = ECCalibration();
156 touch();
157 }
158
162 String toJSON() const {
163 DynamicJsonDocument doc(2048);
164
165 // Метаданные
166 doc["device_id"] = device_id;
167 doc["created_at"] = created_at;
168 doc["updated_at"] = updated_at;
169 doc["is_complete"] = isComplete();
170
171 // Temperature offset
172 JsonObject temp = doc.createNestedObject("temperature");
173 temp["offset"] = temperature.offset;
174 temp["is_valid"] = temperature.is_valid;
175 temp["timestamp"] = temperature.timestamp;
176
177 // Humidity offset
178 JsonObject hum = doc.createNestedObject("humidity");
179 hum["offset"] = humidity.offset;
180 hum["is_valid"] = humidity.is_valid;
181 hum["timestamp"] = humidity.timestamp;
182
183 // pH calibration
184 JsonObject phObj = doc.createNestedObject("ph");
185 JsonArray phPoints = phObj.createNestedArray("points");
186 for (const auto& point : ph.points) {
187 JsonObject p = phPoints.createNestedObject();
188 p["expected"] = point.expected;
189 p["measured"] = point.measured;
190 p["timestamp"] = point.timestamp;
191 }
192 JsonObject phCoeff = phObj.createNestedObject("coefficients");
193 phCoeff["slope"] = ph.coefficients.slope;
194 phCoeff["intercept"] = ph.coefficients.intercept;
195 phCoeff["r_squared"] = ph.coefficients.r_squared;
196 phCoeff["is_valid"] = ph.coefficients.is_valid;
197
198 // EC calibration
199 JsonObject ecObj = doc.createNestedObject("ec");
200 JsonArray ecPoints = ecObj.createNestedArray("points");
201 for (const auto& point : ec.points) {
202 JsonObject p = ecPoints.createNestedObject();
203 p["expected"] = point.expected;
204 p["measured"] = point.measured;
205 p["timestamp"] = point.timestamp;
206 }
207 JsonObject ecCoeff = ecObj.createNestedObject("coefficients");
208 ecCoeff["slope"] = ec.coefficients.slope;
209 ecCoeff["intercept"] = ec.coefficients.intercept;
210 ecCoeff["r_squared"] = ec.coefficients.r_squared;
211 ecCoeff["is_valid"] = ec.coefficients.is_valid;
212
213 // NPK calibration
214 JsonObject npkObj = doc.createNestedObject("npk");
215 npkObj["last_calibration"] = npk.last_calibration;
216
217 JsonObject npkN = npkObj.createNestedObject("nitrogen");
218 npkN["offset"] = npk.nitrogen.offset;
219 npkN["is_valid"] = npk.nitrogen.is_valid;
220 npkN["timestamp"] = npk.nitrogen.timestamp;
221
222 JsonObject npkP = npkObj.createNestedObject("phosphorus");
223 npkP["offset"] = npk.phosphorus.offset;
224 npkP["is_valid"] = npk.phosphorus.is_valid;
225 npkP["timestamp"] = npk.phosphorus.timestamp;
226
227 JsonObject npkK = npkObj.createNestedObject("potassium");
228 npkK["offset"] = npk.potassium.offset;
229 npkK["is_valid"] = npk.potassium.is_valid;
230 npkK["timestamp"] = npk.potassium.timestamp;
231
232 String result;
233 serializeJson(doc, result);
234 return result;
235 }
236
240 bool fromJSON(const String& json) {
241 DynamicJsonDocument doc(2048);
242 DeserializationError error = deserializeJson(doc, json);
243
244 if (error) {
245 return false;
246 }
247
248 // Метаданные
249 device_id = doc["device_id"].as<String>();
250 created_at = doc["created_at"];
251 updated_at = doc["updated_at"];
252
253 // Temperature
254 if (doc.containsKey("temperature")) {
255 JsonObject temp = doc["temperature"];
256 temperature.offset = temp["offset"];
257 temperature.is_valid = temp["is_valid"];
258 temperature.timestamp = temp["timestamp"];
259 }
260
261 // Humidity
262 if (doc.containsKey("humidity")) {
263 JsonObject hum = doc["humidity"];
264 humidity.offset = hum["offset"];
265 humidity.is_valid = hum["is_valid"];
266 humidity.timestamp = hum["timestamp"];
267 }
268
269 // pH
270 if (doc.containsKey("ph")) {
271 JsonObject phObj = doc["ph"];
272
273 // Points
274 if (phObj.containsKey("points")) {
275 ph.points.clear();
276 JsonArray phPoints = phObj["points"];
277 for (JsonObject point : phPoints) {
279 p.expected = point["expected"];
280 p.measured = point["measured"];
281 p.timestamp = point["timestamp"];
282 ph.points.push_back(p);
283 }
284 }
285
286 // Coefficients
287 if (phObj.containsKey("coefficients")) {
288 JsonObject phCoeff = phObj["coefficients"];
289 ph.coefficients.slope = phCoeff["slope"];
290 ph.coefficients.intercept = phCoeff["intercept"];
291 ph.coefficients.r_squared = phCoeff["r_squared"];
292 ph.coefficients.is_valid = phCoeff["is_valid"];
293 }
294 }
295
296 // EC
297 if (doc.containsKey("ec")) {
298 JsonObject ecObj = doc["ec"];
299
300 // Points
301 if (ecObj.containsKey("points")) {
302 ec.points.clear();
303 JsonArray ecPoints = ecObj["points"];
304 for (JsonObject point : ecPoints) {
306 p.expected = point["expected"];
307 p.measured = point["measured"];
308 p.timestamp = point["timestamp"];
309 ec.points.push_back(p);
310 }
311 }
312
313 // Coefficients
314 if (ecObj.containsKey("coefficients")) {
315 JsonObject ecCoeff = ecObj["coefficients"];
316 ec.coefficients.slope = ecCoeff["slope"];
317 ec.coefficients.intercept = ecCoeff["intercept"];
318 ec.coefficients.r_squared = ecCoeff["r_squared"];
319 ec.coefficients.is_valid = ecCoeff["is_valid"];
320 }
321 }
322
323 // NPK
324 if (doc.containsKey("npk")) {
325 JsonObject npkObj = doc["npk"];
326 npk.last_calibration = npkObj["last_calibration"];
327
328 if (npkObj.containsKey("nitrogen")) {
329 JsonObject npkN = npkObj["nitrogen"];
330 npk.nitrogen.offset = npkN["offset"];
331 npk.nitrogen.is_valid = npkN["is_valid"];
332 npk.nitrogen.timestamp = npkN["timestamp"];
333 }
334
335 if (npkObj.containsKey("phosphorus")) {
336 JsonObject npkP = npkObj["phosphorus"];
337 npk.phosphorus.offset = npkP["offset"];
338 npk.phosphorus.is_valid = npkP["is_valid"];
339 npk.phosphorus.timestamp = npkP["timestamp"];
340 }
341
342 if (npkObj.containsKey("potassium")) {
343 JsonObject npkK = npkObj["potassium"];
344 npk.potassium.offset = npkK["offset"];
345 npk.potassium.is_valid = npkK["is_valid"];
346 npk.potassium.timestamp = npkK["timestamp"];
347 }
348 }
349
350 return true;
351 }
352};
Калибровка EC (многоточечная с линейной регрессией)
Definition calibration_data.h:67
std::vector< ModernCalibrationPoint > points
Definition calibration_data.h:68
bool isReady() const
Definition calibration_data.h:73
size_t getPointCount() const
Definition calibration_data.h:72
LinearCoefficients coefficients
Definition calibration_data.h:69
bool hasPoints() const
Definition calibration_data.h:71
Коэффициенты линейной калибровки y = ax + b.
Definition calibration_data.h:30
LinearCoefficients()
Definition calibration_data.h:36
bool is_valid
Definition calibration_data.h:34
float intercept
Definition calibration_data.h:32
float slope
Definition calibration_data.h:31
float r_squared
Definition calibration_data.h:33
Точка калибровки (expected, measured)
Definition calibration_data.h:18
float measured
Definition calibration_data.h:20
ModernCalibrationPoint(float exp, float meas)
Definition calibration_data.h:24
float expected
Definition calibration_data.h:19
uint32_t timestamp
Definition calibration_data.h:21
ModernCalibrationPoint()
Definition calibration_data.h:23
Калибровка NPK (нулевая точка в дистиллированной воде)
Definition calibration_data.h:79
OffsetCalibration nitrogen
Definition calibration_data.h:80
void setZeroPoint(float n_measured, float p_measured, float k_measured)
Definition calibration_data.h:91
OffsetCalibration phosphorus
Definition calibration_data.h:81
bool isReady() const
Definition calibration_data.h:87
uint32_t last_calibration
Definition calibration_data.h:83
NPKCalibration()
Definition calibration_data.h:85
OffsetCalibration potassium
Definition calibration_data.h:82
Простое смещение (offset) для температуры и влажности
Definition calibration_data.h:42
uint32_t timestamp
Definition calibration_data.h:45
OffsetCalibration()
Definition calibration_data.h:47
float offset
Definition calibration_data.h:43
bool is_valid
Definition calibration_data.h:44
Калибровка pH (многоточечная с линейной регрессией)
Definition calibration_data.h:55
bool isReady() const
Definition calibration_data.h:61
size_t getPointCount() const
Definition calibration_data.h:60
std::vector< ModernCalibrationPoint > points
Definition calibration_data.h:56
LinearCoefficients coefficients
Definition calibration_data.h:57
bool hasPoints() const
Definition calibration_data.h:59
Полная калибровка датчика
Definition calibration_data.h:113
String device_id
Definition calibration_data.h:126
NPKCalibration npk
Definition calibration_data.h:123
uint32_t created_at
Definition calibration_data.h:127
void reset()
Сброс всех калибровочных данных
Definition calibration_data.h:150
OffsetCalibration humidity
Definition calibration_data.h:116
OffsetCalibration temperature
Definition calibration_data.h:115
bool fromJSON(const String &json)
Десериализация из JSON.
Definition calibration_data.h:240
uint32_t updated_at
Definition calibration_data.h:128
SensorCalibrationData()
Definition calibration_data.h:130
String toJSON() const
Сериализация в JSON.
Definition calibration_data.h:162
ECCalibration ec
Definition calibration_data.h:120
PHCalibration ph
Definition calibration_data.h:119
void touch()
Обновление времени модификации
Definition calibration_data.h:143
bool isComplete() const
Проверка готовности всей калибровки
Definition calibration_data.h:135