🏗️ Общая архитектура JXCT v3.4.9

Версия документа: 3.4.9
Дата обновления: 2025-06-24
Статус: Актуальная архитектура с фокусом на стабильность

🎯 ПРИНЦИПЫ АРХИТЕКТУРЫ

1. Стабильность превыше всего

2. Модульность и переиспользование

3. Производительность и эффективность

🔧 ОСНОВНЫЕ КОМПОНЕНТЫ

📡 СИСТЕМА ДАТЧИКОВ

🔌 Абстракция датчиков

// Файл: include/ISensor.h

class ISensor {
public:
    virtual ~ISensor() = default;
    virtual bool initialize() = 0;
    virtual SensorData read() = 0;
    virtual bool isConnected() const = 0;
    virtual String getSensorInfo() const = 0;
};

🎭 Адаптеры датчиков

// Файл: src/modbus_sensor.h

class ModbusSensorAdapter : public ISensor {
private:
    ModbusSensor* sensor;
    
public:
    ModbusSensorAdapter(ModbusSensor* s) : sensor(s) {}
    
    bool initialize() override {
        return sensor->begin();
    }
    
    SensorData read() override {
        return sensor->getData();
    }
    
    bool isConnected() const override {
        return sensor->isConnected();
    }
    
    String getSensorInfo() const override {
        return "Modbus Sensor v" + String(sensor->getVersion());
    }
};

🧮 СИСТЕМА КОМПЕНСАЦИИ

✅ ИСПРАВЛЕННАЯ ДВУХЭТАПНАЯ КОМПЕНСАЦИЯ

// Файл: src/modbus_sensor.cpp

void applyCompensationIfEnabled(SensorData& d, const SoilProfile& profile) {
    // ШАГ 1: Применяем калибровочную таблицу CSV (лабораторная поверка)
    float tempCalibrated = CalibrationManager::applyCalibration(d.temperature, profile);
    float humCalibrated = CalibrationManager::applyCalibration(d.humidity, profile);
    float ecCalibrated = CalibrationManager::applyCalibration(d.ec, profile);
    float phCalibrated = CalibrationManager::applyCalibration(d.ph, profile);
    float nCalibrated = CalibrationManager::applyCalibration(d.nitrogen, profile);
    float pCalibrated = CalibrationManager::applyCalibration(d.phosphorus, profile);
    float kCalibrated = CalibrationManager::applyCalibration(d.potassium, profile);

    // ШАГ 2: Применяем математическую компенсацию (температурная, влажностная)
    float ec25 = ecCalibrated / (1.0f + 0.021f * (tempCalibrated - 25.0f));
    d.ec = correctEC(ec25, tempCalibrated, humCalibrated, profile.soilType);
    d.ph = correctPH(phCalibrated, tempCalibrated);
    correctNPK(tempCalibrated, humCalibrated, d.nitrogen, d.phosphorus, d.potassium, profile.soilType);
}

🔧 Калибровочный менеджер

// Файл: src/calibration_manager.cpp

class CalibrationManager {
public:
    // Применение калибровочной таблицы с линейной интерполяцией
    static float applyCalibration(float rawValue, const CalibrationProfile& profile) {
        if (!profile.isLoaded()) {
            return rawValue; // Возвращаем исходное значение если таблица не загружена
        }
        
        // Поиск ближайших точек калибровки
        CalibrationPoint lower, upper;
        if (profile.findInterpolationPoints(rawValue, lower, upper)) {
            // Линейная интерполяция
            float ratio = (rawValue - lower.raw) / (upper.raw - lower.raw);
            return lower.calibrated + ratio * (upper.calibrated - lower.calibrated);
        }
        
        return rawValue; // Вне диапазона калибровки
    }
};

1️⃣ Модель Арчи - EC компенсация

float correctEC(float ec25, float temperature, float humidity, SoilType soilType) {
    // Температурная компенсация (Archie, 1942)
    float tempFactor = 1.0f + 0.021f * (temperature - 25.0f);
    
    // Влажностная компенсация по модели Арчи
    float porosity = getPorosity(soilType);
    float archieCoeff = getArchieCoefficient(soilType);
    float humFactor = pow(humidity / 100.0f, archieCoeff);
    
    return ec25 * tempFactor * humFactor;
}

float getArchieCoefficient(SoilType soilType) {
    switch (soilType) {
        case SAND: return 0.15f;      // Песок
        case LOAM: return 0.30f;      // Суглинок
        case CLAY: return 0.45f;      // Глина
        case PEAT: return 0.10f;      // Торф
        case SANDY_PEAT: return 0.18f; // Песчано-торфяной
        default: return 0.30f;
    }
}

2️⃣ Уравнение Нернста - pH компенсация

float correctPH(float phRaw, float temperature) {
    // Температурная поправка pH по уравнению Нернста
    // dE/dT = -0.003 V/°C для pH электрода
    return phRaw - 0.003f * (temperature - 25.0f);
}

3️⃣ FAO 56 + Eur. J. Soil Sci. - NPK компенсация

void correctNPK(float temperature, float humidity, 
                float& nitrogen, float& phosphorus, float& potassium, 
                SoilType soilType) {
    // Температурная компенсация NPK
    float tempFactor = 1.0f - 0.02f * (temperature - 25.0f);
    
    // Влажностная компенсация по FAO 56
    float humFactor = 1.0f + 0.05f * (humidity - 50.0f) / 50.0f;
    
    // Применение компенсации
    nitrogen *= tempFactor * humFactor;
    phosphorus *= tempFactor * humFactor;
    potassium *= tempFactor * humFactor;
}

🌐 ВЕБ-ИНТЕРФЕЙС

📱 Архитектура веб-интерфейса

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   Web Browser   │    │   ESP32 Web     │    │   Data Storage  │
│   (Frontend)    │◄──►│   Server        │◄──►│   (NVS/Flash)   │
└─────────────────┘    └─────────────────┘    └─────────────────┘
                              │
                              ▼
                       ┌─────────────────┐
                       │   Sensor Data   │
                       │   Processing    │
                       └─────────────────┘

🛣️ Маршрутизация

// Файл: src/web/routes_data.cpp

void setupDataRoutes() {
    // Основные маршруты данных
    server.on("/readings", HTTP_GET, handleReadings);
    server.on("/intervals", HTTP_GET, handleIntervals);
    server.on("/config_manager", HTTP_GET, handleConfigManager);
    server.on("/updates", HTTP_GET, handleUpdates);
    server.on("/service", HTTP_GET, handleService);
}
📋 План рефакторинга QA 2025 H2

📋 План рефакторинга QA 2025 H2

🎯 Цели рефакторинга

🔧 Приоритетные задачи

🔥 Высокий приоритет

  • Исправление критических багов
  • Оптимизация памяти
  • Улучшение обработки ошибок

⚡ Средний приоритет

  • Рефакторинг устаревшего кода
  • Улучшение документации
  • Оптимизация алгоритмов

📈 Низкий приоритет

  • Косметические улучшения
  • Дополнительные функции
  • Расширенная документация
📊 Отчет о техническом долге 2025-06

📊 Отчет о техническом долге 2025-06

📈 Общая оценка

Технический долг проекта находится на приемлемом уровне. Основные области для улучшения:

🔴 Высокий технический долг

  • Устаревшие алгоритмы компенсации
  • Неоптимальное использование памяти
  • Отсутствие полного покрытия тестами

🟡 Средний технический долг

  • Дублирование кода в некоторых модулях
  • Недостаточная документация API
  • Сложность некоторых функций

🟢 Низкий технический долг

  • Хорошая архитектура в целом
  • Консистентное именование
  • Понятная структура проекта

🎯 Рекомендации

🏗️ Общая архитектура JXCT v3.4.9

🏗️ Общая архитектура JXCT v3.4.9

Версия документа: 3.4.9
Дата обновления: 2025-06-24
Статус: Актуальная архитектура с фокусом на стабильность

🎯 ПРИНЦИПЫ АРХИТЕКТУРЫ

1. Стабильность превыше всего

2. Модульность и переиспользование

3. Производительность и эффективность

🔧 ОСНОВНЫЕ КОМПОНЕНТЫ

📡 СИСТЕМА ДАТЧИКОВ

🔌 Абстракция датчиков

// Файл: include/ISensor.h

class ISensor {
public:
    virtual ~ISensor() = default;
    virtual bool initialize() = 0;
    virtual SensorData read() = 0;
    virtual bool isConnected() const = 0;
    virtual String getSensorInfo() const = 0;
};

🎭 Адаптеры датчиков

// Файл: src/modbus_sensor.h

class ModbusSensorAdapter : public ISensor {
private:
    ModbusSensor* sensor;
    
public:
    ModbusSensorAdapter(ModbusSensor* s) : sensor(s) {}
    
    bool initialize() override {
        return sensor->begin();
    }
    
    SensorData read() override {
        return sensor->getData();
    }
    
    bool isConnected() const override {
        return sensor->isConnected();
    }
    
    String getSensorInfo() const override {
        return "Modbus Sensor v" + String(sensor->getVersion());
    }
};

🧮 СИСТЕМА КОМПЕНСАЦИИ

✅ ИСПРАВЛЕННАЯ ДВУХЭТАПНАЯ КОМПЕНСАЦИЯ

// Файл: src/modbus_sensor.cpp

void applyCompensationIfEnabled(SensorData& d, const SoilProfile& profile) {
    // ШАГ 1: Применяем калибровочную таблицу CSV (лабораторная поверка)
    float tempCalibrated = CalibrationManager::applyCalibration(d.temperature, profile);
    float humCalibrated = CalibrationManager::applyCalibration(d.humidity, profile);
    float ecCalibrated = CalibrationManager::applyCalibration(d.ec, profile);
    float phCalibrated = CalibrationManager::applyCalibration(d.ph, profile);
    float nCalibrated = CalibrationManager::applyCalibration(d.nitrogen, profile);
    float pCalibrated = CalibrationManager::applyCalibration(d.phosphorus, profile);
    float kCalibrated = CalibrationManager::applyCalibration(d.potassium, profile);

    // ШАГ 2: Применяем математическую компенсацию (температурная, влажностная)
    float ec25 = ecCalibrated / (1.0f + 0.021f * (tempCalibrated - 25.0f));
    d.ec = correctEC(ec25, tempCalibrated, humCalibrated, profile.soilType);
    d.ph = correctPH(phCalibrated, tempCalibrated);
    correctNPK(tempCalibrated, humCalibrated, d.nitrogen, d.phosphorus, d.potassium, profile.soilType);
}

🔧 Калибровочный менеджер

// Файл: src/calibration_manager.cpp

class CalibrationManager {
public:
    // Применение калибровочной таблицы с линейной интерполяцией
    static float applyCalibration(float rawValue, const CalibrationProfile& profile) {
        if (!profile.isLoaded()) {
            return rawValue; // Возвращаем исходное значение если таблица не загружена
        }
        
        // Поиск ближайших точек калибровки
        CalibrationPoint lower, upper;
        if (profile.findInterpolationPoints(rawValue, lower, upper)) {
            // Линейная интерполяция
            float ratio = (rawValue - lower.raw) / (upper.raw - lower.raw);
            return lower.calibrated + ratio * (upper.calibrated - lower.calibrated);
        }
        
        return rawValue; // Вне диапазона калибровки
    }
};

1️⃣ Модель Арчи - EC компенсация

float correctEC(float ec25, float temperature, float humidity, SoilType soilType) {
    // Температурная компенсация (Archie, 1942)
    float tempFactor = 1.0f + 0.021f * (temperature - 25.0f);
    
    // Влажностная компенсация по модели Арчи
    float porosity = getPorosity(soilType);
    float archieCoeff = getArchieCoefficient(soilType);
    float humFactor = pow(humidity / 100.0f, archieCoeff);
    
    return ec25 * tempFactor * humFactor;
}

float getArchieCoefficient(SoilType soilType) {
    switch (soilType) {
        case SAND: return 0.15f;      // Песок
        case LOAM: return 0.30f;      // Суглинок
        case CLAY: return 0.45f;      // Глина
        case PEAT: return 0.10f;      // Торф
        case SANDY_PEAT: return 0.18f; // Песчано-торфяной
        default: return 0.30f;
    }
}

2️⃣ Уравнение Нернста - pH компенсация

float correctPH(float phRaw, float temperature) {
    // Температурная поправка pH по уравнению Нернста
    // dE/dT = -0.003 V/°C для pH электрода
    return phRaw - 0.003f * (temperature - 25.0f);
}

3️⃣ FAO 56 + Eur. J. Soil Sci. - NPK компенсация

void correctNPK(float temperature, float humidity, 
                float& nitrogen, float& phosphorus, float& potassium, 
                SoilType soilType) {
    // Температурная компенсация NPK
    float tempFactor = 1.0f - 0.02f * (temperature - 25.0f);
    
    // Влажностная компенсация по FAO 56
    float humFactor = 1.0f + 0.05f * (humidity - 50.0f) / 50.0f;
    
    // Применение компенсации
    nitrogen *= tempFactor * humFactor;
    phosphorus *= tempFactor * humFactor;
    potassium *= tempFactor * humFactor;
}

🌐 ВЕБ-ИНТЕРФЕЙС

📱 Архитектура веб-интерфейса

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   Web Browser   │    │   ESP32 Web     │    │   Data Storage  │
│   (Frontend)    │◄──►│   Server        │◄──►│   (NVS/Flash)   │
└─────────────────┘    └─────────────────┘    └─────────────────┘
                              │
                              ▼
                       ┌─────────────────┐
                       │   Sensor Data   │
                       │   Processing    │
                       └─────────────────┘

🛣️ Маршрутизация

// Файл: src/web/routes_data.cpp

void setupDataRoutes() {
    // Основные маршруты данных
    server.on("/readings", HTTP_GET, handleReadings);
    server.on("/intervals", HTTP_GET, handleIntervals);
    server.on("/config_manager", HTTP_GET, handleConfigManager);
    server.on("/updates", HTTP_GET, handleUpdates);
    server.on("/service", HTTP_GET, handleService);
}
📋 План рефакторинга QA 2025 H2

📋 План рефакторинга QA 2025 H2

🎯 Цели рефакторинга

🔧 Приоритетные задачи

🔥 Высокий приоритет

  • Исправление критических багов
  • Оптимизация памяти
  • Улучшение обработки ошибок

⚡ Средний приоритет

  • Рефакторинг устаревшего кода
  • Улучшение документации
  • Оптимизация алгоритмов

📈 Низкий приоритет

  • Косметические улучшения
  • Дополнительные функции
  • Расширенная документация
📊 Отчет о техническом долге 2025-06

📊 Отчет о техническом долге 2025-06

📈 Общая оценка

Технический долг проекта находится на приемлемом уровне. Основные области для улучшения:

🔴 Высокий технический долг

  • Устаревшие алгоритмы компенсации
  • Неоптимальное использование памяти
  • Отсутствие полного покрытия тестами

🟡 Средний технический долг

  • Дублирование кода в некоторых модулях
  • Недостаточная документация API
  • Сложность некоторых функций

🟢 Низкий технический долг

  • Хорошая архитектура в целом
  • Консистентное именование
  • Понятная структура проекта

🎯 Рекомендации

🏗️ Общая архитектура JXCT v3.4.9

🏗️ Общая архитектура JXCT v3.4.9

Версия документа: 3.4.9
Дата обновления: 2025-06-24
Статус: Актуальная архитектура с фокусом на стабильность

🎯 ПРИНЦИПЫ АРХИТЕКТУРЫ

1. Стабильность превыше всего

2. Модульность и переиспользование

3. Производительность и эффективность

🔧 ОСНОВНЫЕ КОМПОНЕНТЫ

📡 СИСТЕМА ДАТЧИКОВ

🔌 Абстракция датчиков

// Файл: include/ISensor.h

class ISensor {
public:
    virtual ~ISensor() = default;
    virtual bool initialize() = 0;
    virtual SensorData read() = 0;
    virtual bool isConnected() const = 0;
    virtual String getSensorInfo() const = 0;
};

🎭 Адаптеры датчиков

// Файл: src/modbus_sensor.h

class ModbusSensorAdapter : public ISensor {
private:
    ModbusSensor* sensor;
    
public:
    ModbusSensorAdapter(ModbusSensor* s) : sensor(s) {}
    
    bool initialize() override {
        return sensor->begin();
    }
    
    SensorData read() override {
        return sensor->getData();
    }
    
    bool isConnected() const override {
        return sensor->isConnected();
    }
    
    String getSensorInfo() const override {
        return "Modbus Sensor v" + String(sensor->getVersion());
    }
};

🧮 СИСТЕМА КОМПЕНСАЦИИ

✅ ИСПРАВЛЕННАЯ ДВУХЭТАПНАЯ КОМПЕНСАЦИЯ

// Файл: src/modbus_sensor.cpp

void applyCompensationIfEnabled(SensorData& d, const SoilProfile& profile) {
    // ШАГ 1: Применяем калибровочную таблицу CSV (лабораторная поверка)
    float tempCalibrated = CalibrationManager::applyCalibration(d.temperature, profile);
    float humCalibrated = CalibrationManager::applyCalibration(d.humidity, profile);
    float ecCalibrated = CalibrationManager::applyCalibration(d.ec, profile);
    float phCalibrated = CalibrationManager::applyCalibration(d.ph, profile);
    float nCalibrated = CalibrationManager::applyCalibration(d.nitrogen, profile);
    float pCalibrated = CalibrationManager::applyCalibration(d.phosphorus, profile);
    float kCalibrated = CalibrationManager::applyCalibration(d.potassium, profile);

    // ШАГ 2: Применяем математическую компенсацию (температурная, влажностная)
    float ec25 = ecCalibrated / (1.0f + 0.021f * (tempCalibrated - 25.0f));
    d.ec = correctEC(ec25, tempCalibrated, humCalibrated, profile.soilType);
    d.ph = correctPH(phCalibrated, tempCalibrated);
    correctNPK(tempCalibrated, humCalibrated, d.nitrogen, d.phosphorus, d.potassium, profile.soilType);
}

🔧 Калибровочный менеджер

// Файл: src/calibration_manager.cpp

class CalibrationManager {
public:
    // Применение калибровочной таблицы с линейной интерполяцией
    static float applyCalibration(float rawValue, const CalibrationProfile& profile) {
        if (!profile.isLoaded()) {
            return rawValue; // Возвращаем исходное значение если таблица не загружена
        }
        
        // Поиск ближайших точек калибровки
        CalibrationPoint lower, upper;
        if (profile.findInterpolationPoints(rawValue, lower, upper)) {
            // Линейная интерполяция
            float ratio = (rawValue - lower.raw) / (upper.raw - lower.raw);
            return lower.calibrated + ratio * (upper.calibrated - lower.calibrated);
        }
        
        return rawValue; // Вне диапазона калибровки
    }
};

1️⃣ Модель Арчи - EC компенсация

float correctEC(float ec25, float temperature, float humidity, SoilType soilType) {
    // Температурная компенсация (Archie, 1942)
    float tempFactor = 1.0f + 0.021f * (temperature - 25.0f);
    
    // Влажностная компенсация по модели Арчи
    float porosity = getPorosity(soilType);
    float archieCoeff = getArchieCoefficient(soilType);
    float humFactor = pow(humidity / 100.0f, archieCoeff);
    
    return ec25 * tempFactor * humFactor;
}

float getArchieCoefficient(SoilType soilType) {
    switch (soilType) {
        case SAND: return 0.15f;      // Песок
        case LOAM: return 0.30f;      // Суглинок
        case CLAY: return 0.45f;      // Глина
        case PEAT: return 0.10f;      // Торф
        case SANDY_PEAT: return 0.18f; // Песчано-торфяной
        default: return 0.30f;
    }
}

2️⃣ Уравнение Нернста - pH компенсация

float correctPH(float phRaw, float temperature) {
    // Температурная поправка pH по уравнению Нернста
    // dE/dT = -0.003 V/°C для pH электрода
    return phRaw - 0.003f * (temperature - 25.0f);
}

3️⃣ FAO 56 + Eur. J. Soil Sci. - NPK компенсация

void correctNPK(float temperature, float humidity, 
                float& nitrogen, float& phosphorus, float& potassium, 
                SoilType soilType) {
    // Температурная компенсация NPK
    float tempFactor = 1.0f - 0.02f * (temperature - 25.0f);
    
    // Влажностная компенсация по FAO 56
    float humFactor = 1.0f + 0.05f * (humidity - 50.0f) / 50.0f;
    
    // Применение компенсации
    nitrogen *= tempFactor * humFactor;
    phosphorus *= tempFactor * humFactor;
    potassium *= tempFactor * humFactor;
}

🌐 ВЕБ-ИНТЕРФЕЙС

📱 Архитектура веб-интерфейса

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   Web Browser   │    │   ESP32 Web     │    │   Data Storage  │
│   (Frontend)    │◄──►│   Server        │◄──►│   (NVS/Flash)   │
└─────────────────┘    └─────────────────┘    └─────────────────┘
                              │
                              ▼
                       ┌─────────────────┐
                       │   Sensor Data   │
                       │   Processing    │
                       └─────────────────┘

🛣️ Маршрутизация

// Файл: src/web/routes_data.cpp

void setupDataRoutes() {
    // Основные маршруты данных
    server.on("/readings", HTTP_GET, handleReadings);
    server.on("/intervals", HTTP_GET, handleIntervals);
    server.on("/config_manager", HTTP_GET, handleConfigManager);
    server.on("/updates", HTTP_GET, handleUpdates);
    server.on("/service", HTTP_GET, handleService);
}
📋 План рефакторинга QA 2025 H2

📋 План рефакторинга QA 2025 H2

🎯 Цели рефакторинга

🔧 Приоритетные задачи

🔥 Высокий приоритет

  • Исправление критических багов
  • Оптимизация памяти
  • Улучшение обработки ошибок

⚡ Средний приоритет

  • Рефакторинг устаревшего кода
  • Улучшение документации
  • Оптимизация алгоритмов

📈 Низкий приоритет

  • Косметические улучшения
  • Дополнительные функции
  • Расширенная документация
📊 Отчет о техническом долге 2025-06

📊 Отчет о техническом долге 2025-06

📈 Общая оценка

Технический долг проекта находится на приемлемом уровне. Основные области для улучшения:

🔴 Высокий технический долг

  • Устаревшие алгоритмы компенсации
  • Неоптимальное использование памяти
  • Отсутствие полного покрытия тестами

🟡 Средний технический долг

  • Дублирование кода в некоторых модулях
  • Недостаточная документация API
  • Сложность некоторых функций

🟢 Низкий технический долг

  • Хорошая архитектура в целом
  • Консистентное именование
  • Понятная структура проекта

🎯 Рекомендации

🏗️ Общая архитектура JXCT v3.4.9

🏗️ Общая архитектура JXCT v3.4.9

Версия документа: 3.4.9
Дата обновления: 2025-06-24
Статус: Актуальная архитектура с фокусом на стабильность

🎯 ПРИНЦИПЫ АРХИТЕКТУРЫ

1. Стабильность превыше всего

2. Модульность и переиспользование

3. Производительность и эффективность

🔧 ОСНОВНЫЕ КОМПОНЕНТЫ

📡 СИСТЕМА ДАТЧИКОВ

🔌 Абстракция датчиков

// Файл: include/ISensor.h

class ISensor {
public:
    virtual ~ISensor() = default;
    virtual bool initialize() = 0;
    virtual SensorData read() = 0;
    virtual bool isConnected() const = 0;
    virtual String getSensorInfo() const = 0;
};

🎭 Адаптеры датчиков

// Файл: src/modbus_sensor.h

class ModbusSensorAdapter : public ISensor {
private:
    ModbusSensor* sensor;
    
public:
    ModbusSensorAdapter(ModbusSensor* s) : sensor(s) {}
    
    bool initialize() override {
        return sensor->begin();
    }
    
    SensorData read() override {
        return sensor->getData();
    }
    
    bool isConnected() const override {
        return sensor->isConnected();
    }
    
    String getSensorInfo() const override {
        return "Modbus Sensor v" + String(sensor->getVersion());
    }
};

🧮 СИСТЕМА КОМПЕНСАЦИИ

✅ ИСПРАВЛЕННАЯ ДВУХЭТАПНАЯ КОМПЕНСАЦИЯ

// Файл: src/modbus_sensor.cpp

void applyCompensationIfEnabled(SensorData& d, const SoilProfile& profile) {
    // ШАГ 1: Применяем калибровочную таблицу CSV (лабораторная поверка)
    float tempCalibrated = CalibrationManager::applyCalibration(d.temperature, profile);
    float humCalibrated = CalibrationManager::applyCalibration(d.humidity, profile);
    float ecCalibrated = CalibrationManager::applyCalibration(d.ec, profile);
    float phCalibrated = CalibrationManager::applyCalibration(d.ph, profile);
    float nCalibrated = CalibrationManager::applyCalibration(d.nitrogen, profile);
    float pCalibrated = CalibrationManager::applyCalibration(d.phosphorus, profile);
    float kCalibrated = CalibrationManager::applyCalibration(d.potassium, profile);

    // ШАГ 2: Применяем математическую компенсацию (температурная, влажностная)
    float ec25 = ecCalibrated / (1.0f + 0.021f * (tempCalibrated - 25.0f));
    d.ec = correctEC(ec25, tempCalibrated, humCalibrated, profile.soilType);
    d.ph = correctPH(phCalibrated, tempCalibrated);
    correctNPK(tempCalibrated, humCalibrated, d.nitrogen, d.phosphorus, d.potassium, profile.soilType);
}

