Air Quality Monitor
Portable C application for collecting, storing, and analyzing air quality sensor readings
Loading...
Searching...
No Matches
alert_system.c
1#include "core/aqm_db.h"
2#include "core/globals.h"
3#include <stdio.h>
4#include <sqlite3.h>
5
6static int exceeds_limits(const AirQualityData *d) {
7 return (d->pm25 > limit_pm25 || d->pm10 > limit_pm10 || d->co > limit_co || d->no2 > limit_no2 ||
8 d->o3 > limit_o3 || d->so2 > limit_so2);
9}
10
11void check_alerts(void) {
12 sqlite3 *db = NULL;
13 if (aqm_db_open(&db) != 0)
14 return;
15
16 sqlite3_stmt *st = NULL;
17 const char *sql =
18 "SELECT r.sensor_id, r.model, r.measured_at, r.pm25, r.pm10, r.co, r.no2, r.o3, r.so2 "
19 "FROM readings r ORDER BY r.measured_at DESC LIMIT 1;";
20
21 if (sqlite3_prepare_v2(db, sql, -1, &st, NULL) != SQLITE_OK) {
22 fprintf(stderr, "Query failed: %s\n", sqlite3_errmsg(db));
23 aqm_db_close(db);
24 return;
25 }
26
27 if (sqlite3_step(st) != SQLITE_ROW) {
28 printf("No readings in database yet.\n");
29 sqlite3_finalize(st);
30 aqm_db_close(db);
31 return;
32 }
33
35 d.sensor_id = sqlite3_column_int(st, 0);
36 const char *model = (const char *)sqlite3_column_text(st, 1);
37 const char *ts = (const char *)sqlite3_column_text(st, 2);
38 snprintf(d.model, sizeof(d.model), "%s", model ? model : "");
39 snprintf(d.timestamp, sizeof(d.timestamp), "%s", ts ? ts : "");
40 d.pm25 = (float)sqlite3_column_double(st, 3);
41 d.pm10 = (float)sqlite3_column_double(st, 4);
42 d.co = (float)sqlite3_column_double(st, 5);
43 d.no2 = (float)sqlite3_column_double(st, 6);
44 d.o3 = (float)sqlite3_column_double(st, 7);
45 d.so2 = (float)sqlite3_column_double(st, 8);
46
47 sqlite3_finalize(st);
48 aqm_db_close(db);
49
50 if (exceeds_limits(&d)) {
51 printf("ALERT: Latest sample exceeds configured limits (sensor %d, model %s, %s).\n", d.sensor_id, d.model,
52 d.timestamp);
53 printf(" PM2.5 %.4f (limit %.4f) PM10 %.4f (limit %.4f) CO %.4f (limit %.4f)\n", d.pm25,
54 limit_pm25, d.pm10, limit_pm10, d.co, limit_co);
55 printf(" NO2 %.6f (limit %.6f) O3 %.6f (limit %.6f) SO2 %.6f (limit %.6f)\n", d.no2, limit_no2,
56 d.o3, limit_o3, d.so2, limit_so2);
57 } else {
58 printf("Latest reading is within configured limits (sensor %d, model %s, %s).\n", d.sensor_id, d.model,
59 d.timestamp);
60 }
61}
One air quality reading: pollutant values plus sensor/timestamp metadata.
Definition globals.h:27
char timestamp[32]
Reading timestamp, formatted "%Y-%m-%d %H:%M:%S".
Definition globals.h:31
char model[64]
Sensor model name, e.g.
Definition globals.h:33
int sensor_id
Numeric sensor identifier, matches SensorPlugin::sensor_id.
Definition globals.h:29