From 1fad48b7d8232d3845efd8a2f9ed694ea4c97b4e Mon Sep 17 00:00:00 2001 From: Reimar Date: Mon, 7 Apr 2025 13:30:02 +0200 Subject: [PATCH] Receive min/max temperature on iot device --- iot/Makefile | 8 +++-- iot/brokers/amqp.c | 43 ++++++++++++++++++++-- iot/brokers/amqp.h | 2 ++ iot/device_id.c | 46 ------------------------ iot/device_id.h | 6 ---- iot/device_properties.c | 80 +++++++++++++++++++++++++++++++++++++++++ iot/device_properties.h | 9 +++++ iot/main.c | 52 +++++++++++++++++++++++---- 8 files changed, 182 insertions(+), 64 deletions(-) delete mode 100644 iot/device_id.c delete mode 100644 iot/device_id.h create mode 100644 iot/device_properties.c create mode 100644 iot/device_properties.h diff --git a/iot/Makefile b/iot/Makefile index 5d11467..82ec2e3 100644 --- a/iot/Makefile +++ b/iot/Makefile @@ -1,7 +1,9 @@ -FILES=main.c brokers/mqtt.c brokers/amqp.c devices/temperature.c devices/display.c devices/buzzer.c device_id.c +FILES=main.c brokers/mqtt.c brokers/amqp.c devices/temperature.c devices/display.c devices/buzzer.c device_properties.c # libgpiod version must be < 2.0 -all: $(FILES) - $(CC) -lmosquitto -lrabbitmq -pthread -li2c -lgpiod $(FILES) +# apt install libmosquitto-dev librabbitmq-dev libi2c-dev libgpiod-dev libcjson-dev + +all: $(FILES) + $(CC) -lmosquitto -lrabbitmq -pthread -li2c -lgpiod -lcjson $(FILES) diff --git a/iot/brokers/amqp.c b/iot/brokers/amqp.c index 20d7c39..32223e8 100644 --- a/iot/brokers/amqp.c +++ b/iot/brokers/amqp.c @@ -1,13 +1,20 @@ #include #include +#include +#include +#include +#include #include "../config.h" amqp_connection_state_t conn; amqp_socket_t *socket; +amqp_channel_t channel = 1; void broker_on_connect(void); +bool broker_on_message(char *exchange, char *message); + void amqp_send_message(char *queue, char *message) { amqp_basic_properties_t props; @@ -15,7 +22,22 @@ void amqp_send_message(char *queue, char *message) props.content_type = amqp_literal_bytes("text/plain"); props.delivery_mode = 2; - amqp_basic_publish(conn, 1, amqp_cstring_bytes(queue), amqp_cstring_bytes(queue), 0, 0, &props, amqp_cstring_bytes(message)); + amqp_basic_publish(conn, channel, amqp_cstring_bytes(queue), amqp_cstring_bytes(queue), 0, 0, &props, amqp_cstring_bytes(message)); +} + +void amqp_subscribe(char *queue) +{ + amqp_basic_consume(conn, channel, amqp_cstring_bytes(queue), amqp_cstring_bytes("iot"), 1, 0, 0, amqp_empty_table); +} + +char *amqp_bytes_to_cstring(amqp_bytes_t bytes) +{ + char *str = malloc(bytes.len + 1); + + memcpy(str, bytes.bytes, bytes.len); + str[bytes.len] = '\0'; + + return str; } void init_amqp(void) @@ -27,9 +49,24 @@ void init_amqp(void) amqp_login(conn, "/", 0, 131072, 0, AMQP_SASL_METHOD_PLAIN, AMQP_USER, AMQP_PASSWORD); - amqp_channel_open(conn, 1); + amqp_channel_open(conn, channel); broker_on_connect(); - for (;;); + while (true) { + amqp_envelope_t envelope; + amqp_consume_message(conn, &envelope, NULL, 0); + + char *exchange_name = amqp_bytes_to_cstring(envelope.exchange); + char *message = amqp_bytes_to_cstring(envelope.message.body); + + if (broker_on_message(exchange_name, message)) { + amqp_basic_ack(conn, channel, envelope.delivery_tag, 0); + } + + free(exchange_name); + free(message); + amqp_destroy_envelope(&envelope); + } } + diff --git a/iot/brokers/amqp.h b/iot/brokers/amqp.h index be45cbb..735c778 100644 --- a/iot/brokers/amqp.h +++ b/iot/brokers/amqp.h @@ -2,3 +2,5 @@ void init_amqp(void); void amqp_send_message(char *topic, char *message); +void amqp_subscribe(char *queue); + diff --git a/iot/device_id.c b/iot/device_id.c deleted file mode 100644 index f85597f..0000000 --- a/iot/device_id.c +++ /dev/null @@ -1,46 +0,0 @@ -#include -#include - -#include "device_id.h" - -#define DEVICE_ID_SIZE 5 - -char *get_device_id(void) -{ - FILE *file = fopen("device_id.txt", "r"); - - if (!file) { - char *device_id = generate_device_id(); - - file = fopen("device_id.txt", "w"); - fprintf(file, "%s", device_id); - fclose(file); - - return device_id; - } - - char *device_id = malloc(DEVICE_ID_SIZE + 1); - fgets(device_id, DEVICE_ID_SIZE + 1, file); - fclose(file); - - return device_id; -} - -char *generate_device_id(void) -{ - char *device_id = malloc(DEVICE_ID_SIZE + 1); - - for (int i = 0; i < DEVICE_ID_SIZE; i++) { - device_id[i] = 'A' + (random() % 26); - } - - device_id[DEVICE_ID_SIZE] = '\0'; - - return device_id; -} - -void destroy_device_id(char *device_id) -{ - free(device_id); -} - diff --git a/iot/device_id.h b/iot/device_id.h deleted file mode 100644 index f7939b4..0000000 --- a/iot/device_id.h +++ /dev/null @@ -1,6 +0,0 @@ -char *get_device_id(void); - -char *generate_device_id(void); - -void destroy_device_id(char *device_id); - diff --git a/iot/device_properties.c b/iot/device_properties.c new file mode 100644 index 0000000..19bef32 --- /dev/null +++ b/iot/device_properties.c @@ -0,0 +1,80 @@ +#include +#include +#include + +#include "device_properties.h" + +#define DEVICE_ID_SIZE 5 + +char *get_device_id(void) +{ + FILE *file = fopen("device_id.txt", "r"); + + if (!file) { + char *device_id = generate_device_id(); + + file = fopen("device_id.txt", "w"); + fprintf(file, "%s", device_id); + fclose(file); + + return device_id; + } + + char *device_id = malloc(DEVICE_ID_SIZE + 1); + fgets(device_id, DEVICE_ID_SIZE + 1, file); + fclose(file); + + return device_id; +} + +char *generate_device_id(void) +{ + char *device_id = malloc(DEVICE_ID_SIZE + 1); + + for (int i = 0; i < DEVICE_ID_SIZE; i++) { + device_id[i] = 'A' + (random() % 26); + } + + device_id[DEVICE_ID_SIZE] = '\0'; + + return device_id; +} + +void set_min_temperature(double temperature) +{ + FILE *file = fopen("min_temp.txt", "w"); + fprintf(file, "%lf", temperature); + fclose(file); +} + +double get_min_temperature(void) +{ + FILE *file = fopen("min_temp.txt", "r"); + if (!file) return NAN; + + double temperature = NAN; + fscanf(file, "%lf", &temperature); + fclose(file); + + return temperature; +} + +void set_max_temperature(double temperature) +{ + FILE *file = fopen("max_temp.txt", "w"); + fprintf(file, "%lf", temperature); + fclose(file); +} + +double get_max_temperature(void) +{ + FILE *file = fopen("max_temp.txt", "r"); + if (!file) return NAN; + + double temperature = NAN; + fscanf(file, "%lf", &temperature); + fclose(file); + + return temperature; +} + diff --git a/iot/device_properties.h b/iot/device_properties.h new file mode 100644 index 0000000..76a1b34 --- /dev/null +++ b/iot/device_properties.h @@ -0,0 +1,9 @@ +char *get_device_id(void); +char *generate_device_id(void); + +void set_min_temperature(double temperature); +double get_min_temperature(void); + +void set_max_temperature(double temperature); +double get_max_temperature(void); + diff --git a/iot/main.c b/iot/main.c index d9319c7..0a598b8 100644 --- a/iot/main.c +++ b/iot/main.c @@ -5,12 +5,14 @@ #include #include #include +#include +#include #include "brokers/amqp.h" #include "devices/temperature.h" #include "devices/display.h" #include "devices/buzzer.h" -#include "device_id.h" +#include "device_properties.h" void *sound_alarm(void *arg) { @@ -31,9 +33,6 @@ void *sound_alarm(void *arg) void *watch_temperature(void *arg) { - // TODO change - int max_temperature = 27, min_temperature = 18; - char *device_id = get_device_id(); printf("Device ID: %s\n", device_id); @@ -49,6 +48,8 @@ void *watch_temperature(void *arg) while (true) { // Retrieve data + double min_temperature = get_min_temperature(); + double max_temperature = get_max_temperature(); double temperature = get_temperature(temp_handle); size_t timestamp = time(NULL); @@ -76,7 +77,10 @@ void *watch_temperature(void *arg) free(str); // Sound alarm if applicable - if (temperature < min_temperature || temperature > max_temperature) { + if ( + min_temperature != NAN && max_temperature != NAN && + (temperature < min_temperature || temperature > max_temperature) + ) { pthread_t alarm_thread; pthread_create(&alarm_thread, NULL, sound_alarm, NULL); } @@ -86,17 +90,53 @@ void *watch_temperature(void *arg) sleep(60); } - destroy_device_id(device_id); + free(device_id); return NULL; } void broker_on_connect(void) { + amqp_subscribe("temperature-limits"); + pthread_t temperature_thread; pthread_create(&temperature_thread, NULL, watch_temperature, NULL); } +bool broker_on_message(char *exchange, char *message) +{ + cJSON *json = cJSON_Parse(message); + if (cJSON_IsInvalid(json)) goto cancel; + + // Get values + cJSON *reference_id = cJSON_GetObjectItem(json, "ReferenceId"); + if (!cJSON_IsString(reference_id)) goto cancel; + + cJSON *min_temp = cJSON_GetObjectItem(json, "TempLow"); + if (!cJSON_IsNumber(min_temp)) goto cancel; + + cJSON *max_temp = cJSON_GetObjectItem(json, "TempHigh"); + if (!cJSON_IsNumber(min_temp)) goto cancel; + + if (strcmp(reference_id->valuestring, get_device_id()) != 0) { + goto cancel; + } + + printf("Min temperature: %lf, Max temperature: %lf\n", min_temp->valuedouble, max_temp->valuedouble); + + set_min_temperature(min_temp->valuedouble); + set_max_temperature(max_temp->valuedouble); + + cJSON_Delete(json); + + return true; + +cancel: + cJSON_Delete(json); + + return false; +} + int main(void) { srand(time(NULL));