🔧 Калибровочный менеджер

// Файл: src/calibration_manager.cpp

class CalibrationManager {
public:
    // Применение калибровочной таблицы с линейной интерполяцией
    static float applyCalibration(float rawValue, const CalibrationProfile& profile) {
        if (!profile.isLoaded()) {
            return rawValue; // Возвращаем исходное значение если таблица не загружена
        }
        
        // Поиск ближайших точек калибровки
        CalibrationPoint lower, upper;
        if (profile.findInterpolationPoints(rawValue, lower, upper)) {
            // Линейная интерполяция
            float ratio = (rawValue - lower.raw) / (upper.raw - lower.raw);
            return lower.calibrated + ratio * (upper.calibrated - lower.calibrated);
        }
        
        return rawValue; // Вне диапазона калибровки
    }
};

1️⃣ Модель Арчи - EC компенсация

float correctEC(float ec25, float temperature, float humidity, SoilType soilType) {
    // Температурная компенсация (Archie, 1942)
    float tempFactor = 1.0f + 0.021f * (temperature - 25.0f);
    
    // Влажностная компенсация по модели Арчи
    float porosity = getPorosity(soilType);
    float archieCoeff = getArchieCoefficient(soilType);
    float humFactor = pow(humidity / 100.0f, archieCoeff);
    
    return ec25 * tempFactor * humFactor;
}

float getArchieCoefficient(SoilType soilType) {
    switch (soilType) {
        case SAND: return 0.15f;      // Песок
        case LOAM: return 0.30f;      // Суглинок
        case CLAY: return 0.45f;      // Глина
        case PEAT: return 0.10f;      // Торф
        case SANDY_PEAT: return 0.18f; // Песчано-торфяной
        default: return 0.30f;
    }
}

2️⃣ Уравнение Нернста - pH компенсация

float correctPH(float phRaw, float temperature) {
    // Температурная поправка pH по уравнению Нернста
    // dE/dT = -0.003 V/°C для pH электрода
    return phRaw - 0.003f * (temperature - 25.0f);
}

3️⃣ FAO 56 + Eur. J. Soil Sci. - NPK компенсация

void correctNPK(float temperature, float humidity, 
                float& nitrogen, float& phosphorus, float& potassium, 
                SoilType soilType) {
    // Температурная компенсация NPK
    float tempFactor = 1.0f - 0.02f * (temperature - 25.0f);
    
    // Влажностная компенсация по FAO 56
    float humFactor = 1.0f + 0.05f * (humidity - 50.0f) / 50.0f;
    
    // Применение компенсации
    nitrogen *= tempFactor * humFactor;
    phosphorus *= tempFactor * humFactor;
    potassium *= tempFactor * humFactor;
}

🌐 ВЕБ-ИНТЕРФЕЙС

📱 Архитектура веб-интерфейса

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   Web Browser   │    │   ESP32 Web     │    │   Data Storage  │
│   (Frontend)    │◄──►│   Server        │◄──►│   (NVS/Flash)   │
└─────────────────┘    └─────────────────┘    └─────────────────┘
                              │
                              ▼
                       ┌─────────────────┐
                       │   Sensor Data   │
                       │   Processing    │
                       └─────────────────┘

🛣️ Маршрутизация

// Файл: src/web/routes_data.cpp

void setupDataRoutes() {
    // Основные маршруты данных
    server.on("/readings", HTTP_GET, handleReadings);
    server.on("/intervals", HTTP_GET, handleIntervals);
    server.on("/config_manager", HTTP_GET, handleConfigManager);
    server.on("/updates", HTTP_GET, handleUpdates);
    server.on("/service", HTTP_GET, handleService);
}
📋 План рефакторинга QA 2025 H2

📋 План рефакторинга QA 2025 H2

🎯 Цели рефакторинга

🔧 Приоритетные задачи

🔥 Высокий приоритет

  • Исправление критических багов
  • Оптимизация памяти
  • Улучшение обработки ошибок

⚡ Средний приоритет

  • Рефакторинг устаревшего кода
  • Улучшение документации
  • Оптимизация алгоритмов

📈 Низкий приоритет

  • Косметические улучшения
  • Дополнительные функции
  • Расширенная документация
📊 Отчет о техническом долге 2025-06

📊 Отчет о техническом долге 2025-06

📈 Общая оценка

Технический долг проекта находится на приемлемом уровне. Основные области для улучшения:

🔴 Высокий технический долг

  • Устаревшие алгоритмы компенсации
  • Неоптимальное использование памяти
  • Отсутствие полного покрытия тестами

🟡 Средний технический долг

  • Дублирование кода в некоторых модулях
  • Недостаточная документация API
  • Сложность некоторых функций

🟢 Низкий технический долг

  • Хорошая архитектура в целом
  • Консистентное именование
  • Понятная структура проекта

🎯 Рекомендации

🏗️ Общая архитектура JXCT v3.4.9

🏗️ Общая архитектура JXCT v3.4.9

Версия документа: 3.4.9
Дата обновления: 2025-06-24
Статус: Актуальная архитектура с фокусом на стабильность

🎯 ПРИНЦИПЫ АРХИТЕКТУРЫ

1. Стабильность превыше всего

2. Модульность и переиспользование

3. Производительность и эффективность

🔧 ОСНОВНЫЕ КОМПОНЕНТЫ

📡 СИСТЕМА ДАТЧИКОВ

🔌 Абстракция датчиков

// Файл: include/ISensor.h

class ISensor {
public:
    virtual ~ISensor() = default;
    virtual bool initialize() = 0;
    virtual SensorData read() = 0;
    virtual bool isConnected() const = 0;
    virtual String getSensorInfo() const = 0;
};

🎭 Адаптеры датчиков

// Файл: src/modbus_sensor.h

class ModbusSensorAdapter : public ISensor {
private:
    ModbusSensor* sensor;
    
public:
    ModbusSensorAdapter(ModbusSensor* s) : sensor(s) {}
    
    bool initialize() override {
        return sensor->begin();
    }
    
    SensorData read() override {
        return sensor->getData();
    }
    
    bool isConnected() const override {
        return sensor->isConnected();
    }
    
    String getSensorInfo() const override {
        return "Modbus Sensor v" + String(sensor->getVersion());
    }
};

🧮 СИСТЕМА КОМПЕНСАЦИИ

✅ ИСПРАВЛЕННАЯ ДВУХЭТАПНАЯ КОМПЕНСАЦИЯ

// Файл: src/modbus_sensor.cpp

void applyCompensationIfEnabled(SensorData& d, const SoilProfile& profile) {
    // ШАГ 1: Применяем калибровочную таблицу CSV (лабораторная поверка)
    float tempCalibrated = CalibrationManager::applyCalibration(d.temperature, profile);
    float humCalibrated = CalibrationManager::applyCalibration(d.humidity, profile);
    float ecCalibrated = CalibrationManager::applyCalibration(d.ec, profile);
    float phCalibrated = CalibrationManager::applyCalibration(d.ph, profile);
    float nCalibrated = CalibrationManager::applyCalibration(d.nitrogen, profile);
    float pCalibrated = CalibrationManager::applyCalibration(d.phosphorus, profile);
    float kCalibrated = CalibrationManager::applyCalibration(d.potassium, profile);

    // ШАГ 2: Применяем математическую компенсацию (температурная, влажностная)
    float ec25 = ecCalibrated / (1.0f + 0.021f * (tempCalibrated - 25.0f));
    d.ec = correctEC(ec25, tempCalibrated, humCalibrated, profile.soilType);
    d.ph = correctPH(phCalibrated, tempCalibrated);
    correctNPK(tempCalibrated, humCalibrated, d.nitrogen, d.phosphorus, d.potassium, profile.soilType);
}

🔧 Калибровочный менеджер

// Файл: src/calibration_manager.cpp

class CalibrationManager {
public:
    // Применение калибровочной таблицы с линейной интерполяцией
    static float applyCalibration(float rawValue, const CalibrationProfile& profile) {
        if (!profile.isLoaded()) {
            return rawValue; // Возвращаем исходное значение если таблица не загружена
        }
        
        // Поиск ближайших точек калибровки
        CalibrationPoint lower, upper;
        if (profile.findInterpolationPoints(rawValue, lower, upper)) {
            // Линейная интерполяция
            float ratio = (rawValue - lower.raw) / (upper.raw - lower.raw);
            return lower.calibrated + ratio * (upper.calibrated - lower.calibrated);
        }
        
        return rawValue; // Вне диапазона калибровки
    }
};

1️⃣ Модель Арчи - EC компенсация

float correctEC(float ec25, float temperature, float humidity, SoilType soilType) {
    // Температурная компенсация (Archie, 1942)
    float tempFactor = 1.0f + 0.021f * (temperature - 25.0f);
    
    // Влажностная компенсация по модели Арчи
    float porosity = getPorosity(soilType);
    float archieCoeff = getArchieCoefficient(soilType);
    float humFactor = pow(humidity / 100.0f, archieCoeff);
    
    return ec25 * tempFactor * humFactor;
}

float getArchieCoefficient(SoilType soilType) {
    switch (soilType) {
        case SAND: return 0.15f;      // Песок
        case LOAM: return 0.30f;      // Суглинок
        case CLAY: return 0.45f;      // Глина
        case PEAT: return 0.10f;      // Торф
        case SANDY_PEAT: return 0.18f; // Песчано-торфяной
        default: return 0.30f;
    }
}

2️⃣ Уравнение Нернста - pH компенсация

float correctPH(float phRaw, float temperature) {
    // Температурная поправка pH по уравнению Нернста
    // dE/dT = -0.003 V/°C для pH электрода
    return phRaw - 0.003f * (temperature - 25.0f);
}

3️⃣ FAO 56 + Eur. J. Soil Sci. - NPK компенсация

void correctNPK(float temperature, float humidity, 
                float& nitrogen, float& phosphorus, float& potassium, 
                SoilType soilType) {
    // Температурная компенсация NPK
    float tempFactor = 1.0f - 0.02f * (temperature - 25.0f);
    
    // Влажностная компенсация по FAO 56
    float humFactor = 1.0f + 0.05f * (humidity - 50.0f) / 50.0f;
    
    // Применение компенсации
    nitrogen *= tempFactor * humFactor;
    phosphorus *= tempFactor * humFactor;
    potassium *= tempFactor * humFactor;
}

🌐 ВЕБ-ИНТЕРФЕЙС

📱 Архитектура веб-интерфейса

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   Web Browser   │    │   ESP32 Web     │    │   Data Storage  │
│   (Frontend)    │◄──►│   Server        │◄──►│   (NVS/Flash)   │
└─────────────────┘    └─────────────────┘    └─────────────────┘
                              │
                              ▼
                       ┌─────────────────┐
                       │   Sensor Data   │
                       │   Processing    │
                       └─────────────────┘

🛣️ Маршрутизация

// Файл: src/web/routes_data.cpp

void setupDataRoutes() {
    // Основные маршруты данных
    server.on("/readings", HTTP_GET, handleReadings);
    server.on("/intervals", HTTP_GET, handleIntervals);
    server.on("/config_manager", HTTP_GET, handleConfigManager);
    server.on("/updates", HTTP_GET, handleUpdates);
    server.on("/service", HTTP_GET, handleService);
}
📋 План рефакторинга QA 2025 H2

📋 План рефакторинга QA 2025 H2

🎯 Цели рефакторинга

🔧 Приоритетные задачи

🔥 Высокий приоритет

  • Исправление критических багов
  • Оптимизация памяти
  • Улучшение обработки ошибок

⚡ Средний приоритет

  • Рефакторинг устаревшего кода
  • Улучшение документации
  • Оптимизация алгоритмов

📈 Низкий приоритет

  • Косметические улучшения
  • Дополнительные функции
  • Расширенная документация
📊 Отчет о техническом долге 2025-06

📊 Отчет о техническом долге 2025-06

📈 Общая оценка

Технический долг проекта находится на приемлемом уровне. Основные области для улучшения:

🔴 Высокий технический долг

  • Устаревшие алгоритмы компенсации
  • Неоптимальное использование памяти
  • Отсутствие полного покрытия тестами

🟡 Средний технический долг

  • Дублирование кода в некоторых модулях
  • Недостаточная документация API
  • Сложность некоторых функций

🟢 Низкий технический долг

  • Хорошая архитектура в целом
  • Консистентное именование
  • Понятная структура проекта

🎯 Рекомендации

🏗️ Общая архитектура JXCT v3.4.9

🏗️ Общая архитектура JXCT v3.4.9

Версия документа: 3.4.9
Дата обновления: 2025-06-24
Статус: Актуальная архитектура с фокусом на стабильность

🎯 ПРИНЦИПЫ АРХИТЕКТУРЫ

1. Стабильность превыше всего

2. Модульность и переиспользование

3. Производительность и эффективность

🔧 ОСНОВНЫЕ КОМПОНЕНТЫ

📡 СИСТЕМА ДАТЧИКОВ

🔌 Абстракция датчиков

// Файл: include/ISensor.h

class ISensor {
public:
    virtual ~ISensor() = default;
    virtual bool initialize() = 0;
    virtual SensorData read() = 0;
    virtual bool isConnected() const = 0;
    virtual String getSensorInfo() const = 0;
};

🎭 Адаптеры датчиков

// Файл: src/modbus_sensor.h

class ModbusSensorAdapter : public ISensor {
private:
    ModbusSensor* sensor;
    
public:
    ModbusSensorAdapter(ModbusSensor* s) : sensor(s) {}
    
    bool initialize() override {
        return sensor->begin();
    }
    
    SensorData read() override {
        return sensor->getData();
    }
    
    bool isConnected() const override {
        return sensor->isConnected();
    }
    
    String getSensorInfo() const override {
        return "Modbus Sensor v" + String(sensor->getVersion());
    }
};

🧮 СИСТЕМА КОМПЕНСАЦИИ

✅ ИСПРАВЛЕННАЯ ДВУХЭТАПНАЯ КОМПЕНСАЦИЯ

// Файл: src/modbus_sensor.cpp

void applyCompensationIfEnabled(SensorData& d, const SoilProfile& profile) {
    // ШАГ 1: Применяем калибровочную таблицу CSV (лабораторная поверка)
    float tempCalibrated = CalibrationManager::applyCalibration(d.temperature, profile);
    float humCalibrated = CalibrationManager::applyCalibration(d.humidity, profile);
    float ecCalibrated = CalibrationManager::applyCalibration(d.ec, profile);
    float phCalibrated = CalibrationManager::applyCalibration(d.ph, profile);
    float nCalibrated = CalibrationManager::applyCalibration(d.nitrogen, profile);
    float pCalibrated = CalibrationManager::applyCalibration(d.phosphorus, profile);
    float kCalibrated = CalibrationManager::applyCalibration(d.potassium, profile);

    // ШАГ 2: Применяем математическую компенсацию (температурная, влажностная)
    float ec25 = ecCalibrated / (1.0f + 0.021f * (tempCalibrated - 25.0f));
    d.ec = correctEC(ec25, tempCalibrated, humCalibrated, profile.soilType);
    d.ph = correctPH(phCalibrated, tempCalibrated);
    correctNPK(tempCalibrated, humCalibrated, d.nitrogen, d.phosphorus, d.potassium, profile.soilType);
}

🔧 Калибровочный менеджер

// Файл: src/calibration_manager.cpp

class CalibrationManager {
public:
    // Применение калибровочной таблицы с линейной интерполяцией
    static float applyCalibration(float rawValue, const CalibrationProfile& profile) {
        if (!profile.isLoaded()) {
            return rawValue; // Возвращаем исходное значение если таблица не загружена
        }
        
        // Поиск ближайших точек калибровки
        CalibrationPoint lower, upper;
        if (profile.findInterpolationPoints(rawValue, lower, upper)) {
            // Линейная интерполяция
            float ratio = (rawValue - lower.raw) / (upper.raw - lower.raw);
            return lower.calibrated + ratio * (upper.calibrated - lower.calibrated);
        }
        
        return rawValue; // Вне диапазона калибровки
    }
};

1️⃣ Модель Арчи - EC компенсация

float correctEC(float ec25, float temperature, float humidity, SoilType soilType) {
    // Температурная компенсация (Archie, 1942)
    float tempFactor = 1.0f + 0.021f * (temperature - 25.0f);
    
    // Влажностная компенсация по модели Арчи
    float porosity = getPorosity(soilType);
    float archieCoeff = getArchieCoefficient(soilType);
    float humFactor = pow(humidity / 100.0f, archieCoeff);
    
    return ec25 * tempFactor * humFactor;
}

float getArchieCoefficient(SoilType soilType) {
    switch (soilType) {
        case SAND: return 0.15f;      // Песок
        case LOAM: return 0.30f;      // Суглинок
        case CLAY: return 0.45f;      // Глина
        case PEAT: return 0.10f;      // Торф
        case SANDY_PEAT: return 0.18f; // Песчано-торфяной
        default: return 0.30f;
    }
}

2️⃣ Уравнение Нернста - pH компенсация

float correctPH(float phRaw, float temperature) {
    // Температурная поправка pH по уравнению Нернста
    // dE/dT = -0.003 V/°C для pH электрода
    return phRaw - 0.003f * (temperature - 25.0f);
}

3️⃣ FAO 56 + Eur. J. Soil Sci. - NPK компенсация

void correctNPK(float temperature, float humidity, 
                float& nitrogen, float& phosphorus, float& potassium, 
                SoilType soilType) {
    // Температурная компенсация NPK
    float tempFactor = 1.0f - 0.02f * (temperature - 25.0f);
    
    // Влажностная компенсация по FAO 56
    float humFactor = 1.0f + 0.05f * (humidity - 50.0f) / 50.0f;
    
    // Применение компенсации
    nitrogen *= tempFactor * humFactor;
    phosphorus *= tempFactor * humFactor;
    potassium *= tempFactor * humFactor;
}

🌐 ВЕБ-ИНТЕРФЕЙС

📱 Архитектура веб-интерфейса

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   Web Browser   │    │   ESP32 Web     │    │   Data Storage  │
│   (Frontend)    │◄──►│   Server        │◄──►│   (NVS/Flash)   │
└─────────────────┘    └─────────────────┘    └─────────────────┘
                              │
                              ▼
                       ┌─────────────────┐
                       │   Sensor Data   │
                       │   Processing    │
                       └─────────────────┘

🛣️ Маршрутизация

// Файл: src/web/routes_data.cpp

void setupDataRoutes() {
    // Основные маршруты данных
    server.on("/readings", HTTP_GET, handleReadings);
    server.on("/intervals", HTTP_GET, handleIntervals);
    server.on("/config_manager", HTTP_GET, handleConfigManager);
    server.on("/updates", HTTP_GET, handleUpdates);
    server.on("/service", HTTP_GET, handleService);
}
📋 План рефакторинга QA 2025 H2

📋 План рефакторинга QA 2025 H2

🎯 Цели рефакторинга

🔧 Приоритетные задачи

🔥 Высокий приоритет

  • Исправление критических багов
  • Оптимизация памяти
  • Улучшение обработки ошибок

⚡ Средний приоритет

  • Рефакторинг устаревшего кода
  • Улучшение документации
  • Оптимизация алгоритмов

📈 Низкий приоритет

  • Косметические улучшения
  • Дополнительные функции
  • Расширенная документация
📊 Отчет о техническом долге 2025-06

📊 Отчет о техническом долге 2025-06

📈 Общая оценка

Технический долг проекта находится на приемлемом уровне. Основные области для улучшения:

🔴 Высокий технический долг

  • Устаревшие алгоритмы компенсации
  • Неоптимальное использование памяти
  • Отсутствие полного покрытия тестами

🟡 Средний технический долг

  • Дублирование кода в некоторых модулях
  • Недостаточная документация API
  • Сложность некоторых функций

🟢 Низкий технический долг

  • Хорошая архитектура в целом
  • Консистентное именование
  • Понятная структура проекта

🎯 Рекомендации

🏗️ Общая архитектура JXCT v3.4.9

🏗️ Общая архитектура JXCT v3.4.9

Версия документа: 3.4.9
Дата обновления: 2025-06-24
Статус: Актуальная архитектура с фокусом на стабильность

🎯 ПРИНЦИПЫ АРХИТЕКТУРЫ

1. Стабильность превыше всего

2. Модульность и переиспользование

3. Производительность и эффективность

🔧 ОСНОВНЫЕ КОМПОНЕНТЫ

📡 СИСТЕМА ДАТЧИКОВ

🔌 Абстракция датчиков

// Файл: include/ISensor.h

class ISensor {
public:
    virtual ~ISensor() = default;
    virtual bool initialize() = 0;
    virtual SensorData read() = 0;
    virtual bool isConnected() const = 0;
    virtual String getSensorInfo() const = 0;
};

🎭 Адаптеры датчиков

// Файл: src/modbus_sensor.h

class ModbusSensorAdapter : public ISensor {
private:
    ModbusSensor* sensor;
    
public:
    ModbusSensorAdapter(ModbusSensor* s) : sensor(s) {}
    
    bool initialize() override {
        return sensor->begin();
    }
    
    SensorData read() override {
        return sensor->getData();
    }
    
    bool isConnected() const override {
        return sensor->isConnected();
    }
    
    String getSensorInfo() const override {
        return "Modbus Sensor v" + String(sensor->getVersion());
    }
};

🧮 СИСТЕМА КОМПЕНСАЦИИ

✅ ИСПРАВЛЕННАЯ ДВУХЭТАПНАЯ КОМПЕНСАЦИЯ

// Файл: src/modbus_sensor.cpp

void applyCompensationIfEnabled(SensorData& d, const SoilProfile& profile) {
    // ШАГ 1: Применяем калибровочную таблицу CSV (лабораторная поверка)
    float tempCalibrated = CalibrationManager::applyCalibration(d.temperature, profile);
    float humCalibrated = CalibrationManager::applyCalibration(d.humidity, profile);
    float ecCalibrated = CalibrationManager::applyCalibration(d.ec, profile);
    float phCalibrated = CalibrationManager::applyCalibration(d.ph, profile);
    float nCalibrated = CalibrationManager::applyCalibration(d.nitrogen, profile);
    float pCalibrated = CalibrationManager::applyCalibration(d.phosphorus, profile);
    float kCalibrated = CalibrationManager::applyCalibration(d.potassium, profile);

    // ШАГ 2: Применяем математическую компенсацию (температурная, влажностная)
    float ec25 = ecCalibrated / (1.0f + 0.021f * (tempCalibrated - 25.0f));
    d.ec = correctEC(ec25, tempCalibrated, humCalibrated, profile.soilType);
    d.ph = correctPH(phCalibrated, tempCalibrated);
    correctNPK(tempCalibrated, humCalibrated, d.nitrogen, d.phosphorus, d.potassium, profile.soilType);
}

🔧 Калибровочный менеджер

// Файл: src/calibration_manager.cpp

class CalibrationManager {
public:
    // Применение калибровочной таблицы с линейной интерполяцией
    static float applyCalibration(float rawValue, const CalibrationProfile& profile) {
        if (!profile.isLoaded()) {
            return rawValue; // Возвращаем исходное значение если таблица не загружена
        }
        
        // Поиск ближайших точек калибровки
        CalibrationPoint lower, upper;
        if (profile.findInterpolationPoints(rawValue, lower, upper)) {
            // Линейная интерполяция
            float ratio = (rawValue - lower.raw) / (upper.raw - lower.raw);
            return lower.calibrated + ratio * (upper.calibrated - lower.calibrated);
        }
        
        return rawValue; // Вне диапазона калибровки
    }
};

1️⃣ Модель Арчи - EC компенсация

float correctEC(float ec25, float temperature, float humidity, SoilType soilType) {
    // Температурная компенсация (Archie, 1942)
    float tempFactor = 1.0f + 0.021f * (temperature - 25.0f);
    
    // Влажностная компенсация по модели Арчи
    float porosity = getPorosity(soilType);
    float archieCoeff = getArchieCoefficient(soilType);
    float humFactor = pow(humidity / 100.0f, archieCoeff);
    
    return ec25 * tempFactor * humFactor;
}

float getArchieCoefficient(SoilType soilType) {
    switch (soilType) {
        case SAND: return 0.15f;      // Песок
        case LOAM: return 0.30f;      // Суглинок
        case CLAY: return 0.45f;      // Глина
        case PEAT: return 0.10f;      // Торф
        case SANDY_PEAT: return 0.18f; // Песчано-торфяной
        default: return 0.30f;
    }
}

2️⃣ Уравнение Нернста - pH компенсация

float correctPH(float phRaw, float temperature) {
    // Температурная поправка pH по уравнению Нернста
    // dE/dT = -0.003 V/°C для pH электрода
    return phRaw - 0.003f * (temperature - 25.0f);
}

3️⃣ FAO 56 + Eur. J. Soil Sci. - NPK компенсация

void correctNPK(float temperature, float humidity, 
                float& nitrogen, float& phosphorus, float& potassium, 
                SoilType soilType) {
    // Температурная компенсация NPK
    float tempFactor = 1.0f - 0.02f * (temperature - 25.0f);
    
    // Влажностная компенсация по FAO 56
    float humFactor = 1.0f + 0.05f * (humidity - 50.0f) / 50.0f;
    
    // Применение компенсации
    nitrogen *= tempFactor * humFactor;
    phosphorus *= tempFactor * humFactor;
    potassium *= tempFactor * humFactor;
}

🌐 ВЕБ-ИНТЕРФЕЙС

