수정중

This commit is contained in:
ihyeon-yong 2023-09-11 09:40:43 +09:00
parent efff31605b
commit e116aa6d06
24 changed files with 693 additions and 19 deletions

View File

@ -1,7 +1,168 @@
package inc.sdt.controlcentermanagement.application;
import com.fasterxml.jackson.core.type.TypeReference;
import inc.sdt.controlcentermanagement.domain.DataResource;
import inc.sdt.controlcentermanagement.domain.Slot;
import inc.sdt.controlcentermanagement.infrastructure.resttemplate.RestTemplateRequestHandler;
import inc.sdt.controlcentermanagement.presentation.StatsCntRecord;
import inc.sdt.controlcentermanagement.presentation.StatsDetailRecord;
import inc.sdt.controlcentermanagement.presentation.StatsRecord;
import inc.sdt.controlcentermanagement.presentation.support.CustomPage;
import inc.sdt.controlcentermanagement.presentation.support.CustomPageable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.web.util.UriComponentsBuilder;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
@Service
public class DefaultStatsService implements StatsService{
private final SlotRepositoryDelegate slotRepositoryDelegate;
private final RestTemplateRequestHandler restTemplateHandler;
private final String dataFallEndPoint;
private final Logger log = LoggerFactory.getLogger(DefaultStatsService.class);
public DefaultStatsService(SlotRepositoryDelegate slotRepositoryDelegate, RestTemplateRequestHandler restTemplateHandler, @Value("${data-fall.endpoint}") String dataFallEndPoint) {
this.slotRepositoryDelegate = slotRepositoryDelegate;
this.restTemplateHandler = restTemplateHandler;
this.dataFallEndPoint = dataFallEndPoint;
}
@Override
public List<StatsRecord> getChamberStats() {
List<Slot> all= slotRepositoryDelegate.getAll();
Map<String, List<Slot>> groupByChamber = all.stream().collect(Collectors.groupingBy(Slot::getChamberNumber));
List<StatsRecord> results = new LinkedList<>();
groupByChamber.forEach((chamberNumber, slotList) -> {
AtomicReference<Integer> onTotalCnt = new AtomicReference<>(0);
AtomicReference<Integer> offTotalCnt = new AtomicReference<>(0);
AtomicReference<Integer> errTotalCnt = new AtomicReference<>(0);
AtomicReference<Integer> onCnt = new AtomicReference<>(0);
AtomicReference<Integer> offCnt = new AtomicReference<>(0);
AtomicReference<Integer> err2Cnt = new AtomicReference<>(0);
for(Slot slot : slotList){
String url = UriComponentsBuilder.fromUriString(dataFallEndPoint)
.path(String.format("/assets/%s/tags/%s/data/latest", slot.getAssetCode(), slot.getSlotNumber()))
.build()
.toUriString();
Optional<CustomPage<DataResource>> optional = restTemplateHandler.httpGetRequestWithAuth(url, "bearer authkey", "", new TypeReference<>() {
});
log.info("optional = {}",optional);
if(optional.isPresent()){
List<DataResource> content = optional.get().getContent();
for(DataResource dataResource : content){
dataResource.getData().forEach((key, value)->{
if(key.contains("er2")){
errTotalCnt.updateAndGet(v -> v + 1);
if((int)value > 0){
err2Cnt.updateAndGet(v -> v + 1);
}
}
if(key.contains("do")){
onTotalCnt.updateAndGet(v -> v + 1);
offTotalCnt.updateAndGet(v -> v + 1);
if((int)value > 0){
onCnt.updateAndGet(v -> v + 1);
}else{
offCnt.updateAndGet(v -> v + 1);
}
}
});
}
}
}
StatsCntRecord onCntRecord = new StatsCntRecord(onCnt.get(), onTotalCnt.get());
StatsCntRecord offCntRecord = new StatsCntRecord(offCnt.get(), offTotalCnt.get());
StatsCntRecord errCntRecord = new StatsCntRecord(err2Cnt.get(), errTotalCnt.get());
StatsRecord statsRecord = new StatsRecord(chamberNumber, onCntRecord, offCntRecord, errCntRecord);
results.add(statsRecord);
});
return results;
}
@Override
public Page<StatsDetailRecord> getChamberStatsDetail(int page, int size, String chamberNumber) {
List<Slot> all= slotRepositoryDelegate.getAll().stream().filter(slot -> slot.getChamberNumber().equals(chamberNumber)).toList();
Pageable pageable = PageRequest.of(page, size);
List<StatsDetailRecord> statsDetailRecords = new LinkedList<>();
all.forEach((slot -> {
String url = UriComponentsBuilder.fromUriString(dataFallEndPoint)
.path(String.format("/assets/%s/tags/%s/data/latest", slot.getAssetCode(), slot.getSlotNumber()))
.build()
.toUriString();
Optional<CustomPage<DataResource>> optional = restTemplateHandler.httpGetRequestWithAuth(url, "bearer authkey", "", new TypeReference<>() {
});
//Tube{code='2', voltageOffset=1.0, ampereOffset=1.0}
Map<String, Object> currentMap = new HashMap<>();
Map<String, Object> voltageMap = new HashMap<>();
Map<String, Object> doMap = new HashMap<>();
Map<String, Object> er1Map = new HashMap<>();
Map<String, Object> er2Map = new HashMap<>();
if(optional.isPresent()){
List<DataResource> content = optional.get().getContent();
for(DataResource dataResource : content){
dataResource.getData().forEach((key, value)->{
if(key.startsWith("current")){
currentMap.put(key.replace("current",""), value);
}else if(key.startsWith("voltage")){
voltageMap.put(key.replace("voltage",""), value);
}else if(key.startsWith("do")){
doMap.put(key.replace("do",""), value);
}else if(key.startsWith("er1")){
er1Map.put(key.replace("er1",""), value);
}else if(key.startsWith("er2")){
er2Map.put(key.replace("er2",""), value);
}
});
}
}
for(int i=0 ; i < 16 ; i++){
StatsDetailRecord statsDetailRecord = new StatsDetailRecord(
slot.getSlotNumber(),
String.valueOf(i),
"status",
String.valueOf(voltageMap.get(String.valueOf(i))),
String.valueOf(currentMap.get(String.valueOf(i))),
String.valueOf(doMap.get(String.valueOf(i))),
String.valueOf(er1Map.get(String.valueOf(i))),
String.valueOf(er2Map.get(String.valueOf(i))),
"passTime",
"retentionRate",
String.valueOf(slot.getTube().get(i).getVoltageOffset()),
String.valueOf(slot.getTube().get(i).getAmpereOffset())
);
statsDetailRecords.add(statsDetailRecord);
}
}));
statsDetailRecords.sort(new StatsDetailSlotNumberComparator());
int start = (int) pageable.getOffset();
int end = Math.min((start + pageable.getPageSize()), statsDetailRecords.size());
List<StatsDetailRecord> pageContent = statsDetailRecords.subList(start, end);
Page<StatsDetailRecord> entities = new PageImpl<>(pageContent, pageable, statsDetailRecords.size());
return entities;
}
}

