Compare commits

...

10 Commits

12 changed files with 214 additions and 102 deletions

119
README.md
View File

@ -1,29 +1,104 @@
# README # # AXR X-Ray Tube 제어/조회 서비스 #
This README would normally document whatever steps are necessary to get your application up and running. ## 기능 ##
* Tube on/off 제어
* Tube 전류, 전압 offset 설정
* 전체 챔버 통계 조회
* 챔버 개별 튜브별 통계 조회
### What is this repository for? ### ## 기술 ##
* Spring Boot 3.1.3
* Spring web
* Spring AMQP
* Spring Data MongoDB
* Gradle
* Quick summary ## 배포 ##
* Version ## build ##
* [Learn Markdown](https://bitbucket.org/tutorials/markdowndemo) ```
$ ./gradlew clean build -x test
```
### How do I get set up? ### ## dockerize ##
```
$ docker build --platform linux/amd64 -t control-center-management .
```
* Summary of set up ## K8s Envs ##
* Configuration ### Office Desktop ###
* Dependencies ```
* Database configuration apiVersion: apps/v1
* How to run tests kind: Deployment
* Deployment instructions metadata:
name: control-center-management
namespace: sdt-cloud
labels:
name: control-center-management
spec:
selector:
matchLabels:
name: control-center-management
replicas: 1
template:
metadata:
labels:
name: control-center-management
spec:
imagePullSecrets:
- name: regcred
containers:
- name: control-center-management
image: 003960268191.dkr.ecr.ap-northeast-2.amazonaws.com/sdt-cloud/control-center-management:0.0.3
imagePullPolicy: Always
ports:
- containerPort: 8087
env:
- name: SPRING_PROFILES_ACTIVE
value: "k8s"
- name: SERVER_PORT
value: "8087"
- name: MONGODB_URL
value: "mongodb://sdt:251327@mongo-db.database.svc.cluster.local/awexomeray?authSource=admin"
- name: DEPLOYER_ENDPOINT
value: "http://device-deployer.sdt-cloud.svc.cluster.local:8085"
- name: IAM_AMQP_HOST
value: "rabbitmq.sdt-cloud.svc.cluster.local"
- name: IAM_AMQP_PORT
value: "5672"
- name: IAM_AMQP_CREDENTIALS_USERNAME
value: "sdt"
- name: IAM_AMQP_CREDENTIALS_PASSWORD
value: "251327"
- name: DATA_FALL_ENDPOINT
value: "http://data-fall.sdt-cloud.svc.cluster.local:8083"
---
apiVersion: v1
kind: Service
metadata:
name: control-center-management
namespace: sdt-cloud
spec:
ports:
- port: 8087
targetPort: 8087
protocol: TCP
name: control-center-management
nodePort: 30870
type: NodePort
selector:
name: control-center-management
```
### Contribution guidelines ###
* Writing tests ## Container Option ##
* Code review | 옵션명 | 설명 | Sample |
* Other guidelines |:----------------------:|:--------------------------------:|:------------------------------------------------------------------------------------:|
| SPRING_PROFILES_ACTIVE | 스프링 부트 프로파일 | k8s |
### Who do I talk to? ### | SERVER_PORT | 서버 포트 | 8087 |
| MONGODB_URL | MongoDB URL | mongodb://sdt:251327@mongo-db.database.svc.cluster.local/awexomeray?authSource=admin |
* Repo owner or admin | DEPLOYER_ENDPOINT | device deployer service endpoint | http://device-deployer.sdt-cloud.svc.cluster.local:8085 |
* Other community or team contact | IAM_AMQP_HOST | RabbitMQ URL | rabbitmq.sdt-cloud.svc.cluster.local |
| IAM_AMQP_PORT | RabbitMQ port | 5672 |
| IAM_AMQP_CREDENTIALS_USERNAME | RabbitMQ 접속 username | sdt |
| IAM_AMQP_CREDENTIALS_PASSWORD | RabbitMQ 접속 password | 2xxxx7 |
| DATA_FALL_ENDPOINT | data fall service endpoint | http://data-fall.sdt-cloud.svc.cluster.local:8083 |

View File

@ -5,7 +5,7 @@ plugins {
} }
group = 'inc.sdt.controlcentermanagement' group = 'inc.sdt.controlcentermanagement'
version = '0.0.3' version = '0.0.6'
java { java {
sourceCompatibility = '17' sourceCompatibility = '17'

View File

@ -1,4 +1,4 @@
aws ecr get-login-password --region ap-northeast-2 | docker login --username AWS --password-stdin 003960268191.dkr.ecr.ap-northeast-2.amazonaws.com aws ecr get-login-password --region ap-northeast-2 | docker login --username AWS --password-stdin 003960268191.dkr.ecr.ap-northeast-2.amazonaws.com
docker build --platform linux/amd64 -t control-center-management ../../ docker build --platform linux/amd64 -t control-center-management ../../
docker tag control-center-management:latest 003960268191.dkr.ecr.ap-northeast-2.amazonaws.com/sdt-cloud/control-center-management:0.0.3 docker tag control-center-management:latest 003960268191.dkr.ecr.ap-northeast-2.amazonaws.com/sdt-cloud/control-center-management:0.0.6
docker push 003960268191.dkr.ecr.ap-northeast-2.amazonaws.com/sdt-cloud/control-center-management:0.0.3 docker push 003960268191.dkr.ecr.ap-northeast-2.amazonaws.com/sdt-cloud/control-center-management:0.0.6

View File

@ -1,21 +1,20 @@
## ON/OFF 제어 ## ON/OFF 제어
#PATCH http://13.209.39.139:30870/chamber/1/tube/toggle #PATCH http://13.209.39.139:30870/chamber/1/tube/toggle
PATCH http://13.209.39.139:32171/chamber/1/tube/toggle #PATCH http://13.209.39.139:32171/chambers/1/tube/toggle
#PATCH http://localhost:8087/chamber/1/tube/toggle PATCH http://localhost:8087/chambers/1/tube/toggle
Content-Type: application/json Content-Type: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJvcmdhbml6YXRpb25JZCI6ImQxZGJlYWExLWY5ZTUtNGE4OC1hMWM4LTYzMWQ4NTMyOWJmYyIsInJvbGVzIjpbIlJPTEVfQURNSU5JU1RSQVRPUiJdLCJpZCI6IjcyYTUxZDUwLTYwMDEtNDAwYy04NjNmLWZlOGU2OGE1MGExMCIsInN1YiI6InNhLmphbmdAc2R0LmluYyIsImlhdCI6MTY5NDEzNjg4OCwiZXhwIjoxNjk0MTQwNDg4fQ.likh7Ix7p4Yf2iwankLG71VGrgCDzQzhn9Z7QJK0blg Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJvcmdhbml6YXRpb25JZCI6ImQxZGJlYWExLWY5ZTUtNGE4OC1hMWM4LTYzMWQ4NTMyOWJmYyIsInJvbGVzIjpbIlJPTEVfQURNSU5JU1RSQVRPUiJdLCJpZCI6IjdjYTBjZWQ5LTk1YjEtNDgzMC05YmJhLWZmZTUwNWVmYzgzMiIsInN1YiI6InNkdC5kZXZAc2R0LmluYyIsImlhdCI6MTY5NDQ5NjE4MiwiZXhwIjoxNjk0NDk5NzgyfQ.n5kpWEiOLrZCSwlc-MWYzJtxbFPGZCOk-NBdhKnlrog
{"command": "ON"}
//{
// "command" : "OFF",
// "assetCode" : "NODEQ-TEST-1",
// "slotNumber" : "1-1",
// "tube": [
// {"code": "1"}, {"code": "3"}, {"code": "11"}, {"code": "16"}
// ]
//}
{
"command" : "ON",
"assetCode" : "NQ-R04-TEST-003",
"tube": [
{"slotNumber": "1", "code": "1"},
{"slotNumber": "1", "code": "3"},
{"slotNumber": "1", "code": "11"},
{"slotNumber": "4", "code": "15"}
]
}
### offset 제어 ### offset 제어
#PATCH http://localhost:8087/chambers/1/slots/1/tubes/1 #PATCH http://localhost:8087/chambers/1/slots/1/tubes/1
@ -27,3 +26,8 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJvcmdhbml6YXRpb25JZCI6ImQxZGJlYWExL
"voltageOffset" : 1.5, "voltageOffset" : 1.5,
"ampereOffset": 1.1 "ampereOffset": 1.1
} }
### 통계 디테일 조회
GET http://localhost:8087/chambers/stats/detail/1
Content-Type: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJvcmdhbml6YXRpb25JZCI6ImQxZGJlYWExLWY5ZTUtNGE4OC1hMWM4LTYzMWQ4NTMyOWJmYyIsInJvbGVzIjpbIlJPTEVfQURNSU5JU1RSQVRPUiJdLCJpZCI6IjdjYTBjZWQ5LTk1YjEtNDgzMC05YmJhLWZmZTUwNWVmYzgzMiIsInN1YiI6InNkdC5kZXZAc2R0LmluYyIsImlhdCI6MTY5NDQ5MjIyMSwiZXhwIjoxNjk0NDk1ODIxfQ.ZKa8-eKnJr0VDnGMmExAQnXFTfE4Y38OsI3nZ18S80E

View File

@ -8,7 +8,6 @@ import inc.sdt.controlcentermanagement.presentation.StatsCntRecord;
import inc.sdt.controlcentermanagement.presentation.StatsDetailRecord; import inc.sdt.controlcentermanagement.presentation.StatsDetailRecord;
import inc.sdt.controlcentermanagement.presentation.StatsRecord; import inc.sdt.controlcentermanagement.presentation.StatsRecord;
import inc.sdt.controlcentermanagement.presentation.support.CustomPage; import inc.sdt.controlcentermanagement.presentation.support.CustomPage;
import inc.sdt.controlcentermanagement.presentation.support.CustomPageable;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
@ -39,6 +38,7 @@ public class DefaultStatsService implements StatsService{
@Override @Override
public List<StatsRecord> getChamberStats() { public List<StatsRecord> getChamberStats() {
log.info("[getChamberStats]");
List<Slot> all= slotRepositoryDelegate.getAll(); List<Slot> all= slotRepositoryDelegate.getAll();
Map<String, List<Slot>> groupByChamber = all.stream().collect(Collectors.groupingBy(Slot::getChamberNumber)); Map<String, List<Slot>> groupByChamber = all.stream().collect(Collectors.groupingBy(Slot::getChamberNumber));
@ -98,6 +98,7 @@ public class DefaultStatsService implements StatsService{
@Override @Override
public Page<StatsDetailRecord> getChamberStatsDetail(int page, int size, String chamberNumber) { public Page<StatsDetailRecord> getChamberStatsDetail(int page, int size, String chamberNumber) {
log.info("[getChamberStatsDetail] chamberNumber: {}", chamberNumber);
List<Slot> all= slotRepositoryDelegate.getAll().stream().filter(slot -> slot.getChamberNumber().equals(chamberNumber)).toList(); List<Slot> all= slotRepositoryDelegate.getAll().stream().filter(slot -> slot.getChamberNumber().equals(chamberNumber)).toList();
Pageable pageable = PageRequest.of(page, size); Pageable pageable = PageRequest.of(page, size);
@ -134,9 +135,13 @@ public class DefaultStatsService implements StatsService{
} }
}); });
} }
} else {
throw new NoSuchElementException();
} }
for(int i=0 ; i < 16 ; i++){ for(int i=0 ; i < 16 ; i++){
StatsDetailRecord statsDetailRecord = new StatsDetailRecord( StatsDetailRecord statsDetailRecord = new StatsDetailRecord(
slot.getAssetCode(),
slot.getSlotNumber(), slot.getSlotNumber(),
String.valueOf(i), String.valueOf(i),
"status", "status",

View File

@ -9,10 +9,7 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.web.util.UriComponentsBuilder; import org.springframework.web.util.UriComponentsBuilder;
import java.util.HashMap; import java.util.*;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/** /**
* @author sunae.jang (sa.jang@sdt.inc) * @author sunae.jang (sa.jang@sdt.inc)
@ -44,59 +41,51 @@ class DefaultTubeService implements TubeService {
} }
@Override @Override
public void controlByTubeCode(String authorization, Slot request) { public void controlByTubeCode(String authorization, Slot slot) {
log.info("[controlByTubeCode] request: {}", request); log.info("[controlByTubeCode] slot: {}", slot);
Map<String, String> tubeMap = new LinkedHashMap<>(); Map<String, Integer> tubeMap = new LinkedHashMap<>();
for (Tube tube : request.getTube()) { Slot request = this.get(slot.getChamberNumber(), slot.getTube().get(0).getSlotNumber()); // TODO: 현재 단건 컨트롤, 추후 변경 필요
for (Tube tube : slot.getTube()) {
Map<String, Integer> tubeOffsetMap = this.tubeOffset(); Map<String, Integer> tubeOffsetMap = this.tubeOffset();
int tubeOffset = tubeOffsetMap.getOrDefault(request.getSlotNumber(), 1); int tubeOffset = tubeOffsetMap.getOrDefault(request.getSlotNumber(), 1);
int tubeKey = Integer.parseInt(tube.getCode()) + tubeOffset; int tubeKey = Integer.parseInt(request.getTube().get(Integer.parseInt(tube.getCode())).getCode()) + tubeOffset;
tubeMap.put(String.valueOf(tubeKey), String.valueOf(request.getCommand().ordinal())); tubeMap.put(String.valueOf(tubeKey), slot.getCommand().ordinal());
} }
DeployRequest deployRequest = DeployRequest.builder() DeployRequest deployRequest = DeployRequest.builder()
.assetCode(request.getAssetCode()) .assetCode(slot.getAssetCode())
.appName(request.getSlotNumber()) .appName("awx_collector") // TODO: appName 픽스되면 수정 필요
.commandType(CommandType.JSON) .commandType(CommandType.JSON)
.name("") // TODO .fileName("config.json")
.parameters(tubeMap) .parameters(tubeMap)
.build(); .build();
this.invokeDeployer(request.getAssetCode(), authorization, deployRequest); log.info("deployRequest: {}", deployRequest);
this.invokeDeployer(slot.getAssetCode(), authorization, deployRequest);
} }
@Override @Override
public void controlAll(String authorization, List<Slot> slots, Command command) { public void controlAll(String authorization, List<Slot> slots, Command command) {
log.info("[controlAll] chamberNumber: {}, command: {}", slots.get(0).getChamberNumber(), command); log.info("[controlAll] chamberNumber: {}, command: {}", slots.get(0).getChamberNumber(), command);
Set<String> assets = new HashSet<>();
Map<String, Map<String, Map<String, String>>> resultMap = new LinkedHashMap<>();
for (Slot slot : slots) { for (Slot slot : slots) {
String assetCode = slot.getAssetCode(); assets.add(slot.getAssetCode());
String slotNumber = slot.getSlotNumber();
List<Tube> tubes = slot.getTube();
Map<String, Map<String, String>> assetMap = resultMap.computeIfAbsent(assetCode, k -> new HashMap<>());
Map<String, String> slotMap = assetMap.computeIfAbsent(slotNumber, k -> new HashMap<>());
for (Tube tube : tubes) {
Map<String, Integer> tubeOffsetMap = this.tubeOffset();
int tubeOffset = tubeOffsetMap.getOrDefault(slotNumber, 1);
int offsetResult = Integer.parseInt(tube.getCode()) + tubeOffset;
slotMap.put(String.valueOf(offsetResult), String.valueOf(command.ordinal()));
}
} }
assets.forEach(assetCode -> {
resultMap.forEach((assetCode, slot) -> slot.forEach((slotNumber, tube) -> { Map<String, Integer> parameterMap = new LinkedHashMap<>();
DeployRequest deployRequest = DeployRequest.builder() parameterMap.put("total", command.ordinal());
.assetCode(assetCode) for (int i = 1; i <= 2; i++) {
.appName(slotNumber) DeployRequest deployRequest = DeployRequest.builder()
.commandType(CommandType.JSON) .assetCode(assetCode)
.name("") // TODO .appName("awx_collector") // TODO
.parameters(tube) .commandType(CommandType.JSON)
.build(); .fileName("config.json")
.parameters(parameterMap)
this.invokeDeployer(assetCode, authorization, deployRequest); .build();
})); log.info("deployRequest: {}", deployRequest);
this.invokeDeployer(assetCode, authorization, deployRequest);
}
});
} }
@Override @Override

View File

@ -9,13 +9,15 @@ public class DeployRequest {
private String assetCode; private String assetCode;
private String appName; private String appName;
private String commandType; private String commandType;
private String fileName;
private String name; private String name;
private Map<String, String> parameters; private Map<String, Integer> parameters;
public DeployRequest(String assetCode, String appName, String commandType, String name, Map<String, String> parameters) { public DeployRequest(String assetCode, String appName, String commandType, String fileName, String name, Map<String, Integer> parameters) {
this.assetCode = assetCode; this.assetCode = assetCode;
this.appName = appName; this.appName = appName;
this.commandType = commandType; this.commandType = commandType;
this.fileName = fileName;
this.name = name; this.name = name;
this.parameters = parameters; this.parameters = parameters;
} }
@ -37,11 +39,15 @@ public class DeployRequest {
return commandType; return commandType;
} }
public String getFileName() {
return fileName;
}
public String getName() { public String getName() {
return name; return name;
} }
public Map<String, String> getParameters() { public Map<String, Integer> getParameters() {
return parameters; return parameters;
} }
@ -51,6 +57,7 @@ public class DeployRequest {
"assetCode='" + assetCode + '\'' + "assetCode='" + assetCode + '\'' +
", appName='" + appName + '\'' + ", appName='" + appName + '\'' +
", commandType='" + commandType + '\'' + ", commandType='" + commandType + '\'' +
", fileName='" + fileName + '\'' +
", name='" + name + '\'' + ", name='" + name + '\'' +
", parameters=" + parameters + ", parameters=" + parameters +
'}'; '}';
@ -61,7 +68,8 @@ public class DeployRequest {
private String appName; private String appName;
private String commandType; private String commandType;
private String name; private String name;
private Map<String, String> parameters; private String fileName;
private Map<String, Integer> parameters;
private Builder() { private Builder() {
} }
@ -86,13 +94,18 @@ public class DeployRequest {
return this; return this;
} }
public Builder parameters(Map<String, String> parameters) { public Builder fileName(String fileName) {
this.fileName = fileName;
return this;
}
public Builder parameters(Map<String, Integer> parameters) {
this.parameters = parameters; this.parameters = parameters;
return this; return this;
} }
public DeployRequest build() { public DeployRequest build() {
return new DeployRequest(assetCode, appName, commandType, name, parameters); return new DeployRequest(assetCode, appName, commandType, name, fileName, parameters);
} }
} }
} }

View File

@ -4,18 +4,30 @@ package inc.sdt.controlcentermanagement.domain;
* @author sunae.jang (sa.jang@sdt.inc) * @author sunae.jang (sa.jang@sdt.inc)
*/ */
public class Tube { public class Tube {
private String slotNumber;
private String code; private String code;
private Float voltageOffset; private Float voltageOffset;
private Float ampereOffset; private Float ampereOffset;
protected Tube() { protected Tube() {
} }
public Tube(String slotNumber, String code, Float voltageOffset, Float ampereOffset) {
this.slotNumber = slotNumber;
this.code = code;
this.voltageOffset = voltageOffset;
this.ampereOffset = ampereOffset;
}
public Tube(String code, Float voltageOffset, Float ampereOffset) { public Tube(String code, Float voltageOffset, Float ampereOffset) {
this.code = code; this.code = code;
this.voltageOffset = voltageOffset; this.voltageOffset = voltageOffset;
this.ampereOffset = ampereOffset; this.ampereOffset = ampereOffset;
} }
public String getSlotNumber() {
return slotNumber;
}
public String getCode() { public String getCode() {
return code; return code;
} }
@ -31,7 +43,8 @@ public class Tube {
@Override @Override
public String toString() { public String toString() {
return "Tube{" + return "Tube{" +
"code='" + code + '\'' + "slotNumber='" + slotNumber + '\'' +
", code='" + code + '\'' +
", voltageOffset=" + voltageOffset + ", voltageOffset=" + voltageOffset +
", ampereOffset=" + ampereOffset + ", ampereOffset=" + ampereOffset +
'}'; '}';
@ -42,6 +55,7 @@ public class Tube {
} }
public static final class Builder { public static final class Builder {
private String slotNumber;
private String code; private String code;
private Float voltageOffset; private Float voltageOffset;
private Float ampereOffset; private Float ampereOffset;
@ -49,6 +63,11 @@ public class Tube {
private Builder() { private Builder() {
} }
public Builder slotNumber(String slotNumber) {
this.slotNumber = slotNumber;
return this;
}
public Builder code(String code) { public Builder code(String code) {
this.code = code; this.code = code;
return this; return this;
@ -65,7 +84,7 @@ public class Tube {
} }
public Tube build() { public Tube build() {
return new Tube(code, voltageOffset, ampereOffset); return new Tube(slotNumber, code, voltageOffset, ampereOffset);
} }
} }
} }

View File

@ -28,7 +28,7 @@ public class StatsController {
@ResponseStatus(HttpStatus.OK) @ResponseStatus(HttpStatus.OK)
@GetMapping("/chambers/stats") @GetMapping("/chambers/stats")
public StatsResult chambers( public StatsResult chambers(
// @RequestHeader("Authorization") String authorization @RequestHeader("Authorization") String authorization
){ ){
log.info("[chambers stats]"); log.info("[chambers stats]");
@ -37,11 +37,11 @@ public class StatsController {
return new StatsResult(chamberStats); return new StatsResult(chamberStats);
} }
@ResourceMapping(name = "Chambers_stats_detail", method = "GET", uri = "/chambers/stats/{chamberNumber}", description = "get chamber stats detail") @ResourceMapping(name = "Chambers_stats_detail", method = "GET", uri = "/chambers/stats/detail/{chamberNumber}", description = "get chamber stats detail")
@ResponseStatus(HttpStatus.OK) @ResponseStatus(HttpStatus.OK)
@GetMapping("/chambers/stats/{chamberNumber}") @GetMapping("/chambers/stats/detail/{chamberNumber}")
public PageableResponse<StatsDetailRecord> detail( public PageableResponse<StatsDetailRecord> detail(
// @RequestHeader("Authorization") String authorization @RequestHeader("Authorization") String authorization,
@PathVariable String chamberNumber, @PathVariable String chamberNumber,
@RequestParam(value = "page", required = false, defaultValue = "0") Integer page, @RequestParam(value = "page", required = false, defaultValue = "0") Integer page,
@RequestParam(value = "size", required = false, defaultValue = "20") Integer size @RequestParam(value = "size", required = false, defaultValue = "20") Integer size

View File

@ -1,6 +1,7 @@
package inc.sdt.controlcentermanagement.presentation; package inc.sdt.controlcentermanagement.presentation;
public class StatsDetailRecord { public class StatsDetailRecord {
private String assetCode;
private String slotNumber; private String slotNumber;
private String tubeId; private String tubeId;
private String status; private String status;
@ -14,7 +15,8 @@ public class StatsDetailRecord {
private String voltageOffset; private String voltageOffset;
private String currentOffset; private String currentOffset;
public StatsDetailRecord(String slotNumber, String tubeId, String status, String voltage, String current, String pin, String err1, String err2, String passTime, String retentionRate, String voltageOffset, String currentOffset) { public StatsDetailRecord(String assetCode, String slotNumber, String tubeId, String status, String voltage, String current, String pin, String err1, String err2, String passTime, String retentionRate, String voltageOffset, String currentOffset) {
this.assetCode = assetCode;
this.slotNumber = slotNumber; this.slotNumber = slotNumber;
this.tubeId = tubeId; this.tubeId = tubeId;
this.status = status; this.status = status;
@ -29,6 +31,10 @@ public class StatsDetailRecord {
this.currentOffset = currentOffset; this.currentOffset = currentOffset;
} }
public String getAssetCode() {
return assetCode;
}
public String getVoltageOffset() { public String getVoltageOffset() {
return voltageOffset; return voltageOffset;
} }

View File

@ -30,12 +30,12 @@ public class TubeController {
@PatchMapping("/chambers/{chamberNumber}/tube/toggle") @PatchMapping("/chambers/{chamberNumber}/tube/toggle")
public void toggle(@RequestHeader("Authorization") String authorization, @PathVariable String chamberNumber, @RequestBody Slot slot) { public void toggle(@RequestHeader("Authorization") String authorization, @PathVariable String chamberNumber, @RequestBody Slot slot) {
log.info("[toggle] chamberNumber: {}, slot: {}", chamberNumber, slot); log.info("[toggle] chamberNumber: {}, slot: {}", chamberNumber, slot);
List<Slot> slots = tubeService.get(chamberNumber);
if (slots.isEmpty()) throw new NoSuchElementException(chamberNumber);
slot.setChamberNumber(chamberNumber); slot.setChamberNumber(chamberNumber);
if (slot.getTube() != null) { if (slot.getTube() != null) {
tubeService.controlByTubeCode(authorization, slot); tubeService.controlByTubeCode(authorization, slot);
} else { } else {
List<Slot> slots = tubeService.get(chamberNumber);
if (slots.isEmpty()) throw new NoSuchElementException(chamberNumber);
tubeService.controlAll(authorization, slots, slot.getCommand()); tubeService.controlAll(authorization, slots, slot.getCommand());
} }
} }

View File

@ -24,10 +24,11 @@ class RestControllerExceptionHandler {
return ExceptionResponse.builder(HttpStatus.BAD_REQUEST) return ExceptionResponse.builder(HttpStatus.BAD_REQUEST)
.build(e.getBindingResult().getAllErrors().get(0).getDefaultMessage()); .build(e.getBindingResult().getAllErrors().get(0).getDefaultMessage());
} }
@ExceptionHandler
@ResponseStatus(HttpStatus.NOT_FOUND) @ExceptionHandler(value = NoSuchElementException.class)
ExceptionResponse handleNoSuchElementException(NoSuchElementException e) { @ResponseStatus(HttpStatus.NO_CONTENT)
return ExceptionResponse.builder(HttpStatus.NOT_FOUND) ExceptionResponse handleNoContentException(NoSuchElementException e) {
.build(e.getMessage() + " does not exist."); return ExceptionResponse.builder(HttpStatus.NO_CONTENT)
.build(e.getMessage());
} }
} }