📱 Архитектура веб-интерфейса

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   Web Browser   │    │   ESP32 Web     │    │   Data Storage  │
│   (Frontend)    │◄──►│   Server        │◄──►│   (NVS/Flash)   │
└─────────────────┘    └─────────────────┘    └─────────────────┘
                              │
                              ▼
                       ┌─────────────────┐
                       │   Sensor Data   │
                       │   Processing    │
                       └─────────────────┘

🛣️ Маршрутизация

// Файл: src/web/routes_data.cpp

void setupDataRoutes() {
    // Основные маршруты данных
    server.on("/readings", HTTP_GET, handleReadings);
    server.on("/intervals", HTTP_GET, handleIntervals);
    server.on("/config_manager", HTTP_GET, handleConfigManager);
    server.on("/updates", HTTP_GET, handleUpdates);
    server.on("/service", HTTP_GET, handleService);
}
📋 План рефакторинга QA 2025 H2

📋 План рефакторинга QA 2025 H2

🎯 Цели рефакторинга

🔧 Приоритетные задачи

🔥 Высокий приоритет

  • Исправление критических багов
  • Оптимизация памяти
  • Улучшение обработки ошибок

⚡ Средний приоритет

  • Рефакторинг устаревшего кода
  • Улучшение документации
  • Оптимизация алгоритмов

📈 Низкий приоритет

  • Косметические улучшения
  • Дополнительные функции
  • Расширенная документация
📊 Отчет о техническом долге 2025-06

📊 Отчет о техническом долге 2025-06

📈 Общая оценка

Технический долг проекта находится на приемлемом уровне. Основные области для улучшения:

🔴 Высокий технический долг

  • Устаревшие алгоритмы компенсации
  • Неоптимальное использование памяти
  • Отсутствие полного покрытия тестами

🟡 Средний технический долг

  • Дублирование кода в некоторых модулях
  • Недостаточная документация API
  • Сложность некоторых функций

🟢 Низкий технический долг

  • Хорошая архитектура в целом
  • Консистентное именование
  • Понятная структура проекта

🎯 Рекомендации

🏗️ Общая архитектура JXCT v3.4.9

🏗️ Общая архитектура JXCT v3.4.9

Версия документа: 3.4.9
Дата обновления: 2025-06-24
Статус: Актуальная архитектура с фокусом на стабильность

🎯 ПРИНЦИПЫ АРХИТЕКТУРЫ

1. Стабильность превыше всего

2. Модульность и переиспользование

3. Производительность и эффективность

🔧 ОСНОВНЫЕ КОМПОНЕНТЫ

📡 СИСТЕМА ДАТЧИКОВ

🔌 Абстракция датчиков

// Файл: include/ISensor.h

class ISensor {
public:
    virtual ~ISensor() = default;
    virtual bool initialize() = 0;
    virtual SensorData read() = 0;
    virtual bool isConnected() const = 0;
    virtual String getSensorInfo() const = 0;
};

🎭 Адаптеры датчиков

// Файл: src/modbus_sensor.h

class ModbusSensorAdapter : public ISensor {
private:
    ModbusSensor* sensor;
    
public:
    ModbusSensorAdapter(ModbusSensor* s) : sensor(s) {}
    
    bool initialize() override {
        return sensor->begin();
    }
    
    SensorData read() override {
        return sensor->getData();
    }
    
    bool isConnected() const override {
        return sensor->isConnected();
    }
    
    String getSensorInfo() const override {
        return "Modbus Sensor v" + String(sensor->getVersion());
    }
};

🧮 СИСТЕМА КОМПЕНСАЦИИ

✅ ИСПРАВЛЕННАЯ ДВУХЭТАПНАЯ КОМПЕНСАЦИЯ

// Файл: src/modbus_sensor.cpp

void applyCompensationIfEnabled(SensorData& d, const SoilProfile& profile) {
    // ШАГ 1: Применяем калибровочную таблицу CSV (лабораторная поверка)
    float tempCalibrated = CalibrationManager::applyCalibration(d.temperature, profile);
    float humCalibrated = CalibrationManager::applyCalibration(d.humidity, profile);
    float ecCalibrated = CalibrationManager::applyCalibration(d.ec, profile);
    float phCalibrated = CalibrationManager::applyCalibration(d.ph, profile);
    float nCalibrated = CalibrationManager::applyCalibration(d.nitrogen, profile);
    float pCalibrated = CalibrationManager::applyCalibration(d.phosphorus, profile);
    float kCalibrated = CalibrationManager::applyCalibration(d.potassium, profile);

    // ШАГ 2: Применяем математическую компенсацию (температурная, влажностная)
    float ec25 = ecCalibrated / (1.0f + 0.021f * (tempCalibrated - 25.0f));
    d.ec = correctEC(ec25, tempCalibrated, humCalibrated, profile.soilType);
    d.ph = correctPH(phCalibrated, tempCalibrated);
    correctNPK(tempCalibrated, humCalibrated, d.nitrogen, d.phosphorus, d.potassium, profile.soilType);
}

🔧 Калибровочный менеджер

// Файл: src/calibration_manager.cpp

class CalibrationManager {
public:
    // Применение калибровочной таблицы с линейной интерполяцией
    static float applyCalibration(float rawValue, const CalibrationProfile& profile) {
        if (!profile.isLoaded()) {
            return rawValue; // Возвращаем исходное значение если таблица не загружена
        }
        
        // Поиск ближайших точек калибровки
        CalibrationPoint lower, upper;
        if (profile.findInterpolationPoints(rawValue, lower, upper)) {
            // Линейная интерполяция
            float ratio = (rawValue - lower.raw) / (upper.raw - lower.raw);
            return lower.calibrated + ratio * (upper.calibrated - lower.calibrated);
        }
        
        return rawValue; // Вне диапазона калибровки
    }
};

1️⃣ Модель Арчи - EC компенсация

float correctEC(float ec25, float temperature, float humidity, SoilType soilType) {
    // Температурная компенсация (Archie, 1942)
    float tempFactor = 1.0f + 0.021f * (temperature - 25.0f);
    
    // Влажностная компенсация по модели Арчи
    float porosity = getPorosity(soilType);
    float archieCoeff = getArchieCoefficient(soilType);
    float humFactor = pow(humidity / 100.0f, archieCoeff);
    
    return ec25 * tempFactor * humFactor;
}

float getArchieCoefficient(SoilType soilType) {
    switch (soilType) {
        case SAND: return 0.15f;      // Песок
        case LOAM: return 0.30f;      // Суглинок
        case CLAY: return 0.45f;      // Глина
        case PEAT: return 0.10f;      // Торф
        case SANDY_PEAT: return 0.18f; // Песчано-торфяной
        default: return 0.30f;
    }
}

2️⃣ Уравнение Нернста - pH компенсация

float correctPH(float phRaw, float temperature) {
    // Температурная поправка pH по уравнению Нернста
    // dE/dT = -0.003 V/°C для pH электрода
    return phRaw - 0.003f * (temperature - 25.0f);
}

3️⃣ FAO 56 + Eur. J. Soil Sci. - NPK компенсация

void correctNPK(float temperature, float humidity, 
                float& nitrogen, float& phosphorus, float& potassium, 
                SoilType soilType) {
    // Температурная компенсация NPK
    float tempFactor = 1.0f - 0.02f * (temperature - 25.0f);
    
    // Влажностная компенсация по FAO 56
    float humFactor = 1.0f + 0.05f * (humidity - 50.0f) / 50.0f;
    
    // Применение компенсации
    nitrogen *= tempFactor * humFactor;
    phosphorus *= tempFactor * humFactor;
    potassium *= tempFactor * humFactor;
}

🌐 ВЕБ-ИНТЕРФЕЙС

📱 Архитектура веб-интерфейса

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   Web Browser   │    │   ESP32 Web     │    │   Data Storage  │
│   (Frontend)    │◄──►│   Server        │◄──►│   (NVS/Flash)   │
└─────────────────┘    └─────────────────┘    └─────────────────┘
                              │
                              ▼
                       ┌─────────────────┐
                       │   Sensor Data   │
                       │   Processing    │
                       └─────────────────┘

🛣️ Маршрутизация

// Файл: src/web/routes_data.cpp

void setupDataRoutes() {
    // Основные маршруты данных
    server.on("/readings", HTTP_GET, handleReadings);
    server.on("/intervals", HTTP_GET, handleIntervals);
    server.on("/config_manager", HTTP_GET, handleConfigManager);
    server.on("/updates", HTTP_GET, handleUpdates);
    server.on("/service", HTTP_GET, handleService);
}
📋 План рефакторинга QA 2025 H2

📋 План рефакторинга QA 2025 H2

🎯 Цели рефакторинга

🔧 Приоритетные задачи

🔥 Высокий приоритет

  • Исправление критических багов
  • Оптимизация памяти
  • Улучшение обработки ошибок

⚡ Средний приоритет

  • Рефакторинг устаревшего кода
  • Улучшение документации
  • Оптимизация алгоритмов

📈 Низкий приоритет

  • Косметические улучшения
  • Дополнительные функции
  • Расширенная документация
📊 Отчет о техническом долге 2025-06

📊 Отчет о техническом долге 2025-06

📈 Общая оценка

Технический долг проекта находится на приемлемом уровне. Основные области для улучшения:

🔴 Высокий технический долг

  • Устаревшие алгоритмы компенсации
  • Неоптимальное использование памяти
  • Отсутствие полного покрытия тестами

🟡 Средний технический долг

  • Дублирование кода в некоторых модулях
  • Недостаточная документация API
  • Сложность некоторых функций

🟢 Низкий технический долг

  • Хорошая архитектура в целом
  • Консистентное именование
  • Понятная структура проекта

🎯 Рекомендации

🏗️ Общая архитектура JXCT v3.4.9

🏗️ Общая архитектура JXCT v3.4.9

Версия документа: 3.4.9
Дата обновления: 2025-06-24
Статус: Актуальная архитектура с фокусом на стабильность

🎯 ПРИНЦИПЫ АРХИТЕКТУРЫ

1. Стабильность превыше всего

2. Модульность и переиспользование

3. Производительность и эффективность

🔧 ОСНОВНЫЕ КОМПОНЕНТЫ

📡 СИСТЕМА ДАТЧИКОВ

🔌 Абстракция датчиков

// Файл: include/ISensor.h

class ISensor {
public:
    virtual ~ISensor() = default;
    virtual bool initialize() = 0;
    virtual SensorData read() = 0;
    virtual bool isConnected() const = 0;
    virtual String getSensorInfo() const = 0;
};

🎭 Адаптеры датчиков

// Файл: src/modbus_sensor.h

class ModbusSensorAdapter : public ISensor {
private:
    ModbusSensor* sensor;
    
public:
    ModbusSensorAdapter(ModbusSensor* s) : sensor(s) {}
    
    bool initialize() override {
        return sensor->begin();
    }
    
    SensorData read() override {
        return sensor->getData();
    }
    
    bool isConnected() const override {
        return sensor->isConnected();
    }
    
    String getSensorInfo() const override {
        return "Modbus Sensor v" + String(sensor->getVersion());
    }
};

🧮 СИСТЕМА КОМПЕНСАЦИИ

✅ ИСПРАВЛЕННАЯ ДВУХЭТАПНАЯ КОМПЕНСАЦИЯ

// Файл: src/modbus_sensor.cpp

void applyCompensationIfEnabled(SensorData& d, const SoilProfile& profile) {
    // ШАГ 1: Применяем калибровочную таблицу CSV (лабораторная поверка)
    float tempCalibrated = CalibrationManager::applyCalibration(d.temperature, profile);
    float humCalibrated = CalibrationManager::applyCalibration(d.humidity, profile);
    float ecCalibrated = CalibrationManager::applyCalibration(d.ec, profile);
    float phCalibrated = CalibrationManager::applyCalibration(d.ph, profile);
    float nCalibrated = CalibrationManager::applyCalibration(d.nitrogen, profile);
    float pCalibrated = CalibrationManager::applyCalibration(d.phosphorus, profile);
    float kCalibrated = CalibrationManager::applyCalibration(d.potassium, profile);

    // ШАГ 2: Применяем математическую компенсацию (температурная, влажностная)
    float ec25 = ecCalibrated / (1.0f + 0.021f * (tempCalibrated - 25.0f));
    d.ec = correctEC(ec25, tempCalibrated, humCalibrated, profile.soilType);
    d.ph = correctPH(phCalibrated, tempCalibrated);
    correctNPK(tempCalibrated, humCalibrated, d.nitrogen, d.phosphorus, d.potassium, profile.soilType);
}

🔧 Калибровочный менеджер

// Файл: src/calibration_manager.cpp

class CalibrationManager {
public:
    // Применение калибровочной таблицы с линейной интерполяцией
    static float applyCalibration(float rawValue, const CalibrationProfile& profile) {
        if (!profile.isLoaded()) {
            return rawValue; // Возвращаем исходное значение если таблица не загружена
        }
        
        // Поиск ближайших точек калибровки
        CalibrationPoint lower, upper;
        if (profile.findInterpolationPoints(rawValue, lower, upper)) {
            // Линейная интерполяция
            float ratio = (rawValue - lower.raw) / (upper.raw - lower.raw);
            return lower.calibrated + ratio * (upper.calibrated - lower.calibrated);
        }
        
        return rawValue; // Вне диапазона калибровки
    }
};

1️⃣ Модель Арчи - EC компенсация

float correctEC(float ec25, float temperature, float humidity, SoilType soilType) {
    // Температурная компенсация (Archie, 1942)
    float tempFactor = 1.0f + 0.021f * (temperature - 25.0f);
    
    // Влажностная компенсация по модели Арчи
    float porosity = getPorosity(soilType);
    float archieCoeff = getArchieCoefficient(soilType);
    float humFactor = pow(humidity / 100.0f, archieCoeff);
    
    return ec25 * tempFactor * humFactor;
}

float getArchieCoefficient(SoilType soilType) {
    switch (soilType) {
        case SAND: return 0.15f;      // Песок
        case LOAM: return 0.30f;      // Суглинок
        case CLAY: return 0.45f;      // Глина
        case PEAT: return 0.10f;      // Торф
        case SANDY_PEAT: return 0.18f; // Песчано-торфяной
        default: return 0.30f;
    }
}

2️⃣ Уравнение Нернста - pH компенсация

float correctPH(float phRaw, float temperature) {
    // Температурная поправка pH по уравнению Нернста
    // dE/dT = -0.003 V/°C для pH электрода
    return phRaw - 0.003f * (temperature - 25.0f);
}

3️⃣ FAO 56 + Eur. J. Soil Sci. - NPK компенсация

void correctNPK(float temperature, float humidity, 
                float& nitrogen, float& phosphorus, float& potassium, 
                SoilType soilType) {
    // Температурная компенсация NPK
    float tempFactor = 1.0f - 0.02f * (temperature - 25.0f);
    
    // Влажностная компенсация по FAO 56
    float humFactor = 1.0f + 0.05f * (humidity - 50.0f) / 50.0f;
    
    // Применение компенсации
    nitrogen *= tempFactor * humFactor;
    phosphorus *= tempFactor * humFactor;
    potassium *= tempFactor * humFactor;
}

🌐 ВЕБ-ИНТЕРФЕЙС

📱 Архитектура веб-интерфейса

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   Web Browser   │    │   ESP32 Web     │    │   Data Storage  │
│   (Frontend)    │◄──►│   Server        │◄──►│   (NVS/Flash)   │
└─────────────────┘    └─────────────────┘    └─────────────────┘
                              │
                              ▼
                       ┌─────────────────┐
                       │   Sensor Data   │
                       │   Processing    │
                       └─────────────────┘

🛣️ Маршрутизация

// Файл: src/web/routes_data.cpp

void setupDataRoutes() {
    // Основные маршруты данных
    server.on("/readings", HTTP_GET, handleReadings);
    server.on("/intervals", HTTP_GET, handleIntervals);
    server.on("/config_manager", HTTP_GET, handleConfigManager);
    server.on("/updates", HTTP_GET, handleUpdates);
    server.on("/service", HTTP_GET, handleService);
}
📋 План рефакторинга QA 2025 H2

📋 План рефакторинга QA 2025 H2

🎯 Цели рефакторинга

🔧 Приоритетные задачи

🔥 Высокий приоритет

  • Исправление критических багов
  • Оптимизация памяти
  • Улучшение обработки ошибок

⚡ Средний приоритет

  • Рефакторинг устаревшего кода
  • Улучшение документации
  • Оптимизация алгоритмов

📈 Низкий приоритет

  • Косметические улучшения
  • Дополнительные функции
  • Расширенная документация
📊 Отчет о техническом долге 2025-06

📊 Отчет о техническом долге 2025-06

📈 Общая оценка

Технический долг проекта находится на приемлемом уровне. Основные области для улучшения:

🔴 Высокий технический долг

  • Устаревшие алгоритмы компенсации
  • Неоптимальное использование памяти
  • Отсутствие полного покрытия тестами

🟡 Средний технический долг

  • Дублирование кода в некоторых модулях
  • Недостаточная документация API
  • Сложность некоторых функций

🟢 Низкий технический долг

  • Хорошая архитектура в целом
  • Консистентное именование
  • Понятная структура проекта

🎯 Рекомендации

🏗️ Общая архитектура JXCT v3.4.9

🏗️ Общая архитектура JXCT v3.4.9

Версия документа: 3.4.9
Дата обновления: 2025-06-24
Статус: Актуальная архитектура с фокусом на стабильность

🎯 ПРИНЦИПЫ АРХИТЕКТУРЫ

1. Стабильность превыше всего

2. Модульность и переиспользование

3. Производительность и эффективность

🔧 ОСНОВНЫЕ КОМПОНЕНТЫ

📡 СИСТЕМА ДАТЧИКОВ

🔌 Абстракция датчиков

// Файл: include/ISensor.h

class ISensor {
public:
    virtual ~ISensor() = default;
    virtual bool initialize() = 0;
    virtual SensorData read() = 0;
    virtual bool isConnected() const = 0;
    virtual String getSensorInfo() const = 0;
};

🎭 Адаптеры датчиков

// Файл: src/modbus_sensor.h

class ModbusSensorAdapter : public ISensor {
private:
    ModbusSensor* sensor;
    
public:
    ModbusSensorAdapter(ModbusSensor* s) : sensor(s) {}
    
    bool initialize() override {
        return sensor->begin();
    }
    
    SensorData read() override {
        return sensor->getData();
    }
    
    bool isConnected() const override {
        return sensor->isConnected();
    }
    
    String getSensorInfo() const override {
        return "Modbus Sensor v" + String(sensor->getVersion());
    }
};

🧮 СИСТЕМА КОМПЕНСАЦИИ

✅ ИСПРАВЛЕННАЯ ДВУХЭТАПНАЯ КОМПЕНСАЦИЯ

// Файл: src/modbus_sensor.cpp

void applyCompensationIfEnabled(SensorData& d, const SoilProfile& profile) {
    // ШАГ 1: Применяем калибровочную таблицу CSV (лабораторная поверка)
    float tempCalibrated = CalibrationManager::applyCalibration(d.temperature, profile);
    float humCalibrated = CalibrationManager::applyCalibration(d.humidity, profile);
    float ecCalibrated = CalibrationManager::applyCalibration(d.ec, profile);
    float phCalibrated = CalibrationManager::applyCalibration(d.ph, profile);
    float nCalibrated = CalibrationManager::applyCalibration(d.nitrogen, profile);
    float pCalibrated = CalibrationManager::applyCalibration(d.phosphorus, profile);
    float kCalibrated = CalibrationManager::applyCalibration(d.potassium, profile);

    // ШАГ 2: Применяем математическую компенсацию (температурная, влажностная)
    float ec25 = ecCalibrated / (1.0f + 0.021f * (tempCalibrated - 25.0f));
    d.ec = correctEC(ec25, tempCalibrated, humCalibrated, profile.soilType);
    d.ph = correctPH(phCalibrated, tempCalibrated);
    correctNPK(tempCalibrated, humCalibrated, d.nitrogen, d.phosphorus, d.potassium, profile.soilType);
}

🔧 Калибровочный менеджер

// Файл: src/calibration_manager.cpp

class CalibrationManager {
public:
    // Применение калибровочной таблицы с линейной интерполяцией
    static float applyCalibration(float rawValue, const CalibrationProfile& profile) {
        if (!profile.isLoaded()) {
            return rawValue; // Возвращаем исходное значение если таблица не загружена
        }
        
        // Поиск ближайших точек калибровки
        CalibrationPoint lower, upper;
        if (profile.findInterpolationPoints(rawValue, lower, upper)) {
            // Линейная интерполяция
            float ratio = (rawValue - lower.raw) / (upper.raw - lower.raw);
            return lower.calibrated + ratio * (upper.calibrated - lower.calibrated);
        }
        
        return rawValue; // Вне диапазона калибровки
    }
};

1️⃣ Модель Арчи - EC компенсация

float correctEC(float ec25, float temperature, float humidity, SoilType soilType) {
    // Температурная компенсация (Archie, 1942)
    float tempFactor = 1.0f + 0.021f * (temperature - 25.0f);
    
    // Влажностная компенсация по модели Арчи
    float porosity = getPorosity(soilType);
    float archieCoeff = getArchieCoefficient(soilType);
    float humFactor = pow(humidity / 100.0f, archieCoeff);
    
    return ec25 * tempFactor * humFactor;
}

float getArchieCoefficient(SoilType soilType) {
    switch (soilType) {
        case SAND: return 0.15f;      // Песок
        case LOAM: return 0.30f;      // Суглинок
        case CLAY: return 0.45f;      // Глина
        case PEAT: return 0.10f;      // Торф
        case SANDY_PEAT: return 0.18f; // Песчано-торфяной
        default: return 0.30f;
    }
}

2️⃣ Уравнение Нернста - pH компенсация

float correctPH(float phRaw, float temperature) {
    // Температурная поправка pH по уравнению Нернста
    // dE/dT = -0.003 V/°C для pH электрода
    return phRaw - 0.003f * (temperature - 25.0f);
}

3️⃣ FAO 56 + Eur. J. Soil Sci. - NPK компенсация

void correctNPK(float temperature, float humidity, 
                float& nitrogen, float& phosphorus, float& potassium, 
                SoilType soilType) {
    // Температурная компенсация NPK
    float tempFactor = 1.0f - 0.02f * (temperature - 25.0f);
    
    // Влажностная компенсация по FAO 56
    float humFactor = 1.0f + 0.05f * (humidity - 50.0f) / 50.0f;
    
    // Применение компенсации
    nitrogen *= tempFactor * humFactor;
    phosphorus *= tempFactor * humFactor;
    potassium *= tempFactor * humFactor;
}

🌐 ВЕБ-ИНТЕРФЕЙС

📱 Архитектура веб-интерфейса

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   Web Browser   │    │   ESP32 Web     │    │   Data Storage  │
│   (Frontend)    │◄──►│   Server        │◄──►│   (NVS/Flash)   │
└─────────────────┘    └─────────────────┘    └─────────────────┘
                              │
                              ▼
                       ┌─────────────────┐
                       │   Sensor Data   │
                       │   Processing    │
                       └─────────────────┘

🛣️ Маршрутизация

// Файл: src/web/routes_data.cpp

void setupDataRoutes() {
    // Основные маршруты данных
    server.on("/readings", HTTP_GET, handleReadings);
    server.on("/intervals", HTTP_GET, handleIntervals);
    server.on("/config_manager", HTTP_GET, handleConfigManager);
    server.on("/updates", HTTP_GET, handleUpdates);
    server.on("/service", HTTP_GET, handleService);
}
📋 План рефакторинга QA 2025 H2

📋 План рефакторинга QA 2025 H2

🎯 Цели рефакторинга

🔧 Приоритетные задачи

🔥 Высокий приоритет

  • Исправление критических багов
  • Оптимизация памяти
  • Улучшение обработки ошибок

⚡ Средний приоритет

  • Рефакторинг устаревшего кода
  • Улучшение документации
  • Оптимизация алгоритмов

📈 Низкий приоритет

  • Косметические улучшения
  • Дополнительные функции
  • Расширенная документация
📊 Отчет о техническом долге 2025-06

📊 Отчет о техническом долге 2025-06

📈 Общая оценка

Технический долг проекта находится на приемлемом уровне. Основные области для улучшения:

🔴 Высокий технический долг

  • Устаревшие алгоритмы компенсации
  • Неоптимальное использование памяти
  • Отсутствие полного покрытия тестами

🟡 Средний технический долг

  • Дублирование кода в некоторых модулях
  • Недостаточная документация API
  • Сложность некоторых функций

🟢 Низкий технический долг

  • Хорошая архитектура в целом
  • Консистентное именование
  • Понятная структура проекта

🎯 Рекомендации

🏗️ Общая архитектура JXCT v3.4.9

🏗️ Общая архитектура JXCT v3.4.9

Версия документа: 3.4.9
Дата обновления: 2025-06-24
Статус: Актуальная архитектура с фокусом на стабильность

🎯 ПРИНЦИПЫ АРХИТЕКТУРЫ

1. Стабильность превыше всего

2. Модульность и переиспользование

3. Производительность и эффективность

🔧 ОСНОВНЫЕ КОМПОНЕНТЫ

📡 СИСТЕМА ДАТЧИКОВ

🔌 Абстракция датчиков

// Файл: include/ISensor.h

class ISensor {
public:
    virtual ~ISensor() = default;
    virtual bool initialize() = 0;
    virtual SensorData read() = 0;
    virtual bool isConnected() const = 0;
    virtual String getSensorInfo() const = 0;
};

🎭 Адаптеры датчиков

// Файл: src/modbus_sensor.h

