Skip to content

Commit f758302

Browse files
authored
Merge pull request #40 from Fac2Real/feature/FRB-156
Feature/frb 156
2 parents fece682 + 90c08ba commit f758302

17 files changed

Lines changed: 612 additions & 2 deletions
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package com.factoreal.backend.controller;
2+
3+
import com.factoreal.backend.dto.abnormalLog.AbnormalPagingDto;
4+
import com.factoreal.backend.dto.abnormalLog.SystemLogResponseDto;
5+
import com.factoreal.backend.service.AbnormalLogService;
6+
import io.swagger.v3.oas.annotations.Operation;
7+
import io.swagger.v3.oas.annotations.Parameter;
8+
import io.swagger.v3.oas.annotations.tags.Tag;
9+
import lombok.RequiredArgsConstructor;
10+
import org.springframework.data.domain.Page;
11+
import org.springframework.http.ResponseEntity;
12+
import org.springframework.web.bind.annotation.*;
13+
14+
@Tag(name = "시스템 로그 API", description = "공간별 시스템 로그 조회 API")
15+
@RestController
16+
@RequestMapping("/api/system-logs")
17+
@RequiredArgsConstructor
18+
public class SystemLogController {
19+
private final AbnormalLogService abnormalLogService;
20+
21+
@Operation(summary = "공간별 시스템 로그 조회", description = "특정 공간(zone)의 시스템 로그를 페이징 처리하여 조회합니다.")
22+
@GetMapping("/zone/{zoneId}")
23+
public ResponseEntity<Page<SystemLogResponseDto>> getSystemLogsByZone(
24+
@Parameter(description = "조회할 공간 ID", required = true)
25+
@PathVariable String zoneId,
26+
@Parameter(description = "페이징 정보 (page: 페이지 번호, size: 페이지 크기)")
27+
@ModelAttribute AbnormalPagingDto pagingDto) {
28+
Page<SystemLogResponseDto> logs = abnormalLogService.findSystemLogsByZoneId(zoneId, pagingDto);
29+
return ResponseEntity.ok(logs);
30+
}
31+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package com.factoreal.backend.controller;
2+
3+
import com.factoreal.backend.dto.WorkerDto;
4+
import com.factoreal.backend.dto.ZoneManagerResponseDto;
5+
import com.factoreal.backend.service.WorkerService;
6+
7+
import io.swagger.v3.oas.annotations.Operation;
8+
import io.swagger.v3.oas.annotations.tags.Tag;
9+
import lombok.RequiredArgsConstructor;
10+
import lombok.extern.slf4j.Slf4j;
11+
import org.springframework.http.ResponseEntity;
12+
import org.springframework.web.bind.annotation.*;
13+
14+
import java.util.List;
15+
16+
@RestController
17+
@RequestMapping("/api/workers")
18+
@RequiredArgsConstructor
19+
@Slf4j
20+
@Tag(name = "작업자 API", description = "작업자 조회 API")
21+
public class WorkerController {
22+
private final WorkerService workerService;
23+
24+
@Operation(summary = "전체 작업자 목록 조회", description = "전체 작업자 목록을 조회합니다.")
25+
@GetMapping
26+
public ResponseEntity<List<WorkerDto>> getAllWorkers() {
27+
log.info("전체 작업자 목록 조회 요청");
28+
List<WorkerDto> workers = workerService.getAllWorkers();
29+
return ResponseEntity.ok(workers);
30+
}
31+
32+
@Operation(summary = "공간별 작업자 목록 조회", description = "공간 ID를 기반으로 현재 해당 공간에 들어가있는 작업자 리스트를 조회합니다.")
33+
@GetMapping("/zone/{zoneId}")
34+
public ResponseEntity<List<WorkerDto>> getWorkersByZoneId(@PathVariable String zoneId) {
35+
log.info("공간 ID: {}의 작업자 목록 조회 요청", zoneId);
36+
List<WorkerDto> zoneWorkers = workerService.getWorkersByZoneId(zoneId);
37+
return ResponseEntity.ok(zoneWorkers);
38+
}
39+
40+
@Operation(summary = "공간 담당자 정보 조회",
41+
description = "공간 ID를 기반으로 해당 공간의 담당자와 현재 위치 정보를 조회합니다.")
42+
@GetMapping("/zone/{zoneId}/manager")
43+
public ResponseEntity<ZoneManagerResponseDto> getZoneManager(@PathVariable String zoneId) {
44+
log.info("공간 ID: {}의 담당자 정보 조회 요청", zoneId);
45+
ZoneManagerResponseDto manager = workerService.getZoneManagerWithLocation(zoneId);
46+
return ResponseEntity.ok(manager);
47+
}
48+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package com.factoreal.backend.controller;
2+
3+
import com.factoreal.backend.dto.WorkerLocationRequest;
4+
import com.factoreal.backend.service.WorkerLocationService;
5+
import io.swagger.v3.oas.annotations.Operation;
6+
import io.swagger.v3.oas.annotations.tags.Tag;
7+
import lombok.RequiredArgsConstructor;
8+
import lombok.extern.slf4j.Slf4j;
9+
10+
import java.time.LocalDateTime;
11+
12+
import org.springframework.http.ResponseEntity;
13+
import org.springframework.web.bind.annotation.*;
14+
15+
@Slf4j
16+
@Tag(name = "작업자 위치 API", description = "작업자의 실시간 위치 정보를 관리하는 API")
17+
@RestController
18+
@RequestMapping("/api/worker-locations")
19+
@RequiredArgsConstructor
20+
// 웨어러블 디바이스에서 받아오는 데이터를 업데이트하는 컨트롤러
21+
public class WorkerLocationController {
22+
23+
private final WorkerLocationService workerLocationService;
24+
25+
@Operation(summary = "작업자 위치 업데이트", description = "웨어러블 디바이스로부터 받은 작업자의 위치 정보를 업데이트합니다.")
26+
@PostMapping("/update")
27+
public ResponseEntity<Void> updateWorkerLocation(@RequestBody WorkerLocationRequest request) {
28+
log.info("작업자 위치 업데이트 요청: {}", request);
29+
workerLocationService.updateWorkerLocation(
30+
request.getWorkerId(),
31+
request.getZoneId(),
32+
request.getTimestamp() != null ? request.getTimestamp() : LocalDateTime.now()
33+
);
34+
return ResponseEntity.ok().build(); // 200 OK 응답
35+
}
36+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package com.factoreal.backend.dto;
2+
3+
import com.factoreal.backend.entity.Worker;
4+
import lombok.AllArgsConstructor;
5+
import lombok.Builder;
6+
import lombok.Getter;
7+
import lombok.NoArgsConstructor;
8+
9+
@Getter
10+
@AllArgsConstructor
11+
@NoArgsConstructor
12+
@Builder
13+
public class WorkerDto {
14+
private String workerId;
15+
private String name;
16+
private String phoneNumber;
17+
private String email;
18+
private Boolean isManager; // 관리자 여부
19+
20+
// Entity -> DTO 변환
21+
public static WorkerDto fromEntity(Worker worker, Boolean isManager) {
22+
return WorkerDto.builder()
23+
.workerId(worker.getWorkerId())
24+
.name(worker.getName())
25+
.phoneNumber(worker.getPhoneNumber())
26+
.email(worker.getEmail())
27+
.isManager(isManager)
28+
.build();
29+
}
30+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.factoreal.backend.dto;
2+
3+
import lombok.Getter;
4+
import lombok.Setter;
5+
import lombok.ToString;
6+
7+
import java.time.LocalDateTime;
8+
9+
@Getter
10+
@Setter
11+
@ToString
12+
// Wearable 장치에서 받아오는 데이터 by 우영. 추후 논의 예정
13+
public class WorkerLocationRequest {
14+
private String workerId;
15+
private String zoneId;
16+
private LocalDateTime timestamp; // 장치에서 받아오는 데이터
17+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package com.factoreal.backend.dto;
2+
3+
import com.factoreal.backend.entity.Worker;
4+
import com.factoreal.backend.entity.Zone;
5+
import lombok.AllArgsConstructor;
6+
import lombok.Builder;
7+
import lombok.Getter;
8+
import lombok.NoArgsConstructor;
9+
10+
@Getter
11+
@Builder
12+
@NoArgsConstructor
13+
@AllArgsConstructor
14+
// 공간 담당자 정보 조회 시 사용되는 DTO (BE -> FE)
15+
public class ZoneManagerResponseDto {
16+
private String workerId; // 작업자 ID
17+
private String name; // 작업자 이름
18+
private String phoneNumber; // 연락처
19+
private String email; // 이메일
20+
private String currentZoneId; // 현재 위치한 공간 ID
21+
private String currentZoneName; // 현재 위치한 공간 이름
22+
23+
public static ZoneManagerResponseDto fromEntity(Worker worker, Zone currentZone) {
24+
return ZoneManagerResponseDto.builder()
25+
.workerId(worker.getWorkerId())
26+
.name(worker.getName())
27+
.phoneNumber(worker.getPhoneNumber())
28+
.email(worker.getEmail())
29+
.currentZoneId(currentZone != null ? currentZone.getZoneId() : null)
30+
.currentZoneName(currentZone != null ? currentZone.getZoneName() : null)
31+
.build();
32+
}
33+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
package com.factoreal.backend.dto.abnormalLog;
22

3+
import io.swagger.v3.oas.annotations.media.Schema;
34
import lombok.Data;
45

56
@Data
7+
@Schema(description = "페이징 정보 DTO")
68
public class AbnormalPagingDto {
9+
@Schema(description = "페이지 번호 (0부터 시작)", example = "0")
710
private int page;
11+
12+
@Schema(description = "페이지 크기", example = "10")
813
private int size;
914
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package com.factoreal.backend.dto.abnormalLog;
2+
3+
import com.factoreal.backend.entity.AbnormalLog;
4+
import lombok.AllArgsConstructor;
5+
import lombok.Builder;
6+
import lombok.Data;
7+
import lombok.NoArgsConstructor;
8+
9+
import java.time.LocalDateTime;
10+
11+
@Data
12+
@Builder
13+
@NoArgsConstructor
14+
@AllArgsConstructor
15+
public class SystemLogResponseDto {
16+
private String zoneId;
17+
private String targetType;
18+
private String sensorType;
19+
private int dangerLevel;
20+
private double value;
21+
private LocalDateTime timestamp;
22+
private String abnormalType;
23+
private String targetId;
24+
25+
public static SystemLogResponseDto fromEntity(AbnormalLog abnormalLog) {
26+
return SystemLogResponseDto.builder()
27+
.zoneId(abnormalLog.getZone().getZoneId())
28+
.targetType(convertLogTypeToKorean(abnormalLog.getTargetType()))
29+
.sensorType(abnormalLog.getTargetType().toString())
30+
.dangerLevel(calculateDangerLevel(abnormalLog.getAbnormalType()))
31+
.value(abnormalLog.getAbnVal())
32+
.timestamp(abnormalLog.getDetectedAt())
33+
.abnormalType(abnormalLog.getAbnormalType())
34+
.targetId(abnormalLog.getTargetId())
35+
.build();
36+
}
37+
38+
private static String convertLogTypeToKorean(LogType logType) {
39+
return switch (logType) {
40+
case Sensor -> "환경";
41+
case Worker -> "작업자";
42+
case Equip -> "설비";
43+
};
44+
}
45+
46+
private static int calculateDangerLevel(String abnormalType) {
47+
if (abnormalType.contains("위험")) return 2;
48+
if (abnormalType.contains("주의")) return 1;
49+
return 0;
50+
}
51+
}
52+
53+
/**
54+
* {
55+
"content": [
56+
{
57+
"zoneId": "zone123",
58+
"targetType": "환경", // 또는 "작업자", "설비"
59+
"sensorType": "TEMPERATURE",
60+
"dangerLevel": 2,
61+
"value": 35.5,
62+
"timestamp": "2024-03-20T14:30:00",
63+
"abnormalType": "온도 위험",
64+
"targetId": "sensor456"
65+
}
66+
// ... 더 많은 로그
67+
],
68+
"pageable": {
69+
"pageNumber": 0,
70+
"pageSize": 10
71+
},
72+
"totalElements": 50,
73+
"totalPages": 5
74+
}
75+
*/

src/main/java/com/factoreal/backend/entity/AbnormalLog.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ public class AbnormalLog {
3030
private String targetId; // 고유 ID : 센서ID, WorkerID, EquipID
3131

3232
@Column(name = "abnormal_type", length = 100)
33-
private String abnormalType; // 이상 유형 : (예: 심박수 이상, 온도 초과, 진동 이상 등)
33+
private String abnormalType; // 이상 유형 : (예: 심박수 위험, 온도 초과 위험, 진동 주의 등)
34+
// 이상은 위험과 주의로 구분이 애매하므로 명확한 표현 필요
3435

3536
@Column(name = "abn_val")
3637
private Double abnVal; // 이상치 값

src/main/java/com/factoreal/backend/kafka/KafkaConsumerD.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ public void consume(String message) {
7171
SensorKafkaDto dto = objectMapper.readValue(message, SensorKafkaDto.class);
7272

7373
// 시스템 로그 (위험도 변화 감지 -> 비동기 전송)
74-
sendSystemLog(dto);
74+
// sendSystemLog(dto);
7575

7676
// 공간 센서일 때만 히트맵용 웹소켓 전송
7777
if (dto.getEquipId() != null && dto.getZoneId() != null && dto.getEquipId().equals(dto.getZoneId())) {
@@ -164,6 +164,7 @@ public void startAlarm(SensorKafkaDto sensorData, AbnormalLog abnormalLog, RiskL
164164

165165
// 공간(zone)별 위험도 변경 시 시스템 로그 전송
166166
@Async
167+
@Deprecated
167168
public void sendSystemLog(SensorKafkaDto dto) {
168169
String zoneId = dto.getZoneId();
169170
int newLevel = getDangerLevel(dto.getSensorType(), dto.getVal());

0 commit comments

Comments
 (0)