From 07cf7c9f07196d7e94dc5ebf0e186ea69588b16b Mon Sep 17 00:00:00 2001 From: Sven Carstensen Date: Sun, 14 Sep 2025 17:15:03 +0200 Subject: [PATCH] MQTT --- .../controller/MessageController.java | 172 ++++-------------- 1 file changed, 31 insertions(+), 141 deletions(-) diff --git a/src/main/java/de/assecutor/votianlt/controller/MessageController.java b/src/main/java/de/assecutor/votianlt/controller/MessageController.java index 42f6048..770d996 100644 --- a/src/main/java/de/assecutor/votianlt/controller/MessageController.java +++ b/src/main/java/de/assecutor/votianlt/controller/MessageController.java @@ -19,7 +19,6 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import de.assecutor.votianlt.mqtt.MqttPublisher; import org.springframework.stereotype.Component; -import org.springframework.beans.factory.annotation.Autowired; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; @@ -38,82 +37,28 @@ public class MessageController { // Map to store userId -> clientId mapping for active sessions private final Map userClientIdMapping = new ConcurrentHashMap<>(); - @Autowired - private MqttPublisher mqttPublisher; + private final MqttPublisher mqttPublisher; - @Autowired - private AppUserRepository appUserRepository; + private final AppUserRepository appUserRepository; - @Autowired - private AppUserService appUserService; + private final AppUserService appUserService; - @Autowired - private JobRepository jobRepository; + private final JobRepository jobRepository; - @Autowired - private CargoItemRepository cargoItemRepository; + private final CargoItemRepository cargoItemRepository; - @Autowired - private TaskRepository taskRepository; + private final TaskRepository taskRepository; - @Autowired - private PhotoRepository photoRepository; + private final PhotoRepository photoRepository; - /** - * Handles messages sent to /app/message and broadcasts them to all subscribers of /topic/messages - */ - public Map handleMessage(Map message) { - log.error("=== ANY MESSAGE RECEIVED === MQTT Endpoint '/app/message' called"); - log.info("MQTT Endpoint '/app/message' called with data: {}", message); - - // Add timestamp to the message - message.put("timestamp", LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)); - message.put("processed", true); - - log.info("MQTT Response for '/app/message' sent to '/topic/messages': {}", message); - return message; - } - - /** - * Handles job status updates from apps - */ - public Map handleJobStatusUpdate(Map jobUpdate) { - log.info("MQTT Endpoint '/app/job/status' called with data: {}", jobUpdate); - - jobUpdate.put("timestamp", LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)); - jobUpdate.put("source", "app"); - - log.info("MQTT Response for '/app/job/status' sent to '/topic/job-updates': {}", jobUpdate); - return jobUpdate; - } - - /** - * Handles device location updates from mobile apps - */ - public Map handleDeviceLocation(Map locationUpdate) { - log.info("MQTT Endpoint '/app/device/location' called with data: {}", locationUpdate); - - locationUpdate.put("timestamp", LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)); - locationUpdate.put("processed", true); - - log.info("MQTT Response for '/app/device/location' sent to '/topic/device-locations': {}", locationUpdate); - return locationUpdate; - } - - /** - * Send notification to specific user (removed MQTT publishing) - */ - public void sendNotificationToUser(String username, String message) { - log.info("Notification for user '{}': {}", username, message); - // Note: MQTT notification publishing has been removed - } - - /** - * Send broadcast message to all connected clients (removed MQTT publishing) - */ - public void sendBroadcastMessage(String message) { - log.info("Broadcast message: {}", message); - // Note: MQTT broadcast publishing has been removed + public MessageController(MqttPublisher mqttPublisher, AppUserRepository appUserRepository, AppUserService appUserService, JobRepository jobRepository, CargoItemRepository cargoItemRepository, TaskRepository taskRepository, PhotoRepository photoRepository) { + this.mqttPublisher = mqttPublisher; + this.appUserRepository = appUserRepository; + this.appUserService = appUserService; + this.jobRepository = jobRepository; + this.cargoItemRepository = cargoItemRepository; + this.taskRepository = taskRepository; + this.photoRepository = photoRepository; } /** @@ -196,10 +141,8 @@ public class MessageController { List tasks = taskRepository.findByJobIdOrderByTaskOrderAsc(job.getId()); // Log task details for debugging - tasks.forEach(task -> { - log.info("Task details for job {}: type={}, order={}", - job.getId(), task.getTaskType(), task.getTaskOrder()); - }); + tasks.forEach(task -> log.info("Task details for job {}: type={}, order={}", + job.getId(), task.getTaskType(), task.getTaskOrder())); return new JobWithRelatedDataDTO(job, cargoItems, tasks); }) @@ -238,9 +181,9 @@ public class MessageController { * Broadcasts to /topic/task-updates and /topic/tasks/{taskId}. * This endpoint accepts any task type (fallback for GENERIC or unknown types). */ - public Map handleTaskCompleted(Map payload) { + public void handleTaskCompleted(Map payload) { log.info("MQTT Endpoint '/app/task/completed' called with data: {}", payload); - return processTaskCompletion(payload, null); // null means accept any task type + processTaskCompletion(payload, null); } /** @@ -248,9 +191,9 @@ public class MessageController { * Client sends to /app/task/confirm with payload { taskId, completedBy?, note? }. * Broadcasts to /topic/task-updates and /topic/tasks/{taskId}. */ - public Map handleTaskConfirmation(Map payload) { + public void handleTaskConfirmation(Map payload) { log.info("MQTT Endpoint '/app/task/confirm' called with data: {}", payload); - return processTaskCompletion(payload, "CONFIRMATION"); + processTaskCompletion(payload, "CONFIRMATION"); } /** @@ -259,46 +202,16 @@ public class MessageController { * The extraData contains: { photos: base64List, count: base64List.length } * Broadcasts to /topic/task-updates and /topic/tasks/{taskId}. */ - public Map handlePhotoTaskCompleted(Map payload) { + public void handlePhotoTaskCompleted(Map payload) { log.info("MQTT Endpoint '/app/task/photo/completed' called"); - return processPhotoTaskCompletion(payload); - } - - /** - * Report signature task completion from apps. - * Client sends to /app/task/signature/completed with payload { taskId, completedBy?, note? }. - * Broadcasts to /topic/task-updates and /topic/tasks/{taskId}. - */ - public Map handleSignatureTaskCompleted(Map payload) { - log.info("MQTT Endpoint '/app/task/signature/completed' called with data: {}", payload); - return processTaskCompletion(payload, "SIGNATURE"); - } - - /** - * Report barcode task completion from apps. - * Client sends to /app/task/barcode/completed with payload { taskId, completedBy?, note? }. - * Broadcasts to /topic/task-updates and /topic/tasks/{taskId}. - */ - public Map handleBarcodeTaskCompleted(Map payload) { - log.info("MQTT Endpoint '/app/task/barcode/completed' called with data: {}", payload); - return processTaskCompletion(payload, "BARCODE"); - } - - /** - * Report todolist task completion from apps. - * Client sends to /app/task/todolist/completed with payload { taskId, completedBy?, note? }. - * Broadcasts to /topic/task-updates and /topic/tasks/{taskId}. - */ - public Map handleTodolistTaskCompleted(Map payload) { - log.info("MQTT Endpoint '/app/task/todolist/completed' called with data: {}", payload); - return processTaskCompletion(payload, "TODOLIST"); + processPhotoTaskCompletion(payload); } /** * Specialized method to process photo task completion with extraData handling. * Saves photo data to the photos collection and processes task completion. */ - private Map processPhotoTaskCompletion(Map payload) { + private void processPhotoTaskCompletion(Map payload) { Map response = new java.util.HashMap<>(); response.put("timestamp", LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)); response.put("type", "taskCompletedAck"); @@ -307,7 +220,7 @@ public class MessageController { response.put("success", false); response.put("message", "taskId ist erforderlich"); log.info("Photo task completion failed: {}", response); - return response; + return; } String taskIdStr = payload.get("taskId").toString(); @@ -320,7 +233,7 @@ public class MessageController { if (opt.isEmpty()) { response.put("success", false); response.put("message", "Task nicht gefunden"); - return response; + return; } BaseTask task = opt.get(); @@ -330,7 +243,7 @@ public class MessageController { response.put("success", false); response.put("message", "Task-Typ stimmt nicht mit dem Endpunkt überein. Erwartet: PHOTO, Gefunden: " + task.getTaskType()); log.warn("Task type mismatch for taskId={}: expected=PHOTO, actual={}", taskIdStr, task.getTaskType()); - return response; + return; } // Process extraData if present @@ -382,16 +295,13 @@ public class MessageController { response.put("success", true); response.putAll(event); log.info("Photo task completion processed successfully for taskId={}", taskIdStr); - return response; } catch (IllegalArgumentException e) { response.put("success", false); response.put("message", "Ungültige taskId"); - return response; } catch (Exception e) { log.error("Error processing photo task completion", e); response.put("success", false); response.put("message", "Fehler bei der Verarbeitung"); - return response; } } @@ -399,7 +309,7 @@ public class MessageController { * Common method to process task completion for different task types. * This method contains the shared logic for all task completion endpoints. */ - private Map processTaskCompletion(Map payload, String expectedTaskType) { + private void processTaskCompletion(Map payload, String expectedTaskType) { Map response = new java.util.HashMap<>(); response.put("timestamp", LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)); response.put("type", "taskCompletedAck"); @@ -408,7 +318,7 @@ public class MessageController { response.put("success", false); response.put("message", "taskId ist erforderlich"); log.info("Task completion failed: {}", response); - return response; + return; } String taskIdStr = payload.get("taskId").toString(); @@ -421,7 +331,7 @@ public class MessageController { if (opt.isEmpty()) { response.put("success", false); response.put("message", "Task nicht gefunden"); - return response; + return; } BaseTask task = opt.get(); @@ -431,7 +341,7 @@ public class MessageController { response.put("success", false); response.put("message", "Task-Typ stimmt nicht mit dem Endpunkt überein. Erwartet: " + expectedTaskType + ", Gefunden: " + task.getTaskType()); log.warn("Task type mismatch for taskId={}: expected={}, actual={}", taskIdStr, expectedTaskType, task.getTaskType()); - return response; + return; } task.setCompleted(true); @@ -456,33 +366,13 @@ public class MessageController { response.put("success", true); response.putAll(event); log.info("Task completion processed successfully for taskId={}, taskType={}", taskIdStr, task.getTaskType()); - return response; } catch (IllegalArgumentException e) { response.put("success", false); response.put("message", "Ungültige taskId"); - return response; } catch (Exception e) { log.error("Error processing task completion", e); response.put("success", false); response.put("message", "Fehler bei der Verarbeitung"); - return response; - } - } - - /** - * Helper method to get the user ID for a task by looking up the associated job - */ - private String getUserIdForTask(BaseTask task) { - try { - java.util.Optional jobOpt = jobRepository.findById(task.getJobId()); - if (jobOpt.isPresent()) { - Job job = jobOpt.get(); - return job.getAppUser(); - } - return null; - } catch (Exception e) { - log.error("Error getting user ID for task {}: {}", task.getIdAsString(), e.getMessage(), e); - return null; } }