diff --git a/appenv/restart_chrome.sh b/appenv/restart_chrome.sh new file mode 100644 index 0000000..d9e2ed7 --- /dev/null +++ b/appenv/restart_chrome.sh @@ -0,0 +1,2 @@ + killall chromium-bin +/etc/zos/zos_setup.sh & \ No newline at end of file diff --git a/appenv/start.sh b/appenv/start.sh new file mode 100644 index 0000000..df4ce56 --- /dev/null +++ b/appenv/start.sh @@ -0,0 +1,3 @@ +#!/bin/bash +echo "A8000 starting ..." +/iflytop/bin/jdk/bin/java -jar /app/app.jar > /app/app.log 2>&1 \ No newline at end of file diff --git a/appenv/zapp.service b/appenv/zapp.service new file mode 100644 index 0000000..073a174 --- /dev/null +++ b/appenv/zapp.service @@ -0,0 +1,15 @@ +[Unit] +# 服务名称,可自定义 +Description =A8000 +After = network.target +Wants = network.target + +[Service] +Type = simple +ExecStart=/app/sh/start.sh +Restart=always +RestartSec=2 +WorkingDirectory=/app/ + +[Install] +WantedBy = multi-user.target diff --git a/bak/20250428-app.db b/bak/20250428-app.db deleted file mode 100644 index 251699f..0000000 Binary files a/bak/20250428-app.db and /dev/null differ diff --git a/bak/20250429-1app.db b/bak/20250429-1app.db deleted file mode 100644 index fca4050..0000000 Binary files a/bak/20250429-1app.db and /dev/null differ diff --git a/bak/20250429-2app.db b/bak/20250429-2app.db deleted file mode 100644 index b9e8cc2..0000000 Binary files a/bak/20250429-2app.db and /dev/null differ diff --git a/bak/20250429-3app.db b/bak/20250613app.db similarity index 70% rename from bak/20250429-3app.db rename to bak/20250613app.db index d5409f9..7e9f67c 100644 Binary files a/bak/20250429-3app.db and b/bak/20250613app.db differ diff --git a/bak/app20250422-21-18.db b/bak/app20250422-21-18.db deleted file mode 100644 index e97f8fa..0000000 Binary files a/bak/app20250422-21-18.db and /dev/null differ diff --git a/doc/README/README.md b/doc/README/README.md index 671674a..a773eab 100644 --- a/doc/README/README.md +++ b/doc/README/README.md @@ -1,259 +1,28 @@ -``` - TODO: - 1. 数据库文件是否被破坏检查 - 2. 数据库文件如果被破坏,自动恢复默认配置 - 3. 添加归零保护,底层检测,如果电机未归零就执行moveTo,则报错。 - - 坐标XY方向约定: - 0 -----------------------> - | (X) - | - | - | - | - | - v(Y) - - - - 舵机位置约定: - 抓手 - 1.夹紧位置为0 - 2.最大张开位置为300 - 3.垂直位置70 - 水平位置 - 初始位置为0 - - 2.水平移动舵机初始化位置为200(处于设备最后端) - - - 复位要求: - 1. 板夹仓推杆电机需要处于零点位置 - 2. 光学模组推杆电机需要处于零点位置 - 3. 试管架通道中没有试管架 - 4. 出料口没有试管架 - 5. 进出料位置没有试管 - -逻辑漏洞 - 1.高试管如果脱帽,会被识别成低试管。 - -TODO: - 1.想办法解决 - -4:号仓位退不出 -14 - - -``` - -``` - - - - - - 入料: - while(true) - { - - - - - } - - - - - - - - - -``` - -``` - -第一层服务 - FrontEndEventRouter 前端事件路由器 - - - 用户服务:(OK) - 1.添加 - 2.删除 - 3.修改 - ID卡服务: - 1.插入检测,插入事件上报(Service,Fn) - 2.删除 - 3.查询 - 系统服务: - 1.时间修改 - 2.本机IP - 系统配置服务: - 1. - - 设备初始化服务: - 设备初始化运行前检查 - - 耗材扫描服务: - - 样本添加服务: - - 主运行服务: - 入料与预处理控制服务: - 滴定 - 反应 - 设备运行状态服务: - - ------------------------------------------------ -第二层服务: - 硬件层 - - - 光学标定服务: - - 报表打印服务: - - - - - 开机---> 设备不动 - - - -service - core_service - event_bus - - app_service - hardware_service - setting_service - appSettingService - - - -TODO: - 初始化服务 - 物料扫描服务 - 入料服务 - 预处理服务 - 孵育服务 - 取样与反应服务 - -``` - -``` - - -``` ``` - 动作: - 入料并扫描 - 准备下一个样本 - 条件: 当前正在处理的样本处理完成 && - 急诊位Pending | 还有剩余试管未处理 +部署说明: +0. 设置好application.properties中的配置项 +1. 使用maven打包 +2. 将app.jar拷贝到 /app/ +3. 将appresource拷贝 到 /app/, (注意,如果是从git上下载下来的工程,需要拷贝bak目录下的最新的app.db到/app/appresource/db/目录下) +4. 将/appenv/目录下的 start.sh 拷贝到/app/sh/目录下 +4. 将/appenv/目录下的 restart_chrome.sh 拷贝到/app/sh/目录下 +5. 如果目标机器没有安装jdk,则需要参考 https://iflytop1.feishu.cn/wiki/FjbWwRrm2iIT08k9rkqcztFbnje 安装jdk +6. 如果没有安装 zapp.service 则创建zapp.service - - 样本处理 - BEFORE_PROCESS 预处理A(脱帽,摇匀) - BEFORE_PROCESS 预处理B(hbot取tip头,移动到待机位) - BEFORE_PROCESS 预处理C(推出反应板夹) - - PROCESS 处理(取样,处理,滴定) - - AFTER_PROCESS 后处理 - - - 将反应板推出到光学扫描位 - 光学扫描 - - - - - 代码规范 - 1. 什么样的检查写在动作中? - 需要进行报错处理的检查写在步骤中 -``` +scp ./target/a8000-1.jar root@192.168.8.10:/app/app.jar +构建基础目录 ssh root@192.168.8.10 'mkdir /app/appresource/static/ && mkdir /app/appresource/db/ && mkdir /app/sh/' +拷贝数据库 scp ./appresource/db/app.db root@192.168.8.10:/app/appresource/db/ +拷贝UI scp -r ./appresource/static/app root@192.168.8.10:/app/appresource/static/ +拷贝EXUI scp -r ./appresource/static/exui root@192.168.8.10:/app/appresource/static/ ``` -任务列表: - 0. 重新思考整个系统的状态 - - 1. 尽可能完成整个流程的控制,如果中间缺少某些位置参数,则只修改状态,让整个流程执行下去。 - 2. 支持急诊位置 - 3. 根据配置,修改对应的动作的细节,使其支持更多的试管架类型,更多的项目类型。 - 4. 完善日志 - 3. 完成剩余动作的校准工作。(取样本,取耗材,滴定,光学扫描,结果分析) - 5. 添加温度控制。 - 5. 支持吸空检测。 - 6. 支持反应板夹类型检测。 ``` - - -``` - -TODO: - 1. 如果当前板夹仓对应位置的耗材批次码没有发生变化,则耗材量不重新初始化。 - 2. tip头只有在第一次扫描时,才会初始化其数量是满的。 - -``` - - -``` -TODO: -1. 软件启动后读取所有单片机版本号。 -2. 添加温度控制服务。(不用向前台提供接口) -3. 扫描耗材时,检查ID卡,同时检查温度是否一致。 -4. MainFlowCtrl监听,温度控制异常事件,当发生异常时,主动暂停MainFlowCtrl -5. 打印结果 -6. 支持扫码枪 - -添加DEBUG模式, - 需要模拟硬件行为的地方。 - 1. 耗材扫描 - 2. 初始化 - 3. 工作流中的所有动作 - 需要产生的虚假行为 - 1. 触发.提供插入一个假的ID卡配置的事件 - 2. 触发.提供假的耗材配置 - 3. 触发.提供假的样本 - 4. 触发.添加一个假的急诊 - - -为前台提供的接口: - 设备控制 - 主流程控制 - 扫描耗材 - 添加急诊 - 开关机 - 配置: - xxx - xxx - xxx - - 数据 - 项目管理 - 用户接口 - - 事件 - ... - 错误码 - ... -``` - - -``` -TODO: - 单片机层添加急停指令,同时添加急停错误。 -``` - -```angular2html - 查看服务的日志 journalctl -u zapp.service -n 100 diff --git a/sh/deply.bat b/sh/deply.bat index 936c162..e175f28 100644 --- a/sh/deply.bat +++ b/sh/deply.bat @@ -17,7 +17,7 @@ scp %JAR_FILE% %REMOTE_USER%@%REMOTE_HOST%:%REMOTE_DIR%%REMOTE_FILE% @REM scp -r appresource %REMOTE_USER%@%REMOTE_HOST%:/app/ :: 重启远程服务器 -ssh %REMOTE_USER%@%REMOTE_HOST% `systemctl start zapp` +@REM ssh %REMOTE_USER%@%REMOTE_HOST% `systemctl start zapp` :: 判断 SCP 命令是否成功 if %errorlevel% neq 0 ( diff --git a/src/main/java/a8k/app/service/analyzer/A8kIdCardDataParseService.java b/src/main/java/a8k/app/service/analyzer/A8kIdCardDataParseService.java index dca2f7f..3bc97c6 100644 --- a/src/main/java/a8k/app/service/analyzer/A8kIdCardDataParseService.java +++ b/src/main/java/a8k/app/service/analyzer/A8kIdCardDataParseService.java @@ -238,8 +238,8 @@ public class A8kIdCardDataParseService { // ASSERT_IS_TRUE(idcard.expiryDate.before(new Date()), A8kEcode.APPE_A8K_PROJ_CARD_EXPIRYED, "ID CARD EXPIRY"); - ASSERT_IS_TRUE(idcard.lotId.length() == 8, "PARSE LOTID IS ERROR"); - ASSERT_IS_TRUE(!idcard.projName.isEmpty(), "PARSE PROJNAME IS ERROR"); + ASSERT_IS_TRUE(!idcard.lotId.isEmpty(), "LOTID IS EMPTY"); + ASSERT_IS_TRUE(!idcard.projName.isEmpty(), "PROJNAME IS EMPTY"); ProjBuildInInfo projBuildinInfo = projInfoMgrService.getProjBuildInInfo(idcard.projId); ASSERT_IS_TRUE(projBuildinInfo != null, A8kEcode.PROJ_CARD_ERROR_WRONG_UNSUPPORTED, "PROJECT ID %d NOT SUPPORTED", idcard.projId); diff --git a/src/main/java/a8k/app/service/background/SensorDataUpdateService.java b/src/main/java/a8k/app/service/background/SensorDataUpdateService.java index 6abd475..2512c8b 100644 --- a/src/main/java/a8k/app/service/background/SensorDataUpdateService.java +++ b/src/main/java/a8k/app/service/background/SensorDataUpdateService.java @@ -97,6 +97,18 @@ public class SensorDataUpdateService { } + synchronized private boolean getRecycleBinOverflowState() throws AppException { + Boolean wasteBinFullFlag0 = inputDetectDriver.getIOState(InputIOId.RecycleBinOverflowPPS); + OS.forceSleep(500); + Boolean wasteBinFullFlag1 = inputDetectDriver.getIOState(InputIOId.RecycleBinOverflowPPS); + OS.forceSleep(500); + Boolean wasteBinFullFlag2 = inputDetectDriver.getIOState(InputIOId.RecycleBinOverflowPPS); + OS.forceSleep(500); + Boolean wasteBinFullFlag3 = inputDetectDriver.getIOState(InputIOId.RecycleBinOverflowPPS); + + return wasteBinFullFlag0 && wasteBinFullFlag1 && wasteBinFullFlag2 && wasteBinFullFlag3; + } + synchronized public List getIncubateBoxTemperatureCurve() { return new ArrayList<>(incubateBoxTemperatureCurve); } @@ -109,7 +121,7 @@ public class SensorDataUpdateService { @PostConstruct public void init() { updateThread = new Thread(() -> { - OS.forceSleep(3000); //等待webSocket连接 + OS.forceSleep(3000); while (true) { if (!gStateMgrService.isDeviceInited()) { @@ -134,10 +146,9 @@ public class SensorDataUpdateService { try { - Boolean wasteBinFullFlag = inputDetectDriver.getIOState(InputIOId.RecycleBinOverflowPPS); + Boolean wasteBinFullFlag = getRecycleBinOverflowState(); gStateMgrService.updateWasteBinFullFlag(wasteBinFullFlag); - OS.forceSleep(100); Double incubateBoxTemp = temperatureControlDriver.readIncubateBoxTemperature(); gStateMgrService.updateIncubateBoxTemperature((int) (incubateBoxTemp + 0.5)); addIncubateBoxTemperatureCurve(incubateBoxTemp); @@ -152,10 +163,11 @@ public class SensorDataUpdateService { log.error("Failed to read temperature data {}", e.getMessage()); setErrorFlag(e); } + if (errorFlag) { OS.forceSleep(5000); } else { - OS.forceSleep(1000); + OS.forceSleep(2000); } } }); diff --git a/src/main/java/a8k/app/service/mainctrl/AppDeviceMainFlowCtrlService.java b/src/main/java/a8k/app/service/mainctrl/AppDeviceMainFlowCtrlService.java index 62d1e36..62d1530 100644 --- a/src/main/java/a8k/app/service/mainctrl/AppDeviceMainFlowCtrlService.java +++ b/src/main/java/a8k/app/service/mainctrl/AppDeviceMainFlowCtrlService.java @@ -34,7 +34,6 @@ public class AppDeviceMainFlowCtrlService { public void startWork() throws AppException { log.info("开始工作"); - appWarningFlagStateMgr.clearAllFlagState(); mainFlowCtrlScheduler.startWork(); } @@ -63,7 +62,6 @@ public class AppDeviceMainFlowCtrlService { public void continueWork() throws AppException { log.info("继续工作"); - appWarningFlagStateMgr.clearAllFlagState(); if (deviceWorkStateMgrService.isMainFlowTaskRun()) { mainFlowCtrlScheduler.continueWork(); } else if (deviceWorkStateMgrService.isEngineerTaskRun()) { diff --git a/src/main/java/a8k/app/service/mainctrl/MainFlowCtrlScheduler.java b/src/main/java/a8k/app/service/mainctrl/MainFlowCtrlScheduler.java index 5315439..7779213 100644 --- a/src/main/java/a8k/app/service/mainctrl/MainFlowCtrlScheduler.java +++ b/src/main/java/a8k/app/service/mainctrl/MainFlowCtrlScheduler.java @@ -55,6 +55,7 @@ public class MainFlowCtrlScheduler { private final OptScanModuleLowerCtrlService optScanModuleLowerCtrlService; private final TubeFeedingCtrlService tubeFeedingCtrlService; + private final AppWarningFlagStateMgr appWarningFlagStateMgr; private ZWorkThread workThread; @@ -99,6 +100,7 @@ public class MainFlowCtrlScheduler { } synchronized public void startWork() throws AppException { + appWarningFlagStateMgr.clearAllFlagState(); startWork(null); } @@ -121,6 +123,7 @@ public class MainFlowCtrlScheduler { } synchronized public void continueWork() throws AppException { + appWarningFlagStateMgr.clearAllFlagState(); checkBeforeCall(); checkBeforeStartOrContinueWork(); deviceWorkStateMgrService.setResumeActionPending(true); diff --git a/src/main/java/a8k/app/service/statemgr/ProjectCxtMgr.java b/src/main/java/a8k/app/service/statemgr/ProjectCxtMgr.java index a96cb01..5c023ac 100644 --- a/src/main/java/a8k/app/service/statemgr/ProjectCxtMgr.java +++ b/src/main/java/a8k/app/service/statemgr/ProjectCxtMgr.java @@ -11,10 +11,10 @@ import java.util.Map; @Slf4j public class ProjectCxtMgr { static public class ProjectCxt { - public Map cxtMap; + public Map cxtMap = new java.util.HashMap<>(); } - Map projectCxtMap; + Map projectCxtMap = new java.util.HashMap<>(); synchronized public Object getCxtValue(String cxtId, String key) { ProjectCxt projectCxt = projectCxtMap.get(cxtId); diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 0ffe1bc..80197a9 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -7,6 +7,11 @@ device.runmode: "RealMode" iflytophald.ip: 192.168.8.10 +#server.port: 80 +#device.runmode: "RealMode" +#iflytophald.ip: 127.0.0.1 + + a8k.enableTemperatureCtrl: false device.enableCanBus: true