1. Arhitectura Sistem
1.1 Diagrama Bloc
┌─────────────────────────────────────────────────────────────────┐
│ ESP32 (Dual-Core, 240 MHz) │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────┐ │
│ │ Core 0 │ │ Core 1 │ │ WiFi │ │ LittleFS │ │
│ │ AsyncTCP │ │ main() │ │ 802.11n │ │ Filesystem │ │
│ │ callbacks│ │ loop() │ │ 2.4 GHz │ │ OTA+Logs │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────────┘ │
│ │
│ ┌──────────────────────┐ ┌──────────────────────────────┐ │
│ │ NVS Preferences │ │ RAM Buffers │ │
│ │ "config" + "alarm" │ │ Log: 288 entries (24h) │ │
│ │ namespaces │ │ Pending emails: 6 slots │ │
│ └──────────────────────┘ └──────────────────────────────┘ │
└───┬──────┬──────┬──────┬──────┬──────┬──────┬──────┬──────────┘
│ │ │ │ │ │ │ │
┌───▼──┐┌──▼──┐┌──▼──┐┌──▼──┐┌──▼──┐┌──▼──┐┌──▼──┐┌──▼────────┐
│I2C-1 ││I2C-2││UART1││UART2││ 22 ││ 23 ││ 13 ││ 12 │
│SEN66 ││MS637││RS485││Nextn││CONFIG││ RUN ││NeoP ││Status LED │
└──────┘└─────┘└─────┘└─────┘└─────┘└─────┘└─────┘└───────────┘
1.2 Model de Executie
| Componenta | Context de Executie | Note |
| AsyncTCP (Modbus, MQTT, Zabbix) | Task lwIP (Core 0) | Callback-uri non-blocante |
| AsyncWebServer (porturi 80/8080/8081/8082) | Task lwIP (Core 0) | ESPAsyncWebServer |
| BACnet/IP UDP | Bucla principala (Core 1) | Socket raw lwIP, poll() |
| Citire senzor (SEN66) | Bucla principala (Core 1) | I2C blocant, interval ~5 min |
| Citire presiune (MS5637) | Bucla principala (Core 1) | Perioada de esantionare 500ms |
| Salvare log | Bucla principala (Core 1) | 5 min RAM, orar FS |
| Evaluare alarme | Bucla principala (Core 1) | Dupa fiecare citire senzor |
| Scanare butoane | Bucla principala (Core 1) | CONFIG (GPIO22) / RUN (GPIO23) |
| Watchdog | WDT Hardware | Timeout 50 secunde |
1.3 Organizare Memorie
| Partitie | Utilizare |
| NVS | Stocare preferinte (namespace-uri config + alarm) |
| OTA_0 / OTA_1 | Partitii duale firmware pentru rollback OTA |
| SPIFFS/LittleFS | Sistem de fisiere: loguri (day0-day6.csv), baza NTP, firmware temporar |
| RAM | Buffer log (288 × ~48B = ~14 KB), emailuri in asteptare (6 sloturi) |
2. Specificatii Senzori
2.1 Sensirion SEN66
| Parametru | Domeniu | Precizie | Note |
| CO2 (NDIR) | 0–40.000 ppm | ±30 ppm + 3% | Incalzire: 30s de baza, 3 min precis |
| PM1.0 | 0–1.000 µg/m³ | ±5 µg/m³ + 5% | Imprastiere laser |
| PM2.5 | 0–1.000 µg/m³ | ±5 µg/m³ + 5% | Imprastiere laser |
| PM4.0 | 0–1.000 µg/m³ | ±25 µg/m³ + 5% | Imprastiere laser |
| PM10 | 0–1.000 µg/m³ | ±25 µg/m³ + 5% | Imprastiere laser |
| Indice VOC | 1–500 | — | MOx, procesat algoritmic. 12h conditionare. |
| Indice NOx | 1–500 | — | MOx, procesat algoritmic. 12h conditionare. |
| Temperatura | −40 la +125 °C | ±0,4 °C | Pe cip |
| Umiditate | 0–100 %RH | ±4,5 %RH | Pe cip |
Interfata: Bus I2C 1 — SDA: GPIO 26, SCL: GPIO 25, 100 kHz
2.2 TE Connectivity MS5637
| Parametru | Valoare |
| Tip | Senzor de presiune piezorezistiv |
| Domeniu presiune | 300–1.200 hPa |
| Adresa I2C | 0x76 |
| Interfata | Bus I2C 2: SDA GPIO 33, SCL GPIO 32, 100 kHz |
| OSR implicit | 4096 (~8,22 ms conversie) |
| Perioada de esantionare | 500 ms (D1=presiune, D2=temperatura alternativ) |
Setari OSR
| OSR | Valoare Bit | Timp de Conversie |
| 256 | 0x00 | ~0,54 ms |
| 512 | 0x02 | ~1,06 ms |
| 1024 | 0x04 | ~2,08 ms |
| 2048 | 0x06 | ~4,13 ms |
| 4096 (implicit) | 0x08 | ~8,22 ms |
| 8192 | 0x0A | ~16,44 ms |
Coeficienti de Calibrare PROM
| Index | Nume | Descriere |
| C0 | FACTORY | Date fabrica + CRC |
| C1 | SENS | Sensibilitate presiune |
| C2 | OFF | Offset presiune |
| C3 | TCS | Coeficient temperatura al sensibilitatii |
| C4 | TCO | Coeficient temperatura al offset-ului |
| C5 | TREF | Temperatura de referinta |
| C6 | TEMPSENS | Coeficient temperatura al temperaturii |
| C7 | CRC | Suma de control CRC |
3. Algoritm de Calcul TVOC
Echivalent TVOC derivat din Indicele VOC folosind Mølhave / WELL Building Standard:
tvocW = (ln(501 - vocIndex) - 6.24) * (-996.94) [µg/m³]
// Implementare C:
static inline float tvoc_well_from_vi(float vi) {
if (vi < 1.f) vi = 1.f;
if (vi > 499.f) vi = 499.f;
return (logf(501.f - vi) - 6.24f) * (-996.94f);
}
| Indice VOC | TVOC (µg/m³) | Calitate Aer |
| 1–50 | < 100 | Excelenta |
| 50–100 | 100–300 | Buna |
| 100–200 | 300–1.000 | Moderata |
| 200–350 | 1.000–3.000 | Slaba |
| 350–500 | 3.000–6.000+ | Nesanatoasa |
4. Referinta GPIO & Hardware
| GPIO | Functie | Directie | Configurare | Note |
| 13 | NeoPixel LED | Iesire | NEO_GRB + 800 kHz | 1 × WS2812B |
| 22 | Buton CONFIG | Intrare | INPUT_PULLUP | Activ LOW. Spatele modulului. Declanseaza modul AP + repornire. |
| 23 | Buton RUN | Intrare | INPUT_PULLUP | Activ LOW. Spatele modulului. Declanseaza modul STA + repornire. |
| 12 | LED Status | Iesire | Digital | Indicator general |
| 2 | RS-485 DE/RE | Iesire | Digital | HIGH = activare TX |
| 16 | Serial1 RX | Intrare | UART | RS-485, 19200 baud |
| 17 | Serial1 TX | Iesire | UART | RS-485, 19200 baud |
| 14 | Serial2 RX | Intrare | UART | Nextion, 115200 baud |
| 27 | Serial2 TX | Iesire | UART | Nextion, 115200 baud |
| 26 | I2C-1 SDA | Bidirectional | 100 kHz | SEN66 |
| 25 | I2C-1 SCL | Iesire | 100 kHz | SEN66 |
| 33 | I2C-2 SDA | Bidirectional | 100 kHz | MS5637 @ 0x76 |
| 32 | I2C-2 SCL | Iesire | 100 kHz | MS5637 @ 0x76 |
6. Detalii Protocol BACnet/IP
| Specificatie | Valoare |
| Standard | ASHRAE 135-2020, Anexa J |
| Transport | UDP port 47808 (0xBAC0) |
| Socket | Socket raw lwIP (bind pe toate interfetele) |
| Tipuri BVLC | Original-Unicast (0x0A), Original-Broadcast (0x0B), Forwarded (0x04) |
| Dimensiune Buffer | 1024 bytes Rx / 1024 bytes Tx |
| Segmentare | Nesuportata |
| Max APDU | 480 bytes |
| Obiecte | 1 Device + 11 Analog Input |
| Producator | MICRO-ELEMENTS S.R.L. |
Proprietati Obiect Device
| Proprietate | ID | Valoare |
| Object_Identifier | 75 | Device:instanta |
| Object_Name | 77 | hostname-mac |
| Vendor_Name | 121 | MICRO-ELEMENTS S.R.L. |
| Firmware_Revision | 44 | PureAware_V1.027 |
| System_Status | 112 | Operational (0) |
| Object_List | 76 | 12 intrari (Device + 11 AI) |
Obiecte AI (0–10)
Fiecare AI expune: Object_Identifier(75), Object_Name(77), Object_Type(79), Present_Value(85), Status_Flags(111), Event_State(36), Out_Of_Service(81), Units(117), Reliability(103), Description(28).
7. Detalii Modbus TCP Async
| Parametru | Valoare |
| Biblioteca | ModbusTCPAsyncServer (personalizata, bazata pe AsyncTCP) |
| Port | 502 |
| Clienti Maximi | 10 (limita hard), implicit 3 |
| Timeout Inactivitate | 60.000 ms |
| Buffer RX | 300 bytes per client |
| FC-uri Suportate | 01, 02, 03, 04, 05, 06, 0F, 10 |
Detalii Registre de Intrare (FC 04)
| Adresa | Constanta | Parametru | Unitate | Scala |
| 0 | IR_DEVICE_TYPE | Tip Dispozitiv | — | Fix: 1 |
| 1 | IR_VOC | Indice VOC | — | 1:1 |
| 2 | IR_NOX | Indice NOx | — | 1:1 |
| 3 | IR_PM1 | PM1.0 | µg/m³ | 1:1 |
| 4 | IR_PM25 | PM2.5 | µg/m³ | 1:1 |
| 5 | IR_PM4 | PM4.0 | µg/m³ | 1:1 |
| 6 | IR_PM10 | PM10 | µg/m³ | 1:1 |
| 7 | IR_TEMP_X10 | Temperatura | °C | ÷ 10 |
| 8 | IR_HUM_X10 | Umiditate | %RH | ÷ 10 |
| 9 | IR_CO2 | CO2 | ppm | 1:1 |
| 10 | IR_TVOCW | TVOC (WELL) | µg/m³ | 1:1 |
| 11 | IR_PRESS_X10 | Presiune | hPa | ÷ 10 |
8. Protocoale MQTT & Zabbix
MQTT (Async)
| Functionalitate | Valoare |
| Client | Complet asincron prin AsyncClient |
| Format Topic | {mtopic}/{mac6}/data |
| ID Client | PureAware-{mac6} |
| QoS / Retain | 0 / Nu |
| Interval Minim | 10 secunde |
| Payload | JSON cu 13 campuri (toate ca stringuri): device_type, name, co2, pm1, pm25, pm4, pm10, voc, nox, tvocw, temp, hum, press, rssi |
| Port WebSocket | 8083 (pentru monitorizare browser/aplicatie prin ws://broker:8083/mqtt) |
| Broker Implicit | broker.emqx.io (public, pentru testare) |
Zabbix Sender
| Functionalitate | Valoare |
| Protocol | Zabbix Sender (JSON peste TCP) |
| Server Implicit | monitor.microelemente.ro:55051 |
| Timer | Independent de MQTT |
9. Motor Email SMTP
| Functionalitate | Valoare |
| Moduri | STARTTLS (port 587) si SSL Implicit (port 465) |
| Autentificare | AUTH LOGIN (Base64) |
| TLS | WiFiClientSecure (setInsecure) |
| Coada Email | 6 sloturi: 2 per alarma (declansare + rearmare) |
| Intarziere Reconectare | 5s dupa reconectare WiFi |
| Limbi | EN, RO, HU, NO, JA |
10. Harta Preferinte NVS
Namespace: "config"
| Cheie | Tip | Implicit | Descriere |
| ssid | String | "ssid" | SSID WiFi |
| password | String | "password" | Parola WiFi |
| wifi_mode | UChar | 0 | 0=AP, 1=STA, 2=OFFLINE |
| hostname | String | "pureaware" | Baza hostname mDNS |
| static_ip_en | UChar | 0 | Activare IP static |
| static_ip, static_gw, static_sn, static_dns | String | "", "", "255.255.255.0", "8.8.8.8" | Configurare IP static |
| mqtt_en | UChar | 0 | Activare MQTT |
| mserver, mport, muser, mpass, mtopic, mint | Mixt | "none", 1883, "none", "none", zhost, 60 | Configurare MQTT |
| zbx_en | UChar | 1 | Activare Zabbix |
| zserver, zport, zhost, zbx_int | Mixt | "monitor.microelemente.ro", 55051, "PureAware_Default", 60 | Configurare Zabbix |
| bacnet_en, bacnet_id | UChar/ULong | 0/0 | Activare BACnet + Instanta Device |
| sleep_en, sleep_sh/sm/eh/em | UChar | 0, 22:00-06:00 | Program repaus WiFi |
| led_enabled | UChar | 1 | Activare NeoPixel LED |
| tdim | UInt | 50 | Luminozitate ecran (0-100) |
| lang | String | "en" | Limba interfata |
| mbaddr | UChar | 1 | Adresa slave Modbus (1-247) |
| fw_size | ULong | 0 | Dimensiune ultima actualizare firmware OTA |
| cfg_ver | UChar | 0 | Versiune config pentru migrare NVS |
Namespace: "alarm"
| Cheie | Tip | Descriere |
| email_en | UChar | Activare globala email |
| smtp_s/p/tls/u/pw/f/t | Mixt | Configurare SMTP |
| aNen, aNpm, aNtr, aNhy, aNdr | Mixt | Configurare Alarma N (N=0,1,2) |
11. Arhitectura Inregistrare Date
struct LogEntry {
uint32_t ts; // Unix timestamp
float temp, hum, press, co2;
float pm1, pm25, pm4, pm10;
float voc, nox, tvocw;
};
LogEntry logBuf[288]; // 288 × 5 min = 24 ore (circular)
| Nivel | Detalii |
| Buffer RAM | 288 intrari, intervale de 5 min, circular |
| Logare fisiere | day0.csv–day6.csv, rotatie la miezul noptii, scrieri orare |
| NTP Nivel 1 | time() sincronizat prin NTP (precizie maxima) |
| NTP Nivel 2 | Baza salvata din /ntp_base.txt (deviatie < 1h) |
| NTP Nivel 3 | Alternativa: 2026-01-01 + uptime |
12. Motor Alarme
struct AlarmCfg {
uint8_t enabled, dir; // dir: 1=peste, 0=sub
String param; // "co2","pm25","voc","temp","hum","press"...
float trigger, hyst; // prag + histerezis banda moarta
uint8_t state; // 0=OK, 1=Armat, 2=Declansat
};
AlarmCfg alarms[3]; // 3 alarme independente
// Masina de stari:
// OK → Armat (valoarea intra in banda moarta)
// → Declansat (pragul depasit, email trimis)
// → Rearmat (valoarea revine sub histerezis, email trimis)
// → OK
Emailuri in asteptare: 2 sloturi per alarma (declansare + rearmare). Trimise la reconectare WiFi cu intarziere de 5s.
13. Arhitectura Server Web
| Port | Tip | Scop | Autentificare |
| 80 | AsyncWebServer | Tablou de bord status, API JSON, loguri | Fara |
| 8080 | AsyncWebServer | Configurare, import/export | admin / pureaware |
| 8081 | AsyncWebServer | Incarcare firmware OTA | Fara |
| 8082 | AsyncWebServer | Incarcare Nextion TFT | Fara |
14. Mecanism Actualizare OTA
| Metoda | Detalii |
| Manual | Incarcare .bin prin interfata web port 8081 |
| Automat | Verificare HTTPS la fiecare 24h la update.microelemente.ro/firmware.bin |
| Siguranta | In doua etape: descarcare pe LittleFS mai intai, apoi flash. Comparatie dimensiune pentru a evita re-descarcarea. |
15. Numar de Serie & Identificare
| Camp | Valoare |
| Model Produs | PureAQS66 |
| Revizie Hardware | AQS-PureAware-R1.2 |
| Firmware | PureAware_V1.027 |
| Data Compilare | 2026-03-14 |
| Numar de Serie | AQS2608-[MAC_HEX] |
| Hostname | <baza>-<mac3bytes> (ex., pureaware-8a0de8) |
| SSID AP | PureAware_XXXXXX (6 caractere hex din MAC) |
| IP AP | 192.168.1.25 (fix) |