From 149a49059ad119c02366bad42c53814b633ed2ec Mon Sep 17 00:00:00 2001 From: heewonn09 Date: Tue, 28 Oct 2025 03:19:20 +0900 Subject: [PATCH] Add parking gate authorization feedback --- src/main/java/controller/MainController.java | 2 +- src/main/java/dao/ParkingDAO.java | 10 ++++- src/main/java/dao/ParkingDAOImpl.java | 26 +++++++----- .../java/dto/mqttMsg/MqttGateCommandDTO.java | 40 +++++++++++++++++++ .../java/mqtt/devices/ParkingHandler.java | 25 +++++++++++- 5 files changed, 88 insertions(+), 15 deletions(-) create mode 100644 src/main/java/dto/mqttMsg/MqttGateCommandDTO.java diff --git a/src/main/java/controller/MainController.java b/src/main/java/controller/MainController.java index 6f7d385..a9b8ea8 100644 --- a/src/main/java/controller/MainController.java +++ b/src/main/java/controller/MainController.java @@ -44,7 +44,7 @@ public void settingDevice(){ } catch (InterruptedException e) { e.printStackTrace(); } - ParkingHandler parkingHandler = new ParkingHandler(parkingDAO); + ParkingHandler parkingHandler = new ParkingHandler(parkingDAO, mqttManager); String parkingTopic = "parking/car/#"; this.mqttManager.addListener(parkingTopic, parkingHandler); diff --git a/src/main/java/dao/ParkingDAO.java b/src/main/java/dao/ParkingDAO.java index 4ef3808..4f888f3 100644 --- a/src/main/java/dao/ParkingDAO.java +++ b/src/main/java/dao/ParkingDAO.java @@ -9,5 +9,13 @@ public interface ParkingDAO { public ParkingLogDTO getCurrentParkingStatus(int userId); public List getParkingLogsByUser(int userId); public List getAllSpaces(); - void processVehicleLog(String carNo, String action); + /** + * 차량 로그를 처리하고 DB 내 등록 여부를 확인합니다. + * + * @param carNo 차량 번호 + * @param action 차량 이동 액션 (IN/OUT) + * @return 차량이 등록되어 있어 게이트를 열어도 되는 경우 {@code true}, + * 그렇지 않으면 {@code false} + */ + boolean processVehicleLog(String carNo, String action); } diff --git a/src/main/java/dao/ParkingDAOImpl.java b/src/main/java/dao/ParkingDAOImpl.java index 7476a57..4f89fff 100644 --- a/src/main/java/dao/ParkingDAOImpl.java +++ b/src/main/java/dao/ParkingDAOImpl.java @@ -67,10 +67,10 @@ public List getAllSpaces() { } @Override - public void processVehicleLog(String carNo, String action) { + public boolean processVehicleLog(String carNo, String action) { if (carNo == null || carNo.trim().isEmpty()) { System.out.println("🚗 차량 번호가 비어 있어 로그를 처리할 수 없습니다."); - return; + return false; } String normalizedAction = (action == null || action.trim().isEmpty()) ? "IN" : action.trim().toUpperCase(); @@ -89,26 +89,29 @@ public void processVehicleLog(String carNo, String action) { if (userId == null) { System.out.printf("🚫 차량 번호 %s 에 해당하는 등록 정보가 없습니다.%n", carNo); - return; + return false; } + boolean success = false; switch (normalizedAction) { case "IN": - logVehicleEntry(con, userId, carNo); + success = logVehicleEntry(con, userId, carNo); break; case "OUT": - logVehicleExit(con, userId, carNo); + success = logVehicleExit(con, userId, carNo); break; default: System.out.printf("⚠️ 지원하지 않는 차량 액션: %s%n", normalizedAction); - return; + return false; } + return success; } catch (SQLException e) { e.printStackTrace(); + return false; } } - private void logVehicleEntry(Connection con, int userId, String carNo) throws SQLException { + private boolean logVehicleEntry(Connection con, int userId, String carNo) throws SQLException { String insertSql = """ INSERT INTO parking_log (user_id, space_id, action, note, in_time) VALUES (?, ?, 'IN', ?, NOW()) @@ -117,11 +120,11 @@ INSERT INTO parking_log (user_id, space_id, action, note, in_time) insert.setInt(1, userId); insert.setNull(2, Types.INTEGER); insert.setString(3, buildNote("입차", carNo)); - insert.executeUpdate(); + return insert.executeUpdate() > 0; } } - private void logVehicleExit(Connection con, int userId, String carNo) throws SQLException { + private boolean logVehicleExit(Connection con, int userId, String carNo) throws SQLException { String findOpenSql = """ SELECT parking_id, in_time FROM parking_log @@ -149,7 +152,7 @@ private void logVehicleExit(Connection con, int userId, String carNo) throws SQL update.setInt(2, duration); update.setString(3, buildNote("출차", carNo)); update.setInt(4, parkingId); - update.executeUpdate(); + return update.executeUpdate() > 0; } } else { String insertOutSql = """ @@ -160,11 +163,12 @@ INSERT INTO parking_log (user_id, space_id, action, note, out_time) insert.setInt(1, userId); insert.setNull(2, Types.INTEGER); insert.setString(3, buildNote("출차", carNo)); - insert.executeUpdate(); + return insert.executeUpdate() > 0; } } } } + return false; } private String buildNote(String prefix, String carNo) { diff --git a/src/main/java/dto/mqttMsg/MqttGateCommandDTO.java b/src/main/java/dto/mqttMsg/MqttGateCommandDTO.java new file mode 100644 index 0000000..587b9a1 --- /dev/null +++ b/src/main/java/dto/mqttMsg/MqttGateCommandDTO.java @@ -0,0 +1,40 @@ +package dto.mqttMsg; + +public class MqttGateCommandDTO { + private String command; + private String carNo; + private boolean authorized; + + public MqttGateCommandDTO() { + } + + public MqttGateCommandDTO(String command, String carNo, boolean authorized) { + this.command = command; + this.carNo = carNo; + this.authorized = authorized; + } + + public String getCommand() { + return command; + } + + public void setCommand(String command) { + this.command = command; + } + + public String getCarNo() { + return carNo; + } + + public void setCarNo(String carNo) { + this.carNo = carNo; + } + + public boolean isAuthorized() { + return authorized; + } + + public void setAuthorized(boolean authorized) { + this.authorized = authorized; + } +} diff --git a/src/main/java/mqtt/devices/ParkingHandler.java b/src/main/java/mqtt/devices/ParkingHandler.java index d4f333a..f0921ff 100644 --- a/src/main/java/mqtt/devices/ParkingHandler.java +++ b/src/main/java/mqtt/devices/ParkingHandler.java @@ -3,16 +3,22 @@ import com.google.gson.Gson; import com.google.gson.JsonSyntaxException; import dao.ParkingDAO; +import dto.mqttMsg.MqttGateCommandDTO; import dto.mqttMsg.MqttParkingDTO; +import mqtt.MqttManager; import mqtt.OnMessageCallback; public class ParkingHandler implements OnMessageCallback { private final ParkingDAO parkingDAO; + private final MqttManager mqttManager; private final Gson gson = new Gson(); - public ParkingHandler(ParkingDAO parkingDAO) { + private static final String GATE_COMMAND_TOPIC = "parking/gate/cmd"; + + public ParkingHandler(ParkingDAO parkingDAO, MqttManager mqttManager) { this.parkingDAO = parkingDAO; + this.mqttManager = mqttManager; } @Override @@ -24,10 +30,25 @@ public void handle(String topic, String payload) { return; } - parkingDAO.processVehicleLog(dto.getCarNo(), dto.getAction()); + boolean authorized = parkingDAO.processVehicleLog(dto.getCarNo(), dto.getAction()); + publishGateCommand(dto.getCarNo(), authorized); } catch (JsonSyntaxException ex) { System.out.printf("⚠️ 차량 로그 JSON 파싱 실패: %s%n", ex.getMessage()); } } + + private void publishGateCommand(String carNo, boolean authorized) { + if (mqttManager == null) { + System.out.println("⚠️ MQTT 매니저가 초기화되지 않아 게이트 명령을 전송하지 못했습니다."); + return; + } + + String command = authorized ? "OPEN" : "KEEP_CLOSED"; + MqttGateCommandDTO response = new MqttGateCommandDTO(command, carNo, authorized); + String message = gson.toJson(response); + + mqttManager.publish(GATE_COMMAND_TOPIC, message); + System.out.printf("🚦 게이트 명령 전송: %s -> %s%n", carNo, command); + } }