View File

@ -9,4 +9,6 @@ import java.util.List;
*/
public interface SlotRepositoryDelegate {
List<Slot> get(String chamberNumber);
List<Slot> getAll();
}

View File

@ -0,0 +1,17 @@
package inc.sdt.controlcentermanagement.application;
import inc.sdt.controlcentermanagement.presentation.StatsDetailRecord;
import java.util.Comparator;
public class StatsDetailSlotNumberComparator implements Comparator<StatsDetailRecord> {
@Override
public int compare(StatsDetailRecord o1, StatsDetailRecord o2) {
if(Integer.parseInt(o1.getSlotNumber()) > Integer.parseInt(o2.getSlotNumber())){
return 1;
}else if(Integer.parseInt(o1.getSlotNumber()) < Integer.parseInt(o2.getSlotNumber())){
return -1;
}
return 0;
}
}

View File

@ -0,0 +1,17 @@
package inc.sdt.controlcentermanagement.application;
import inc.sdt.controlcentermanagement.presentation.StatsDetailRecord;
import java.util.Comparator;
public class StatsDetailTubeIdComparator implements Comparator<StatsDetailRecord> {
@Override
public int compare(StatsDetailRecord o1, StatsDetailRecord o2) {
if(Integer.parseInt(o1.getTubeId()) > Integer.parseInt(o2.getTubeId())){
return 1;
}else if(Integer.parseInt(o1.getTubeId()) < Integer.parseInt(o2.getTubeId())){
return -1;
}
return 0;
}
}

View File

@ -1,4 +1,13 @@
package inc.sdt.controlcentermanagement.application;
import inc.sdt.controlcentermanagement.presentation.StatsDetailRecord;
import inc.sdt.controlcentermanagement.presentation.StatsRecord;
import org.springframework.data.domain.Page;
import java.util.List;
public interface StatsService {
List<StatsRecord> getChamberStats();
Page<StatsDetailRecord> getChamberStatsDetail(int page, int size, String chamberNumber);
}

View File

