Browse Source

feat:新增拍照接口

master
白凤吉 1 week ago
parent
commit
5e7e14eee2
  1. 7
      src/main/java/com/iflytop/colortitration/app/controller/PhotoController.java
  2. 7
      src/main/java/com/iflytop/colortitration/app/core/state/TitrationModuleState.java
  3. 11
      src/main/java/com/iflytop/colortitration/app/model/dto/PhotoTakeDTO.java
  4. 7
      src/main/java/com/iflytop/colortitration/app/service/module/TitrationModuleService.java
  5. 4
      src/main/java/com/iflytop/colortitration/app/websocket/server/WebSocketMessageType.java
  6. 77
      src/main/java/com/iflytop/colortitration/common/service/PhotosService.java
  7. BIN
      src/main/resources/static/1.png
  8. BIN
      src/main/resources/static/2.png
  9. BIN
      src/main/resources/static/3.png

7
src/main/java/com/iflytop/colortitration/app/controller/PhotoController.java

@ -1,6 +1,7 @@
package com.iflytop.colortitration.app.controller;
import com.iflytop.colortitration.app.model.dto.PhotoSaveDTO;
import com.iflytop.colortitration.app.model.dto.PhotoTakeDTO;
import com.iflytop.colortitration.common.base.BasePageQuery;
import com.iflytop.colortitration.common.model.vo.PhotoListVO;
import com.iflytop.colortitration.common.model.vo.PhotoVO;
@ -40,11 +41,11 @@ public class PhotoController {
@Operation(summary = "拍摄一张照片")
@PostMapping("/take")
public Result<String> take() throws Exception {
return Result.success(photosService.take());
public Result<?> take(@RequestBody PhotoTakeDTO photoTakeDTO) throws Exception {
photosService.take(photoTakeDTO.getModuleCode());
return Result.success();
}
@Operation(summary = "保存照片")
@PostMapping("/save")
public Result<?> save(@RequestBody PhotoSaveDTO photoSaveDTO) {

7
src/main/java/com/iflytop/colortitration/app/core/state/TitrationModuleState.java

@ -8,12 +8,14 @@ import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import java.io.File;
@Schema(description = "当前滴定模块状态")
@Data
@Component
@Scope("prototype")
@RequiredArgsConstructor
@JsonIgnoreProperties(value = {"advisors", "frozen", "preFiltered", "proxyTargetClass", "targetSource", "exposeProxy", "advisorCount", "proxiedInterfaces", "targetClass"})
@JsonIgnoreProperties(value = {"advisors", "frozen", "preFiltered", "proxyTargetClass", "targetSource", "exposeProxy", "advisorCount", "proxiedInterfaces", "targetClass", "currentPhoto"})
public class TitrationModuleState {
@Schema(description = "滴定模块code")
private MultipleModuleCode moduleCode;
@ -21,6 +23,9 @@ public class TitrationModuleState {
@Schema(description = "是否存在试管,true 存在 false不存在")
private boolean tubeExist = false;
@Schema(description = "当前滴定位照片")
private File currentPhoto;
public TitrationModuleState(MultipleModuleCode moduleCode) {
this.moduleCode = moduleCode;
}

11
src/main/java/com/iflytop/colortitration/app/model/dto/PhotoTakeDTO.java

@ -0,0 +1,11 @@
package com.iflytop.colortitration.app.model.dto;
import com.iflytop.colortitration.app.common.enums.MultipleModuleCode;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
public class PhotoTakeDTO {
@Schema(description = "滴定模块code")
private MultipleModuleCode moduleCode;
}

7
src/main/java/com/iflytop/colortitration/app/service/module/TitrationModuleService.java

@ -362,4 +362,11 @@ public class TitrationModuleService {
deviceCommandService.sendCommand(deviceCommand);
}
/**
* 判断指定滴定模块是否有试管
*/
public boolean hasTestTube(MultipleModuleCode moduleCode){
return true;
}
}

4
src/main/java/com/iflytop/colortitration/app/websocket/server/WebSocketMessageType.java

@ -47,5 +47,9 @@ public class WebSocketMessageType {
* 加热倒计时
*/
public static final String HEAT_COUNTDOWN = "heat_countdown";
/**
* 照片
*/
public static final String PHOTO = "photo";
}

77
src/main/java/com/iflytop/colortitration/common/service/PhotosService.java

@ -4,7 +4,11 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.iflytop.colortitration.app.common.enums.MultipleModuleCode;
import com.iflytop.colortitration.app.core.state.DeviceState;
import com.iflytop.colortitration.app.model.dto.PhotoSaveDTO;
import com.iflytop.colortitration.app.websocket.server.WebSocketMessageType;
import com.iflytop.colortitration.app.websocket.server.WebSocketSender;
import com.iflytop.colortitration.common.base.BasePageQuery;
import com.iflytop.colortitration.common.enums.PhotoModeType;
import com.iflytop.colortitration.common.exception.AppException;
@ -16,17 +20,19 @@ import com.iflytop.colortitration.common.result.ResultCode;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Service;
import org.springframework.util.StreamUtils;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;
/**
@ -36,6 +42,9 @@ import java.util.stream.Collectors;
@Service
@RequiredArgsConstructor
public class PhotosService extends ServiceImpl<PhotosMapper, Photos> {
private final ResourceLoader resourceLoader;
private final DeviceState deviceState;
private final WebSocketSender webSocketSender;
@Value("${photo.url}")
private String url;
@ -79,32 +88,42 @@ public class PhotosService extends ServiceImpl<PhotosMapper, Photos> {
return null;
}
public String take() throws Exception {
// Path directoryPath = Paths.get(path + "/temp");
// try (Stream<Path> paths = Files.list(directoryPath)) {
// paths.forEach(file -> {
// try {
// Files.delete(file);
// } catch (IOException e) {
// log.error("删除文件时发生错误", e);
// }
// });
// } catch (IOException e) {
// log.error("读取目录时发生错误", e);
// }
//
// try {
// String tempFilePath = "/temp/" + System.currentTimeMillis() + ".png";
// String filePath = path + tempFilePath;
// driver.enable();
// driver.saveColorImg(filePath);
// return url + tempFilePath;
// } catch (Exception e) {
// throw new AppException(ResultCode.SYSTEM_ERROR);
// } finally {
// driver.disable();
// }
return null;
public void take(MultipleModuleCode moduleCode) throws IOException {
File file = getStaticFile("1.png");
deviceState.getTitrationModuleStateMap().get(moduleCode).setCurrentPhoto(file);
// 1. 读取图片并转 Base64
byte[] bytes = Files.readAllBytes(file.toPath());
String b64 = Base64.getEncoder().encodeToString(bytes);
String dataUrl = "data:image/png;base64," + b64;
// 2. 构造要发送的对象
Map<String, Object> payload = new HashMap<>();
payload.put("moduleCode", moduleCode);
payload.put("image", dataUrl);
webSocketSender.push(WebSocketMessageType.PHOTO, payload);
}
public File getStaticFile(String fileName) throws IOException {
Resource res = resourceLoader.getResource("classpath:static/" + fileName);
if (!res.exists()) {
throw new FileNotFoundException("找不到资源");
}
try {
// 运行在解压目录下直接返回真实文件
return res.getFile();
} catch (IOException e) {
// 运行在 JAR 内部复制到临时文件
File tmp = File.createTempFile("static-" + fileName, ".png");
try (InputStream is = res.getInputStream();
OutputStream os = new FileOutputStream(tmp)) {
StreamUtils.copy(is, os);
}
// JVM 退出时删除
tmp.deleteOnExit();
return tmp;
}
}
public void save(PhotoSaveDTO photoSaveDTO) {

BIN
src/main/resources/static/1.png

After

Width: 2670  |  Height: 2670  |  Size: 5.0 MiB

BIN
src/main/resources/static/2.png

After

Width: 2670  |  Height: 2670  |  Size: 3.3 MiB

BIN
src/main/resources/static/3.png

After

Width: 2670  |  Height: 2670  |  Size: 3.1 MiB

Loading…
Cancel
Save