| | | 1 | | #include "sensor_service.h" |
| | | 2 | | #include "db_connection.h" |
| | | 3 | | #include "logger.h" |
| | | 4 | | #include <stdio.h> |
| | | 5 | | #include <stdlib.h> |
| | | 6 | | #include <string.h> |
| | | 7 | | #include "alert_service.h" |
| | | 8 | | |
| | 8 | 9 | | int get_machine_sensor_stats(int machine_id, SensorStatus *out_stats, int max_sensors) { |
| | 8 | 10 | | DBConnection *conn_wrapper = db_pool_acquire(); |
| | | 11 | | |
| | 8 | 12 | | if (!conn_wrapper) { |
| | 2 | 13 | | LOG_ERROR("Could not acquire connection for machine health check (ID: %d).", machine_id); |
| | 2 | 14 | | return 0; |
| | | 15 | | } |
| | | 16 | | |
| | | 17 | | char query[512]; |
| | 6 | 18 | | snprintf(query, sizeof(query), |
| | | 19 | | "SELECT DISTINCT ON (s.id) " |
| | | 20 | | "s.id, s.sensor_type, sd.value, s.unit, " |
| | | 21 | | "to_char(sd.timestamp, 'YYYY-MM-DD HH24:MI:SS') " |
| | | 22 | | "FROM sensors s " |
| | | 23 | | "JOIN sensor_data sd ON s.id = sd.sensor_id " |
| | | 24 | | "WHERE s.machine_id = %d " |
| | | 25 | | "ORDER BY s.id, sd.timestamp DESC;", |
| | | 26 | | machine_id); |
| | 6 | 27 | | PGresult *res = PQexec(conn_wrapper->pg_conn, query); |
| | | 28 | | |
| | 6 | 29 | | if (PQresultStatus(res) != PGRES_TUPLES_OK) { |
| | 2 | 30 | | PQclear(res); |
| | 2 | 31 | | db_pool_release(conn_wrapper); |
| | 2 | 32 | | return 0; |
| | | 33 | | } |
| | | 34 | | |
| | 4 | 35 | | int rows = PQntuples(res); |
| | 4 | 36 | | int count = (rows < max_sensors) ? rows : max_sensors; |
| | | 37 | | |
| | 8 | 38 | | for (int i = 0; i < count; i++) { |
| | 4 | 39 | | out_stats[i].sensor_id = atoi(PQgetvalue(res, i, 0)); |
| | 4 | 40 | | strncpy(out_stats[i].sensor_type, PQgetvalue(res, i, 1), 31); |
| | 4 | 41 | | out_stats[i].sensor_type[31] = '\0'; |
| | 4 | 42 | | out_stats[i].last_value = atof(PQgetvalue(res, i, 2)); |
| | 4 | 43 | | strncpy(out_stats[i].unit, PQgetvalue(res, i, 3), 9); |
| | 4 | 44 | | out_stats[i].unit[9] = '\0'; |
| | 4 | 45 | | strncpy(out_stats[i].recorded_at, PQgetvalue(res, i, 4), 31); |
| | 4 | 46 | | out_stats[i].recorded_at[31] = '\0'; |
| | | 47 | | } |
| | | 48 | | |
| | 4 | 49 | | PQclear(res); |
| | 4 | 50 | | db_pool_release(conn_wrapper); |
| | 4 | 51 | | return count; |
| | | 52 | | } |
| | | 53 | | |
| | 6 | 54 | | bool add_sensor_reading(int sensor_id, const char *sensor_type, double value) { |
| | 6 | 55 | | DBConnection *conn_wrapper = db_pool_acquire(); |
| | | 56 | | |
| | 6 | 57 | | if (!conn_wrapper) { |
| | 2 | 58 | | return false; |
| | | 59 | | } |
| | | 60 | | |
| | | 61 | | char query[256]; |
| | 4 | 62 | | snprintf(query, sizeof(query), |
| | | 63 | | "INSERT INTO sensor_data (sensor_id, value) VALUES (%d, %.2f);", |
| | | 64 | | sensor_id, value); |
| | 4 | 65 | | PGresult *res = PQexec(conn_wrapper->pg_conn, query); |
| | | 66 | | |
| | 4 | 67 | | if (PQresultStatus(res) != PGRES_COMMAND_OK) { |
| | 2 | 68 | | PQclear(res); |
| | 2 | 69 | | db_pool_release(conn_wrapper); |
| | 2 | 70 | | return false; |
| | | 71 | | } |
| | | 72 | | |
| | 2 | 73 | | PQclear(res); |
| | 2 | 74 | | db_pool_release(conn_wrapper); |
| | 2 | 75 | | check_and_trigger_alerts(sensor_id, sensor_type, value); |
| | 2 | 76 | | return true; |
| | | 77 | | } |