Air Quality Monitor
Portable C application for collecting, storing, and analyzing air quality sensor readings
Loading...
Searching...
No Matches
insert_data.c
1#include "core/aqm_db.h"
2#include "core/globals.h"
3#include <stdio.h>
4#include <sqlite3.h>
5
6static int ensure_sensor(sqlite3 *db, int sensor_id) {
7 sqlite3_stmt *st = NULL;
8 const char *sql = "INSERT OR IGNORE INTO sensors (id, name) VALUES (?, ?);";
9 if (sqlite3_prepare_v2(db, sql, -1, &st, NULL) != SQLITE_OK) {
10 fprintf(stderr, "SQLite prepare error: %s\n", sqlite3_errmsg(db));
11 return -1;
12 }
13
14 char name[64];
15 const char *forced_name = NULL;
16 switch (sensor_id) {
17 case 22:
18 forced_name = "DHT22";
19 break;
20 case 680:
21 forced_name = "BME680";
22 break;
23 case 5003:
24 forced_name = "PMS5003";
25 break;
26 case 1900:
27 forced_name = "MH-Z19";
28 break;
29 default:
30 forced_name = NULL;
31 break;
32 }
33
34 int n = forced_name ? snprintf(name, sizeof(name), "%s", forced_name)
35 : snprintf(name, sizeof(name), "Sensor %d", sensor_id);
36 if (n < 0 || (size_t)n >= sizeof(name)) {
37 sqlite3_finalize(st);
38 return -1;
39 }
40
41 sqlite3_bind_int(st, 1, sensor_id);
42 sqlite3_bind_text(st, 2, name, -1, SQLITE_TRANSIENT);
43 sqlite3_step(st);
44 sqlite3_finalize(st);
45 return 0;
46}
47
48static const char *default_model_name(int sensor_id) {
49 switch (sensor_id) {
50 case 22:
51 return "DHT22";
52 case 680:
53 return "BME680";
54 case 5003:
55 return "PMS5003";
56 case 1900:
57 return "MH-Z19";
58 default:
59 return "unknown";
60 }
61}
62
63static int insert_data_db(sqlite3 *db, const AirQualityData *data) {
64 if (!db || !data)
65 return -1;
66
67 if (ensure_sensor(db, data->sensor_id) != 0)
68 return -1;
69
70 sqlite3_stmt *st = NULL;
71 const char *sql = "INSERT INTO readings (sensor_id, measured_at, model, pm25, pm10, co, no2, o3, so2) "
72 "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?);";
73 if (sqlite3_prepare_v2(db, sql, -1, &st, NULL) != SQLITE_OK) {
74 fprintf(stderr, "SQLite prepare error: %s\n", sqlite3_errmsg(db));
75 return -1;
76 }
77
78 sqlite3_bind_int(st, 1, data->sensor_id);
79 sqlite3_bind_text(st, 2, data->timestamp, -1, SQLITE_STATIC);
80 const char *model = data->model[0] ? data->model : default_model_name(data->sensor_id);
81 sqlite3_bind_text(st, 3, model, -1, SQLITE_TRANSIENT);
82 sqlite3_bind_double(st, 4, (double)data->pm25);
83 sqlite3_bind_double(st, 5, (double)data->pm10);
84 sqlite3_bind_double(st, 6, (double)data->co);
85 sqlite3_bind_double(st, 7, (double)data->no2);
86 sqlite3_bind_double(st, 8, (double)data->o3);
87 sqlite3_bind_double(st, 9, (double)data->so2);
88
89 int rc = sqlite3_step(st);
90 sqlite3_finalize(st);
91
92 if (rc != SQLITE_DONE) {
93 fprintf(stderr, "Insert failed: %s\n", sqlite3_errmsg(db));
94 return -1;
95 }
96
97 const char *model_name = data->model[0] ? data->model : default_model_name(data->sensor_id);
98 printf("Data from %s (ID: %d) inserted successfully.\n", model_name, data->sensor_id);
99 return 0;
100}
101
102int insert_data_sqlite(sqlite3 *db, const AirQualityData *data) {
103 return insert_data_db(db, data);
104}
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