class ModbusSensorAdapter : public ISensor {
private:
    ModbusSensor* sensor;
    
public:
    ModbusSensorAdapter(ModbusSensor* s) : sensor(s) {}
    
    bool initialize() override {
        return sensor->begin();
    }
    
    SensorData read() override {
        return sensor->getData();
    }
    
    bool isConnected() const override {
        return sensor->isConnected();
    }
    
    String getSensorInfo() const override {
        return "Modbus Sensor v" + String(sensor->getVersion());
    }
};

🧮 СИСТЕМА КОМПЕНСАЦИИ

✅ ИСПРАВЛЕННАЯ ДВУХЭТАПНАЯ КОМПЕНСАЦИЯ

// Файл: src/modbus_sensor.cpp

void applyCompensationIfEnabled(SensorData& d, const SoilProfile& profile) {
    // ШАГ 1: Применяем калибровочную таблицу CSV (лабораторная поверка)
    float tempCalibrated = CalibrationManager::applyCalibration(d.temperature, profile);
    float humCalibrated = CalibrationManager::applyCalibration(d.humidity, profile);
    float ecCalibrated = CalibrationManager::applyCalibration(d.ec, profile);
    float phCalibrated = CalibrationManager::applyCalibration(d.ph, profile);
    float nCalibrated = CalibrationManager::applyCalibration(d.nitrogen, profile);
    float pCalibrated = CalibrationManager::applyCalibration(d.phosphorus, profile);
    float kCalibrated = CalibrationManager::applyCalibration(d.potassium, profile);

    // ШАГ 2: Применяем математическую компенсацию (температурная, влажностная)
    float ec25 = ecCalibrated / (1.0f + 0.021f * (tempCalibrated - 25.0f));
    d.ec = correctEC(ec25, tempCalibrated, humCalibrated, profile.soilType);
    d.ph = correctPH(phCalibrated, tempCalibrated);
    correctNPK(tempCalibrated, humCalibrated, d.nitrogen, d.phosphorus, d.potassium, profile.soilType);
}

🔧 Калибровочный менеджер

// Файл: src/calibration_manager.cpp

class CalibrationManager {
public:
    // Применение калибровочной таблицы с линейной интерполяцией
    static float applyCalibration(float rawValue, const CalibrationProfile& profile) {
        if (!profile.isLoaded()) {
            return rawValue; // Возвращаем исходное значение если таблица не загружена
        }
        
        // Поиск ближайших точек калибровки
        CalibrationPoint lower, upper;
        if (profile.findInterpolationPoints(rawValue, lower, upper)) {
            // Линейная интерполяция
            float ratio = (rawValue - lower.raw) / (upper.raw - lower.raw);
            return lower.calibrated + ratio * (upper.calibrated - lower.calibrated);
        }
        
        return rawValue; // Вне диапазона калибровки
    }
};

1️⃣ Модель Арчи - EC компенсация

float correctEC(float ec25, float temperature, float humidity, SoilType soilType) {
    // Температурная компенсация (Archie, 1942)
    float tempFactor = 1.0f + 0.021f * (temperature - 25.0f);
    
    // Влажностная компенсация по модели Арчи
    float porosity = getPorosity(soilType);
    float archieCoeff = getArchieCoefficient(soilType);
    float humFactor = pow(humidity / 100.0f, archieCoeff);
    
    return ec25 * tempFactor * humFactor;
}

float getArchieCoefficient(SoilType soilType) {
    switch (soilType) {
        case SAND: return 0.15f;      // Песок
        case LOAM: return 0.30f;      // Суглинок
        case CLAY: return 0.45f;      // Глина
        case PEAT: return 0.10f;      // Торф
        case SANDY_PEAT: return 0.18f; // Песчано-торфяной
        default: return 0.30f;
    }
}

2️⃣ Уравнение Нернста - pH компенсация

float correctPH(float phRaw, float temperature) {
    // Температурная поправка pH по уравнению Нернста
    // dE/dT = -0.003 V/°C для pH электрода
    return phRaw - 0.003f * (temperature - 25.0f);
}

3️⃣ FAO 56 + Eur. J. Soil Sci. - NPK компенсация

void correctNPK(float temperature, float humidity, 
                float& nitrogen, float& phosphorus, float& potassium, 
                SoilType soilType) {
    // Температурная компенсация NPK
    float tempFactor = 1.0f - 0.02f * (temperature - 25.0f);
    
    // Влажностная компенсация по FAO 56
    float humFactor = 1.0f + 0.05f * (humidity - 50.0f) / 50.0f;
    
    // Применение компенсации
    nitrogen *= tempFactor * humFactor;
    phosphorus *= tempFactor * humFactor;
    potassium *= tempFactor * humFactor;
}

🌐 ВЕБ-ИНТЕРФЕЙС

📱 Архитектура веб-интерфейса

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   Web Browser   │    │   ESP32 Web     │    │   Data Storage  │
│   (Frontend)    │◄──►│   Server        │◄──►│   (NVS/Flash)   │
└─────────────────┘    └─────────────────┘    └─────────────────┘
                              │
                              ▼
                       ┌─────────────────┐
                       │   Sensor Data   │
                       │   Processing    │
                       └─────────────────┘

🛣️ Маршрутизация

// Файл: src/web/routes_data.cpp

void setupDataRoutes() {
    // Основные маршруты данных
    server.on("/readings", HTTP_GET, handleReadings);
    server.on("/intervals", HTTP_GET, handleIntervals);
    server.on("/config_manager", HTTP_GET, handleConfigManager);
    server.on("/updates", HTTP_GET, handleUpdates);
    server.on("/service", HTTP_GET, handleService);
}
📋 План рефакторинга QA 2025 H2

📋 План рефакторинга QA 2025 H2

🎯 Цели рефакторинга

🔧 Приоритетные задачи

🔥 Высокий приоритет

  • Исправление критических багов
  • Оптимизация памяти
  • Улучшение обработки ошибок

⚡ Средний приоритет

  • Рефакторинг устаревшего кода
  • Улучшение документации
  • Оптимизация алгоритмов

📈 Низкий приоритет

  • Косметические улучшения
  • Дополнительные функции
  • Расширенная документация
📊 Отчет о техническом долге 2025-06

📊 Отчет о техническом долге 2025-06

📈 Общая оценка

Технический долг проекта находится на приемлемом уровне. Основные области для улучшения:

🔴 Высокий технический долг

  • Устаревшие алгоритмы компенсации
  • Неоптимальное использование памяти
  • Отсутствие полного покрытия тестами

🟡 Средний технический долг

  • Дублирование кода в некоторых модулях
  • Недостаточная документация API
  • Сложность некоторых функций

🟢 Низкий технический долг

  • Хорошая архитектура в целом
  • Консистентное именование
  • Понятная структура проекта

🎯 Рекомендации

🏗️ Общая архитектура JXCT v3.4.9

🏗️ Общая архитектура JXCT v3.4.9

Версия документа: 3.4.9
Дата обновления: 2025-06-24
Статус: Актуальная архитектура с фокусом на стабильность

🎯 ПРИНЦИПЫ АРХИТЕКТУРЫ

1. Стабильность превыше всего

2. Модульность и переиспользование

3. Производительность и эффективность

🔧 ОСНОВНЫЕ КОМПОНЕНТЫ

📡 СИСТЕМА ДАТЧИКОВ

🔌 Абстракция датчиков

// Файл: include/ISensor.h

class ISensor {
public:
    virtual ~ISensor() = default;
    virtual bool initialize() = 0;
    virtual SensorData read() = 0;
    virtual bool isConnected() const = 0;
    virtual String getSensorInfo() const = 0;
};

🎭 Адаптеры датчиков

// Файл: src/modbus_sensor.h

class ModbusSensorAdapter : public ISensor {
private:
    ModbusSensor* sensor;
    
public:
    ModbusSensorAdapter(ModbusSensor* s) : sensor(s) {}
    
    bool initialize() override {
        return sensor->begin();
    }
    
    SensorData read() override {
        return sensor->getData();
    }
    
    bool isConnected() const override {
        return sensor->isConnected();
    }
    
    String getSensorInfo() const override {
        return "Modbus Sensor v" + String(sensor->getVersion());
    }
};

🧮 СИСТЕМА КОМПЕНСАЦИИ

✅ ИСПРАВЛЕННАЯ ДВУХЭТАПНАЯ КОМПЕНСАЦИЯ

// Файл: src/modbus_sensor.cpp

void applyCompensationIfEnabled(SensorData& d, const SoilProfile& profile) {
    // ШАГ 1: Применяем калибровочную таблицу CSV (лабораторная поверка)
    float tempCalibrated = CalibrationManager::applyCalibration(d.temperature, profile);
    float humCalibrated = CalibrationManager::applyCalibration(d.humidity, profile);
    float ecCalibrated = CalibrationManager::applyCalibration(d.ec, profile);
    float phCalibrated = CalibrationManager::applyCalibration(d.ph, profile);
    float nCalibrated = CalibrationManager::applyCalibration(d.nitrogen, profile);
    float pCalibrated = CalibrationManager::applyCalibration(d.phosphorus, profile);
    float kCalibrated = CalibrationManager::applyCalibration(d.potassium, profile);

    // ШАГ 2: Применяем математическую компенсацию (температурная, влажностная)
    float ec25 = ecCalibrated / (1.0f + 0.021f * (tempCalibrated - 25.0f));
    d.ec = correctEC(ec25, tempCalibrated, humCalibrated, profile.soilType);
    d.ph = correctPH(phCalibrated, tempCalibrated);
    correctNPK(tempCalibrated, humCalibrated, d.nitrogen, d.phosphorus, d.potassium, profile.soilType);
}

🔧 Калибровочный менеджер

// Файл: src/calibration_manager.cpp

class CalibrationManager {
public:
    // Применение калибровочной таблицы с линейной интерполяцией
    static float applyCalibration(float rawValue, const CalibrationProfile& profile) {
        if (!profile.isLoaded()) {
            return rawValue; // Возвращаем исходное значение если таблица не загружена
        }
        
        // Поиск ближайших точек калибровки
        CalibrationPoint lower, upper;
        if (profile.findInterpolationPoints(rawValue, lower, upper)) {
            // Линейная интерполяция
            float ratio = (rawValue - lower.raw) / (upper.raw - lower.raw);
            return lower.calibrated + ratio * (upper.calibrated - lower.calibrated);
        }
        
        return rawValue; // Вне диапазона калибровки
    }
};

1️⃣ Модель Арчи - EC компенсация

float correctEC(float ec25, float temperature, float humidity, SoilType soilType) {
    // Температурная компенсация (Archie, 1942)
    float tempFactor = 1.0f + 0.021f * (temperature - 25.0f);
    
    // Влажностная компенсация по модели Арчи
    float porosity = getPorosity(soilType);
    float archieCoeff = getArchieCoefficient(soilType);
    float humFactor = pow(humidity / 100.0f, archieCoeff);
    
    return ec25 * tempFactor * humFactor;
}

float getArchieCoefficient(SoilType soilType) {
    switch (soilType) {
        case SAND: return 0.15f;      // Песок
        case LOAM: return 0.30f;      // Суглинок
        case CLAY: return 0.45f;      // Глина
        case PEAT: return 0.10f;      // Торф
        case SANDY_PEAT: return 0.18f; // Песчано-торфяной
        default: return 0.30f;
    }
}

2️⃣ Уравнение Нернста - pH компенсация

float correctPH(float phRaw, float temperature) {
    // Температурная поправка pH по уравнению Нернста
    // dE/dT = -0.003 V/°C для pH электрода
    return phRaw - 0.003f * (temperature - 25.0f);
}

3️⃣ FAO 56 + Eur. J. Soil Sci. - NPK компенсация

void correctNPK(float temperature, float humidity, 
                float& nitrogen, float& phosphorus, float& potassium, 
                SoilType soilType) {
    // Температурная компенсация NPK
    float tempFactor = 1.0f - 0.02f * (temperature - 25.0f);
    
    // Влажностная компенсация по FAO 56
    float humFactor = 1.0f + 0.05f * (humidity - 50.0f) / 50.0f;
    
    // Применение компенсации
    nitrogen *= tempFactor * humFactor;
    phosphorus *= tempFactor * humFactor;
    potassium *= tempFactor * humFactor;
}

🌐 ВЕБ-ИНТЕРФЕЙС

📱 Архитектура веб-интерфейса

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   Web Browser   │    │   ESP32 Web     │    │   Data Storage  │
│   (Frontend)    │◄──►│   Server        │◄──►│   (NVS/Flash)   │
└─────────────────┘    └─────────────────┘    └─────────────────┘
                              │
                              ▼
                       ┌─────────────────┐
                       │   Sensor Data   │
                       │   Processing    │
                       └─────────────────┘

🛣️ Маршрутизация

// Файл: src/web/routes_data.cpp

void setupDataRoutes() {
    // Основные маршруты данных
    server.on("/readings", HTTP_GET, handleReadings);
    server.on("/intervals", HTTP_GET, handleIntervals);
    server.on("/config_manager", HTTP_GET, handleConfigManager);
    server.on("/updates", HTTP_GET, handleUpdates);
    server.on("/service", HTTP_GET, handleService);
}
📋 План рефакторинга QA 2025 H2

📋 План рефакторинга QA 2025 H2

🎯 Цели рефакторинга

🔧 Приоритетные задачи

🔥 Высокий приоритет

  • Исправление критических багов
  • Оптимизация памяти
  • Улучшение обработки ошибок

⚡ Средний приоритет

  • Рефакторинг устаревшего кода
  • Улучшение документации
  • Оптимизация алгоритмов

📈 Низкий приоритет

  • Косметические улучшения
  • Дополнительные функции
  • Расширенная документация
📊 Отчет о техническом долге 2025-06

📊 Отчет о техническом долге 2025-06

📈 Общая оценка

Технический долг проекта находится на приемлемом уровне. Основные области для улучшения:

🔴 Высокий технический долг

  • Устаревшие алгоритмы компенсации
  • Неоптимальное использование памяти
  • Отсутствие полного покрытия тестами

🟡 Средний технический долг

  • Дублирование кода в некоторых модулях
  • Недостаточная документация API
  • Сложность некоторых функций

🟢 Низкий технический долг

  • Хорошая архитектура в целом
  • Консистентное именование
  • Понятная структура проекта

🎯 Рекомендации

🏗️ Общая архитектура JXCT v3.4.9

🏗️ Общая архитектура JXCT v3.4.9

Версия документа: 3.4.9
Дата обновления: 2025-06-24
Статус: Актуальная архитектура с фокусом на стабильность

🎯 ПРИНЦИПЫ АРХИТЕКТУРЫ

1. Стабильность превыше всего

2. Модульность и переиспользование

3. Производительность и эффективность

🔧 ОСНОВНЫЕ КОМПОНЕНТЫ

📡 СИСТЕМА ДАТЧИКОВ

🔌 Абстракция датчиков

// Файл: include/ISensor.h

class ISensor {
public:
    virtual ~ISensor() = default;
    virtual bool initialize() = 0;
    virtual SensorData read() = 0;
    virtual bool isConnected() const = 0;
    virtual String getSensorInfo() const = 0;
};

🎭 Адаптеры датчиков

// Файл: src/modbus_sensor.h

class ModbusSensorAdapter : public ISensor {
private:
    ModbusSensor* sensor;
    
public:
    ModbusSensorAdapter(ModbusSensor* s) : sensor(s) {}
    
    bool initialize() override {
        return sensor->begin();
    }
    
    SensorData read() override {
        return sensor->getData();
    }
    
    bool isConnected() const override {
        return sensor->isConnected();
    }
    
    String getSensorInfo() const override {
        return "Modbus Sensor v" + String(sensor->getVersion());
    }
};

🧮 СИСТЕМА КОМПЕНСАЦИИ

✅ ИСПРАВЛЕННАЯ ДВУХЭТАПНАЯ КОМПЕНСАЦИЯ

// Файл: src/modbus_sensor.cpp

void applyCompensationIfEnabled(SensorData& d, const SoilProfile& profile) {
    // ШАГ 1: Применяем калибровочную таблицу CSV (лабораторная поверка)
    float tempCalibrated = CalibrationManager::applyCalibration(d.temperature, profile);
    float humCalibrated = CalibrationManager::applyCalibration(d.humidity, profile);
    float ecCalibrated = CalibrationManager::applyCalibration(d.ec, profile);
    float phCalibrated = CalibrationManager::applyCalibration(d.ph, profile);
    float nCalibrated = CalibrationManager::applyCalibration(d.nitrogen, profile);
    float pCalibrated = CalibrationManager::applyCalibration(d.phosphorus, profile);
    float kCalibrated = CalibrationManager::applyCalibration(d.potassium, profile);

    // ШАГ 2: Применяем математическую компенсацию (температурная, влажностная)
    float ec25 = ecCalibrated / (1.0f + 0.021f * (tempCalibrated - 25.0f));
    d.ec = correctEC(ec25, tempCalibrated, humCalibrated, profile.soilType);
    d.ph = correctPH(phCalibrated, tempCalibrated);
    correctNPK(tempCalibrated, humCalibrated, d.nitrogen, d.phosphorus, d.potassium, profile.soilType);
}

🔧 Калибровочный менеджер

// Файл: src/calibration_manager.cpp

class CalibrationManager {
public:
    // Применение калибровочной таблицы с линейной интерполяцией
    static float applyCalibration(float rawValue, const CalibrationProfile& profile) {
        if (!profile.isLoaded()) {
            return rawValue; // Возвращаем исходное значение если таблица не загружена
        }
        
        // Поиск ближайших точек калибровки
        CalibrationPoint lower, upper;
        if (profile.findInterpolationPoints(rawValue, lower, upper)) {
            // Линейная интерполяция
            float ratio = (rawValue - lower.raw) / (upper.raw - lower.raw);
            return lower.calibrated + ratio * (upper.calibrated - lower.calibrated);
        }
        
        return rawValue; // Вне диапазона калибровки
    }
};

1️⃣ Модель Арчи - EC компенсация

float correctEC(float ec25, float temperature, float humidity, SoilType soilType) {
    // Температурная компенсация (Archie, 1942)
    float tempFactor = 1.0f + 0.021f * (temperature - 25.0f);
    
    // Влажностная компенсация по модели Арчи
    float porosity = getPorosity(soilType);
    float archieCoeff = getArchieCoefficient(soilType);
    float humFactor = pow(humidity / 100.0f, archieCoeff);
    
    return ec25 * tempFactor * humFactor;
}

float getArchieCoefficient(SoilType soilType) {
    switch (soilType) {
        case SAND: return 0.15f;      // Песок
        case LOAM: return 0.30f;      // Суглинок
        case CLAY: return 0.45f;      // Глина
        case PEAT: return 0.10f;      // Торф
        case SANDY_PEAT: return 0.18f; // Песчано-торфяной
        default: return 0.30f;
    }
}

2️⃣ Уравнение Нернста - pH компенсация

float correctPH(float phRaw, float temperature) {
    // Температурная поправка pH по уравнению Нернста
    // dE/dT = -0.003 V/°C для pH электрода
    return phRaw - 0.003f * (temperature - 25.0f);
}

3️⃣ FAO 56 + Eur. J. Soil Sci. - NPK компенсация

void correctNPK(float temperature, float humidity, 
                float& nitrogen, float& phosphorus, float& potassium, 
                SoilType soilType) {
    // Температурная компенсация NPK
    float tempFactor = 1.0f - 0.02f * (temperature - 25.0f);
    
    // Влажностная компенсация по FAO 56
    float humFactor = 1.0f + 0.05f * (humidity - 50.0f) / 50.0f;
    
    // Применение компенсации
    nitrogen *= tempFactor * humFactor;
    phosphorus *= tempFactor * humFactor;
    potassium *= tempFactor * humFactor;
}

🌐 ВЕБ-ИНТЕРФЕЙС

📱 Архитектура веб-интерфейса

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   Web Browser   │    │   ESP32 Web     │    │   Data Storage  │
│   (Frontend)    │◄──►│   Server        │◄──►│   (NVS/Flash)   │
└─────────────────┘    └─────────────────┘    └─────────────────┘
                              │
                              ▼
                       ┌─────────────────┐
                       │   Sensor Data   │
                       │   Processing    │
                       └─────────────────┘

🛣️ Маршрутизация

// Файл: src/web/routes_data.cpp

void setupDataRoutes() {
    // Основные маршруты данных
    server.on("/readings", HTTP_GET, handleReadings);
    server.on("/intervals", HTTP_GET, handleIntervals);
    server.on("/config_manager", HTTP_GET, handleConfigManager);
    server.on("/updates", HTTP_GET, handleUpdates);
    server.on("/service", HTTP_GET, handleService);
}
📋 План рефакторинга QA 2025 H2

📋 План рефакторинга QA 2025 H2

🎯 Цели рефакторинга

🔧 Приоритетные задачи

🔥 Высокий приоритет

  • Исправление критических багов
  • Оптимизация памяти
  • Улучшение обработки ошибок

⚡ Средний приоритет

  • Рефакторинг устаревшего кода
  • Улучшение документации
  • Оптимизация алгоритмов

📈 Низкий приоритет

  • Косметические улучшения
  • Дополнительные функции
  • Расширенная документация
📊 Отчет о техническом долге 2025-06

📊 Отчет о техническом долге 2025-06

📈 Общая оценка

Технический долг проекта находится на приемлемом уровне. Основные области для улучшения:

🔴 Высокий технический долг

  • Устаревшие алгоритмы компенсации
  • Неоптимальное использование памяти
  • Отсутствие полного покрытия тестами

🟡 Средний технический долг

  • Дублирование кода в некоторых модулях
  • Недостаточная документация API
  • Сложность некоторых функций

🟢 Низкий технический долг

  • Хорошая архитектура в целом
  • Консистентное именование
  • Понятная структура проекта

🎯 Рекомендации

🏗️ Общая архитектура JXCT v3.4.9

🏗️ Общая архитектура JXCT v3.4.9

Версия документа: 3.4.9
Дата обновления: 2025-06-24
Статус: Актуальная архитектура с фокусом на стабильность

🎯 ПРИНЦИПЫ АРХИТЕКТУРЫ

1. Стабильность превыше всего

2. Модульность и переиспользование

3. Производительность и эффективность

🔧 ОСНОВНЫЕ КОМПОНЕНТЫ

📡 СИСТЕМА ДАТЧИКОВ

🔌 Абстракция датчиков

// Файл: include/ISensor.h

class ISensor {
public:
    virtual ~ISensor() = default;
    virtual bool initialize() = 0;
    virtual SensorData read() = 0;
    virtual bool isConnected() const = 0;
    virtual String getSensorInfo() const = 0;
};

🎭 Адаптеры датчиков

// Файл: src/modbus_sensor.h

class ModbusSensorAdapter : public ISensor {
private:
    ModbusSensor* sensor;
    
public:
    ModbusSensorAdapter(ModbusSensor* s) : sensor(s) {}
    
    bool initialize() override {
        return sensor->begin();
    }
    
    SensorData read() override {
        return sensor->getData();
    }
    
    bool isConnected() const override {
        return sensor->isConnected();
    }
    
    String getSensorInfo() const override {
        return "Modbus Sensor v" + String(sensor->getVersion());
    }
};

🧮 СИСТЕМА КОМПЕНСАЦИИ

✅ ИСПРАВЛЕННАЯ ДВУХЭТАПНАЯ КОМПЕНСАЦИЯ

// Файл: src/modbus_sensor.cpp

void applyCompensationIfEnabled(SensorData& d, const SoilProfile& profile) {
    // ШАГ 1: Применяем калибровочную таблицу CSV (лабораторная поверка)
    float tempCalibrated = CalibrationManager::applyCalibration(d.temperature, profile);
    float humCalibrated = CalibrationManager::applyCalibration(d.humidity, profile);
    float ecCalibrated = CalibrationManager::applyCalibration(d.ec, profile);
    float phCalibrated = CalibrationManager::applyCalibration(d.ph, profile);
    float nCalibrated = CalibrationManager::applyCalibration(d.nitrogen, profile);
    float pCalibrated = CalibrationManager::applyCalibration(d.phosphorus, profile);
    float kCalibrated = CalibrationManager::applyCalibration(d.potassium, profile);

    // ШАГ 2: Применяем математическую компенсацию (температурная, влажностная)
    float ec25 = ecCalibrated / (1.0f + 0.021f * (tempCalibrated - 25.0f));
    d.ec = correctEC(ec25, tempCalibrated, humCalibrated, profile.soilType);
    d.ph = correctPH(phCalibrated, tempCalibrated);
    correctNPK(tempCalibrated, humCalibrated, d.nitrogen, d.phosphorus, d.potassium, profile.soilType);
}

🔧 Калибровочный менеджер

// Файл: src/calibration_manager.cpp

class CalibrationManager {
public:
    // Применение калибровочной таблицы с линейной интерполяцией
    static float applyCalibration(float rawValue, const CalibrationProfile& profile) {
        if (!profile.isLoaded()) {
            return rawValue; // Возвращаем исходное значение если таблица не загружена
        }
        
        // Поиск ближайших точек калибровки
        CalibrationPoint lower, upper;
        if (profile.findInterpolationPoints(rawValue, lower, upper)) {
            // Линейная интерполяция
            float ratio = (rawValue - lower.raw) / (upper.raw - lower.raw);
            return lower.calibrated + ratio * (upper.calibrated - lower.calibrated);
        }
        
        return rawValue; // Вне диапазона калибровки
    }
};

1️⃣ Модель Арчи - EC компенсация