@ -0,0 +1,49 @@
package inc.sdt.controlcentermanagement.domain;
import java.util.Map;
/**
* @author eunsan.goh (esgoh@sdt.inc)
**/
public class DataResource {
private String assetCode;
private String modelCode;
private Long timestamp;
private Map<String, Object> data;
private DataType dataType;
public DataResource() {
}
@Override
public String toString() {
return "DataResource{" +
"assetCode='" + assetCode + '\'' +
", modelCode='" + modelCode + '\'' +
", timestamp=" + timestamp +
", data.size=" + data.size() +
", dataType=" + dataType +
'}';
}
public String getAssetCode() {
return assetCode;
}
public String getModelCode() {
return modelCode;
}
public Long getTimestamp() {
return timestamp;
}
public Map<String, Object> getData() {
return data;
}
public DataType getDataType() {
return dataType;
}
}

View File

@ -0,0 +1,9 @@
package inc.sdt.controlcentermanagement.domain;
/**
* @author eunsan.goh (esgoh@sdt.inc)
**/
public enum DataType {
STATE,
DATA
}

View File

@ -51,6 +51,6 @@ class RegisterResourceProducer implements Consumer<ResourceMessagePayload> {
public void accept(ResourceMessagePayload payload) {
log.info("[accept] payload={}", payload);
Message message = messageConverter.toMessage(payload, messageProperties);
rabbitTemplate.send(exchange, routingKey, message);
// rabbitTemplate.send(exchange, routingKey, message);
}
}

View File

@ -32,6 +32,15 @@ public class SlotNoSQLRepository implements SlotRepositoryDelegate {
.toList();
}
@Override
public List<Slot> getAll() {
log.debug("[getAll]");
return slotRepository.findAllByOrderByChamberNumberAscSlotNumberAsc()
.stream()
.map(this::to)
.toList();
}
private Slot to(SlotDocument slotDocument) {
return Slot.builder()
.id(slotDocument.getId())

View File

@ -9,4 +9,5 @@ import java.util.List;
*/
public interface SlotRepository extends MongoRepository<SlotDocument, String> {
List<SlotDocument> findAllByChamberNumber(String chamberNumber);
List<SlotDocument> findAllByOrderByChamberNumberAscSlotNumberAsc();
}

View File

@ -6,4 +6,5 @@ import java.util.Optional;
public interface RestTemplateHandler {
<T> Optional<T> httpPostRequestWithAuth(String url, String authorization, Object body, TypeReference<T> typeReference);
<T> Optional<T> httpGetRequestWithAuth(String url, String authorization, Object body, TypeReference<T> typeReference);
}

View File

@ -30,4 +30,15 @@ public class RestTemplateRequestHandler implements RestTemplateHandler {
ResponseEntity<T> response = restTemplate.exchange(url, HttpMethod.POST, new HttpEntity<>(body, headers), parameterizedType);
return Optional.ofNullable(response.getBody());
}
@Override
public <T> Optional<T> httpGetRequestWithAuth(String url, String authorization, Object body, TypeReference<T> typeReference) {
log.info("[httpGetRequestWithAuth] url = {}", url);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setBearerAuth(authorization.split(" ")[1]);
ParameterizedTypeReference<T> parameterizedType = ParameterizedTypeReference.forType(typeReference.getType());
ResponseEntity<T> response = restTemplate.exchange(url, HttpMethod.GET, new HttpEntity<>(body, headers), parameterizedType);
return Optional.ofNullable(response.getBody());
}
}

View File

@ -0,0 +1,19 @@
package inc.sdt.controlcentermanagement.presentation;
public class StatsCntRecord {
private Integer correctCount;
private Integer totalCount;
public StatsCntRecord(Integer correctCount, Integer totalCount) {
this.correctCount = correctCount;
this.totalCount = totalCount;
}
public Integer getCorrectCount() {
return correctCount;
}
public Integer getTotalCount() {
return totalCount;
}
}

View File

