Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 33 additions & 23 deletions src/main/java/controller/MainController.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
import dto.LoginUserDTO;
import dto.MemberDTO;
import mqtt.MqttManager;
import mqtt.devices.DHtHandler;
import mqtt.devices.ELVHandler;
import mqtt.devices.ELVHandler;
import mqtt.devices.ParkingHandler;
import dao.ParkingDAO;
import dao.ParkingDAOImpl;
import service.UserService;
import service.UserServiceImpl;
import controller.AccessController;
Expand All @@ -18,7 +20,9 @@ public class MainController {
private MemberDTO currentUser = null; // 현재 로그인한 사용자 정보
private final MainUI view = new MainUI(); // 화면을 담당할 View 객체
private MqttManager mqttManager;
private ElevatorController evController;
private ElevatorController evController;
private final ParkingDAO parkingDAO = new ParkingDAOImpl();
private boolean devicesInitialized = false;


public MainController() {
Expand All @@ -27,25 +31,31 @@ public MainController() {
}

// 브로커 서버와 연결, subscribe topic 설정
public void settingDevice(){
Thread mqttThread = new Thread(mqttManager);
mqttThread.start();
System.out.println("🚀 Main thread started MQTT connection thread.");

// 메인 스레드가 바로 종료되는 것을 방지하기 위해 잠시 대기
try {
// 스레드가 연결될 시간을 잠시 줍니다.
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 2. ✅ 각 전문 컨트롤러들을 생성하여 필요한 MqttManager를 주입 (의존성 주입)
evController = new ElevatorController(currentUser, mqttManager);
// DHtController dhtController = new DhtController(mqttManager); // 예시
// LedController ledController = new LedController(mqttManager); // 예시

System.out.println("✅ All device controllers have been initialized and listeners are set.");
}
public void settingDevice(){
if (!devicesInitialized) {
Thread mqttThread = new Thread(mqttManager);
mqttThread.start();
System.out.println("🚀 Main thread started MQTT connection thread.");

// 메인 스레드가 바로 종료되는 것을 방지하기 위해 잠시 대기
try {
// 스레드가 연결될 시간을 잠시 줍니다.
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
ParkingHandler parkingHandler = new ParkingHandler(parkingDAO);
String parkingTopic = "parking/car/#";
this.mqttManager.addListener(parkingTopic, parkingHandler);

System.out.println("✅ All device controllers have been initialized and listeners are set.");
devicesInitialized = true;
}
// 2. ✅ 각 전문 컨트롤러들을 생성하여 필요한 MqttManager를 주입 (의존성 주입)
evController = new ElevatorController(currentUser, mqttManager);
// DHtController dhtController = new DhtController(mqttManager); // 예시
// LedController ledController = new LedController(mqttManager); // 예시
}

public void run() {
while (true) {
Expand Down Expand Up @@ -168,4 +178,4 @@ private void exitProgram() {
// TODO Auto-generated method stub

}
}
}
1 change: 1 addition & 0 deletions src/main/java/dao/ParkingDAO.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ public interface ParkingDAO {
public ParkingLogDTO getCurrentParkingStatus(int userId);
public List<ParkingLogDTO> getParkingLogsByUser(int userId);
public List<ParkingSpaceDTO> getAllSpaces();
void processVehicleLog(String carNo, String action);
}
134 changes: 119 additions & 15 deletions src/main/java/dao/ParkingDAOImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import util.DBUtil;
import dto.ParkingLogDTO;
import dto.ParkingSpaceDTO;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.List;

import util.DBUtil;
import dto.ParkingLogDTO;
import dto.ParkingSpaceDTO;

public class ParkingDAOImpl implements ParkingDAO {

Expand Down Expand Up @@ -58,12 +60,114 @@ public List<ParkingLogDTO> getParkingLogsByUser(int userId) {

return null;
}

@Override
public List<ParkingSpaceDTO> getAllSpaces() {

return null;
}


}
@Override
public List<ParkingSpaceDTO> getAllSpaces() {

return null;
}

@Override
public void processVehicleLog(String carNo, String action) {
if (carNo == null || carNo.trim().isEmpty()) {
System.out.println("🚗 차량 번호가 비어 있어 로그를 처리할 수 없습니다.");
return;
}

String normalizedAction = (action == null || action.trim().isEmpty()) ? "IN" : action.trim().toUpperCase();
try (Connection con = DBUtil.getConnect()) {

Integer userId = null;
String findUserSql = "SELECT user_id FROM users WHERE vehicle_no = ?";
try (PreparedStatement findUser = con.prepareStatement(findUserSql)) {
findUser.setString(1, carNo);
try (ResultSet userRs = findUser.executeQuery()) {
if (userRs.next()) {
userId = userRs.getInt("user_id");
}
}
}

if (userId == null) {
System.out.printf("🚫 차량 번호 %s 에 해당하는 등록 정보가 없습니다.%n", carNo);
return;
}

switch (normalizedAction) {
case "IN":
logVehicleEntry(con, userId, carNo);
break;
case "OUT":
logVehicleExit(con, userId, carNo);
break;
default:
System.out.printf("⚠️ 지원하지 않는 차량 액션: %s%n", normalizedAction);
return;
}
} catch (SQLException e) {
e.printStackTrace();
}
}

private void 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())
""";
try (PreparedStatement insert = con.prepareStatement(insertSql)) {
insert.setInt(1, userId);
insert.setNull(2, Types.INTEGER);
insert.setString(3, buildNote("입차", carNo));
insert.executeUpdate();
}
}

private void logVehicleExit(Connection con, int userId, String carNo) throws SQLException {
String findOpenSql = """
SELECT parking_id, in_time
FROM parking_log
WHERE user_id = ? AND out_time IS NULL
ORDER BY in_time DESC
LIMIT 1
""";
try (PreparedStatement findOpen = con.prepareStatement(findOpenSql)) {
findOpen.setInt(1, userId);
try (ResultSet openRs = findOpen.executeQuery()) {
if (openRs.next()) {
int parkingId = openRs.getInt("parking_id");
Timestamp inTime = openRs.getTimestamp("in_time");
Timestamp now = new Timestamp(System.currentTimeMillis());
long diff = now.getTime() - (inTime != null ? inTime.getTime() : now.getTime());
int duration = diff > 0 ? (int) (diff / 60000) : 0;

String updateSql = """
UPDATE parking_log
SET out_time = ?, duration_min = ?, action = 'OUT', note = ?
WHERE parking_id = ?
""";
try (PreparedStatement update = con.prepareStatement(updateSql)) {
update.setTimestamp(1, now);
update.setInt(2, duration);
update.setString(3, buildNote("출차", carNo));
update.setInt(4, parkingId);
update.executeUpdate();
}
} else {
String insertOutSql = """
INSERT INTO parking_log (user_id, space_id, action, note, out_time)
VALUES (?, ?, 'OUT', ?, NOW())
""";
try (PreparedStatement insert = con.prepareStatement(insertOutSql)) {
insert.setInt(1, userId);
insert.setNull(2, Types.INTEGER);
insert.setString(3, buildNote("출차", carNo));
insert.executeUpdate();
}
}
}
}
}

private String buildNote(String prefix, String carNo) {
return String.format("%s: %s", prefix, carNo);
}
}
23 changes: 23 additions & 0 deletions src/main/java/dto/mqttMsg/MqttParkingDTO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package dto.mqttMsg;

public class MqttParkingDTO {
private String carNo;
private String action;

public String getCarNo() {
return carNo;
}

public void setCarNo(String carNo) {
this.carNo = carNo;
}

public String getAction() {
return action;
}

public void setAction(String action) {
this.action = action;
}
}

33 changes: 33 additions & 0 deletions src/main/java/mqtt/devices/ParkingHandler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package mqtt.devices;

import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import dao.ParkingDAO;
import dto.mqttMsg.MqttParkingDTO;
import mqtt.OnMessageCallback;

public class ParkingHandler implements OnMessageCallback {

private final ParkingDAO parkingDAO;
private final Gson gson = new Gson();

public ParkingHandler(ParkingDAO parkingDAO) {
this.parkingDAO = parkingDAO;
}

@Override
public void handle(String topic, String payload) {
try {
MqttParkingDTO dto = gson.fromJson(payload, MqttParkingDTO.class);
if (dto == null || dto.getCarNo() == null) {
System.out.printf("⚠️ 파싱된 차량 데이터가 없어 무시합니다. topic=%s payload=%s%n", topic, payload);
return;
}

parkingDAO.processVehicleLog(dto.getCarNo(), dto.getAction());
} catch (JsonSyntaxException ex) {
System.out.printf("⚠️ 차량 로그 JSON 파싱 실패: %s%n", ex.getMessage());
}
}
}