float correctEC(float ec25, float temperature, float humidity, SoilType soilType) {
    // Температурная компенсация (Archie, 1942)
    float tempFactor = 1.0f + 0.021f * (temperature - 25.0f);
    
    // Влажностная компенсация по модели Арчи
    float porosity = getPorosity(soilType);
    float archieCoeff = getArchieCoefficient(soilType);
    float humFactor = pow(humidity / 100.0f, archieCoeff);
    
    return ec25 * tempFactor * humFactor;
}

float getArchieCoefficient(SoilType soilType) {
    switch (soilType) {
        case SAND: return 0.15f;      // Песок
        case LOAM: return 0.30f;      // Суглинок
        case CLAY: return 0.45f;      // Глина
        case PEAT: return 0.10f;      // Торф
        case SANDY_PEAT: return 0.18f; // Песчано-торфяной
        default: return 0.30f;
    }
}

2️⃣ Уравнение Нернста - pH компенсация

float correctPH(float phRaw, float temperature) {
    // Температурная поправка pH по уравнению Нернста
    // dE/dT = -0.003 V/°C для pH электрода
    return phRaw - 0.003f * (temperature - 25.0f);
}

3️⃣ FAO 56 + Eur. J. Soil Sci. - NPK компенсация

void correctNPK(float temperature, float humidity, 
                float& nitrogen, float& phosphorus, float& potassium, 
                SoilType soilType) {
    // Температурная компенсация NPK
    float tempFactor = 1.0f - 0.02f * (temperature - 25.0f);
    
    // Влажностная компенсация по FAO 56
    float humFactor = 1.0f + 0.05f * (humidity - 50.0f) / 50.0f;
    
    // Применение компенсации
    nitrogen *= tempFactor * humFactor;
    phosphorus *= tempFactor * humFactor;
    potassium *= tempFactor * humFactor;
}

🌐 ВЕБ-ИНТЕРФЕЙС

📱 Архитектура веб-интерфейса

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   Web Browser   │    │   ESP32 Web     │    │   Data Storage  │
│   (Frontend)    │◄──►│   Server        │◄──►│   (NVS/Flash)   │
└─────────────────┘    └─────────────────┘    └─────────────────┘
                              │
                              ▼
                       ┌─────────────────┐
                       │   Sensor Data   │
                       │   Processing    │
                       └─────────────────┘

🛣️ Маршрутизация

// Файл: src/web/routes_data.cpp

void setupDataRoutes() {
    // Основные маршруты данных
    server.on("/readings", HTTP_GET, handleReadings);
    server.on("/intervals", HTTP_GET, handleIntervals);
    server.on("/config_manager", HTTP_GET, handleConfigManager);
    server.on("/updates", HTTP_GET, handleUpdates);
    server.on("/service", HTTP_GET, handleService);
}
📋 План рефакторинга QA 2025 H2

📋 План рефакторинга QA 2025 H2

🎯 Цели рефакторинга

🔧 Приоритетные задачи

🔥 Высокий приоритет

  • Исправление критических багов
  • Оптимизация памяти
  • Улучшение обработки ошибок

⚡ Средний приоритет

  • Рефакторинг устаревшего кода
  • Улучшение документации
  • Оптимизация алгоритмов

📈 Низкий приоритет

  • Косметические улучшения
  • Дополнительные функции
  • Расширенная документация
📊 Отчет о техническом долге 2025-06

📊 Отчет о техническом долге 2025-06

📈 Общая оценка

Технический долг проекта находится на приемлемом уровне. Основные области для улучшения:

🔴 Высокий технический долг

  • Устаревшие алгоритмы компенсации
  • Неоптимальное использование памяти
  • Отсутствие полного покрытия тестами

🟡 Средний технический долг

  • Дублирование кода в некоторых модулях
  • Недостаточная документация API
  • Сложность некоторых функций

🟢 Низкий технический долг

  • Хорошая архитектура в целом
  • Консистентное именование
  • Понятная структура проекта

🎯 Рекомендации

🏗️ Общая архитектура JXCT v3.4.9

🏗️ Общая архитектура JXCT v3.4.9

Версия документа: 3.4.9
Дата обновления: 2025-06-24
Статус: Актуальная архитектура с фокусом на стабильность

🎯 ПРИНЦИПЫ АРХИТЕКТУРЫ

1. Стабильность превыше всего

2. Модульность и переиспользование

3. Производительность и эффективность

🔧 ОСНОВНЫЕ КОМПОНЕНТЫ

📡 СИСТЕМА ДАТЧИКОВ

🔌 Абстракция датчиков

// Файл: include/ISensor.h

class ISensor {
public:
    virtual ~ISensor() = default;
    virtual bool initialize() = 0;
    virtual SensorData read() = 0;
    virtual bool isConnected() const = 0;
    virtual String getSensorInfo() const = 0;
};

🎭 Адаптеры датчиков

// Файл: src/modbus_sensor.h

class ModbusSensorAdapter : public ISensor {
private:
    ModbusSensor* sensor;
    
public:
    ModbusSensorAdapter(ModbusSensor* s) : sensor(s) {}
    
    bool initialize() override {
        return sensor->begin();
    }
    
    SensorData read() override {
        return sensor->getData();
    }
    
    bool isConnected() const override {
        return sensor->isConnected();
    }
    
    String getSensorInfo() const override {
        return "Modbus Sensor v" + String(sensor->getVersion());
    }
};

🧮 СИСТЕМА КОМПЕНСАЦИИ

✅ ИСПРАВЛЕННАЯ ДВУХЭТАПНАЯ КОМПЕНСАЦИЯ

// Файл: src/modbus_sensor.cpp

void applyCompensationIfEnabled(SensorData& d, const SoilProfile& profile) {
    // ШАГ 1: Применяем калибровочную таблицу CSV (лабораторная поверка)
    float tempCalibrated = CalibrationManager::applyCalibration(d.temperature, profile);
    float humCalibrated = CalibrationManager::applyCalibration(d.humidity, profile);
    float ecCalibrated = CalibrationManager::applyCalibration(d.ec, profile);
    float phCalibrated = CalibrationManager::applyCalibration(d.ph, profile);
    float nCalibrated = CalibrationManager::applyCalibration(d.nitrogen, profile);
    float pCalibrated = CalibrationManager::applyCalibration(d.phosphorus, profile);
    float kCalibrated = CalibrationManager::applyCalibration(d.potassium, profile);

    // ШАГ 2: Применяем математическую компенсацию (температурная, влажностная)
    float ec25 = ecCalibrated / (1.0f + 0.021f * (tempCalibrated - 25.0f));
    d.ec = correctEC(ec25, tempCalibrated, humCalibrated, profile.soilType);
    d.ph = correctPH(phCalibrated, tempCalibrated);
    correctNPK(tempCalibrated, humCalibrated, d.nitrogen, d.phosphorus, d.potassium, profile.soilType);
}

🔧 Калибровочный менеджер

// Файл: src/calibration_manager.cpp

class CalibrationManager {
public:
    // Применение калибровочной таблицы с линейной интерполяцией
    static float applyCalibration(float rawValue, const CalibrationProfile& profile) {
        if (!profile.isLoaded()) {
            return rawValue; // Возвращаем исходное значение если таблица не загружена
        }
        
        // Поиск ближайших точек калибровки
        CalibrationPoint lower, upper;
        if (profile.findInterpolationPoints(rawValue, lower, upper)) {
            // Линейная интерполяция
            float ratio = (rawValue - lower.raw) / (upper.raw - lower.raw);
            return lower.calibrated + ratio * (upper.calibrated - lower.calibrated);
        }
        
        return rawValue; // Вне диапазона калибровки
    }
};

1️⃣ Модель Арчи - EC компенсация

float correctEC(float ec25, float temperature, float humidity, SoilType soilType) {
    // Температурная компенсация (Archie, 1942)
    float tempFactor = 1.0f + 0.021f * (temperature - 25.0f);
    
    // Влажностная компенсация по модели Арчи
    float porosity = getPorosity(soilType);
    float archieCoeff = getArchieCoefficient(soilType);
    float humFactor = pow(humidity / 100.0f, archieCoeff);
    
    return ec25 * tempFactor * humFactor;
}

float getArchieCoefficient(SoilType soilType) {
    switch (soilType) {
        case SAND: return 0.15f;      // Песок
        case LOAM: return 0.30f;      // Суглинок
        case CLAY: return 0.45f;      // Глина
        case PEAT: return 0.10f;      // Торф
        case SANDY_PEAT: return 0.18f; // Песчано-торфяной
        default: return 0.30f;
    }
}

2️⃣ Уравнение Нернста - pH компенсация

float correctPH(float phRaw, float temperature) {
    // Температурная поправка pH по уравнению Нернста
    // dE/dT = -0.003 V/°C для pH электрода
    return phRaw - 0.003f * (temperature - 25.0f);
}

3️⃣ FAO 56 + Eur. J. Soil Sci. - NPK компенсация

void correctNPK(float temperature, float humidity, 
                float& nitrogen, float& phosphorus, float& potassium, 
                SoilType soilType) {
    // Температурная компенсация NPK
    float tempFactor = 1.0f - 0.02f * (temperature - 25.0f);
    
    // Влажностная компенсация по FAO 56
    float humFactor = 1.0f + 0.05f * (humidity - 50.0f) / 50.0f;
    
    // Применение компенсации
    nitrogen *= tempFactor * humFactor;
    phosphorus *= tempFactor * humFactor;
    potassium *= tempFactor * humFactor;
}

🌐 ВЕБ-ИНТЕРФЕЙС

📱 Архитектура веб-интерфейса

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   Web Browser   │    │   ESP32 Web     │    │   Data Storage  │
│   (Frontend)    │◄──►│   Server        │◄──►│   (NVS/Flash)   │
└─────────────────┘    └─────────────────┘    └─────────────────┘
                              │
                              ▼
                       ┌─────────────────┐
                       │   Sensor Data   │
                       │   Processing    │
                       └─────────────────┘

🛣️ Маршрутизация

// Файл: src/web/routes_data.cpp

void setupDataRoutes() {
    // Основные маршруты данных
    server.on("/readings", HTTP_GET, handleReadings);
    server.on("/intervals", HTTP_GET, handleIntervals);
    server.on("/config_manager", HTTP_GET, handleConfigManager);
    server.on("/updates", HTTP_GET, handleUpdates);
    server.on("/service", HTTP_GET, handleService);
}
📋 План рефакторинга QA 2025 H2

📋 План рефакторинга QA 2025 H2

🎯 Цели рефакторинга

🔧 Приоритетные задачи

🔥 Высокий приоритет

  • Исправление критических багов
  • Оптимизация памяти
  • Улучшение обработки ошибок

⚡ Средний приоритет

  • Рефакторинг устаревшего кода
  • Улучшение документации
  • Оптимизация алгоритмов

📈 Низкий приоритет

  • Косметические улучшения
  • Дополнительные функции
  • Расширенная документация
📊 Отчет о техническом долге 2025-06

📊 Отчет о техническом долге 2025-06

📈 Общая оценка

Технический долг проекта находится на приемлемом уровне. Основные области для улучшения:

🔴 Высокий технический долг

  • Устаревшие алгоритмы компенсации
  • Неоптимальное использование памяти
  • Отсутствие полного покрытия тестами

🟡 Средний технический долг

  • Дублирование кода в некоторых модулях
  • Недостаточная документация API
  • Сложность некоторых функций

🟢 Низкий технический долг

  • Хорошая архитектура в целом
  • Консистентное именование
  • Понятная структура проекта

🎯 Рекомендации

🏗️ Общая архитектура JXCT v3.4.9

🏗️ Общая архитектура JXCT v3.4.9

Версия документа: 3.4.9
Дата обновления: 2025-06-24
Статус: Актуальная архитектура с фокусом на стабильность

🎯 ПРИНЦИПЫ АРХИТЕКТУРЫ

1. Стабильность превыше всего

2. Модульность и переиспользование

3. Производительность и эффективность

🔧 ОСНОВНЫЕ КОМПОНЕНТЫ

📡 СИСТЕМА ДАТЧИКОВ

🔌 Абстракция датчиков

// Файл: include/ISensor.h

class ISensor {
public:
    virtual ~ISensor() = default;
    virtual bool initialize() = 0;
    virtual SensorData read() = 0;
    virtual bool isConnected() const = 0;
    virtual String getSensorInfo() const = 0;
};

🎭 Адаптеры датчиков

// Файл: src/modbus_sensor.h

class ModbusSensorAdapter : public ISensor {
private:
    ModbusSensor* sensor;
    
public:
    ModbusSensorAdapter(ModbusSensor* s) : sensor(s) {}
    
    bool initialize() override {
        return sensor->begin();
    }
    
    SensorData read() override {
        return sensor->getData();
    }
    
    bool isConnected() const override {
        return sensor->isConnected();
    }
    
    String getSensorInfo() const override {
        return "Modbus Sensor v" + String(sensor->getVersion());
    }
};

🧮 СИСТЕМА КОМПЕНСАЦИИ

✅ ИСПРАВЛЕННАЯ ДВУХЭТАПНАЯ КОМПЕНСАЦИЯ

// Файл: src/modbus_sensor.cpp

void applyCompensationIfEnabled(SensorData& d, const SoilProfile& profile) {
    // ШАГ 1: Применяем калибровочную таблицу CSV (лабораторная поверка)
    float tempCalibrated = CalibrationManager::applyCalibration(d.temperature, profile);
    float humCalibrated = CalibrationManager::applyCalibration(d.humidity, profile);
    float ecCalibrated = CalibrationManager::applyCalibration(d.ec, profile);
    float phCalibrated = CalibrationManager::applyCalibration(d.ph, profile);
    float nCalibrated = CalibrationManager::applyCalibration(d.nitrogen, profile);
    float pCalibrated = CalibrationManager::applyCalibration(d.phosphorus, profile);
    float kCalibrated = CalibrationManager::applyCalibration(d.potassium, profile);

    // ШАГ 2: Применяем математическую компенсацию (температурная, влажностная)
    float ec25 = ecCalibrated / (1.0f + 0.021f * (tempCalibrated - 25.0f));
    d.ec = correctEC(ec25, tempCalibrated, humCalibrated, profile.soilType);
    d.ph = correctPH(phCalibrated, tempCalibrated);
    correctNPK(tempCalibrated, humCalibrated, d.nitrogen, d.phosphorus, d.potassium, profile.soilType);
}

🔧 Калибровочный менеджер

// Файл: src/calibration_manager.cpp

class CalibrationManager {
public:
    // Применение калибровочной таблицы с линейной интерполяцией
    static float applyCalibration(float rawValue, const CalibrationProfile& profile) {
        if (!profile.isLoaded()) {
            return rawValue; // Возвращаем исходное значение если таблица не загружена
        }
        
        // Поиск ближайших точек калибровки
        CalibrationPoint lower, upper;
        if (profile.findInterpolationPoints(rawValue, lower, upper)) {
            // Линейная интерполяция
            float ratio = (rawValue - lower.raw) / (upper.raw - lower.raw);
            return lower.calibrated + ratio * (upper.calibrated - lower.calibrated);
        }
        
        return rawValue; // Вне диапазона калибровки
    }
};

1️⃣ Модель Арчи - EC компенсация

float correctEC(float ec25, float temperature, float humidity, SoilType soilType) {
    // Температурная компенсация (Archie, 1942)
    float tempFactor = 1.0f + 0.021f * (temperature - 25.0f);
    
    // Влажностная компенсация по модели Арчи
    float porosity = getPorosity(soilType);
    float archieCoeff = getArchieCoefficient(soilType);
    float humFactor = pow(humidity / 100.0f, archieCoeff);
    
    return ec25 * tempFactor * humFactor;
}

float getArchieCoefficient(SoilType soilType) {
    switch (soilType) {
        case SAND: return 0.15f;      // Песок
        case LOAM: return 0.30f;      // Суглинок
        case CLAY: return 0.45f;      // Глина
        case PEAT: return 0.10f;      // Торф
        case SANDY_PEAT: return 0.18f; // Песчано-торфяной
        default: return 0.30f;
    }
}

2️⃣ Уравнение Нернста - pH компенсация

float correctPH(float phRaw, float temperature) {
    // Температурная поправка pH по уравнению Нернста
    // dE/dT = -0.003 V/°C для pH электрода
    return phRaw - 0.003f * (temperature - 25.0f);
}

3️⃣ FAO 56 + Eur. J. Soil Sci. - NPK компенсация

void correctNPK(float temperature, float humidity, 
                float& nitrogen, float& phosphorus, float& potassium, 
                SoilType soilType) {
    // Температурная компенсация NPK
    float tempFactor = 1.0f - 0.02f * (temperature - 25.0f);
    
    // Влажностная компенсация по FAO 56
    float humFactor = 1.0f + 0.05f * (humidity - 50.0f) / 50.0f;
    
    // Применение компенсации
    nitrogen *= tempFactor * humFactor;
    phosphorus *= tempFactor * humFactor;
    potassium *= tempFactor * humFactor;
}

🌐 ВЕБ-ИНТЕРФЕЙС

📱 Архитектура веб-интерфейса

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   Web Browser   │    │   ESP32 Web     │    │   Data Storage  │
│   (Frontend)    │◄──►│   Server        │◄──►│   (NVS/Flash)   │
└─────────────────┘    └─────────────────┘    └─────────────────┘
                              │
                              ▼
                       ┌─────────────────┐
                       │   Sensor Data   │
                       │   Processing    │
                       └─────────────────┘

🛣️ Маршрутизация

// Файл: src/web/routes_data.cpp

void setupDataRoutes() {
    // Основные маршруты данных
    server.on("/readings", HTTP_GET, handleReadings);
    server.on("/intervals", HTTP_GET, handleIntervals);
    server.on("/config_manager", HTTP_GET, handleConfigManager);
    server.on("/updates", HTTP_GET, handleUpdates);
    server.on("/service", HTTP_GET, handleService);
}
📋 План рефакторинга QA 2025 H2

📋 План рефакторинга QA 2025 H2

🎯 Цели рефакторинга

🔧 Приоритетные задачи

🔥 Высокий приоритет

  • Исправление критических багов
  • Оптимизация памяти
  • Улучшение обработки ошибок

⚡ Средний приоритет

  • Рефакторинг устаревшего кода
  • Улучшение документации
  • Оптимизация алгоритмов

📈 Низкий приоритет

  • Косметические улучшения
  • Дополнительные функции
  • Расширенная документация
📊 Отчет о техническом долге 2025-06

📊 Отчет о техническом долге 2025-06

📈 Общая оценка

Технический долг проекта находится на приемлемом уровне. Основные области для улучшения:

🔴 Высокий технический долг

  • Устаревшие алгоритмы компенсации
  • Неоптимальное использование памяти
  • Отсутствие полного покрытия тестами

🟡 Средний технический долг

  • Дублирование кода в некоторых модулях
  • Недостаточная документация API
  • Сложность некоторых функций

🟢 Низкий технический долг

  • Хорошая архитектура в целом
  • Консистентное именование
  • Понятная структура проекта

🎯 Рекомендации

🏗️ Общая архитектура JXCT v3.4.9

🏗️ Общая архитектура JXCT v3.4.9

Версия документа: 3.4.9
Дата обновления: 2025-06-24
Статус: Актуальная архитектура с фокусом на стабильность

🎯 ПРИНЦИПЫ АРХИТЕКТУРЫ

1. Стабильность превыше всего

2. Модульность и переиспользование

3. Производительность и эффективность

🔧 ОСНОВНЫЕ КОМПОНЕНТЫ

📡 СИСТЕМА ДАТЧИКОВ

🔌 Абстракция датчиков

// Файл: include/ISensor.h

class ISensor {
public:
    virtual ~ISensor() = default;
    virtual bool initialize() = 0;
    virtual SensorData read() = 0;
    virtual bool isConnected() const = 0;
    virtual String getSensorInfo() const = 0;
};

🎭 Адаптеры датчиков

// Файл: src/modbus_sensor.h

class ModbusSensorAdapter : public ISensor {
private:
    ModbusSensor* sensor;
    
public:
    ModbusSensorAdapter(ModbusSensor* s) : sensor(s) {}
    
    bool initialize() override {
        return sensor->begin();
    }
    
    SensorData read() override {
        return sensor->getData();
    }
    
    bool isConnected() const override {
        return sensor->isConnected();
    }
    
    String getSensorInfo() const override {
        return "Modbus Sensor v" + String(sensor->getVersion());
    }
};

🧮 СИСТЕМА КОМПЕНСАЦИИ

✅ ИСПРАВЛЕННАЯ ДВУХЭТАПНАЯ КОМПЕНСАЦИЯ

// Файл: src/modbus_sensor.cpp

void applyCompensationIfEnabled(SensorData& d, const SoilProfile& profile) {
    // ШАГ 1: Применяем калибровочную таблицу CSV (лабораторная поверка)
    float tempCalibrated = CalibrationManager::applyCalibration(d.temperature, profile);
    float humCalibrated = CalibrationManager::applyCalibration(d.humidity, profile);
    float ecCalibrated = CalibrationManager::applyCalibration(d.ec, profile);
    float phCalibrated = CalibrationManager::applyCalibration(d.ph, profile);
    float nCalibrated = CalibrationManager::applyCalibration(d.nitrogen, profile);
    float pCalibrated = CalibrationManager::applyCalibration(d.phosphorus, profile);
    float kCalibrated = CalibrationManager::applyCalibration(d.potassium, profile);

    // ШАГ 2: Применяем математическую компенсацию (температурная, влажностная)
    float ec25 = ecCalibrated / (1.0f + 0.021f * (tempCalibrated - 25.0f));
    d.ec = correctEC(ec25, tempCalibrated, humCalibrated, profile.soilType);
    d.ph = correctPH(phCalibrated, tempCalibrated);
    correctNPK(tempCalibrated, humCalibrated, d.nitrogen, d.phosphorus, d.potassium, profile.soilType);
}

🔧 Калибровочный менеджер

// Файл: src/calibration_manager.cpp

class CalibrationManager {
public:
    // Применение калибровочной таблицы с линейной интерполяцией
    static float applyCalibration(float rawValue, const CalibrationProfile& profile) {
        if (!profile.isLoaded()) {
            return rawValue; // Возвращаем исходное значение если таблица не загружена
        }
        
        // Поиск ближайших точек калибровки
        CalibrationPoint lower, upper;
        if (profile.findInterpolationPoints(rawValue, lower, upper)) {
            // Линейная интерполяция
            float ratio = (rawValue - lower.raw) / (upper.raw - lower.raw);
            return lower.calibrated + ratio * (upper.calibrated - lower.calibrated);
        }
        
        return rawValue; // Вне диапазона калибровки
    }
};

1️⃣ Модель Арчи - EC компенсация

float correctEC(float ec25, float temperature, float humidity, SoilType soilType) {
    // Температурная компенсация (Archie, 1942)
    float tempFactor = 1.0f + 0.021f * (temperature - 25.0f);
    
    // Влажностная компенсация по модели Арчи
    float porosity = getPorosity(soilType);
    float archieCoeff = getArchieCoefficient(soilType);
    float humFactor = pow(humidity / 100.0f, archieCoeff);
    
    return ec25 * tempFactor * humFactor;
}

float getArchieCoefficient(SoilType soilType) {
    switch (soilType) {
        case SAND: return 0.15f;      // Песок
        case LOAM: return 0.30f;      // Суглинок
        case CLAY: return 0.45f;      // Глина
        case PEAT: return 0.10f;      // Торф
        case SANDY_PEAT: return 0.18f; // Песчано-торфяной
        default: return 0.30f;
    }
}

2️⃣ Уравнение Нернста - pH компенсация

float correctPH(float phRaw, float temperature) {
    // Температурная поправка pH по уравнению Нернста
    // dE/dT = -0.003 V/°C для pH электрода
    return phRaw - 0.003f * (temperature - 25.0f);
}

3️⃣ FAO 56 + Eur. J. Soil Sci. - NPK компенсация

void correctNPK(float temperature, float humidity, 
                float& nitrogen, float& phosphorus, float& potassium, 
                SoilType soilType) {
    // Температурная компенсация NPK
    float tempFactor = 1.0f - 0.02f * (temperature - 25.0f);
    
    // Влажностная компенсация по FAO 56
    float humFactor = 1.0f + 0.05f * (humidity - 50.0f) / 50.0f;
    
    // Применение компенсации
    nitrogen *= tempFactor * humFactor;
    phosphorus *= tempFactor * humFactor;
    potassium *= tempFactor * humFactor;
}

🌐 ВЕБ-ИНТЕРФЕЙС

📱 Архитектура веб-интерфейса

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   Web Browser   │    │   ESP32 Web     │    │   Data Storage  │
│   (Frontend)    │◄──►│   Server        │◄──►│   (NVS/Flash)   │
└─────────────────┘    └─────────────────┘    └─────────────────┘
                              │
                              ▼
                       ┌─────────────────┐
                       │   Sensor Data   │
                       │   Processing    │
                       └─────────────────┘

🛣️ Маршрутизация

// Файл: src/web/routes_data.cpp

void setupDataRoutes() {
    // Основные маршруты данных
    server.on("/readings", HTTP_GET, handleReadings);
    server.on("/intervals", HTTP_GET, handleIntervals);
    server.on("/config_manager", HTTP_GET, handleConfigManager);
    server.on("/updates", HTTP_GET, handleUpdates);
    server.on("/service", HTTP_GET, handleService);
}
📋 План рефакторинга QA 2025 H2

📋 План рефакторинга QA 2025 H2

🎯 Цели рефакторинга

🔧 Приоритетные задачи

🔥 Высокий приоритет

  • Исправление критических багов
  • Оптимизация памяти
  • Улучшение обработки ошибок

