From 832589efec3cf71411ff8921de4320f440c222bc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 30 Mar 2026 12:08:29 +0000 Subject: [PATCH] Add AI home cam WATCHING/NOTWATCHING state API with JWT auth Agent-Logs-Url: https://github.com/jowh324/BBS/sessions/59e68de0-17d8-4cfe-8174-587105722157 Co-authored-by: hgjwilly-koreatech <183201303+hgjwilly-koreatech@users.noreply.github.com> --- .../com/example/api/DTO/CamStateDTOs.java | 19 +++++++++ .../java/com/example/api/Entity/CamState.java | 23 +++++++++++ .../com/example/api/Entity/CamStateType.java | 5 +++ .../api/Repository/CamStateRepository.java | 7 ++++ .../example/api/Service/CamStateService.java | 41 +++++++++++++++++++ .../api/controller/CamStateController.java | 29 +++++++++++++ 6 files changed, 124 insertions(+) create mode 100644 src/main/java/com/example/api/DTO/CamStateDTOs.java create mode 100644 src/main/java/com/example/api/Entity/CamState.java create mode 100644 src/main/java/com/example/api/Entity/CamStateType.java create mode 100644 src/main/java/com/example/api/Repository/CamStateRepository.java create mode 100644 src/main/java/com/example/api/Service/CamStateService.java create mode 100644 src/main/java/com/example/api/controller/CamStateController.java diff --git a/src/main/java/com/example/api/DTO/CamStateDTOs.java b/src/main/java/com/example/api/DTO/CamStateDTOs.java new file mode 100644 index 0000000..9e1643e --- /dev/null +++ b/src/main/java/com/example/api/DTO/CamStateDTOs.java @@ -0,0 +1,19 @@ +package com.example.api.DTO; + +import com.example.api.Entity.CamStateType; +import jakarta.validation.constraints.NotNull; + +import java.time.Instant; + +public class CamStateDTOs { + + public record UpdateRequest( + @NotNull + CamStateType state + ) {} + + public record StateResponse( + String state, + Instant updatedAt + ) {} +} diff --git a/src/main/java/com/example/api/Entity/CamState.java b/src/main/java/com/example/api/Entity/CamState.java new file mode 100644 index 0000000..e282bda --- /dev/null +++ b/src/main/java/com/example/api/Entity/CamState.java @@ -0,0 +1,23 @@ +package com.example.api.Entity; + +import jakarta.persistence.*; +import lombok.Getter; +import lombok.Setter; + +import java.time.Instant; + +@Entity +@Table(name = "cam_state") +@Getter @Setter +public class CamState { + + @Id + private Long id; // Always 1 — singleton record + + @Enumerated(EnumType.STRING) + @Column(nullable = false, length = 20) + private CamStateType state; // WATCHING, NOTWATCHING + + @Column(nullable = false) + private Instant updatedAt; +} diff --git a/src/main/java/com/example/api/Entity/CamStateType.java b/src/main/java/com/example/api/Entity/CamStateType.java new file mode 100644 index 0000000..0611c36 --- /dev/null +++ b/src/main/java/com/example/api/Entity/CamStateType.java @@ -0,0 +1,5 @@ +package com.example.api.Entity; + +public enum CamStateType { + WATCHING, NOTWATCHING +} diff --git a/src/main/java/com/example/api/Repository/CamStateRepository.java b/src/main/java/com/example/api/Repository/CamStateRepository.java new file mode 100644 index 0000000..e826b31 --- /dev/null +++ b/src/main/java/com/example/api/Repository/CamStateRepository.java @@ -0,0 +1,7 @@ +package com.example.api.Repository; + +import com.example.api.Entity.CamState; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface CamStateRepository extends JpaRepository { +} diff --git a/src/main/java/com/example/api/Service/CamStateService.java b/src/main/java/com/example/api/Service/CamStateService.java new file mode 100644 index 0000000..53537ba --- /dev/null +++ b/src/main/java/com/example/api/Service/CamStateService.java @@ -0,0 +1,41 @@ +package com.example.api.Service; + +import com.example.api.DTO.CamStateDTOs; +import com.example.api.Entity.CamState; +import com.example.api.Entity.CamStateType; +import com.example.api.Repository.CamStateRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.Instant; + +@Service +@RequiredArgsConstructor +public class CamStateService { + + private static final long SINGLETON_ID = 1L; + + private final CamStateRepository camStateRepository; + + @Transactional(readOnly = true) + public CamStateDTOs.StateResponse getState() { + return camStateRepository.findById(SINGLETON_ID) + .map(s -> new CamStateDTOs.StateResponse(s.getState().name(), s.getUpdatedAt())) + .orElse(new CamStateDTOs.StateResponse(CamStateType.NOTWATCHING.name(), null)); + } + + @Transactional + public CamStateDTOs.StateResponse updateState(CamStateType state) { + CamState camState = camStateRepository.findById(SINGLETON_ID) + .orElseGet(() -> { + CamState s = new CamState(); + s.setId(SINGLETON_ID); + return s; + }); + camState.setState(state); + camState.setUpdatedAt(Instant.now()); + camStateRepository.save(camState); + return new CamStateDTOs.StateResponse(camState.getState().name(), camState.getUpdatedAt()); + } +} diff --git a/src/main/java/com/example/api/controller/CamStateController.java b/src/main/java/com/example/api/controller/CamStateController.java new file mode 100644 index 0000000..1a8f72c --- /dev/null +++ b/src/main/java/com/example/api/controller/CamStateController.java @@ -0,0 +1,29 @@ +package com.example.api.controller; + +import com.example.api.DTO.CamStateDTOs; +import com.example.api.Service.CamStateService; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/cam") +public class CamStateController { + + private final CamStateService camStateService; + + // 현재 관찰 상태 조회 + @GetMapping("/state") + public ResponseEntity getState() { + return ResponseEntity.ok(camStateService.getState()); + } + + // 관찰 상태 갱신 + @PutMapping("/state") + public ResponseEntity updateState( + @Valid @RequestBody CamStateDTOs.UpdateRequest req) { + return ResponseEntity.ok(camStateService.updateState(req.state())); + } +}