diff --git a/src/main/java/com/iflytop/colortitration/app/common/enums/MultipleModuleCode.java b/src/main/java/com/iflytop/colortitration/app/common/enums/MultipleModuleCode.java new file mode 100644 index 0000000..b30d8a5 --- /dev/null +++ b/src/main/java/com/iflytop/colortitration/app/common/enums/MultipleModuleCode.java @@ -0,0 +1,9 @@ +package com.iflytop.colortitration.app.common.enums; + +/** + * 多模块枚举类型 + */ +public enum MultipleModuleCode { + MODULE_1, + MODULE_2, +} diff --git a/src/main/java/com/iflytop/colortitration/app/controller/CraftsController.java b/src/main/java/com/iflytop/colortitration/app/controller/CraftsController.java new file mode 100644 index 0000000..58aedc4 --- /dev/null +++ b/src/main/java/com/iflytop/colortitration/app/controller/CraftsController.java @@ -0,0 +1,87 @@ +package com.iflytop.colortitration.app.controller; + +import com.iflytop.colortitration.common.model.entity.Crafts; +import com.iflytop.colortitration.common.result.Result; +import com.iflytop.colortitration.common.result.ResultCode; +import com.iflytop.colortitration.common.service.CraftsService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Arrays; + +@Tag(name = "工艺管理") +@RestController +@RequestMapping("/api/crafts") +@RequiredArgsConstructor +@Slf4j +@Validated +public class CraftsController { + private final CraftsService craftsService; + + @Operation(summary = "添加新工艺") + @PostMapping("") + public Result add(@Valid @RequestBody Crafts crafts) { + Crafts existingCrafts = craftsService.findByName(crafts.getName()); + if (existingCrafts == null) { + boolean isSuccess = craftsService.save(crafts); + if (isSuccess) { + return Result.success(); + } + } else { + return Result.failed(ResultCode.DATA_ALREADY_EXISTS); + } + return Result.failed(); + } + + @Operation(summary = "更新工艺") + @PutMapping("") + public Result updateCrafts(@Valid @RequestBody Crafts crafts) { + boolean isSuccess = craftsService.updateById(crafts); + if (isSuccess) { + return Result.success(); + } + return Result.failed(); + } + + @Operation(summary = "删除工艺") + @DeleteMapping("/{ids}") + public Result delete(@PathVariable String ids) { + boolean success = craftsService.removeBatchByIds( + Arrays.stream(ids.split(",")).map(Long::valueOf).toList() + ); + return success ? Result.success() : Result.failed(); + } + +// @Operation(summary = "开始执行工艺") +// @PostMapping("/start") +// public Result startCrafts(@Valid @RequestBody CraftsStartDTO startCraftsDTO) { +// return Result.success(craftsService.startCrafts(startCraftsDTO)); +// } +// +// @Operation(summary = "暂停执行工艺") +// @PostMapping("/pause") +// public Result pauseCrafts(@Valid @RequestBody CraftsPauseDto pauseCraftsDto) { +// craftsService.pauseCrafts(pauseCraftsDto.getHeatId()); +// return Result.success(); +// } +// +// @Operation(summary = "恢复执行工艺") +// @PostMapping("/resume") +// public Result resumeCrafts(@Valid @RequestBody CraftsResumeDTO resumeCraftsDto) { +// craftsService.resumeCrafts(resumeCraftsDto.getHeatId()); +// return Result.success(); +// } +// +// @Operation(summary = "停止执行工艺") +// @PostMapping("/stop") +// public Result stopCrafts(@Valid @RequestBody CraftsStopDTO stopCraftsDto) { +// craftsService.stopCrafts(stopCraftsDto.getHeatId()); +// return Result.success(); +// } + +} diff --git a/src/main/java/com/iflytop/colortitration/app/core/state/DeviceState.java b/src/main/java/com/iflytop/colortitration/app/core/state/DeviceState.java index b906e18..afdb7ff 100644 --- a/src/main/java/com/iflytop/colortitration/app/core/state/DeviceState.java +++ b/src/main/java/com/iflytop/colortitration/app/core/state/DeviceState.java @@ -2,7 +2,7 @@ package com.iflytop.colortitration.app.core.state; import cn.hutool.json.JSONObject; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.iflytop.colortitration.common.enums.Device; +import com.iflytop.colortitration.app.common.enums.MultipleModuleCode; import com.iflytop.colortitration.common.model.entity.User; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -17,8 +17,24 @@ import java.util.Map; @Component @JsonIgnoreProperties(value = {"advisors", "frozen", "preFiltered", "proxyTargetClass", "targetSource", "exposeProxy", "advisorCount", "proxiedInterfaces", "targetClass"}) public class DeviceState { - @Schema(description = "加热模块属性") - private Map heatModule = new HashMap<>(); + + @Schema(description = "滴定模块") + private final Map titrationModuleStateMap = new HashMap<>(); + + @Schema(description = "加热模块") + private final Map heatModuleStateMap = new HashMap<>(); + + @Schema(description = "托盘1 试管状态") + private final Map trayTubeStateMap1 = new HashMap<>(); + + @Schema(description = "托盘2 试管状态") + private final Map trayTubeStateMap2 = new HashMap<>(); + + @Schema(description = "托盘1是否存在,true 存在 false不存在") + private boolean trayExist1 = false; + + @Schema(description = "托盘2是否存在,true 存在 false不存在") + private boolean trayExist2 = false; @Schema(description = "虚拟模式,true为虚拟") private boolean virtual = false; @@ -37,12 +53,16 @@ public class DeviceState { public JSONObject toJSON() { JSONObject json = new JSONObject(); - json.putOnce("heatModule", new ArrayList<>(heatModule.values())); - json.putOnce("virtual", virtual); - json.putOnce("initComplete", initComplete); - json.putOnce("selfTest", selfTest); - json.putOnce("emergencyStop", emergencyStop); - json.putOnce("currentUser", currentUser); + json.putOnce("titrationModule", new ArrayList<>(titrationModuleStateMap.values())); + json.putOnce("tray1TubeState", new ArrayList<>(trayTubeStateMap1.values())); + json.putOnce("tray2TubeState", new ArrayList<>(trayTubeStateMap2.values())); + json.putOnce("trayExist1", virtual); + json.putOnce("trayExist2", virtual); + json.putOnce("virtual", virtual); + json.putOnce("initComplete", initComplete); + json.putOnce("selfTest", selfTest); + json.putOnce("emergencyStop", emergencyStop); + json.putOnce("currentUser", currentUser); return json; } } \ No newline at end of file diff --git a/src/main/java/com/iflytop/colortitration/app/core/state/HeatModuleState.java b/src/main/java/com/iflytop/colortitration/app/core/state/HeatModuleState.java index 79579ed..eb2c7ee 100644 --- a/src/main/java/com/iflytop/colortitration/app/core/state/HeatModuleState.java +++ b/src/main/java/com/iflytop/colortitration/app/core/state/HeatModuleState.java @@ -1,7 +1,7 @@ package com.iflytop.colortitration.app.core.state; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.iflytop.colortitration.common.enums.Device; +import com.iflytop.colortitration.app.common.enums.MultipleModuleCode; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.RequiredArgsConstructor; @@ -18,7 +18,10 @@ import java.time.LocalDateTime; @JsonIgnoreProperties(value = {"advisors", "frozen", "preFiltered", "proxyTargetClass", "targetSource", "exposeProxy", "advisorCount", "proxiedInterfaces", "targetClass"}) public class HeatModuleState { @Schema(description = "加热模块code") - private Device deviceCode; + private MultipleModuleCode moduleCode; + + @Schema(description = "是否存在试管,true 存在 false不存在") + private boolean bubeExist = false; @Schema(description = "是否启动加热,true为正在加热,false为未在加热") private boolean open = false; @@ -34,8 +37,4 @@ public class HeatModuleState { @Schema(description = "开始加热的时间") private LocalDateTime startHeatTime = null; - - public HeatModuleState(Device deviceCode) { - this.deviceCode = deviceCode; - } } diff --git a/src/main/java/com/iflytop/colortitration/app/core/state/TitrationModule.java b/src/main/java/com/iflytop/colortitration/app/core/state/TitrationModule.java new file mode 100644 index 0000000..d897b6b --- /dev/null +++ b/src/main/java/com/iflytop/colortitration/app/core/state/TitrationModule.java @@ -0,0 +1,24 @@ +package com.iflytop.colortitration.app.core.state; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.iflytop.colortitration.app.common.enums.MultipleModuleCode; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +@Schema(description = "当前滴定模块状态") +@Data +@Component +@Scope("prototype") +@RequiredArgsConstructor +@JsonIgnoreProperties(value = {"advisors", "frozen", "preFiltered", "proxyTargetClass", "targetSource", "exposeProxy", "advisorCount", "proxiedInterfaces", "targetClass"}) +public class TitrationModule { + @Schema(description = "滴定模块code") + private MultipleModuleCode moduleCode; + + @Schema(description = "是否存在试管,true 存在 false不存在") + private boolean bubeExist = false; + +} diff --git a/src/main/java/com/iflytop/colortitration/app/core/state/TubeState.java b/src/main/java/com/iflytop/colortitration/app/core/state/TubeState.java new file mode 100644 index 0000000..27e9f68 --- /dev/null +++ b/src/main/java/com/iflytop/colortitration/app/core/state/TubeState.java @@ -0,0 +1,30 @@ +package com.iflytop.colortitration.app.core.state; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +@Schema(description = "当前试管状态") +@Data +@Component +@Scope("prototype") +@RequiredArgsConstructor +@JsonIgnoreProperties(value = {"advisors", "frozen", "preFiltered", "proxyTargetClass", "targetSource", "exposeProxy", "advisorCount", "proxiedInterfaces", "targetClass"}) +public class TubeState { + + @Schema(description = "试管位编号") + private Integer bubeNum; + + @Schema(description = "是否存在试管") + private boolean trayExist = false; + + @Schema(description = "体积") + private Double volume; + + @Schema(description = "结果") + private Double result; + +} diff --git a/src/main/java/com/iflytop/colortitration/app/model/dto/CraftsPauseDto.java b/src/main/java/com/iflytop/colortitration/app/model/dto/CraftsPauseDto.java new file mode 100644 index 0000000..511fa92 --- /dev/null +++ b/src/main/java/com/iflytop/colortitration/app/model/dto/CraftsPauseDto.java @@ -0,0 +1,12 @@ +package com.iflytop.colortitration.app.model.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "暂停执行工艺") +@Data +public class CraftsPauseDto { +// @NotNull +// @Schema(description = "加热区id") +// private HeatModuleCode heatId; +} diff --git a/src/main/java/com/iflytop/colortitration/app/model/dto/CraftsResumeDTO.java b/src/main/java/com/iflytop/colortitration/app/model/dto/CraftsResumeDTO.java new file mode 100644 index 0000000..4d68ed9 --- /dev/null +++ b/src/main/java/com/iflytop/colortitration/app/model/dto/CraftsResumeDTO.java @@ -0,0 +1,12 @@ +package com.iflytop.colortitration.app.model.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "恢复执行工艺") +@Data +public class CraftsResumeDTO { +// @NotNull +// @Schema(description = "加热区id") +// private HeatModuleCode heatId; +} diff --git a/src/main/java/com/iflytop/colortitration/app/model/dto/CraftsStartDTO.java b/src/main/java/com/iflytop/colortitration/app/model/dto/CraftsStartDTO.java new file mode 100644 index 0000000..8bcec7c --- /dev/null +++ b/src/main/java/com/iflytop/colortitration/app/model/dto/CraftsStartDTO.java @@ -0,0 +1,21 @@ +package com.iflytop.colortitration.app.model.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Positive; +import lombok.Data; + +@Schema(description = "开始工艺") +@Data +public class CraftsStartDTO { + @Positive(message = "工艺ID 必须是正数") + @NotNull + @Schema(description = "工艺id") + private Long craftId; +// +// @Schema(description = "加热区id,非必填,如果不传递则自动分配加热区") +// private HeatModuleCode heatId; + + @Schema(description = "需要加液的试管") + private int[] tubes; +} diff --git a/src/main/java/com/iflytop/colortitration/app/model/dto/CraftsStopDTO.java b/src/main/java/com/iflytop/colortitration/app/model/dto/CraftsStopDTO.java new file mode 100644 index 0000000..b7477e5 --- /dev/null +++ b/src/main/java/com/iflytop/colortitration/app/model/dto/CraftsStopDTO.java @@ -0,0 +1,12 @@ +package com.iflytop.colortitration.app.model.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "恢复执行工艺") +@Data +public class CraftsStopDTO { +// @NotNull +// @Schema(description = "加热区id") +// private HeatModuleCode heatId; +} diff --git a/src/main/java/com/iflytop/colortitration/app/service/DeviceInitService.java b/src/main/java/com/iflytop/colortitration/app/service/DeviceInitService.java new file mode 100644 index 0000000..668c5bc --- /dev/null +++ b/src/main/java/com/iflytop/colortitration/app/service/DeviceInitService.java @@ -0,0 +1,58 @@ +package com.iflytop.colortitration.app.service; + +import com.iflytop.colortitration.app.common.enums.MultipleModuleCode; +import com.iflytop.colortitration.app.core.state.DeviceState; +import com.iflytop.colortitration.app.core.state.TitrationModule; +import com.iflytop.colortitration.hardware.service.AppEventBusService; +import com.iflytop.colortitration.hardware.type.appevent.A8kCanBusOnConnectEvent; +import com.iflytop.colortitration.hardware.type.appevent.AppEvent; +import jakarta.annotation.PostConstruct; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.stereotype.Service; + +@Slf4j +@Service +@RequiredArgsConstructor +public class DeviceInitService { + private final AppEventBusService eventBus; + private boolean isLink = false; + private final DeviceState deviceState; + private final ObjectProvider trayStateObjectProvider; + + @PostConstruct + public void init() { + eventBus.regListener(this::onAppEvent); + new Thread(() -> { + try { + log.info("初始化开始"); + + initDeviceState(); + + deviceState.setInitComplete(true); + log.info("初始化完毕"); + } catch (Exception e) { + } + }).start(); + + } + + private void onAppEvent(AppEvent event) { + if (event instanceof A8kCanBusOnConnectEvent) { + isLink = true; + } + } + + public void initDeviceState() { + log.info("初始化 initDeviceState"); + TitrationModule trayModule1 = trayStateObjectProvider.getObject(); + trayModule1.setModuleCode(MultipleModuleCode.MODULE_1); + deviceState.getTitrationModuleStateMap().put(MultipleModuleCode.MODULE_1, trayModule1); + TitrationModule trayModule2 = trayStateObjectProvider.getObject(); + trayModule2.setModuleCode(MultipleModuleCode.MODULE_2); + deviceState.getTitrationModuleStateMap().put(MultipleModuleCode.MODULE_2, trayModule2); + log.info("初始化 initDeviceState完毕"); + } + +} diff --git a/src/main/java/com/iflytop/colortitration/common/mapper/CraftsMapper.java b/src/main/java/com/iflytop/colortitration/common/mapper/CraftsMapper.java new file mode 100644 index 0000000..61a0a87 --- /dev/null +++ b/src/main/java/com/iflytop/colortitration/common/mapper/CraftsMapper.java @@ -0,0 +1,13 @@ +package com.iflytop.colortitration.common.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.iflytop.colortitration.common.model.entity.Crafts; +import org.apache.ibatis.annotations.Mapper; + +/** + * 工艺持久层接口 + */ +@Mapper +public interface CraftsMapper extends BaseMapper { + +} diff --git a/src/main/java/com/iflytop/colortitration/common/model/entity/Crafts.java b/src/main/java/com/iflytop/colortitration/common/model/entity/Crafts.java new file mode 100644 index 0000000..4570826 --- /dev/null +++ b/src/main/java/com/iflytop/colortitration/common/model/entity/Crafts.java @@ -0,0 +1,27 @@ +package com.iflytop.colortitration.common.model.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.iflytop.colortitration.common.base.BaseEntity; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@EqualsAndHashCode(callSuper = true) +@Schema(description = "工艺") +@TableName("crafts") +@Data +public class Crafts extends BaseEntity { + + @NotNull + @NotBlank + @Schema(description = "工艺名称") + private String name; + + @NotNull + @NotBlank + @Schema(description = "工艺步骤") + private String steps; + +} diff --git a/src/main/java/com/iflytop/colortitration/common/service/CraftsService.java b/src/main/java/com/iflytop/colortitration/common/service/CraftsService.java new file mode 100644 index 0000000..dda38ef --- /dev/null +++ b/src/main/java/com/iflytop/colortitration/common/service/CraftsService.java @@ -0,0 +1,23 @@ +package com.iflytop.colortitration.common.service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.iflytop.colortitration.common.mapper.CraftsMapper; +import com.iflytop.colortitration.common.model.entity.Crafts; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * 工艺接口服务 + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class CraftsService extends ServiceImpl { + + public Crafts findByName(String name) { + return this.getOne(new LambdaQueryWrapper<>(new Crafts()).eq(Crafts::getName, name)); + } + +} diff --git a/src/main/resources/sql/init.sql b/src/main/resources/sql/init.sql index 6957d56..e57b566 100644 --- a/src/main/resources/sql/init.sql +++ b/src/main/resources/sql/init.sql @@ -91,3 +91,12 @@ CREATE TABLE IF NOT EXISTS color update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); +-- crafts 工艺 表 +CREATE TABLE IF NOT EXISTS crafts +( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name VARCHAR NOT NULL, + steps TEXT, + create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP +);