sige 1 year ago
parent
commit
3d61b2abd8
  1. 16
      src/src/main/java/com/my/graphiteDigesterBg/move/MoveHeatPlateSlotHeating.java
  2. 30
      src/src/main/java/com/my/graphiteDigesterBg/resource/ResHeatingTubeRackSlot.java
  3. 10
      src/src/main/java/com/my/graphiteDigesterBg/resource/ResHeatingTubeRackSlotManager.java
  4. 24
      src/src/main/java/com/my/graphiteDigesterBg/task/TaskHeating.java
  5. 23
      src/web/src/pages/main/contents/Operation.vue
  6. 97
      src/web/src/pages/main/contents/OperationTubeRackTemperature.vue

16
src/src/main/java/com/my/graphiteDigesterBg/move/MoveHeatPlateSlotHeating.java

@ -16,6 +16,8 @@ public class MoveHeatPlateSlotHeating extends DiTaskMoveBase {
public Integer temperature;
// duration
public Integer duration;
// task uuid
public String taskUuid;
// done callback
private FinishCallback finishCallback;
// slot
@ -27,10 +29,12 @@ public class MoveHeatPlateSlotHeating extends DiTaskMoveBase {
public void run() {
var slotMan = this.getResourceManager(ResHeatingTubeRackSlotManager.class);
this.slot = slotMan.getSlotByIndex(this.slotIndex);
this.slot.srcTemperature = this.slot.temperature;
this.slot.destTemperature = this.temperature * 100;
this.slot.heatingDuration = this.duration * 60;
this.slot.heatingStartedAt = null;
this.slot.isHeating = true;
this.slot.taskUuid = this.taskUuid;
this.isHeatingOn = false;
String message = String.format("试管架%d : 开始加热", this.slotIndex);
@ -38,6 +42,12 @@ public class MoveHeatPlateSlotHeating extends DiTaskMoveBase {
this.heating();
}
// cancel
public void cancel() {
this.slot.heatingDuration = 0;
this.slot.destTemperature = null;
}
// on done
public void onFinish( FinishCallback callback ) {
this.finishCallback = callback;
@ -47,7 +57,7 @@ public class MoveHeatPlateSlotHeating extends DiTaskMoveBase {
public void heating() {
String heaterKey = "HeatPlateSlotHeater" + this.slotIndex;
// 如果温度低于目标温度打开加热器
if ( this.slot.temperature < this.slot.destTemperature ) {
if ( null != this.slot.destTemperature && this.slot.temperature < this.slot.destTemperature ) {
if ( !this.isHeatingOn ) {
this.getDevice().getIO().setValue(heaterKey, 1);
this.isHeatingOn = true;
@ -69,10 +79,12 @@ public class MoveHeatPlateSlotHeating extends DiTaskMoveBase {
// 检查时间到了没有 ~~~
var duration = System.currentTimeMillis()/1000 - this.slot.heatingStartedAt;
if ( duration > this.slot.heatingDuration ) {
if ( duration >= this.slot.heatingDuration ) {
String message = String.format("试管架%d : 加热完成", this.slotIndex);
this.getDevice().getRuntimeVariables().setString(message, "StatusMessage");
this.slot.isHeating = false;
this.slot.heatingStartedAt = null;
this.slot.taskUuid = null;
this.finishCallback.callback();
return ;
}

30
src/src/main/java/com/my/graphiteDigesterBg/resource/ResHeatingTubeRackSlot.java

@ -12,6 +12,8 @@ public class ResHeatingTubeRackSlot {
public Integer destTemperature;
// temperature
public Integer temperature;
// src temperature
public Integer srcTemperature;
// heating started at
public Integer heatingStartedAt;
// heating duration
@ -26,10 +28,12 @@ public class ResHeatingTubeRackSlot {
private Boolean isLocked;
// is heating
public Boolean isHeating;
// task uuid
public String taskUuid;
// manager
private final ResHeatingTubeRackSlotManager manager;
// tube status list
private List<String> tubeStatusList;
private final List<String> tubeStatusList;
// constructor
public ResHeatingTubeRackSlot( ResHeatingTubeRackSlotManager manager, Integer index ) {
@ -78,28 +82,4 @@ public class ResHeatingTubeRackSlot {
}
return indexes;
}
// heating on
public void heatingOn() {
LOG.info("[Resource TubeRackSlot#{}] Heating On", this.index);
this.isHeating = true;
// @TODO : 加热未实现
LOG.error("开始加热未实现");
this.temperature = this.destTemperature;
}
// heating off
public void heatingOff() {
LOG.info("[Resource TubeRackSlot#{}] Heating Off", this.index);
// @TODO : 加热未实现
LOG.error("停止加热未实现");
this.isHeating = false;
}
// get is heating
public Boolean getIsHeating() {
return this.isHeating;
}
}

10
src/src/main/java/com/my/graphiteDigesterBg/resource/ResHeatingTubeRackSlotManager.java

@ -41,11 +41,11 @@ public class ResHeatingTubeRackSlotManager extends DiResourceManagerBase {
// refresh slot temperature
public void refreshSlotTemperature() {
// var registers = this.getDevice().getRegisters();
// for (ResHeatingTubeRackSlot slot : this.slots) {
// slot.temperature = registers.getValue("HeatingPlateSlotTemperature" + slot.index);
// LOG.info("[Heating Slot {}] temperature: {}", slot.index, slot.temperature);
// }
var registers = this.getDevice().getRegisters();
for (ResHeatingTubeRackSlot slot : this.slots) {
slot.temperature = registers.getValue("HeatingPlateSlotTemperature" + slot.index);
LOG.info("[Heating Slot {}] temperature: {}", slot.index, slot.temperature);
}
}
// get resource data

24
src/src/main/java/com/my/graphiteDigesterBg/task/TaskHeating.java

@ -13,22 +13,28 @@ public class TaskHeating extends DiTaskBase {
public Integer temperature;
// duration
public Integer duration;
// timer
private Timer timer;
// heating move
private MoveHeatPlateSlotHeating heating;
@Override
public void run() {
MdbOperationLog.log(this.getUser(), "试管架%d : 样本加热 温度=%d, 时间=%d", this.slotIndex, this.temperature, this.duration);
var heating = new MoveHeatPlateSlotHeating();
heating.slotIndex = this.slotIndex;
heating.temperature = this.temperature;
heating.duration = this.duration;
heating.setDevice(this.getDevice());
heating.onFinish(() -> {
this.heating = new MoveHeatPlateSlotHeating();
this.heating.taskUuid = this.getUUID();
this.heating.slotIndex = this.slotIndex;
this.heating.temperature = this.temperature;
this.heating.duration = this.duration;
this.heating.setDevice(this.getDevice());
this.heating.onFinish(() -> {
this.setStatus(DiTask.TaskStatus.FINISHED);
});
heating.run();
this.heating.run();
this.setStatus(DiTask.TaskStatus.WAITING);
}
// cancel
public void cancel() {
this.heating.cancel();
}
}

23
src/web/src/pages/main/contents/Operation.vue

@ -112,7 +112,7 @@
</a-modal>
<!-- 加热 -->
<a-modal v-model:visible="heating.enable" title="加热" @ok="actionHeatingOk" @cancel="actionHeatingCancel" ok-text="确认" cancel-text="取消">
<a-modal v-model:visible="heating.enable" title="加热">
<a-form :label-col="{span:4}" :wrapper-col="{span:20}" label-align="left" class="py-5">
<a-form-item label="位置">
<a-radio-group v-model:value="heating.slotIndex" button-style="solid">
@ -130,6 +130,18 @@
<a-input-number v-model:value="heating.duration" :min="0" addon-after="分钟" />
</a-form-item>
</a-form>
<template #footer>
<a-row>
<a-col :span="12" class="text-left">
<a-button @click="actionHeatingStop">停止</a-button>
</a-col>
<a-col :span="12">
<a-button @click="actionHeatingCancel">取消</a-button>
<a-button type="primary" @click="actionHeatingOk">确认</a-button>
</a-col>
</a-row>
</template>
</a-modal>
</div>
</template>
@ -282,6 +294,15 @@ async function actionHeatingOk() {
function actionHeatingCancel() {
heating.value.enable = false;
}
//
async function actionHeatingStop() {
let slotIndex = heating.value.slotIndex * 1;
let taskId = tubeRackSlots.value[slotIndex].taskUuid;
heating.value.enable = false;
let client = ApiClient.getClient();
await client.taskActionExecute(taskId, 'cancel');
}
</script>
<style scoped>
.heating-plate {background: #EEEFF8;border: solid 12px #E5E7F2;}

97
src/web/src/pages/main/contents/OperationTubeRackTemperature.vue

@ -1,17 +1,40 @@
<template>
<div class="h-full flex flex-col bg-white rounded-2xl p-5">
<div class="h-0 grow">
<div v-for="tubeRackSlot in tubeRackSlots" :key="tubeRackSlot.index" class="bg-gray-100 mb-2 flex flex-row p-2 rounded-2xl">
<div class="h-full flex flex-col bg-white rounded-2xl p-5" style="background-color: #EEF5FF;">
<div class="h-0 grow flex flex-col justify-between">
<div v-for="tubeRackSlot in tubeRackSlots" :key="tubeRackSlot.index" class="mb-2">
<div class="flex flex-row justify-between text-gray-400 px-2 py-1 rounded-t-md" style="background-color:#DCE8F7;">
<div v-if="!tubeRackSlot.isErrorSlot">A-{{ tubeRackSlot.index + 1 }}</div>
<div v-else>异常处理</div>
<div>目标温度{{ tubeRackSlot.destTemperature/100 }}</div>
</div>
<div class="flex flex-row p-2 rounded-b-md" style="background-color: #E2EEFD;">
<div class="flex flex-row items-center">
<a-progress type="circle" status="exception" :size="50" :strokeWidth="18" :percent="getTubeRackSlotHeatingProgress(tubeRackSlot)" >
<!-- 加热进度 -->
<a-progress type="circle" v-if="null === tubeRackSlot.heatingStartedAt"
stroke-color="#ff5b5b"
:size="50" :strokeWidth="18"
:percent="getTubeRackSlotHeatingProgress(tubeRackSlot)"
>
<template #format="percent">
<span v-if="tubeRackSlot.isHeating" style="color: #ff5b5b">{{ percent }}%</span>
</template>
</a-progress>
<!-- 保持进度 -->
<a-progress type="circle" v-else
:size="50" :strokeWidth="18"
strokeColor="#fa8c16"
:percent="getTubeRackSlotHoldingProgress(tubeRackSlot)"
>
<template #format>
<span class="text-red-400 text-xs">{{ getTubeRackSlotHeatingProgressCountdown(tubeRackSlot) }}</span>
<span class="text-xs" style="color:#fa8c16"
>{{ getTubeRackSlotHoldingCountdown(tubeRackSlot) }}</span>
</template>
</a-progress>
</div>
<div class="ml-2 bg-amber-500 rounded-2xl py-2 px-4 text-white w-0 grow text-center">
<p class="mb-0 text-2xl">{{ tubeRackSlot.temperature / 100 }}</p>
<p class="mb-0">A - {{ tubeRackSlot.index + 1 }}</p>
<div class="temperature" :class="{heating:tubeRackSlot.isHeating,holding:null !== tubeRackSlot.heatingStartedAt}">
<div>{{ (tubeRackSlot.temperature / 100).toFixed(2) }}</div>
<div></div>
</div>
</div>
</div>
</div>
@ -29,26 +52,64 @@ const tubeRackSlots = ref([]);
watch(() => props.tubeRackSlots, newValue => tubeRackSlots.value = newValue);
//
function getTubeRackSlotHeatingProgressCountdown(tubeRackSlot) {
function getTubeRackSlotHeatingProgress(tubeRackSlot) {
if ( !tubeRackSlot.isHeating ) {
return `00:00`;
return 0;
}
let duration = tubeRackSlot.heatingDuration - (Date.now() / 1000 - tubeRackSlot.heatingStartedAt);
duration = parseInt(duration);
let min = parseInt(duration / 60);
let sec = duration % 60;
return `${min.toString().padStart(2,'0')}:${sec.toString().padStart(2,'0')}`;
let heating = tubeRackSlot.temperature - tubeRackSlot.srcTemperature;
let total = tubeRackSlot.destTemperature - tubeRackSlot.srcTemperature;
return Math.round(heating / total * 100);
}
//
function getTubeRackSlotHeatingProgress(tubeRackSlot) {
//
function getTubeRackSlotHoldingProgress(tubeRackSlot) {
if ( !tubeRackSlot.isHeating ) {
return 0;
}
let duration = Date.now() / 1000 - tubeRackSlot.heatingStartedAt;
let progress = duration / tubeRackSlot.heatingDuration * 100;
return Math.round(progress);
}
//
function getTubeRackSlotHoldingCountdown(tubeRackSlot) {
if ( !tubeRackSlot.isHeating ) {
return `00:00`;
}
let duration = tubeRackSlot.heatingDuration - (Date.now() / 1000 - tubeRackSlot.heatingStartedAt);
duration = parseInt(duration);
if ( duration < 0 ) {
duration = 0;
}
let min = parseInt(duration / 60);
let sec = duration % 60;
return `${min.toString().padStart(2,'0')}:${sec.toString().padStart(2,'0')}`;
}
</script>
<style scoped>
.temperature {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
font-size: 1.5rem;
color: #8799AB;
font-weight: bold;
width: 0;
flex-grow: 1;
box-shadow: inset 0px 0px 14px 2px rgb(10 10 10 / 8%);
margin-left: 0.5rem;
border-radius: 0.5rem;
padding-top: 0.25rem;
padding-bottom: 0.25rem;
padding-left: 1rem;
padding-right: 1rem;
}
.temperature.heating {color: #ff5b5b;}
.temperature.holding {color: #fa8c16;}
</style>
Loading…
Cancel
Save