@ -1,12 +1,16 @@
package inc.sdt.controlcentermanagement.presentation;
import inc.sdt.controlcentermanagement.application.StatsService;
import inc.sdt.controlcentermanagement.presentation.support.CustomPageable;
import inc.sdt.controlcentermanagement.presentation.support.CustomPageableImpl;
import inc.sdt.controlcentermanagement.presentation.support.PageableResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
public class StatsController {
@ -20,24 +24,36 @@ public class StatsController {
@ResponseStatus(HttpStatus.OK)
@GetMapping("/chambers")
public String chambers(
@GetMapping("/chamber/stats")
public StatsResult chambers(
// @RequestHeader("Authorization") String authorization
){
log.info("[chambers]");
log.info("[chambers stats]");
List<StatsRecord> chamberStats = statsService.getChamberStats();
return new StatsResult(chamberStats);
}
@ResponseStatus(HttpStatus.OK)
@GetMapping("/chamber/stats/{chamberNumber}")
public PageableResponse<StatsDetailRecord> detail(
// @RequestHeader("Authorization") String authorization
@PathVariable String chamberNumber,
@RequestParam(value = "page", required = false, defaultValue = "0") Integer page,
@RequestParam(value = "size", required = false, defaultValue = "20") Integer size
){
log.info("[chambers stats]");
Page<StatsDetailRecord> chamberStatsDetail = statsService.getChamberStatsDetail(Integer.max(0, page), (page >= 0 ? size : Integer.MAX_VALUE), chamberNumber);
if(chamberStatsDetail.hasContent()){
return PageableResponse.from(chamberStatsDetail, this::from);
}
return null;
}
// 챔버 갯수 및 번호 주는 api
// 이건 전체 화면 챔버 번호 들어오면 그 챔버에 있는 노드큐 및 슬롯으로 수경님 api 호출해서 합산하기
// 상세에서는 번호는 슬롯번호 mes code는 튜번호로 해서 쭉 보여주기
//@ResourceMapping(name = "Tube_Control", method = "PATCH", uri = "/chamber/{chamberNumber}/tube/toggle", description = "Tube On/Off 제어")
// @ResponseStatus(HttpStatus.OK)
// @PatchMapping("/chamber/{chamberNumber}/tube/toggle")
private StatsDetailRecord from(StatsDetailRecord statsDetailRecord){
return statsDetailRecord;
}
}

View File

@ -0,0 +1,79 @@
package inc.sdt.controlcentermanagement.presentation;
public class StatsDetailRecord {
private String slotNumber;
private String tubeId;
private String status;
private String voltage;
private String current;
private String pin;
private String err1;
private String err2;
private String passTime;
private String retentionRate;
private String voltageOffset;
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) {
this.slotNumber = slotNumber;
this.tubeId = tubeId;
this.status = status;
this.voltage = voltage;
this.current = current;
this.pin = pin;
this.err1 = err1;
this.err2 = err2;
this.passTime = passTime;
this.retentionRate = retentionRate;
this.voltageOffset = voltageOffset;
this.currentOffset = currentOffset;
}
public String getVoltageOffset() {
return voltageOffset;
}
public String getCurrentOffset() {
return currentOffset;
}
public String getSlotNumber() {
return slotNumber;
}
public String getTubeId() {
return tubeId;
}
public String getStatus() {
return status;
}
public String getVoltage() {
return voltage;
}
public String getCurrent() {
return current;
}
public String getPin() {
return pin;
}
public String getErr1() {
return err1;
}
public String getErr2() {
return err2;
}
public String getPassTime() {
return passTime;
}
public String getRetentionRate() {
return retentionRate;
}
}

View File

@ -0,0 +1,31 @@
package inc.sdt.controlcentermanagement.presentation;
public class StatsRecord {
private String chamberNumber;
private StatsCntRecord onCnt;
private StatsCntRecord offCnt;
private StatsCntRecord errCnt;
public StatsRecord(String chamberNumber, StatsCntRecord onCnt, StatsCntRecord offCnt, StatsCntRecord errCnt) {
this.chamberNumber = chamberNumber;
this.onCnt = onCnt;
this.offCnt = offCnt;
this.errCnt = errCnt;
}
public String getChamberNumber() {
return chamberNumber;
}
public StatsCntRecord getOnCnt() {
return onCnt;
}
public StatsCntRecord getOffCnt() {
return offCnt;
}
public StatsCntRecord getErrCnt() {
return errCnt;
}
}

View File

@ -0,0 +1,15 @@
package inc.sdt.controlcentermanagement.presentation;
import java.util.List;
public class StatsResult {
private List<StatsRecord> contents;
public StatsResult(List<StatsRecord> contents) {
this.contents = contents;
}
public List<StatsRecord> getContents() {
return contents;
}
}

View File

@ -0,0 +1,42 @@
package inc.sdt.controlcentermanagement.presentation.support;
import org.springframework.util.Assert;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* @author eunsan.goh (esgoh@sdt.inc)
**/
public class CustomPage<T> {
private List<T> content;
private CustomPageableImpl pageable;
public CustomPage(List<T> content, CustomPageableImpl pageable) {
this.content = content;
this.pageable = pageable;
}
public CustomPage() {
}
public List<T> getContent() {
return content;
}
public CustomPageableImpl getPageable() {
return pageable;
}
// public <U> CustomPage<U> map(Function<? super T, ? extends U> converter) {
// return new CustomPage<>(getConvertedContent(converter), getPageable());
// }
private <U> List<U> getConvertedContent(Function<? super T, ? extends U> converter) {
Assert.notNull(converter, "Function must not be null");
return content.stream().map(converter).collect(Collectors.toList());
}
}

View File

@ -0,0 +1,20 @@
package inc.sdt.controlcentermanagement.presentation.support;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
/**
* @author eunsan.goh (esgoh@sdt.inc)
**/
public interface CustomPageable {
long getTotalElements();
int getTotalPages();
int getSize();
int getPage();
int offset();
String sortDirection();
}

View File

@ -0,0 +1,63 @@
package inc.sdt.controlcentermanagement.presentation.support;
/**
* @author eunsan.goh (esgoh@sdt.inc)
**/
public class CustomPageableImpl implements CustomPageable {
private long totalElements;
private int totalPages;
private int size;
private int page;
private String sortDirection;
private CustomPageableImpl() {
}
public static CustomPageableImpl createPageRequest(int size, int page, String sortDirection) {
CustomPageableImpl pageable = new CustomPageableImpl();
pageable.size = size;
pageable.page = page;
pageable.sortDirection = sortDirection;
return pageable;
}
public static CustomPageableImpl createPageableResource(CustomPageable pageable, long totalElements, int totalPages) {
CustomPageableImpl pageableResource = new CustomPageableImpl();
pageableResource.totalElements = totalElements;
pageableResource.totalPages = pageable.getPage() < 0 ? 1 : totalPages;
pageableResource.size = pageable.getPage() < 0 ? (int) totalElements : pageable.getSize();
pageableResource.page = Math.max(pageable.getPage(), 0);
pageableResource.sortDirection = pageable.sortDirection();
return pageableResource;
}
@Override
public long getTotalElements() {
return totalElements;
}
@Override
public int getTotalPages() {
return totalPages;
}
@Override
public int getSize() {
return size;
}
@Override
public int getPage() {
return page;
}
@Override
public int offset() {
return size * page;
}
@Override
public String sortDirection() {
return sortDirection;
}
}

View File

@ -0,0 +1,14 @@
package inc.sdt.controlcentermanagement.presentation.support;
/**
* @author Minkyu Kim (minkyu.kim@sdt.inc)
*/
public interface PageableResource {
long getTotalElements();
int getTotalPages();
int getSize();
int getPage();
}

View File

@ -0,0 +1,53 @@
package inc.sdt.controlcentermanagement.presentation.support;
import org.springframework.data.domain.Page;
import java.io.Serial;
import java.io.Serializable;
/**
* @author Minkyu Kim (minkyu.kim@sdt.inc)
*/
public class PageableResourceImpl implements PageableResource, Serializable {
@Serial
private static final long serialVersionUID = 8670430894447655773L;
private final long totalElements;
private final int totalPage;
private final int size;
private final int page;
PageableResourceImpl(long totalElements, int totalPage, int size, int page) {
this.totalElements = totalElements;
this.totalPage = totalPage;
this.size = size;
this.page = page;
}
public static <T> PageableResourceImpl from(Page<T> page) {
return new PageableResourceImpl(
page.getTotalElements(),
page.getTotalPages(),
page.getSize(),
page.getPageable().getPageNumber());
}
@Override
public long getTotalElements() {
return totalElements;
}
@Override
public int getTotalPages() {
return totalPage;
}
@Override
public int getSize() {
return size;
}
@Override
public int getPage() {
return page;
}
}

View File

@ -0,0 +1,34 @@
package inc.sdt.controlcentermanagement.presentation.support;
import org.springframework.data.domain.Page;
import java.util.List;
import java.util.function.Function;
/**
* @author Minkyu Kim (minkyu.kim@sdt.inc)
*/
public class PageableResponse<T> {
private final List<T> content;
private final PageableResource pageable;
PageableResponse(List<T> content, PageableResource pageable) {
this.content = content;
this.pageable = pageable;
}
public static <T, U> PageableResponse<U> from(Page<T> page, Function<T, U> converter) {
return new PageableResponse<>(
page.map(converter).getContent(),
PageableResourceImpl.from(page));
}
public PageableResource getPageable() {
return pageable;
}
public List<T> getContent() {
return content;
}
}

View File

@ -6,8 +6,10 @@ spring:
name: control-center-management
data:
mongodb:
uri: mongodb://13.209.39.139:32000/awexomeray?authSource=admin
uri: mongodb://sdt:251327@13.209.39.139:32000/awexomeray?authSource=admin
data-fall:
endpoint: http://13.209.39.139:32171
deployer:
endpoint: http://localhost:8085