⚡ Средний приоритет

  • Рефакторинг устаревшего кода
  • Улучшение документации
  • Оптимизация алгоритмов

📈 Низкий приоритет

  • Косметические улучшения
  • Дополнительные функции
  • Расширенная документация
📊 Отчет о техническом долге 2025-06

📊 Отчет о техническом долге 2025-06

📈 Общая оценка

Технический долг проекта находится на приемлемом уровне. Основные области для улучшения:

🔴 Высокий технический долг

  • Устаревшие алгоритмы компенсации
  • Неоптимальное использование памяти
  • Отсутствие полного покрытия тестами

🟡 Средний технический долг

  • Дублирование кода в некоторых модулях
  • Недостаточная документация API
  • Сложность некоторых функций

🟢 Низкий технический долг

  • Хорошая архитектура в целом
  • Консистентное именование
  • Понятная структура проекта

🎯 Рекомендации

🏗️ Общая архитектура JXCT v3.4.9

🏗️ Общая архитектура JXCT v3.4.9

Версия документа: 3.4.9
Дата обновления: 2025-06-24
Статус: Актуальная архитектура с фокусом на стабильность

🎯 ПРИНЦИПЫ АРХИТЕКТУРЫ

1. Стабильность превыше всего

2. Модульность и переиспользование

3. Производительность и эффективность

🔧 ОСНОВНЫЕ КОМПОНЕНТЫ

📡 СИСТЕМА ДАТЧИКОВ

🔌 Абстракция датчиков

// Файл: include/ISensor.h

class ISensor {
public:
    virtual ~ISensor() = default;
    virtual bool initialize() = 0;
    virtual SensorData read() = 0;
    virtual bool isConnected() const = 0;
    virtual String getSensorInfo() const = 0;
};

🎭 Адаптеры датчиков

// Файл: src/modbus_sensor.h

class ModbusSensorAdapter : public ISensor {
private:
    ModbusSensor* sensor;
    
public:
    ModbusSensorAdapter(ModbusSensor* s) : sensor(s) {}
    
    bool initialize() override {
        return sensor->begin();
    }
    
    SensorData read() override {
        return sensor->getData();
    }
    
    bool isConnected() const override {
        return sensor->isConnected();
    }
    
    String getSensorInfo() const override {
        return "Modbus Sensor v" + String(sensor->getVersion());
    }
};

🧮 СИСТЕМА КОМПЕНСАЦИИ

✅ ИСПРАВЛЕННАЯ ДВУХЭТАПНАЯ КОМПЕНСАЦИЯ

// Файл: src/modbus_sensor.cpp

void applyCompensationIfEnabled(SensorData& d, const SoilProfile& profile) {
    // ШАГ 1: Применяем калибровочную таблицу CSV (лабораторная поверка)
    float tempCalibrated = CalibrationManager::applyCalibration(d.temperature, profile);
    float humCalibrated = CalibrationManager::applyCalibration(d.humidity, profile);
    float ecCalibrated = CalibrationManager::applyCalibration(d.ec, profile);
    float phCalibrated = CalibrationManager::applyCalibration(d.ph, profile);
    float nCalibrated = CalibrationManager::applyCalibration(d.nitrogen, profile);
    float pCalibrated = CalibrationManager::applyCalibration(d.phosphorus, profile);
    float kCalibrated = CalibrationManager::applyCalibration(d.potassium, profile);

    // ШАГ 2: Применяем математическую компенсацию (температурная, влажностная)
    float ec25 = ecCalibrated / (1.0f + 0.021f * (tempCalibrated - 25.0f));
    d.ec = correctEC(ec25, tempCalibrated, humCalibrated, profile.soilType);
    d.ph = correctPH(phCalibrated, tempCalibrated);
    correctNPK(tempCalibrated, humCalibrated, d.nitrogen, d.phosphorus, d.potassium, profile.soilType);
}

🔧 Калибровочный менеджер

// Файл: src/calibration_manager.cpp

class CalibrationManager {
public:
    // Применение калибровочной таблицы с линейной интерполяцией
    static float applyCalibration(float rawValue, const CalibrationProfile& profile) {
        if (!profile.isLoaded()) {
            return rawValue; // Возвращаем исходное значение если таблица не загружена
        }
        
        // Поиск ближайших точек калибровки
        CalibrationPoint lower, upper;
        if (profile.findInterpolationPoints(rawValue, lower, upper)) {
            // Линейная интерполяция
            float ratio = (rawValue - lower.raw) / (upper.raw - lower.raw);
            return lower.calibrated + ratio * (upper.calibrated - lower.calibrated);
        }
        
        return rawValue; // Вне диапазона калибровки
    }
};

1️⃣ Модель Арчи - EC компенсация

float correctEC(float ec25, float temperature, float humidity, SoilType soilType) {
    // Температурная компенсация (Archie, 1942)
    float tempFactor = 1.0f + 0.021f * (temperature - 25.0f);
    
    // Влажностная компенсация по модели Арчи
    float porosity = getPorosity(soilType);
    float archieCoeff = getArchieCoefficient(soilType);
    float humFactor = pow(humidity / 100.0f, archieCoeff);
    
    return ec25 * tempFactor * humFactor;
}

float getArchieCoefficient(SoilType soilType) {
    switch (soilType) {
        case SAND: return 0.15f;      // Песок
        case LOAM: return 0.30f;      // Суглинок
        case CLAY: return 0.45f;      // Глина
        case PEAT: return 0.10f;      // Торф
        case SANDY_PEAT: return 0.18f; // Песчано-торфяной
        default: return 0.30f;
    }
}

2️⃣ Уравнение Нернста - pH компенсация

float correctPH(float phRaw, float temperature) {
    // Температурная поправка pH по уравнению Нернста
    // dE/dT = -0.003 V/°C для pH электрода
    return phRaw - 0.003f * (temperature - 25.0f);
}

3️⃣ FAO 56 + Eur. J. Soil Sci. - NPK компенсация

void correctNPK(float temperature, float humidity, 
                float& nitrogen, float& phosphorus, float& potassium, 
                SoilType soilType) {
    // Температурная компенсация NPK
    float tempFactor = 1.0f - 0.02f * (temperature - 25.0f);
    
    // Влажностная компенсация по FAO 56
    float humFactor = 1.0f + 0.05f * (humidity - 50.0f) / 50.0f;
    
    // Применение компенсации
    nitrogen *= tempFactor * humFactor;
    phosphorus *= tempFactor * humFactor;
    potassium *= tempFactor * humFactor;
}

🌐 ВЕБ-ИНТЕРФЕЙС

📱 Архитектура веб-интерфейса

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   Web Browser   │    │   ESP32 Web     │    │   Data Storage  │
│   (Frontend)    │◄──►│   Server        │◄──►│   (NVS/Flash)   │
└─────────────────┘    └─────────────────┘    └─────────────────┘
                              │
                              ▼
                       ┌─────────────────┐
                       │   Sensor Data   │
                       │   Processing    │
                       └─────────────────┘

🛣️ Маршрутизация

// Файл: src/web/routes_data.cpp

void setupDataRoutes() {
    // Основные маршруты данных
    server.on("/readings", HTTP_GET, handleReadings);
    server.on("/intervals", HTTP_GET, handleIntervals);
    server.on("/config_manager", HTTP_GET, handleConfigManager);
    server.on("/updates", HTTP_GET, handleUpdates);
    server.on("/service", HTTP_GET, handleService);
}
📋 План рефакторинга QA 2025 H2

📋 План рефакторинга QA 2025 H2

🎯 Цели рефакторинга

🔧 Приоритетные задачи

🔥 Высокий приоритет

  • Исправление критических багов
  • Оптимизация памяти
  • Улучшение обработки ошибок

⚡ Средний приоритет

  • Рефакторинг устаревшего кода
  • Улучшение документации
  • Оптимизация алгоритмов

📈 Низкий приоритет

  • Косметические улучшения
  • Дополнительные функции
  • Расширенная документация
📊 Отчет о техническом долге 2025-06

📊 Отчет о техническом долге 2025-06

📈 Общая оценка

Технический долг проекта находится на приемлемом уровне. Основные области для улучшения:

🔴 Высокий технический долг

  • Устаревшие алгоритмы компенсации
  • Неоптимальное использование памяти
  • Отсутствие полного покрытия тестами

🟡 Средний технический долг

  • Дублирование кода в некоторых модулях
  • Недостаточная документация API
  • Сложность некоторых функций

🟢 Низкий технический долг

  • Хорошая архитектура в целом
  • Консистентное именование
  • Понятная структура проекта

🎯 Рекомендации

🏗️ Общая архитектура JXCT v3.4.9

🏗️ Общая архитектура JXCT v3.4.9

Версия документа: 3.4.9
Дата обновления: 2025-06-24
Статус: Актуальная архитектура с фокусом на стабильность

🎯 ПРИНЦИПЫ АРХИТЕКТУРЫ

1. Стабильность превыше всего

2. Модульность и переиспользование

3. Производительность и эффективность

🔧 ОСНОВНЫЕ КОМПОНЕНТЫ

📡 СИСТЕМА ДАТЧИКОВ

🔌 Абстракция датчиков

// Файл: include/ISensor.h

class ISensor {
public:
    virtual ~ISensor() = default;
    virtual bool initialize() = 0;
    virtual SensorData read() = 0;
    virtual bool isConnected() const = 0;
    virtual String getSensorInfo() const = 0;
};

🎭 Адаптеры датчиков

// Файл: src/modbus_sensor.h

class ModbusSensorAdapter : public ISensor {
private:
    ModbusSensor* sensor;
    
public:
    ModbusSensorAdapter(ModbusSensor* s) : sensor(s) {}
    
    bool initialize() override {
        return sensor->begin();
    }
    
    SensorData read() override {
        return sensor->getData();
    }
    
    bool isConnected() const override {
        return sensor->isConnected();
    }
    
    String getSensorInfo() const override {
        return "Modbus Sensor v" + String(sensor->getVersion());
    }
};

🧮 СИСТЕМА КОМПЕНСАЦИИ

✅ ИСПРАВЛЕННАЯ ДВУХЭТАПНАЯ КОМПЕНСАЦИЯ

// Файл: src/modbus_sensor.cpp

void applyCompensationIfEnabled(SensorData& d, const SoilProfile& profile) {
    // ШАГ 1: Применяем калибровочную таблицу CSV (лабораторная поверка)
    float tempCalibrated = CalibrationManager::applyCalibration(d.temperature, profile);
    float humCalibrated = CalibrationManager::applyCalibration(d.humidity, profile);
    float ecCalibrated = CalibrationManager::applyCalibration(d.ec, profile);
    float phCalibrated = CalibrationManager::applyCalibration(d.ph, profile);
    float nCalibrated = CalibrationManager::applyCalibration(d.nitrogen, profile);
    float pCalibrated = CalibrationManager::applyCalibration(d.phosphorus, profile);
    float kCalibrated = CalibrationManager::applyCalibration(d.potassium, profile);

    // ШАГ 2: Применяем математическую компенсацию (температурная, влажностная)
    float ec25 = ecCalibrated / (1.0f + 0.021f * (tempCalibrated - 25.0f));
    d.ec = correctEC(ec25, tempCalibrated, humCalibrated, profile.soilType);
    d.ph = correctPH(phCalibrated, tempCalibrated);
    correctNPK(tempCalibrated, humCalibrated, d.nitrogen, d.phosphorus, d.potassium, profile.soilType);
}

🔧 Калибровочный менеджер

// Файл: src/calibration_manager.cpp

class CalibrationManager {
public:
    // Применение калибровочной таблицы с линейной интерполяцией
    static float applyCalibration(float rawValue, const CalibrationProfile& profile) {
        if (!profile.isLoaded()) {
            return rawValue; // Возвращаем исходное значение если таблица не загружена
        }
        
        // Поиск ближайших точек калибровки
        CalibrationPoint lower, upper;
        if (profile.findInterpolationPoints(rawValue, lower, upper)) {
            // Линейная интерполяция
            float ratio = (rawValue - lower.raw) / (upper.raw - lower.raw);
            return lower.calibrated + ratio * (upper.calibrated - lower.calibrated);
        }
        
        return rawValue; // Вне диапазона калибровки
    }
};

1️⃣ Модель Арчи - EC компенсация

float correctEC(float ec25, float temperature, float humidity, SoilType soilType) {
    // Температурная компенсация (Archie, 1942)
    float tempFactor = 1.0f + 0.021f * (temperature - 25.0f);
    
    // Влажностная компенсация по модели Арчи
    float porosity = getPorosity(soilType);
    float archieCoeff = getArchieCoefficient(soilType);
    float humFactor = pow(humidity / 100.0f, archieCoeff);
    
    return ec25 * tempFactor * humFactor;
}

float getArchieCoefficient(SoilType soilType) {
    switch (soilType) {
        case SAND: return 0.15f;      // Песок
        case LOAM: return 0.30f;      // Суглинок
        case CLAY: return 0.45f;      // Глина
        case PEAT: return 0.10f;      // Торф
        case SANDY_PEAT: return 0.18f; // Песчано-торфяной
        default: return 0.30f;
    }
}

2️⃣ Уравнение Нернста - pH компенсация

float correctPH(float phRaw, float temperature) {
    // Температурная поправка pH по уравнению Нернста
    // dE/dT = -0.003 V/°C для pH электрода
    return phRaw - 0.003f * (temperature - 25.0f);
}

3️⃣ FAO 56 + Eur. J. Soil Sci. - NPK компенсация

void correctNPK(float temperature, float humidity, 
                float& nitrogen, float& phosphorus, float& potassium, 
                SoilType soilType) {
    // Температурная компенсация NPK
    float tempFactor = 1.0f - 0.02f * (temperature - 25.0f);
    
    // Влажностная компенсация по FAO 56
    float humFactor = 1.0f + 0.05f * (humidity - 50.0f) / 50.0f;
    
    // Применение компенсации
    nitrogen *= tempFactor * humFactor;
    phosphorus *= tempFactor * humFactor;
    potassium *= tempFactor * humFactor;
}

🌐 ВЕБ-ИНТЕРФЕЙС

📱 Архитектура веб-интерфейса

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   Web Browser   │    │   ESP32 Web     │    │   Data Storage  │
│   (Frontend)    │◄──►│   Server        │◄──►│   (NVS/Flash)   │
└─────────────────┘    └─────────────────┘    └─────────────────┘
                              │
                              ▼
                       ┌─────────────────┐
                       │   Sensor Data   │
                       │   Processing    │
                       └─────────────────┘

🛣️ Маршрутизация

// Файл: src/web/routes_data.cpp

void setupDataRoutes() {
    // Основные маршруты данных
    server.on("/readings", HTTP_GET, handleReadings);
    server.on("/intervals", HTTP_GET, handleIntervals);
    server.on("/config_manager", HTTP_GET, handleConfigManager);
    server.on("/updates", HTTP_GET, handleUpdates);
    server.on("/service", HTTP_GET, handleService);
}
📋 План рефакторинга QA 2025 H2

📋 План рефакторинга QA 2025 H2

🎯 Цели рефакторинга

🔧 Приоритетные задачи

🔥 Высокий приоритет

  • Исправление критических багов
  • Оптимизация памяти
  • Улучшение обработки ошибок

⚡ Средний приоритет

  • Рефакторинг устаревшего кода
  • Улучшение документации
  • Оптимизация алгоритмов

📈 Низкий приоритет

  • Косметические улучшения
  • Дополнительные функции
  • Расширенная документация
📊 Отчет о техническом долге 2025-06

📊 Отчет о техническом долге 2025-06

📈 Общая оценка

Технический долг проекта находится на приемлемом уровне. Основные области для улучшения:

🔴 Высокий технический долг

  • Устаревшие алгоритмы компенсации
  • Неоптимальное использование памяти
  • Отсутствие полного покрытия тестами

🟡 Средний технический долг

  • Дублирование кода в некоторых модулях
  • Недостаточная документация API
  • Сложность некоторых функций

🟢 Низкий технический долг

  • Хорошая архитектура в целом
  • Консистентное именование
  • Понятная структура проекта

🎯 Рекомендации

🏗️ Общая архитектура JXCT v3.4.9

🏗️ Общая архитектура JXCT v3.4.9

Версия документа: 3.4.9
Дата обновления: 2025-06-24
Статус: Актуальная архитектура с фокусом на стабильность

🎯 ПРИНЦИПЫ АРХИТЕКТУРЫ

1. Стабильность превыше всего

2. Модульность и переиспользование

3. Производительность и эффективность

🔧 ОСНОВНЫЕ КОМПОНЕНТЫ

📡 СИСТЕМА ДАТЧИКОВ

🔌 Абстракция датчиков

// Файл: include/ISensor.h

class ISensor {
public:
    virtual ~ISensor() = default;
    virtual bool initialize() = 0;
    virtual SensorData read() = 0;
    virtual bool isConnected() const = 0;
    virtual String getSensorInfo() const = 0;
};

🎭 Адаптеры датчиков

// Файл: src/modbus_sensor.h

class ModbusSensorAdapter : public ISensor {
private:
    ModbusSensor* sensor;
    
public:
    ModbusSensorAdapter(ModbusSensor* s) : sensor(s) {}
    
    bool initialize() override {
        return sensor->begin();
    }
    
    SensorData read() override {
        return sensor->getData();
    }
    
    bool isConnected() const override {
        return sensor->isConnected();
    }
    
    String getSensorInfo() const override {
        return "Modbus Sensor v" + String(sensor->getVersion());
    }
};

🧮 СИСТЕМА КОМПЕНСАЦИИ

✅ ИСПРАВЛЕННАЯ ДВУХЭТАПНАЯ КОМПЕНСАЦИЯ

// Файл: src/modbus_sensor.cpp

void applyCompensationIfEnabled(SensorData& d, const SoilProfile& profile) {
    // ШАГ 1: Применяем калибровочную таблицу CSV (лабораторная поверка)
    float tempCalibrated = CalibrationManager::applyCalibration(d.temperature, profile);
    float humCalibrated = CalibrationManager::applyCalibration(d.humidity, profile);
    float ecCalibrated = CalibrationManager::applyCalibration(d.ec, profile);
    float phCalibrated = CalibrationManager::applyCalibration(d.ph, profile);
    float nCalibrated = CalibrationManager::applyCalibration(d.nitrogen, profile);
    float pCalibrated = CalibrationManager::applyCalibration(d.phosphorus, profile);
    float kCalibrated = CalibrationManager::applyCalibration(d.potassium, profile);

    // ШАГ 2: Применяем математическую компенсацию (температурная, влажностная)
    float ec25 = ecCalibrated / (1.0f + 0.021f * (tempCalibrated - 25.0f));
    d.ec = correctEC(ec25, tempCalibrated, humCalibrated, profile.soilType);
    d.ph = correctPH(phCalibrated, tempCalibrated);
    correctNPK(tempCalibrated, humCalibrated, d.nitrogen, d.phosphorus, d.potassium, profile.soilType);
}

🔧 Калибровочный менеджер

// Файл: src/calibration_manager.cpp

class CalibrationManager {
public:
    // Применение калибровочной таблицы с линейной интерполяцией
    static float applyCalibration(float rawValue, const CalibrationProfile& profile) {
        if (!profile.isLoaded()) {
            return rawValue; // Возвращаем исходное значение если таблица не загружена
        }
        
        // Поиск ближайших точек калибровки
        CalibrationPoint lower, upper;
        if (profile.findInterpolationPoints(rawValue, lower, upper)) {
            // Линейная интерполяция
            float ratio = (rawValue - lower.raw) / (upper.raw - lower.raw);
            return lower.calibrated + ratio * (upper.calibrated - lower.calibrated);
        }
        
        return rawValue; // Вне диапазона калибровки
    }
};

1️⃣ Модель Арчи - EC компенсация

float correctEC(float ec25, float temperature, float humidity, SoilType soilType) {
    // Температурная компенсация (Archie, 1942)
    float tempFactor = 1.0f + 0.021f * (temperature - 25.0f);
    
    // Влажностная компенсация по модели Арчи
    float porosity = getPorosity(soilType);
    float archieCoeff = getArchieCoefficient(soilType);
    float humFactor = pow(humidity / 100.0f, archieCoeff);
    
    return ec25 * tempFactor * humFactor;
}

float getArchieCoefficient(SoilType soilType) {
    switch (soilType) {
        case SAND: return 0.15f;      // Песок
        case LOAM: return 0.30f;      // Суглинок
        case CLAY: return 0.45f;      // Глина
        case PEAT: return 0.10f;      // Торф
        case SANDY_PEAT: return 0.18f; // Песчано-торфяной
        default: return 0.30f;
    }
}

2️⃣ Уравнение Нернста - pH компенсация

float correctPH(float phRaw, float temperature) {
    // Температурная поправка pH по уравнению Нернста
    // dE/dT = -0.003 V/°C для pH электрода
    return phRaw - 0.003f * (temperature - 25.0f);
}

3️⃣ FAO 56 + Eur. J. Soil Sci. - NPK компенсация

void correctNPK(float temperature, float humidity, 
                float& nitrogen, float& phosphorus, float& potassium, 
                SoilType soilType) {
    // Температурная компенсация NPK
    float tempFactor = 1.0f - 0.02f * (temperature - 25.0f);
    
    // Влажностная компенсация по FAO 56
    float humFactor = 1.0f + 0.05f * (humidity - 50.0f) / 50.0f;
    
    // Применение компенсации
    nitrogen *= tempFactor * humFactor;
    phosphorus *= tempFactor * humFactor;
    potassium *= tempFactor * humFactor;
}

🌐 ВЕБ-ИНТЕРФЕЙС

📱 Архитектура веб-интерфейса

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   Web Browser   │    │   ESP32 Web     │    │   Data Storage  │
│   (Frontend)    │◄──►│   Server        │◄──►│   (NVS/Flash)   │
└─────────────────┘    └─────────────────┘    └─────────────────┘
                              │
                              ▼
                       ┌─────────────────┐
                       │   Sensor Data   │
                       │   Processing    │
                       └─────────────────┘

🛣️ Маршрутизация

// Файл: src/web/routes_data.cpp

void setupDataRoutes() {
    // Основные маршруты данных
    server.on("/readings", HTTP_GET, handleReadings);
    server.on("/intervals", HTTP_GET, handleIntervals);
    server.on("/config_manager", HTTP_GET, handleConfigManager);
    server.on("/updates", HTTP_GET, handleUpdates);
    server.on("/service", HTTP_GET, handleService);
}
📋 План рефакторинга QA 2025 H2

📋 План рефакторинга QA 2025 H2

🎯 Цели рефакторинга

🔧 Приоритетные задачи

🔥 Высокий приоритет

  • Исправление критических багов
  • Оптимизация памяти
  • Улучшение обработки ошибок

⚡ Средний приоритет

  • Рефакторинг устаревшего кода
  • Улучшение документации
  • Оптимизация алгоритмов

📈 Низкий приоритет

  • Косметические улучшения
  • Дополнительные функции
  • Расширенная документация
📊 Отчет о техническом долге 2025-06

📊 Отчет о техническом долге 2025-06

📈 Общая оценка

Технический долг проекта находится на приемлемом уровне. Основные области для улучшения:

🔴 Высокий технический долг

  • Устаревшие алгоритмы компенсации
  • Неоптимальное использование памяти
  • Отсутствие полного покрытия тестами

🟡 Средний технический долг

  • Дублирование кода в некоторых модулях
  • Недостаточная документация API
  • Сложность некоторых функций

🟢 Низкий технический долг

  • Хорошая архитектура в целом
  • Консистентное именование
  • Понятная структура проекта

🎯 Рекомендации

🏗️ Общая архитектура JXCT v3.4.9

🏗️ Общая архитектура JXCT v3.4.9

Версия документа: 3.4.9
Дата обновления: 2025-06-24
Статус: Актуальная архитектура с фокусом на стабильность

🎯 ПРИНЦИПЫ АРХИТЕКТУРЫ

1. Стабильность превыше всего

2. Модульность и переиспользование

3. Производительность и эффективность

🔧 ОСНОВНЫЕ КОМПОНЕНТЫ

📡 СИСТЕМА ДАТЧИКОВ

🔌 Абстракция датчиков

// Файл: include/ISensor.h

class ISensor {
public:
    virtual ~ISensor() = default;
    virtual bool initialize() = 0;
    virtual SensorData read() = 0;
    virtual bool isConnected() const = 0;
    virtual String getSensorInfo() const = 0;
};

🎭 Адаптеры датчиков

// Файл: src/modbus_sensor.h

class ModbusSensorAdapter : public ISensor {
private:
    ModbusSensor* sensor;
    
public:
    ModbusSensorAdapter(ModbusSensor* s) : sensor(s) {}
    
    bool initialize() override {
        return sensor->begin();
    }
    
    SensorData read() override {
        return sensor->getData();
    }
    
    bool isConnected() const override {
        return sensor->isConnected();
    }
    
    String getSensorInfo() const override {
        return "Modbus Sensor v" + String(sensor->getVersion());
    }
};

🧮 СИСТЕМА КОМПЕНСАЦИИ

✅ ИСПРАВЛЕННАЯ ДВУХЭТАПНАЯ КОМПЕНСАЦИЯ

// Файл: src/modbus_sensor.cpp

