This commit is contained in:
2025-09-14 17:15:03 +02:00
parent b58c3e2398
commit 07cf7c9f07

View File

@@ -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<String, String> 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<String, Object> handleMessage(Map<String, Object> 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<String, Object> handleJobStatusUpdate(Map<String, Object> 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<String, Object> handleDeviceLocation(Map<String, Object> 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<BaseTask> 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<String, Object> handleTaskCompleted(Map<String, Object> payload) {
public void handleTaskCompleted(Map<String, Object> 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<String, Object> handleTaskConfirmation(Map<String, Object> payload) {
public void handleTaskConfirmation(Map<String, Object> 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<String, Object> handlePhotoTaskCompleted(Map<String, Object> payload) {
public void handlePhotoTaskCompleted(Map<String, Object> 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<String, Object> handleSignatureTaskCompleted(Map<String, Object> 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<String, Object> handleBarcodeTaskCompleted(Map<String, Object> 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<String, Object> handleTodolistTaskCompleted(Map<String, Object> 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<String, Object> processPhotoTaskCompletion(Map<String, Object> payload) {
private void processPhotoTaskCompletion(Map<String, Object> payload) {
Map<String, Object> 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<String, Object> processTaskCompletion(Map<String, Object> payload, String expectedTaskType) {
private void processTaskCompletion(Map<String, Object> payload, String expectedTaskType) {
Map<String, Object> 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<Job> 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;
}
}