diff options
Diffstat (limited to 'analysis/rtt')
| -rw-r--r-- | analysis/rtt/Dockerfile | 29 | ||||
| -rw-r--r-- | analysis/rtt/Makefile | 22 | ||||
| -rw-r--r-- | analysis/rtt/src/logger.c | 86 | ||||
| -rw-r--r-- | analysis/rtt/src/logger.h | 9 | ||||
| -rw-r--r-- | analysis/rtt/src/main.c | 28 | ||||
| -rw-r--r-- | analysis/rtt/src/mqtt_client.c | 48 | ||||
| -rw-r--r-- | analysis/rtt/src/mqtt_client.h | 16 | ||||
| -rw-r--r-- | analysis/rtt/src/mqtt_rtt_logger.c | 117 |
8 files changed, 355 insertions, 0 deletions
diff --git a/analysis/rtt/Dockerfile b/analysis/rtt/Dockerfile new file mode 100644 index 0000000..cb58f62 --- /dev/null +++ b/analysis/rtt/Dockerfile | |||
| @@ -0,0 +1,29 @@ | |||
| 1 | # FROM debian:bookworm-slim | ||
| 2 | # RUN apt-get update && apt-get install -y \ | ||
| 3 | # gcc \ | ||
| 4 | # make \ | ||
| 5 | # libmosquitto-dev \ | ||
| 6 | # && rm -rf /var/lib/apt/lists/* | ||
| 7 | # WORKDIR /app | ||
| 8 | # COPY . . | ||
| 9 | # RUN make | ||
| 10 | |||
| 11 | FROM alpine:latest AS builder | ||
| 12 | |||
| 13 | RUN apk add --no-cache \ | ||
| 14 | gcc \ | ||
| 15 | make \ | ||
| 16 | musl-dev \ | ||
| 17 | mosquitto-dev | ||
| 18 | |||
| 19 | WORKDIR /app | ||
| 20 | COPY Makefile mqtt_rtt_logger.c ./ | ||
| 21 | RUN make | ||
| 22 | |||
| 23 | FROM alpine:latest | ||
| 24 | |||
| 25 | WORKDIR /app | ||
| 26 | |||
| 27 | COPY --from=builder /app/build/mqtt_rtt_logger ./mqtt_rtt_logger | ||
| 28 | |||
| 29 | CMD ["./mqtt_rtt_logger"] | ||
diff --git a/analysis/rtt/Makefile b/analysis/rtt/Makefile new file mode 100644 index 0000000..8b8d38e --- /dev/null +++ b/analysis/rtt/Makefile | |||
| @@ -0,0 +1,22 @@ | |||
| 1 | TARGET = mqtt_rtt_logger | ||
| 2 | SRC_DIR = src | ||
| 3 | SRC = $(SRC_DIR)/mqtt_rtt_logger.c | ||
| 4 | OUT_DIR = build | ||
| 5 | CC = gcc | ||
| 6 | CFLAGS = -Wall -Wextra -O2 | ||
| 7 | LDFLAGS = -lmosquitto | ||
| 8 | DOCKER_IMAGE = mqtt_rtt_logger-c-mqtt-logger | ||
| 9 | |||
| 10 | all: $(OUT_DIR) $(OUT_DIR)/$(TARGET) | ||
| 11 | |||
| 12 | $(OUT_DIR): | ||
| 13 | mkdir -p $(OUT_DIR) | ||
| 14 | |||
| 15 | $(OUT_DIR)/$(TARGET): $(SRC) | ||
| 16 | $(CC) $(CFLAGS) -o $@ $(SRC) $(LDFLAGS) | ||
| 17 | |||
| 18 | clean: | ||
| 19 | rm -rf $(OUT_DIR) | ||
| 20 | |||
| 21 | docker-build: $(OUT_DIR) | ||
| 22 | docker run --rm -v "$(PWD):/app" -w /app $(DOCKER_IMAGE) make all | ||
diff --git a/analysis/rtt/src/logger.c b/analysis/rtt/src/logger.c new file mode 100644 index 0000000..ed5f6e5 --- /dev/null +++ b/analysis/rtt/src/logger.c | |||
| @@ -0,0 +1,86 @@ | |||
| 1 | |||
| 2 | #include "logger.h" | ||
| 3 | #include <stdio.h> | ||
| 4 | #include <stdlib.h> | ||
| 5 | #include <string.h> | ||
| 6 | #include <sys/time.h> | ||
| 7 | #include <time.h> | ||
| 8 | |||
| 9 | #define WINDOW_SEC 1 | ||
| 10 | #define MAX_TIMES 1000 | ||
| 11 | |||
| 12 | static FILE *csv_file = NULL; | ||
| 13 | static double msg_times[MAX_TIMES]; | ||
| 14 | static int msg_count = 0; | ||
| 15 | |||
| 16 | static long long current_time_ms() { | ||
| 17 | struct timeval tv; | ||
| 18 | gettimeofday(&tv, NULL); | ||
| 19 | return ((long long)tv.tv_sec * 1000) + (tv.tv_usec / 1000); | ||
| 20 | } | ||
| 21 | |||
| 22 | static double current_time_sec() { | ||
| 23 | struct timeval tv; | ||
| 24 | gettimeofday(&tv, NULL); | ||
| 25 | return (double)tv.tv_sec + (tv.tv_usec / 1e6); | ||
| 26 | } | ||
| 27 | |||
| 28 | static int update_throughput_window(double now) { | ||
| 29 | int i, new_count = 0; | ||
| 30 | for (i = 0; i < msg_count; i++) { | ||
| 31 | if (now - msg_times[i] < WINDOW_SEC) { | ||
| 32 | msg_times[new_count++] = msg_times[i]; | ||
| 33 | } | ||
| 34 | } | ||
| 35 | msg_times[new_count++] = now; | ||
| 36 | msg_count = new_count; | ||
| 37 | return msg_count; | ||
| 38 | } | ||
| 39 | |||
| 40 | void logger_init(const char *filename) { | ||
| 41 | csv_file = fopen(filename, "w"); | ||
| 42 | if (!csv_file) { | ||
| 43 | perror("Cannot open CSV file"); | ||
| 44 | exit(EXIT_FAILURE); | ||
| 45 | } | ||
| 46 | fprintf(csv_file, | ||
| 47 | "timestamp,sent_ms,received_ms,rtt_ms,throughput_msg_per_s\n"); | ||
| 48 | fflush(csv_file); | ||
| 49 | } | ||
| 50 | |||
| 51 | void logger_cleanup() { | ||
| 52 | if (csv_file) { | ||
| 53 | fclose(csv_file); | ||
| 54 | csv_file = NULL; | ||
| 55 | } | ||
| 56 | } | ||
| 57 | |||
| 58 | void logger_handle_message(const void *payload, int payloadlen) { | ||
| 59 | char *payload_str = malloc(payloadlen + 1); | ||
| 60 | if (!payload_str) | ||
| 61 | return; | ||
| 62 | memcpy(payload_str, payload, payloadlen); | ||
| 63 | payload_str[payloadlen] = '\0'; | ||
| 64 | |||
| 65 | long long sent_ms = atoll(payload_str); | ||
| 66 | free(payload_str); | ||
| 67 | |||
| 68 | long long received_ms = current_time_ms(); | ||
| 69 | long long rtt = received_ms - sent_ms; | ||
| 70 | |||
| 71 | double now_sec = current_time_sec(); | ||
| 72 | int throughput = update_throughput_window(now_sec); | ||
| 73 | |||
| 74 | time_t now = time(NULL); | ||
| 75 | struct tm *tm_info = localtime(&now); | ||
| 76 | char iso_time[32]; | ||
| 77 | strftime(iso_time, sizeof(iso_time), "%Y-%m-%dT%H:%M:%S", tm_info); | ||
| 78 | |||
| 79 | if (csv_file) { | ||
| 80 | fprintf(csv_file, "%s,%lld,%lld,%lld,%d\n", iso_time, sent_ms, received_ms, | ||
| 81 | rtt, throughput); | ||
| 82 | fflush(csv_file); | ||
| 83 | } | ||
| 84 | |||
| 85 | printf("RTT: %lld ms | Throughput: %d msg/s\n", rtt, throughput); | ||
| 86 | } | ||
diff --git a/analysis/rtt/src/logger.h b/analysis/rtt/src/logger.h new file mode 100644 index 0000000..f1602c9 --- /dev/null +++ b/analysis/rtt/src/logger.h | |||
| @@ -0,0 +1,9 @@ | |||
| 1 | |||
| 2 | #ifndef LOGGER_H | ||
| 3 | #define LOGGER_H | ||
| 4 | |||
| 5 | void logger_init(const char *filename); | ||
| 6 | void logger_cleanup(); | ||
| 7 | void logger_handle_message(const void *payload, int payloadlen); | ||
| 8 | |||
| 9 | #endif // LOGGER_H | ||
diff --git a/analysis/rtt/src/main.c b/analysis/rtt/src/main.c new file mode 100644 index 0000000..13f7716 --- /dev/null +++ b/analysis/rtt/src/main.c | |||
| @@ -0,0 +1,28 @@ | |||
| 1 | |||
| 2 | #include "logger.h" | ||
| 3 | #include "mqtt_client.h" | ||
| 4 | #include <stdio.h> | ||
| 5 | |||
| 6 | #define BROKER_ADDRESS "192.168.1.101" | ||
| 7 | #define BROKER_PORT 1883 | ||
| 8 | #define TOPIC "device/echo/in" | ||
| 9 | #define CSV_FILE "rtt_throughput_log.csv" | ||
| 10 | |||
| 11 | int main() { | ||
| 12 | mqtt_client_t client; | ||
| 13 | |||
| 14 | logger_init(CSV_FILE); | ||
| 15 | |||
| 16 | if (mqtt_client_init(&client, BROKER_ADDRESS, BROKER_PORT, TOPIC) != 0) { | ||
| 17 | fprintf(stderr, "MQTT initialization error\n"); | ||
| 18 | return 1; | ||
| 19 | } | ||
| 20 | |||
| 21 | printf("Connection established.Waiting for messages...\n"); | ||
| 22 | mqtt_client_loop(&client); | ||
| 23 | |||
| 24 | logger_cleanup(); | ||
| 25 | mqtt_client_cleanup(&client); | ||
| 26 | |||
| 27 | return 0; | ||
| 28 | } | ||
diff --git a/analysis/rtt/src/mqtt_client.c b/analysis/rtt/src/mqtt_client.c new file mode 100644 index 0000000..43a06d8 --- /dev/null +++ b/analysis/rtt/src/mqtt_client.c | |||
| @@ -0,0 +1,48 @@ | |||
| 1 | #include "mqtt_client.h" | ||
| 2 | #include "logger.h" | ||
| 3 | #include <stdio.h> | ||
| 4 | #include <stdlib.h> | ||
| 5 | |||
| 6 | #define WINDOW_SEC 1 | ||
| 7 | |||
| 8 | static void on_message(struct mosquitto *mosq, void *userdata, | ||
| 9 | const struct mosquitto_message *msg); | ||
| 10 | |||
| 11 | int mqtt_client_init(mqtt_client_t *client, const char *broker_address, | ||
| 12 | int port, const char *topic) { | ||
| 13 | mosquitto_lib_init(); | ||
| 14 | client->mosq = mosquitto_new(NULL, true, NULL); | ||
| 15 | if (!client->mosq) { | ||
| 16 | fprintf(stderr, "Cannot create MQTT client\n"); | ||
| 17 | return 1; | ||
| 18 | } | ||
| 19 | |||
| 20 | mosquitto_message_callback_set(client->mosq, on_message); | ||
| 21 | |||
| 22 | if (mosquitto_connect(client->mosq, broker_address, port, 60) != | ||
| 23 | MOSQ_ERR_SUCCESS) { | ||
| 24 | fprintf(stderr, "Nie można połączyć się z brokerem MQTT\n"); | ||
| 25 | return 1; | ||
| 26 | } | ||
| 27 | |||
| 28 | if (mosquitto_subscribe(client->mosq, NULL, topic, 0) != MOSQ_ERR_SUCCESS) { | ||
| 29 | fprintf(stderr, "Cannot subscribe to topic\n"); | ||
| 30 | return 1; | ||
| 31 | } | ||
| 32 | |||
| 33 | return 0; | ||
| 34 | } | ||
| 35 | |||
| 36 | void mqtt_client_cleanup(mqtt_client_t *client) { | ||
| 37 | mosquitto_destroy(client->mosq); | ||
| 38 | mosquitto_lib_cleanup(); | ||
| 39 | } | ||
| 40 | |||
| 41 | void mqtt_client_loop(mqtt_client_t *client) { | ||
| 42 | mosquitto_loop_forever(client->mosq, -1, 1); | ||
| 43 | } | ||
| 44 | |||
| 45 | static void on_message(struct mosquitto *mosq, void *userdata, | ||
| 46 | const struct mosquitto_message *msg) { | ||
| 47 | logger_handle_message(msg->payload, msg->payloadlen); | ||
| 48 | } | ||
diff --git a/analysis/rtt/src/mqtt_client.h b/analysis/rtt/src/mqtt_client.h new file mode 100644 index 0000000..781e742 --- /dev/null +++ b/analysis/rtt/src/mqtt_client.h | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | |||
| 2 | #ifndef MQTT_CLIENT_H | ||
| 3 | #define MQTT_CLIENT_H | ||
| 4 | |||
| 5 | #include <mosquitto.h> | ||
| 6 | |||
| 7 | typedef struct { | ||
| 8 | struct mosquitto *mosq; | ||
| 9 | } mqtt_client_t; | ||
| 10 | |||
| 11 | int mqtt_client_init(mqtt_client_t *client, const char *broker_address, | ||
| 12 | int port, const char *topic); | ||
| 13 | void mqtt_client_cleanup(mqtt_client_t *client); | ||
| 14 | void mqtt_client_loop(mqtt_client_t *client); | ||
| 15 | |||
| 16 | #endif // MQTT_CLIENT_H | ||
diff --git a/analysis/rtt/src/mqtt_rtt_logger.c b/analysis/rtt/src/mqtt_rtt_logger.c new file mode 100644 index 0000000..60e5d2d --- /dev/null +++ b/analysis/rtt/src/mqtt_rtt_logger.c | |||
| @@ -0,0 +1,117 @@ | |||
| 1 | // #include <mosquitto.h> | ||
| 2 | // #include <stdio.h> | ||
| 3 | // #include <stdlib.h> | ||
| 4 | // #include <string.h> | ||
| 5 | // #include <sys/time.h> | ||
| 6 | // #include <time.h> | ||
| 7 | // #include <unistd.h> | ||
| 8 | // | ||
| 9 | // #define BROKER_ADDRESS "192.168.1.101" | ||
| 10 | // #define BROKER_PORT 1883 | ||
| 11 | // #define TOPIC "device/echo/in" | ||
| 12 | // #define CSV_FILE "rtt_throughput_log.csv" | ||
| 13 | // #define WINDOW_SEC 1 | ||
| 14 | // #define MAX_TIMES 1000 | ||
| 15 | // | ||
| 16 | // // Kolejka czasów przyjścia wiadomości (dla throughput) | ||
| 17 | // double msg_times[MAX_TIMES]; | ||
| 18 | // int msg_count = 0; | ||
| 19 | // | ||
| 20 | // // Zwraca aktualny czas w milisekundach | ||
| 21 | // long long current_time_ms() { | ||
| 22 | // struct timeval tv; | ||
| 23 | // gettimeofday(&tv, NULL); | ||
| 24 | // return ((long long)tv.tv_sec * 1000) + (tv.tv_usec / 1000); | ||
| 25 | // } | ||
| 26 | // | ||
| 27 | // // Zwraca aktualny czas w sekundach z ułamkiem | ||
| 28 | // double current_time_sec() { | ||
| 29 | // struct timeval tv; | ||
| 30 | // gettimeofday(&tv, NULL); | ||
| 31 | // return (double)tv.tv_sec + (tv.tv_usec / 1e6); | ||
| 32 | // } | ||
| 33 | // | ||
| 34 | // // Aktualizuje throughput window i zwraca liczbę wiadomości w oknie | ||
| 35 | // int update_throughput_window(double now) { | ||
| 36 | // int i, new_count = 0; | ||
| 37 | // for (i = 0; i < msg_count; i++) { | ||
| 38 | // if (now - msg_times[i] < WINDOW_SEC) { | ||
| 39 | // msg_times[new_count++] = msg_times[i]; | ||
| 40 | // } | ||
| 41 | // } | ||
| 42 | // msg_times[new_count++] = now; | ||
| 43 | // msg_count = new_count; | ||
| 44 | // return msg_count; | ||
| 45 | // } | ||
| 46 | // | ||
| 47 | // // Callback po odebraniu wiadomości | ||
| 48 | // void on_message(struct mosquitto *mosq, void *userdata, | ||
| 49 | // const struct mosquitto_message *msg) { | ||
| 50 | // char *payload = (char *)msg->payload; | ||
| 51 | // long long sent_ms = atoll(payload); | ||
| 52 | // long long received_ms = current_time_ms(); | ||
| 53 | // long long rtt = received_ms - sent_ms; | ||
| 54 | // | ||
| 55 | // double now_sec = current_time_sec(); | ||
| 56 | // int throughput = update_throughput_window(now_sec); | ||
| 57 | // | ||
| 58 | // // Timestamp ISO 8601 | ||
| 59 | // time_t now = time(NULL); | ||
| 60 | // struct tm *tm_info = localtime(&now); | ||
| 61 | // char iso_time[32]; | ||
| 62 | // strftime(iso_time, sizeof(iso_time), "%Y-%m-%dT%H:%M:%S", tm_info); | ||
| 63 | // | ||
| 64 | // // Zapisz do CSV | ||
| 65 | // FILE *f = fopen(CSV_FILE, "a"); | ||
| 66 | // if (f) { | ||
| 67 | // fprintf(f, "%s,%lld,%lld,%lld,%d\n", iso_time, sent_ms, received_ms, rtt, | ||
| 68 | // throughput); | ||
| 69 | // fclose(f); | ||
| 70 | // } | ||
| 71 | // | ||
| 72 | // // Wydruk | ||
| 73 | // printf("RTT: %lld ms | Throughput: %d msg/s\n", rtt, throughput); | ||
| 74 | // } | ||
| 75 | // | ||
| 76 | // int main() { | ||
| 77 | // printf("Start programu\n"); | ||
| 78 | // | ||
| 79 | // FILE *f = fopen(CSV_FILE, "w"); | ||
| 80 | // if (!f) { | ||
| 81 | // perror("Nie można otworzyć pliku CSV"); | ||
| 82 | // return 1; | ||
| 83 | // } | ||
| 84 | // fprintf(f, "timestamp,sent_ms,received_ms,rtt_ms,throughput_msg_per_s\n"); | ||
| 85 | // fclose(f); | ||
| 86 | // printf("Plik CSV utworzony\n"); | ||
| 87 | // | ||
| 88 | // mosquitto_lib_init(); | ||
| 89 | // struct mosquitto *mosq = mosquitto_new(NULL, true, NULL); | ||
| 90 | // if (!mosq) { | ||
| 91 | // fprintf(stderr, "Błąd tworzenia klienta MQTT\n"); | ||
| 92 | // return 1; | ||
| 93 | // } | ||
| 94 | // printf("Klient MQTT utworzony\n"); | ||
| 95 | // | ||
| 96 | // mosquitto_message_callback_set(mosq, on_message); | ||
| 97 | // | ||
| 98 | // int rc = mosquitto_connect(mosq, BROKER_ADDRESS, BROKER_PORT, 60); | ||
| 99 | // if (rc != MOSQ_ERR_SUCCESS) { | ||
| 100 | // fprintf(stderr, "Nie można połączyć się z brokerem MQTT, kod błędu: | ||
| 101 | // %d\n", | ||
| 102 | // rc); | ||
| 103 | // return 1; | ||
| 104 | // } | ||
| 105 | // printf("Połączono z brokerem MQTT\n"); | ||
| 106 | // | ||
| 107 | // mosquitto_subscribe(mosq, NULL, TOPIC, 0); | ||
| 108 | // printf("Subskrypcja tematu %s ustawiona\n", TOPIC); | ||
| 109 | // | ||
| 110 | // printf("Oczekiwanie na wiadomości...\n"); | ||
| 111 | // mosquitto_loop_forever(mosq, -1, 1); | ||
| 112 | // | ||
| 113 | // mosquitto_destroy(mosq); | ||
| 114 | // mosquitto_lib_cleanup(); | ||
| 115 | // | ||
| 116 | // return 0; | ||
| 117 | // } | ||