void applyCompensationIfEnabled(SensorData& d, const SoilProfile& profile) {
    // ШАГ 1: Применяем калибровочную таблицу CSV (лабораторная поверка)
    float tempCalibrated = CalibrationManager::applyCalibration(d.temperature, profile);
    float humCalibrated = CalibrationManager::applyCalibration(d.humidity, profile);
    float ecCalibrated = CalibrationManager::applyCalibration(d.ec, profile);
    float phCalibrated = CalibrationManager::applyCalibration(d.ph, profile);
    float nCalibrated = CalibrationManager::applyCalibration(d.nitrogen, profile);
    float pCalibrated = CalibrationManager::applyCalibration(d.phosphorus, profile);
    float kCalibrated = CalibrationManager::applyCalibration(d.potassium, profile);

    // ШАГ 2: Применяем математическую компенсацию (температурная, влажностная)
    float ec25 = ecCalibrated / (1.0f + 0.021f * (tempCalibrated - 25.0f));
    d.ec = correctEC(ec25, tempCalibrated, humCalibrated, profile.soilType);
    d.ph = correctPH(phCalibrated, tempCalibrated);
    correctNPK(tempCalibrated, humCalibrated, d.nitrogen, d.phosphorus, d.potassium, profile.soilType);
}

🔧 Калибровочный менеджер

// Файл: src/calibration_manager.cpp

class CalibrationManager {
public:
    // Применение калибровочной таблицы с линейной интерполяцией
    static float applyCalibration(float rawValue, const CalibrationProfile& profile) {
        if (!profile.isLoaded()) {
            return rawValue; // Возвращаем исходное значение если таблица не загружена
        }
        
        // Поиск ближайших точек калибровки
        CalibrationPoint lower, upper;
        if (profile.findInterpolationPoints(rawValue, lower, upper)) {
            // Линейная интерполяция
            float ratio = (rawValue - lower.raw) / (upper.raw - lower.raw);
            return lower.calibrated + ratio * (upper.calibrated - lower.calibrated);
        }
        
        return rawValue; // Вне диапазона калибровки
    }
};

1️⃣ Модель Арчи - EC компенсация

float correctEC(float ec25, float temperature, float humidity, SoilType soilType) {
    // Температурная компенсация (Archie, 1942)
    float tempFactor = 1.0f + 0.021f * (temperature - 25.0f);
    
    // Влажностная компенсация по модели Арчи
    float porosity = getPorosity(soilType);
    float archieCoeff = getArchieCoefficient(soilType);
    float humFactor = pow(humidity / 100.0f, archieCoeff);
    
    return ec25 * tempFactor * humFactor;
}

float getArchieCoefficient(SoilType soilType) {
    switch (soilType) {
        case SAND: return 0.15f;      // Песок
        case LOAM: return 0.30f;      // Суглинок
        case CLAY: return 0.45f;      // Глина
        case PEAT: return 0.10f;      // Торф
        case SANDY_PEAT: return 0.18f; // Песчано-торфяной
        default: return 0.30f;
    }
}

2️⃣ Уравнение Нернста - pH компенсация

float correctPH(float phRaw, float temperature) {
    // Температурная поправка pH по уравнению Нернста
    // dE/dT = -0.003 V/°C для pH электрода
    return phRaw - 0.003f * (temperature - 25.0f);
}

3️⃣ FAO 56 + Eur. J. Soil Sci. - NPK компенсация

void correctNPK(float temperature, float humidity, 
                float& nitrogen, float& phosphorus, float& potassium, 
                SoilType soilType) {
    // Температурная компенсация NPK
    float tempFactor = 1.0f - 0.02f * (temperature - 25.0f);
    
    // Влажностная компенсация по FAO 56
    float humFactor = 1.0f + 0.05f * (humidity - 50.0f) / 50.0f;
    
    // Применение компенсации
    nitrogen *= tempFactor * humFactor;
    phosphorus *= tempFactor * humFactor;
    potassium *= tempFactor * humFactor;
}

🌐 ВЕБ-ИНТЕРФЕЙС

📱 Архитектура веб-интерфейса

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   Web Browser   │    │   ESP32 Web     │    │   Data Storage  │
│   (Frontend)    │◄──►│   Server        │◄──►│   (NVS/Flash)   │
└─────────────────┘    └─────────────────┘    └─────────────────┘
                              │
                              ▼
                       ┌─────────────────┐
                       │   Sensor Data   │
                       │   Processing    │
                       └─────────────────┘

🛣️ Маршрутизация

// Файл: src/web/routes_data.cpp

void setupDataRoutes() {
    // Основные маршруты данных
    server.on("/readings", HTTP_GET, handleReadings);
    server.on("/intervals", HTTP_GET, handleIntervals);
    server.on("/config_manager", HTTP_GET, handleConfigManager);
    server.on("/updates", HTTP_GET, handleUpdates);
    server.on("/service", HTTP_GET, handleService);
}
📋 План рефакторинга QA 2025 H2

📋 План рефакторинга QA 2025 H2

🎯 Цели рефакторинга

🔧 Приоритетные задачи

🔥 Высокий приоритет

  • Исправление критических багов
  • Оптимизация памяти
  • Улучшение обработки ошибок

⚡ Средний приоритет

  • Рефакторинг устаревшего кода
  • Улучшение документации
  • Оптимизация алгоритмов

📈 Низкий приоритет

  • Косметические улучшения
  • Дополнительные функции
  • Расширенная документация
📊 Отчет о техническом долге 2025-06

📊 Отчет о техническом долге 2025-06

📈 Общая оценка

Технический долг проекта находится на приемлемом уровне. Основные области для улучшения:

🔴 Высокий технический долг

  • Устаревшие алгоритмы компенсации
  • Неоптимальное использование памяти
  • Отсутствие полного покрытия тестами

🟡 Средний технический долг

  • Дублирование кода в некоторых модулях
  • Недостаточная документация API
  • Сложность некоторых функций

🟢 Низкий технический долг

  • Хорошая архитектура в целом
  • Консистентное именование
  • Понятная структура проекта

🎯 Рекомендации

🏗️ Общая архитектура JXCT v3.4.9

🏗️ Общая архитектура JXCT v3.4.9

Версия документа: 3.4.9
Дата обновления: 2025-06-24
Статус: Актуальная архитектура с фокусом на стабильность

🎯 ПРИНЦИПЫ АРХИТЕКТУРЫ

1. Стабильность превыше всего

2. Модульность и переиспользование

3. Производительность и эффективность

🔧 ОСНОВНЫЕ КОМПОНЕНТЫ

📡 СИСТЕМА ДАТЧИКОВ

🔌 Абстракция датчиков

// Файл: include/ISensor.h

class ISensor {
public:
    virtual ~ISensor() = default;
    virtual bool initialize() = 0;
    virtual SensorData read() = 0;
    virtual bool isConnected() const = 0;
    virtual String getSensorInfo() const = 0;
};

🎭 Адаптеры датчиков

// Файл: src/modbus_sensor.h

class ModbusSensorAdapter : public ISensor {
private:
    ModbusSensor* sensor;
    
public:
    ModbusSensorAdapter(ModbusSensor* s) : sensor(s) {}
    
    bool initialize() override {
        return sensor->begin();
    }
    
    SensorData read() override {
        return sensor->getData();
    }
    
    bool isConnected() const override {
        return sensor->isConnected();
    }
    
    String getSensorInfo() const override {
        return "Modbus Sensor v" + String(sensor->getVersion());
    }
};

🧮 СИСТЕМА КОМПЕНСАЦИИ

✅ ИСПРАВЛЕННАЯ ДВУХЭТАПНАЯ КОМПЕНСАЦИЯ

// Файл: src/modbus_sensor.cpp

void applyCompensationIfEnabled(SensorData& d, const SoilProfile& profile) {
    // ШАГ 1: Применяем калибровочную таблицу CSV (лабораторная поверка)
    float tempCalibrated = CalibrationManager::applyCalibration(d.temperature, profile);
    float humCalibrated = CalibrationManager::applyCalibration(d.humidity, profile);
    float ecCalibrated = CalibrationManager::applyCalibration(d.ec, profile);
    float phCalibrated = CalibrationManager::applyCalibration(d.ph, profile);
    float nCalibrated = CalibrationManager::applyCalibration(d.nitrogen, profile);
    float pCalibrated = CalibrationManager::applyCalibration(d.phosphorus, profile);
    float kCalibrated = CalibrationManager::applyCalibration(d.potassium, profile);

    // ШАГ 2: Применяем математическую компенсацию (температурная, влажностная)
    float ec25 = ecCalibrated / (1.0f + 0.021f * (tempCalibrated - 25.0f));
    d.ec = correctEC(ec25, tempCalibrated, humCalibrated, profile.soilType);
    d.ph = correctPH(phCalibrated, tempCalibrated);
    correctNPK(tempCalibrated, humCalibrated, d.nitrogen, d.phosphorus, d.potassium, profile.soilType);
}

🔧 Калибровочный менеджер

// Файл: src/calibration_manager.cpp

class CalibrationManager {
public:
    // Применение калибровочной таблицы с линейной интерполяцией
    static float applyCalibration(float rawValue, const CalibrationProfile& profile) {
        if (!profile.isLoaded()) {
            return rawValue; // Возвращаем исходное значение если таблица не загружена
        }
        
        // Поиск ближайших точек калибровки
        CalibrationPoint lower, upper;
        if (profile.findInterpolationPoints(rawValue, lower, upper)) {
            // Линейная интерполяция
            float ratio = (rawValue - lower.raw) / (upper.raw - lower.raw);
            return lower.calibrated + ratio * (upper.calibrated - lower.calibrated);
        }
        
        return rawValue; // Вне диапазона калибровки
    }
};

1️⃣ Модель Арчи - EC компенсация

float correctEC(float ec25, float temperature, float humidity, SoilType soilType) {
    // Температурная компенсация (Archie, 1942)
    float tempFactor = 1.0f + 0.021f * (temperature - 25.0f);
    
    // Влажностная компенсация по модели Арчи
    float porosity = getPorosity(soilType);
    float archieCoeff = getArchieCoefficient(soilType);
    float humFactor = pow(humidity / 100.0f, archieCoeff);
    
    return ec25 * tempFactor * humFactor;
}

float getArchieCoefficient(SoilType soilType) {
    switch (soilType) {
        case SAND: return 0.15f;      // Песок
        case LOAM: return 0.30f;      // Суглинок
        case CLAY: return 0.45f;      // Глина
        case PEAT: return 0.10f;      // Торф
        case SANDY_PEAT: return 0.18f; // Песчано-торфяной
        default: return 0.30f;
    }
}

2️⃣ Уравнение Нернста - pH компенсация

float correctPH(float phRaw, float temperature) {
    // Температурная поправка pH по уравнению Нернста
    // dE/dT = -0.003 V/°C для pH электрода
    return phRaw - 0.003f * (temperature - 25.0f);
}

3️⃣ FAO 56 + Eur. J. Soil Sci. - NPK компенсация

void correctNPK(float temperature, float humidity, 
                float& nitrogen, float& phosphorus, float& potassium, 
                SoilType soilType) {
    // Температурная компенсация NPK
    float tempFactor = 1.0f - 0.02f * (temperature - 25.0f);
    
    // Влажностная компенсация по FAO 56
    float humFactor = 1.0f + 0.05f * (humidity - 50.0f) / 50.0f;
    
    // Применение компенсации
    nitrogen *= tempFactor * humFactor;
    phosphorus *= tempFactor * humFactor;
    potassium *= tempFactor * humFactor;
}

🌐 ВЕБ-ИНТЕРФЕЙС

📱 Архитектура веб-интерфейса

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   Web Browser   │    │   ESP32 Web     │    │   Data Storage  │
│   (Frontend)    │◄──►│   Server        │◄──►│   (NVS/Flash)   │
└─────────────────┘    └─────────────────┘    └─────────────────┘
                              │
                              ▼
                       ┌─────────────────┐
                       │   Sensor Data   │
                       │   Processing    │
                       └─────────────────┘

🛣️ Маршрутизация

// Файл: src/web/routes_data.cpp

void setupDataRoutes() {
    // Основные маршруты данных
    server.on("/readings", HTTP_GET, handleReadings);
    server.on("/intervals", HTTP_GET, handleIntervals);
    server.on("/config_manager", HTTP_GET, handleConfigManager);
    server.on("/updates", HTTP_GET, handleUpdates);
    server.on("/service", HTTP_GET, handleService);
}
📋 План рефакторинга QA 2025 H2

📋 План рефакторинга QA 2025 H2

🎯 Цели рефакторинга

🔧 Приоритетные задачи

🔥 Высокий приоритет

  • Исправление критических багов
  • Оптимизация памяти
  • Улучшение обработки ошибок

⚡ Средний приоритет

  • Рефакторинг устаревшего кода
  • Улучшение документации
  • Оптимизация алгоритмов

📈 Низкий приоритет

  • Косметические улучшения
  • Дополнительные функции
  • Расширенная документация
📊 Отчет о техническом долге 2025-06

📊 Отчет о техническом долге 2025-06

📈 Общая оценка

Технический долг проекта находится на приемлемом уровне. Основные области для улучшения:

🔴 Высокий технический долг

  • Устаревшие алгоритмы компенсации
  • Неоптимальное использование памяти
  • Отсутствие полного покрытия тестами

🟡 Средний технический долг

  • Дублирование кода в некоторых модулях
  • Недостаточная документация API
  • Сложность некоторых функций

🟢 Низкий технический долг

  • Хорошая архитектура в целом
  • Консистентное именование
  • Понятная структура проекта

🎯 Рекомендации

🏗️ Общая архитектура JXCT v3.4.9

🏗️ Общая архитектура JXCT v3.4.9

Версия документа: 3.4.9
Дата обновления: 2025-06-24
Статус: Актуальная архитектура с фокусом на стабильность

🎯 ПРИНЦИПЫ АРХИТЕКТУРЫ

1. Стабильность превыше всего

2. Модульность и переиспользование

3. Производительность и эффективность

🔧 ОСНОВНЫЕ КОМПОНЕНТЫ

📡 СИСТЕМА ДАТЧИКОВ

🔌 Абстракция датчиков

// Файл: include/ISensor.h

class ISensor {
public:
    virtual ~ISensor() = default;
    virtual bool initialize() = 0;
    virtual SensorData read() = 0;
    virtual bool isConnected() const = 0;
    virtual String getSensorInfo() const = 0;
};

🎭 Адаптеры датчиков

// Файл: src/modbus_sensor.h

class ModbusSensorAdapter : public ISensor {
private:
    ModbusSensor* sensor;
    
public:
    ModbusSensorAdapter(ModbusSensor* s) : sensor(s) {}
    
    bool initialize() override {
        return sensor->begin();
    }
    
    SensorData read() override {
        return sensor->getData();
    }
    
    bool isConnected() const override {
        return sensor->isConnected();
    }
    
    String getSensorInfo() const override {
        return "Modbus Sensor v" + String(sensor->getVersion());
    }
};

🧮 СИСТЕМА КОМПЕНСАЦИИ

✅ ИСПРАВЛЕННАЯ ДВУХЭТАПНАЯ КОМПЕНСАЦИЯ

// Файл: src/modbus_sensor.cpp

void applyCompensationIfEnabled(SensorData& d, const SoilProfile& profile) {
    // ШАГ 1: Применяем калибровочную таблицу CSV (лабораторная поверка)
    float tempCalibrated = CalibrationManager::applyCalibration(d.temperature, profile);
    float humCalibrated = CalibrationManager::applyCalibration(d.humidity, profile);
    float ecCalibrated = CalibrationManager::applyCalibration(d.ec, profile);
    float phCalibrated = CalibrationManager::applyCalibration(d.ph, profile);
    float nCalibrated = CalibrationManager::applyCalibration(d.nitrogen, profile);
    float pCalibrated = CalibrationManager::applyCalibration(d.phosphorus, profile);
    float kCalibrated = CalibrationManager::applyCalibration(d.potassium, profile);

    // ШАГ 2: Применяем математическую компенсацию (температурная, влажностная)
    float ec25 = ecCalibrated / (1.0f + 0.021f * (tempCalibrated - 25.0f));
    d.ec = correctEC(ec25, tempCalibrated, humCalibrated, profile.soilType);
    d.ph = correctPH(phCalibrated, tempCalibrated);
    correctNPK(tempCalibrated, humCalibrated, d.nitrogen, d.phosphorus, d.potassium, profile.soilType);
}

🔧 Калибровочный менеджер

// Файл: src/calibration_manager.cpp

class CalibrationManager {
public:
    // Применение калибровочной таблицы с линейной интерполяцией
    static float applyCalibration(float rawValue, const CalibrationProfile& profile) {
        if (!profile.isLoaded()) {
            return rawValue; // Возвращаем исходное значение если таблица не загружена
        }
        
        // Поиск ближайших точек калибровки
        CalibrationPoint lower, upper;
        if (profile.findInterpolationPoints(rawValue, lower, upper)) {
            // Линейная интерполяция
            float ratio = (rawValue - lower.raw) / (upper.raw - lower.raw);
            return lower.calibrated + ratio * (upper.calibrated - lower.calibrated);
        }
        
        return rawValue; // Вне диапазона калибровки
    }
};

1️⃣ Модель Арчи - EC компенсация

float correctEC(float ec25, float temperature, float humidity, SoilType soilType) {
    // Температурная компенсация (Archie, 1942)
    float tempFactor = 1.0f + 0.021f * (temperature - 25.0f);
    
    // Влажностная компенсация по модели Арчи
    float porosity = getPorosity(soilType);
    float archieCoeff = getArchieCoefficient(soilType);
    float humFactor = pow(humidity / 100.0f, archieCoeff);
    
    return ec25 * tempFactor * humFactor;
}

float getArchieCoefficient(SoilType soilType) {
    switch (soilType) {
        case SAND: return 0.15f;      // Песок
        case LOAM: return 0.30f;      // Суглинок
        case CLAY: return 0.45f;      // Глина
        case PEAT: return 0.10f;      // Торф
        case SANDY_PEAT: return 0.18f; // Песчано-торфяной
        default: return 0.30f;
    }
}

2️⃣ Уравнение Нернста - pH компенсация

float correctPH(float phRaw, float temperature) {
    // Температурная поправка pH по уравнению Нернста
    // dE/dT = -0.003 V/°C для pH электрода
    return phRaw - 0.003f * (temperature - 25.0f);
}

3️⃣ FAO 56 + Eur. J. Soil Sci. - NPK компенсация

void correctNPK(float temperature, float humidity, 
                float& nitrogen, float& phosphorus, float& potassium, 
                SoilType soilType) {
    // Температурная компенсация NPK
    float tempFactor = 1.0f - 0.02f * (temperature - 25.0f);
    
    // Влажностная компенсация по FAO 56
    float humFactor = 1.0f + 0.05f * (humidity - 50.0f) / 50.0f;
    
    // Применение компенсации
    nitrogen *= tempFactor * humFactor;
    phosphorus *= tempFactor * humFactor;
    potassium *= tempFactor * humFactor;
}

🌐 ВЕБ-ИНТЕРФЕЙС

📱 Архитектура веб-интерфейса

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   Web Browser   │    │   ESP32 Web     │    │   Data Storage  │
│   (Frontend)    │◄──►│   Server        │◄──►│   (NVS/Flash)   │
└─────────────────┘    └─────────────────┘    └─────────────────┘
                              │
                              ▼
                       ┌─────────────────┐
                       │   Sensor Data   │
                       │   Processing    │
                       └─────────────────┘

🛣️ Маршрутизация

// Файл: src/web/routes_data.cpp

void setupDataRoutes() {
    // Основные маршруты данных
    server.on("/readings", HTTP_GET, handleReadings);
    server.on("/intervals", HTTP_GET, handleIntervals);
    server.on("/config_manager", HTTP_GET, handleConfigManager);
    server.on("/updates", HTTP_GET, handleUpdates);
    server.on("/service", HTTP_GET, handleService);
}
📋 План рефакторинга QA 2025 H2

📋 План рефакторинга QA 2025 H2

🎯 Цели рефакторинга

🔧 Приоритетные задачи

🔥 Высокий приоритет

  • Исправление критических багов
  • Оптимизация памяти
  • Улучшение обработки ошибок

⚡ Средний приоритет

  • Рефакторинг устаревшего кода
  • Улучшение документации
  • Оптимизация алгоритмов

📈 Низкий приоритет

  • Косметические улучшения
  • Дополнительные функции
  • Расширенная документация
📊 Отчет о техническом долге 2025-06

📊 Отчет о техническом долге 2025-06

📈 Общая оценка

Технический долг проекта находится на приемлемом уровне. Основные области для улучшения:

🔴 Высокий технический долг

  • Устаревшие алгоритмы компенсации
  • Неоптимальное использование памяти
  • Отсутствие полного покрытия тестами

🟡 Средний технический долг

  • Дублирование кода в некоторых модулях
  • Недостаточная документация API
  • Сложность некоторых функций

🟢 Низкий технический долг

  • Хорошая архитектура в целом
  • Консистентное именование
  • Понятная структура проекта

🎯 Рекомендации

🏗️ Общая архитектура JXCT v3.4.9

🏗️ Общая архитектура JXCT v3.4.9

Версия документа: 3.4.9
Дата обновления: 2025-06-24
Статус: Актуальная архитектура с фокусом на стабильность

🎯 ПРИНЦИПЫ АРХИТЕКТУРЫ

1. Стабильность превыше всего

2. Модульность и переиспользование

3. Производительность и эффективность

🔧 ОСНОВНЫЕ КОМПОНЕНТЫ

📡 СИСТЕМА ДАТЧИКОВ

🔌 Абстракция датчиков

// Файл: include/ISensor.h

class ISensor {
public:
    virtual ~ISensor() = default;
    virtual bool initialize() = 0;
    virtual SensorData read() = 0;
    virtual bool isConnected() const = 0;
    virtual String getSensorInfo() const = 0;
};

🎭 Адаптеры датчиков

// Файл: src/modbus_sensor.h

class ModbusSensorAdapter : public ISensor {
private:
    ModbusSensor* sensor;
    
public:
    ModbusSensorAdapter(ModbusSensor* s) : sensor(s) {}
    
    bool initialize() override {
        return sensor->begin();
    }
    
    SensorData read() override {
        return sensor->getData();
    }
    
    bool isConnected() const override {
        return sensor->isConnected();
    }
    
    String getSensorInfo() const override {
        return "Modbus Sensor v" + String(sensor->getVersion());
    }
};

🧮 СИСТЕМА КОМПЕНСАЦИИ

✅ ИСПРАВЛЕННАЯ ДВУХЭТАПНАЯ КОМПЕНСАЦИЯ

// Файл: src/modbus_sensor.cpp

void applyCompensationIfEnabled(SensorData& d, const SoilProfile& profile) {
    // ШАГ 1: Применяем калибровочную таблицу CSV (лабораторная поверка)
    float tempCalibrated = CalibrationManager::applyCalibration(d.temperature, profile);
    float humCalibrated = CalibrationManager::applyCalibration(d.humidity, profile);
    float ecCalibrated = CalibrationManager::applyCalibration(d.ec, profile);
    float phCalibrated = CalibrationManager::applyCalibration(d.ph, profile);
    float nCalibrated = CalibrationManager::applyCalibration(d.nitrogen, profile);
    float pCalibrated = CalibrationManager::applyCalibration(d.phosphorus, profile);
    float kCalibrated = CalibrationManager::applyCalibration(d.potassium, profile);

    // ШАГ 2: Применяем математическую компенсацию (температурная, влажностная)
    float ec25 = ecCalibrated / (1.0f + 0.021f * (tempCalibrated - 25.0f));
    d.ec = correctEC(ec25, tempCalibrated, humCalibrated, profile.soilType);
    d.ph = correctPH(phCalibrated, tempCalibrated);
    correctNPK(tempCalibrated, humCalibrated, d.nitrogen, d.phosphorus, d.potassium, profile.soilType);
}

🔧 Калибровочный менеджер

// Файл: src/calibration_manager.cpp

class CalibrationManager {
public:
    // Применение калибровочной таблицы с линейной интерполяцией
    static float applyCalibration(float rawValue, const CalibrationProfile& profile) {
        if (!profile.isLoaded()) {
            return rawValue; // Возвращаем исходное значение если таблица не загружена
        }
        
        // Поиск ближайших точек калибровки
        CalibrationPoint lower, upper;
        if (profile.findInterpolationPoints(rawValue, lower, upper)) {
            // Линейная интерполяция
            float ratio = (rawValue - lower.raw) / (upper.raw - lower.raw);
            return lower.calibrated + ratio * (upper.calibrated - lower.calibrated);
        }
        
        return rawValue; // Вне диапазона калибровки
    }
};

1️⃣ Модель Арчи - EC компенсация

float correctEC(float ec25, float temperature, float humidity, SoilType soilType) {
    // Температурная компенсация (Archie, 1942)
    float tempFactor = 1.0f + 0.021f * (temperature - 25.0f);
    
    // Влажностная компенсация по модели Арчи
    float porosity = getPorosity(soilType);
    float archieCoeff = getArchieCoefficient(soilType);
    float humFactor = pow(humidity / 100.0f, archieCoeff);
    
    return ec25 * tempFactor * humFactor;
}

float getArchieCoefficient(SoilType soilType) {
    switch (soilType) {
        case SAND: return 0.15f;      // Песок
        case LOAM: return 0.30f;      // Суглинок
        case CLAY: return 0.45f;      // Глина
        case PEAT: return 0.10f;      // Торф
        case SANDY_PEAT: return 0.18f; // Песчано-торфяной
        default: return 0.30f;
    }
}

2️⃣ Уравнение Нернста - pH компенсация

float correctPH(float phRaw, float temperature) {
    // Температурная поправка pH по уравнению Нернста
    // dE/dT = -0.003 V/°C для pH электрода
    return phRaw - 0.003f * (temperature - 25.0f);
}

3️⃣ FAO 56 + Eur. J. Soil Sci. - NPK компенсация

void correctNPK(float temperature, float humidity, 
                float& nitrogen, float& phosphorus, float& potassium, 
                SoilType soilType) {
    // Температурная компенсация NPK
    float tempFactor = 1.0f - 0.02f * (temperature - 25.0f);
    
    // Влажностная компенсация по FAO 56
    float humFactor = 1.0f + 0.05f * (humidity - 50.0f) / 50.0f;
    
    // Применение компенсации
    nitrogen *= tempFactor * humFactor;
    phosphorus *= tempFactor * humFactor;
    potassium *= tempFactor * humFactor;
}

🌐 ВЕБ-ИНТЕРФЕЙС

📱 Архитектура веб-интерфейса

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   Web Browser   │    │   ESP32 Web     │    │   Data Storage  │
│   (Frontend)    │◄──►│   Server        │◄──►│   (NVS/Flash)   │
└─────────────────┘    └─────────────────┘    └─────────────────┘
                              │
                              ▼
                       ┌─────────────────┐
                       │   Sensor Data   │
                       │   Processing    │
                       └─────────────────┘

🛣️ Маршрутизация

// Файл: src/web/routes_data.cpp

void setupDataRoutes() {
    // Основные маршруты данных
    server.on("/readings", HTTP_GET, handleReadings);
    server.on("/intervals", HTTP_GET, handleIntervals);
    server.on("/config_manager", HTTP_GET, handleConfigManager);
    server.on("/updates", HTTP_GET, handleUpdates);
    server.on("/service", HTTP_GET, handleService);
}
📋 План рефакторинга QA 2025 H2

📋 План рефакторинга QA 2025 H2

🎯 Цели рефакторинга

🔧 Приоритетные задачи

🔥 Высокий приоритет

  • Исправление критических багов
  • Оптимизация памяти
  • Улучшение обработки ошибок

⚡ Средний приоритет

  • Рефакторинг устаревшего кода
  • Улучшение документации
  • Оптимизация алгоритмов

📈 Низкий приоритет

  • Косметические улучшения
  • Дополнительные функции
  • Расширенная документация
📊 Отчет о техническом долге 2025-06

📊 Отчет о техническом долге 2025-06

📈 Общая оценка

Технический долг проекта находится на приемлемом уровне. Основные области для улучшения:

🔴 Высокий технический долг

  • Устаревшие алгоритмы компенсации
  • Неоптимальное использование памяти
  • Отсутствие полного покрытия тестами

🟡 Средний технический долг

  • Дублирование кода в некоторых модулях
  • Недостаточная документация API
  • Сложность некоторых функций

🟢 Низкий технический долг

  • Хорошая архитектура в целом
  • Консистентное именование
  • Понятная структура проекта

🎯 Рекомендации

🏗️ Общая архитектура JXCT v3.4.9

🏗️ Общая архитектура JXCT v3.4.9

Версия документа: 3.4.9
Дата обновления: 2025-06-24
Статус: Актуальная архитектура с фокусом на стабильность

🎯 ПРИНЦИПЫ АРХИТЕКТУРЫ

1. Стабильность превыше всего

2. Модульность и переиспользование

3. Производительность и эффективность

🔧 ОСНОВНЫЕ КОМПОНЕНТЫ

📡 СИСТЕМА ДАТЧИКОВ

🔌 Абстракция датчиков

// Файл: include/ISensor.h

class ISensor {
public:
    virtual ~ISensor() = default;
    virtual bool initialize() = 0;
    virtual SensorData read() = 0;
    virtual bool isConnected() const = 0;
    virtual String getSensorInfo() const = 0;
};

🎭 Адаптеры датчиков

// Файл: src/modbus_sensor.h

class ModbusSensorAdapter : public ISensor {
private:
    ModbusSensor* sensor;
    
public:
    ModbusSensorAdapter(ModbusSensor* s) : sensor(s) {}
    
    bool initialize() override {
        return sensor->begin();
    }
    
    SensorData read() override {
        return sensor->getData();
    }
    
    bool isConnected() const override {
        return sensor->isConnected();
    }
    
    String getSensorInfo() const override {
        return "Modbus Sensor v" + String(sensor->getVersion());
    }
};

🧮 СИСТЕМА КОМПЕНСАЦИИ

✅ ИСПРАВЛЕННАЯ ДВУХЭТАПНАЯ КОМПЕНСАЦИЯ

// Файл: src/modbus_sensor.cpp

void applyCompensationIfEnabled(SensorData& d, const SoilProfile& profile) {
    // ШАГ 1: Применяем калибровочную таблицу CSV (лабораторная поверка)
    float tempCalibrated = CalibrationManager::applyCalibration(d.temperature, profile);
    float humCalibrated = CalibrationManager::applyCalibration(d.humidity, profile);
    float ecCalibrated = CalibrationManager::applyCalibration(d.ec, profile);
    float phCalibrated = CalibrationManager::applyCalibration(d.ph, profile);
    float nCalibrated = CalibrationManager::applyCalibration(d.nitrogen, profile);
    float pCalibrated = CalibrationManager::applyCalibration(d.phosphorus, profile);
    float kCalibrated = CalibrationManager::applyCalibration(d.potassium, profile);

    // ШАГ 2: Применяем математическую компенсацию (температурная, влажностная)
    float ec25 = ecCalibrated / (1.0f + 0.021f * (tempCalibrated - 25.0f));
    d.ec = correctEC(ec25, tempCalibrated, humCalibrated, profile.soilType);
    d.ph = correctPH(phCalibrated, tempCalibrated);
    correctNPK(tempCalibrated, humCalibrated, d.nitrogen, d.phosphorus, d.potassium, profile.soilType);
}

🔧 Калибровочный менеджер

// Файл: src/calibration_manager.cpp

class CalibrationManager {
public:
    // Применение калибровочной таблицы с линейной интерполяцией
    static float applyCalibration(float rawValue, const CalibrationProfile& profile) {
        if (!profile.isLoaded()) {
            return rawValue; // Возвращаем исходное значение если таблица не загружена
        }
        
        // Поиск ближайших точек калибровки
        CalibrationPoint lower, upper;
        if (profile.findInterpolationPoints(rawValue, lower, upper)) {
            // Линейная интерполяция
            float ratio = (rawValue - lower.raw) / (upper.raw - lower.raw);
            return lower.calibrated + ratio * (upper.calibrated - lower.calibrated);
        }
        
        return rawValue; // Вне диапазона калибровки
    }
};

1️⃣ Модель Арчи - EC компенсация

float correctEC(float ec25, float temperature, float humidity, SoilType soilType) {
    // Температурная компенсация (Archie, 1942)
    float tempFactor = 1.0f + 0.021f * (temperature - 25.0f);
    
    // Влажностная компенсация по модели Арчи
    float porosity = getPorosity(soilType);
    float archieCoeff = getArchieCoefficient(soilType);
    float humFactor = pow(humidity / 100.0f, archieCoeff);
    
    return ec25 * tempFactor * humFactor;
}

float getArchieCoefficient(SoilType soilType) {
    switch (soilType) {
        case SAND: return 0.15f;      // Песок
        case LOAM: return 0.30f;      // Суглинок
        case CLAY: return 0.45f;      // Глина
        case PEAT: return 0.10f;      // Торф
        case SANDY_PEAT: return 0.18f; // Песчано-торфяной
        default: return 0.30f;
    }
}

2️⃣ Уравнение Нернста - pH компенсация

float correctPH(float phRaw, float temperature) {
    // Температурная поправка pH по уравнению Нернста
    // dE/dT = -0.003 V/°C для pH электрода
    return phRaw - 0.003f * (temperature - 25.0f);
}

3️⃣ FAO 56 + Eur. J. Soil Sci. - NPK компенсация

void correctNPK(float temperature, float humidity, 
                float& nitrogen, float& phosphorus, float& potassium, 
                SoilType soilType) {
    // Температурная компенсация NPK
    float tempFactor = 1.0f - 0.02f * (temperature - 25.0f);
    
    // Влажностная компенсация по FAO 56
    float humFactor = 1.0f + 0.05f * (humidity - 50.0f) / 50.0f;
    
    // Применение компенсации
    nitrogen *= tempFactor * humFactor;
    phosphorus *= tempFactor * humFactor;
    potassium *= tempFactor * humFactor;
}

🌐 ВЕБ-ИНТЕРФЕЙС

📱 Архитектура веб-интерфейса

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   Web Browser   │    │   ESP32 Web     │    │   Data Storage  │
│   (Frontend)    │◄──►│   Server        │◄──►│   (NVS/Flash)   │
└─────────────────┘    └─────────────────┘    └─────────────────┘
                              │
                              ▼
                       ┌─────────────────┐
                       │   Sensor Data   │
                       │   Processing    │
                       └─────────────────┘

🛣️ Маршрутизация

// Файл: src/web/routes_data.cpp

void setupDataRoutes() {
    // Основные маршруты данных
    server.on("/readings", HTTP_GET, handleReadings);
    server.on("/intervals", HTTP_GET, handleIntervals);
    server.on("/config_manager", HTTP_GET, handleConfigManager);
    server.on("/updates", HTTP_GET, handleUpdates);
    server.on("/service", HTTP_GET, handleService);
}
📋 План рефакторинга QA 2025 H2

📋 План рефакторинга QA 2025 H2

🎯 Цели рефакторинга

🔧 Приоритетные задачи

🔥 Высокий приоритет

  • Исправление критических багов
  • Оптимизация памяти
  • Улучшение обработки ошибок

⚡ Средний приоритет

  • Рефакторинг устаревшего кода
  • Улучшение документации
  • Оптимизация алгоритмов

📈 Низкий приоритет

  • Косметические улучшения
  • Дополнительные функции
  • Расширенная документация
📊 Отчет о техническом долге 2025-06

📊 Отчет о техническом долге 2025-06

📈 Общая оценка

Технический долг проекта находится на приемлемом уровне. Основные области для улучшения:

🔴 Высокий технический долг

  • Устаревшие алгоритмы компенсации
  • Неоптимальное использование памяти
  • Отсутствие полного покрытия тестами

🟡 Средний технический долг

  • Дублирование кода в некоторых модулях
  • Недостаточная документация API
  • Сложность некоторых функций

🟢 Низкий технический долг

  • Хорошая архитектура в целом
  • Консистентное именование
  • Понятная структура проекта

🎯 Рекомендации

🏗️ Общая архитектура JXCT v3.4.9

🏗️ Общая архитектура JXCT v3.4.9

Версия документа: 3.4.9
Дата обновления: 2025-06-24
Статус: Актуальная архитектура с фокусом на стабильность

🎯 ПРИНЦИПЫ АРХИТЕКТУРЫ

1. Стабильность превыше всего

2. Модульность и переиспользование

3. Производительность и эффективность

🔧 ОСНОВНЫЕ КОМПОНЕНТЫ

📡 СИСТЕМА ДАТЧИКОВ

🔌 Абстракция датчиков

// Файл: include/ISensor.h

class ISensor {
public:
    virtual ~ISensor() = default;
    virtual bool initialize() = 0;
    virtual SensorData read() = 0;
    virtual bool isConnected() const = 0;
    virtual String getSensorInfo() const = 0;
};

🎭 Адаптеры датчиков

// Файл: src/modbus_sensor.h

class ModbusSensorAdapter : public ISensor {
private:
    ModbusSensor* sensor;
    
public:
    ModbusSensorAdapter(ModbusSensor* s) : sensor(s) {}
    
    bool initialize() override {
        return sensor->begin();
    }
    
    SensorData read() override {
        return sensor->getData();
    }
    
    bool isConnected() const override {
        return sensor->isConnected();
    }
    
    String getSensorInfo() const override {
        return "Modbus Sensor v" + String(sensor->getVersion());
    }
};

🧮 СИСТЕМА КОМПЕНСАЦИИ

✅ ИСПРАВЛЕННАЯ ДВУХЭТАПНАЯ КОМПЕНСАЦИЯ

// Файл: src/modbus_sensor.cpp

void applyCompensationIfEnabled(SensorData& d, const SoilProfile& profile) {
    // ШАГ 1: Применяем калибровочную таблицу CSV (лабораторная поверка)
    float tempCalibrated = CalibrationManager::applyCalibration(d.temperature, profile);
    float humCalibrated = CalibrationManager::applyCalibration(d.humidity, profile);
    float ecCalibrated = CalibrationManager::applyCalibration(d.ec, profile);
    float phCalibrated = CalibrationManager::applyCalibration(d.ph, profile);
    float nCalibrated = CalibrationManager::applyCalibration(d.nitrogen, profile);
    float pCalibrated = CalibrationManager::applyCalibration(d.phosphorus, profile);
    float kCalibrated = CalibrationManager::applyCalibration(d.potassium, profile);

    // ШАГ 2: Применяем математическую компенсацию (температурная, влажностная)
    float ec25 = ecCalibrated / (1.0f + 0.021f * (tempCalibrated - 25.0f));
    d.ec = correctEC(ec25, tempCalibrated, humCalibrated, profile.soilType);
    d.ph = correctPH(phCalibrated, tempCalibrated);
    correctNPK(tempCalibrated, humCalibrated, d.nitrogen, d.phosphorus, d.potassium, profile.soilType);
}

🔧 Калибровочный менеджер

// Файл: src/calibration_manager.cpp

class CalibrationManager {
public:
    // Применение калибровочной таблицы с линейной интерполяцией
    static float applyCalibration(float rawValue, const CalibrationProfile& profile) {
        if (!profile.isLoaded()) {
            return rawValue; // Возвращаем исходное значение если таблица не загружена
        }
        
        // Поиск ближайших точек калибровки
        CalibrationPoint lower, upper;
        if (profile.findInterpolationPoints(rawValue, lower, upper)) {
            // Линейная интерполяция
            float ratio = (rawValue - lower.raw) / (upper.raw - lower.raw);
            return lower.calibrated + ratio * (upper.calibrated - lower.calibrated);
        }
        
        return rawValue; // Вне диапазона калибровки
    }
};

1️⃣ Модель Арчи - EC компенсация

float correctEC(float ec25, float temperature, float humidity, SoilType soilType) {
    // Температурная компенсация (Archie, 1942)
    float tempFactor = 1.0f + 0.021f * (temperature - 25.0f);
    
    // Влажностная компенсация по модели Арчи
    float porosity = getPorosity(soilType);
    float archieCoeff = getArchieCoefficient(soilType);
    float humFactor = pow(humidity / 100.0f, archieCoeff);
    
    return ec25 * tempFactor * humFactor;
}

float getArchieCoefficient(SoilType soilType) {
    switch (soilType) {
        case SAND: return 0.15f;      // Песок
        case LOAM: return 0.30f;      // Суглинок
        case CLAY: return 0.45f;      // Глина
        case PEAT: return 0.10f;      // Торф
        case SANDY_PEAT: return 0.18f; // Песчано-торфяной
        default: return 0.30f;
    }
}

2️⃣ Уравнение Нернста - pH компенсация

float correctPH(float phRaw, float temperature) {
    // Температурная поправка pH по уравнению Нернста
    // dE/dT = -0.003 V/°C для pH электрода
    return phRaw - 0.003f * (temperature - 25.0f);
}

3️⃣ FAO 56 + Eur. J. Soil Sci. - NPK компенсация

void correctNPK(float temperature, float humidity, 
                float& nitrogen, float& phosphorus, float& potassium, 
                SoilType soilType) {
    // Температурная компенсация NPK
    float tempFactor = 1.0f - 0.02f * (temperature - 25.0f);
    
    // Влажностная компенсация по FAO 56
    float humFactor = 1.0f + 0.05f * (humidity - 50.0f) / 50.0f;
    
    // Применение компенсации
    nitrogen *= tempFactor * humFactor;
    phosphorus *= tempFactor * humFactor;
    potassium *= tempFactor * humFactor;
}

🌐 ВЕБ-ИНТЕРФЕЙС

📱 Архитектура веб-интерфейса

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   Web Browser   │    │   ESP32 Web     │    │   Data Storage  │
│   (Frontend)    │◄──►│   Server        │◄──►│   (NVS/Flash)   │
└─────────────────┘    └─────────────────┘    └─────────────────┘
                              │
                              ▼
                       ┌─────────────────┐
                       │   Sensor Data   │
                       │   Processing    │
                       └─────────────────┘

🛣️ Маршрутизация

// Файл: src/web/routes_data.cpp

void setupDataRoutes() {
    // Основные маршруты данных
    server.on("/readings", HTTP_GET, handleReadings);
    server.on("/intervals", HTTP_GET, handleIntervals);
    server.on("/config_manager", HTTP_GET, handleConfigManager);
    server.on("/updates", HTTP_GET, handleUpdates);
    server.on("/service", HTTP_GET, handleService);
}
📋 План рефакторинга QA 2025 H2

📋 План рефакторинга QA 2025 H2

🎯 Цели рефакторинга

🔧 Приоритетные задачи

🔥 Высокий приоритет

  • Исправление критических багов
  • Оптимизация памяти
  • Улучшение обработки ошибок

⚡ Средний приоритет

  • Рефакторинг устаревшего кода
  • Улучшение документации
  • Оптимизация алгоритмов

📈 Низкий приоритет

  • Косметические улучшения
  • Дополнительные функции
  • Расширенная документация
📊 Отчет о техническом долге 2025-06

📊 Отчет о техническом долге 2025-06

📈 Общая оценка

Технический долг проекта находится на приемлемом уровне. Основные области для улучшения:

🔴 Высокий технический долг

  • Устаревшие алгоритмы компенсации
  • Неоптимальное использование памяти
  • Отсутствие полного покрытия тестами

🟡 Средний технический долг

  • Дублирование кода в некоторых модулях
  • Недостаточная документация API
  • Сложность некоторых функций

🟢 Низкий технический долг

  • Хорошая архитектура в целом
  • Консистентное именование
  • Понятная структура проекта

🎯 Рекомендации

🏗️ Общая архитектура JXCT v3.4.9

🏗️ Общая архитектура JXCT v3.4.9

Версия документа: 3.4.9
Дата обновления: 2025-06-24
Статус: Актуальная архитектура с фокусом на стабильность

🎯 ПРИНЦИПЫ АРХИТЕКТУРЫ

1. Стабильность превыше всего

2. Модульность и переиспользование

3. Производительность и эффективность

🔧 ОСНОВНЫЕ КОМПОНЕНТЫ

📡 СИСТЕМА ДАТЧИКОВ

🔌 Абстракция датчиков

// Файл: include/ISensor.h

class ISensor {
public:
    virtual ~ISensor() = default;
    virtual bool initialize() = 0;
    virtual SensorData read() = 0;
    virtual bool isConnected() const = 0;
    virtual String getSensorInfo() const = 0;
};

🎭 Адаптеры датчиков

// Файл: src/modbus_sensor.h

class ModbusSensorAdapter : public ISensor {
private:
    ModbusSensor* sensor;
    
public:
    ModbusSensorAdapter(ModbusSensor* s) : sensor(s) {}
    
    bool initialize() override {
        return sensor->begin();
    }
    
    SensorData read() override {
        return sensor->getData();
    }
    
    bool isConnected() const override {
        return sensor->isConnected();
    }
    
    String getSensorInfo() const override {
        return "Modbus Sensor v" + String(sensor->getVersion());
    }
};

🧮 СИСТЕМА КОМПЕНСАЦИИ

✅ ИСПРАВЛЕННАЯ ДВУХЭТАПНАЯ КОМПЕНСАЦИЯ

// Файл: src/modbus_sensor.cpp

void applyCompensationIfEnabled(SensorData& d, const SoilProfile& profile) {
    // ШАГ 1: Применяем калибровочную таблицу CSV (лабораторная поверка)
    float tempCalibrated = CalibrationManager::applyCalibration(d.temperature, profile);
    float humCalibrated = CalibrationManager::applyCalibration(d.humidity, profile);
    float ecCalibrated = CalibrationManager::applyCalibration(d.ec, profile);
    float phCalibrated = CalibrationManager::applyCalibration(d.ph, profile);
    float nCalibrated = CalibrationManager::applyCalibration(d.nitrogen, profile);
    float pCalibrated = CalibrationManager::applyCalibration(d.phosphorus, profile);
    float kCalibrated = CalibrationManager::applyCalibration(d.potassium, profile);

    // ШАГ 2: Применяем математическую компенсацию (температурная, влажностная)
    float ec25 = ecCalibrated / (1.0f + 0.021f * (tempCalibrated - 25.0f));
    d.ec = correctEC(ec25, tempCalibrated, humCalibrated, profile.soilType);
    d.ph = correctPH(phCalibrated, tempCalibrated);
    correctNPK(tempCalibrated, humCalibrated, d.nitrogen, d.phosphorus, d.potassium, profile.soilType);
}

🔧 Калибровочный менеджер

// Файл: src/calibration_manager.cpp

class CalibrationManager {
public:
    // Применение калибровочной таблицы с линейной интерполяцией
    static float applyCalibration(float rawValue, const CalibrationProfile& profile) {
        if (!profile.isLoaded()) {
            return rawValue; // Возвращаем исходное значение если таблица не загружена
        }
        
        // Поиск ближайших точек калибровки
        CalibrationPoint lower, upper;
        if (profile.findInterpolationPoints(rawValue, lower, upper)) {
            // Линейная интерполяция
            float ratio = (rawValue - lower.raw) / (upper.raw - lower.raw);
            return lower.calibrated + ratio * (upper.calibrated - lower.calibrated);
        }
        
        return rawValue; // Вне диапазона калибровки
    }
};

1️⃣ Модель Арчи - EC компенсация

float correctEC(float ec25, float temperature, float humidity, SoilType soilType) {
    // Температурная компенсация (Archie, 1942)
    float tempFactor = 1.0f + 0.021f * (temperature - 25.0f);
    
    // Влажностная компенсация по модели Арчи
    float porosity = getPorosity(soilType);
    float archieCoeff = getArchieCoefficient(soilType);
    float humFactor = pow(humidity / 100.0f, archieCoeff);
    
    return ec25 * tempFactor * humFactor;
}

float getArchieCoefficient(SoilType soilType) {
    switch (soilType) {
        case SAND: return 0.15f;      // Песок
        case LOAM: return 0.30f;      // Суглинок
        case CLAY: return 0.45f;      // Глина
        case PEAT: return 0.10f;      // Торф
        case SANDY_PEAT: return 0.18f; // Песчано-торфяной
        default: return 0.30f;
    }
}

2️⃣ Уравнение Нернста - pH компенсация

float correctPH(float phRaw, float temperature) {
    // Температурная поправка pH по уравнению Нернста
    // dE/dT = -0.003 V/°C для pH электрода
    return phRaw - 0.003f * (temperature - 25.0f);
}

3️⃣ FAO 56 + Eur. J. Soil Sci. - NPK компенсация

void correctNPK(float temperature, float humidity, 
                float& nitrogen, float& phosphorus, float& potassium, 
                SoilType soilType) {
    // Температурная компенсация NPK
    float tempFactor = 1.0f - 0.02f * (temperature - 25.0f);
    
    // Влажностная компенсация по FAO 56
    float humFactor = 1.0f + 0.05f * (humidity - 50.0f) / 50.0f;
    
    // Применение компенсации
    nitrogen *= tempFactor * humFactor;
    phosphorus *= tempFactor * humFactor;
    potassium *= tempFactor * humFactor;
}

🌐 ВЕБ-ИНТЕРФЕЙС

📱 Архитектура веб-интерфейса

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   Web Browser   │    │   ESP32 Web     │    │   Data Storage  │
│   (Frontend)    │◄──►│   Server        │◄──►│   (NVS/Flash)   │
└─────────────────┘    └─────────────────┘    └─────────────────┘
                              │
                              ▼
                       ┌─────────────────┐
                       │   Sensor Data   │
                       │   Processing    │
                       └─────────────────┘

🛣️ Маршрутизация

// Файл: src/web/routes_data.cpp

void setupDataRoutes() {
    // Основные маршруты данных
    server.on("/readings", HTTP_GET, handleReadings);
    server.on("/intervals", HTTP_GET, handleIntervals);
    server.on("/config_manager", HTTP_GET, handleConfigManager);
    server.on("/updates", HTTP_GET, handleUpdates);
    server.on("/service", HTTP_GET, handleService);
}
📋 План рефакторинга QA 2025 H2

📋 План рефакторинга QA 2025 H2

🎯 Цели рефакторинга

🔧 Приоритетные задачи

🔥 Высокий приоритет

  • Исправление критических багов
  • Оптимизация памяти
  • Улучшение обработки ошибок

⚡ Средний приоритет

  • Рефакторинг устаревшего кода
  • Улучшение документации
  • Оптимизация алгоритмов

📈 Низкий приоритет

  • Косметические улучшения
  • Дополнительные функции
  • Расширенная документация
📊 Отчет о техническом долге 2025-06

📊 Отчет о техническом долге 2025-06

📈 Общая оценка

Технический долг проекта находится на приемлемом уровне. Основные области для улучшения:

🔴 Высокий технический долг

  • Устаревшие алгоритмы компенсации
  • Неоптимальное использование памяти
  • Отсутствие полного покрытия тестами

🟡 Средний технический долг

  • Дублирование кода в некоторых модулях
  • Недостаточная документация API
  • Сложность некоторых функций

🟢 Низкий технический долг

  • Хорошая архитектура в целом
  • Консистентное именование
  • Понятная структура проекта

🎯 Рекомендации