diff --git a/app.db b/app.db index b3fb896..8eeab88 100644 Binary files a/app.db and b/app.db differ diff --git a/src/main/java/com/iflytop/digester/DigestionTaskThread.java b/src/main/java/com/iflytop/digester/DigestionTaskThread.java index 7eeecf9..d9efb9e 100644 --- a/src/main/java/com/iflytop/digester/DigestionTaskThread.java +++ b/src/main/java/com/iflytop/digester/DigestionTaskThread.java @@ -4,6 +4,7 @@ import com.iflytop.digester.model.MdbDigestionTask; import com.iflytop.digester.model.MdbDigestionSolution; import com.iflytop.digester.model.MdbDigestionTaskLog; import com.iflytop.digester.underframework.dao.model.UfMdbNotification; +import com.iflytop.digester.underframework.dao.model.UfMdbOption; import com.iflytop.digester.underframework.dao.record.UfActiveRecord; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -107,14 +108,15 @@ public class DigestionTaskThread extends Thread { lastRound = rounds.remove(rounds.size() - 1); } - // 执行第一轮 - if ( null != firstRound ) { - this.executeRound(firstRound); - } - // 执行中间轮 - for (var round : rounds) { - this.executeRound(round); - } +// // 执行第一轮 +// if ( null != firstRound ) { +// this.updateTaskStatus("FirstRound", "执行第一轮配置"); +// this.executeRound(firstRound); +// } +// // 执行中间轮 +// for (var round : rounds) { +// this.executeRound(round); +// } // 执行最后一轮 if ( null != lastRound ) { this.executeLastRound(lastRound); @@ -224,6 +226,7 @@ public class DigestionTaskThread extends Thread { // 执行消解每轮配置 private void executeRound( MdbDigestionSolution.DigestionSolutionRound digestionRound ) throws InterruptedException { + this.updateTaskStatus("RoundStart", "配置轮次开始执行"); var device = Device.getInstance(); // 加液 @@ -232,6 +235,7 @@ public class DigestionTaskThread extends Thread { for ( var liquid : digestionRound.liquids ) { this.updateTaskStatus("Liquid", String.format("加液 %s %d", liquid.type, liquid.volume)); liquidAddition.addLiquidToTubes(tubes, liquid.type, liquid.volume); + liquidAddition.shake(digestionRound.shakingCount); } // 搬运到加热转盘 @@ -245,10 +249,12 @@ public class DigestionTaskThread extends Thread { // 移至加液区, 以便执行下一轮 device.transferArm.moveTubeRackToLiquidPlate(this.heatingSlot.index); + this.updateTaskStatus("RoundFinish", "配置轮次执行结束"); } // 执行消解最后一轮配置 private void executeLastRound( MdbDigestionSolution.DigestionSolutionRound digestionRound ) throws InterruptedException { + this.updateTaskStatus("LastRound", "执行最后一轮配置开始"); this.isPrecheckFinished = false; var device = Device.getInstance(); @@ -257,13 +263,15 @@ public class DigestionTaskThread extends Thread { for ( var heating : digestionRound.heatings ) { totalDurationCount += heating.duration; } - long preCheckDuration = totalDurationCount - 10; - if ( 0 >= preCheckDuration ) { - preCheckDuration = 0; + Integer preCheckTimeOption = UfMdbOption.getInteger("DigestionLastRoundPreCheckTime", 10); + long preCheckTime = totalDurationCount - preCheckTimeOption; + if ( 0 >= preCheckTime ) { + preCheckTime = 0; } var preCheckTimerTask = new TimerTask() { @Override public void run() { + DigestionTaskThread.this.updateTaskStatus("LastRoundPreCheck", "末轮预检查开始"); try { // 检查试管 DigestionTaskThread.this.tubeCheckAndMove(); @@ -275,17 +283,22 @@ public class DigestionTaskThread extends Thread { DigestionTaskThread.this.precheckLock.notifyAll(); } } catch (Exception e) { + DigestionTaskThread.this.updateTaskStatus("LastRoundPreCheck", String.format("末轮预检查异常: %s", e.getMessage())); throw new RuntimeException(e); + } finally { + DigestionTaskThread.this.updateTaskStatus("LastRoundPreCheck", "末轮预检查结束"); } } }; var preCheckTimer = new Timer(); - preCheckTimer.schedule(preCheckTimerTask, preCheckDuration * 60 * 1000); + this.updateTaskStatus("LastRound",String.format("预检将于%d秒后执行", preCheckTime * 60)); + preCheckTimer.schedule(preCheckTimerTask, preCheckTime * 60 * 1000); // 加热 for ( var heating : digestionRound.heatings ) { - this.updateTaskStatus("heating", String.format("加热 %d℃ %d分钟", heating.temperature, heating.duration)); + this.updateTaskStatus("Heating", String.format("加热 %d℃ %d分钟", heating.temperature, heating.duration)); this.heatingSlot.heating(heating.temperature, heating.duration); + this.updateTaskStatus("Heating", "加热完成"); } // 等待预检查完成 @@ -298,6 +311,7 @@ public class DigestionTaskThread extends Thread { throw new RuntimeException(e); } } + this.updateTaskStatus("PreCheckWait", "预检完成"); } // 加水定容 @@ -318,45 +332,73 @@ public class DigestionTaskThread extends Thread { // 释放加热位 this.heatingSlot.setTubeRackNo(null); } + this.updateTaskStatus("LastRound", "执行最后一轮配置结束"); } - // 执行消解异常处理配置 + /** + * 执行消解异常处理配置 + * @param errorRound - 异常处理配置 + * @throws InterruptedException - + */ private void executeErrorRound( MdbDigestionSolution.DigestionSolutionErrorRound errorRound ) throws InterruptedException { + String errorTubeIndexListStr = String.join(",", this.errorTubeIndexes.stream().map(Object::toString).toArray(String[]::new)); + this.updateTaskStatus("ErrorRound", String.format("异常轮次开始 : [%s]", errorTubeIndexListStr)); + var device = Device.getInstance(); + var errorSlot = device.heatingTurntable.getErrorSlot(); - // 移至加液区 - device.transferArm.moveTubeRackToLiquidPlate(this.heatingSlot.index); +// this.updateTaskStatus("ErrorRound", "移动异常试管架至加液区"); +// device.transferArm.moveTubeRackToLiquidPlate(errorSlot.index); +// +// var liquidAddition = device.liquidAddition; +// for ( var liquid : errorRound.liquids ) { +// this.updateTaskStatus("ErrorRoundLiquidAdd", String.format("异常加液 %s %d", liquid.type, liquid.volume)); +// liquidAddition.addLiquidToTubes(this.errorTubeIndexes, liquid.type, liquid.volume); +// } +// this.updateTaskStatus("ErrorRoundLiquidAdd", "异常摇匀"); +// liquidAddition.shake(errorRound.shakingCount); +// +// this.updateTaskStatus("ErrorRound", "移动异常试管架至加热区"); +// device.transferArm.moveTubeRackToHeatingTurntable(errorSlot.index); +// +// for ( var heating : errorRound.heatings ) { +// this.updateTaskStatus("ErrorRoundHeating", String.format("异常加热 %d℃ %d分钟", heating.temperature, heating.duration)); +// this.heatingSlot.heating(heating.temperature, heating.duration); +// } +// +// this.updateTaskStatus("ErrorRound", "移动异常试管架至加液区"); +// device.transferArm.moveTubeRackToLiquidPlate(errorSlot.index); - // 加液 - var liquidAddition = device.liquidAddition; - for ( var liquid : errorRound.liquids ) { - this.updateTaskStatus("liquid", String.format("异常加液 %s %d", liquid.type, liquid.volume)); - liquidAddition.addLiquidToTubes(this.errorTubeIndexes, liquid.type, liquid.volume); - } - - // 搬运到加热转盘 - device.transferArm.moveTubeRackToHeatingTurntable(this.heatingSlot.index); + // 拍照检查是否存在消解完成的试管 + this.takeShotAndCheckFinishedTubes(); - // 加热 - for ( var heating : errorRound.heatings ) { - this.updateTaskStatus("heating", String.format("异常加热 %d℃ %d分钟", heating.temperature, heating.duration)); - this.heatingSlot.heating(heating.temperature, heating.duration); + // 如果不存在消解完成的试管则本轮次结束 + if (this.finishedErrorTubeIndexes.isEmpty()) { + return ; } - // 移至加液区 - device.transferArm.moveTubeRackToLiquidPlate(this.heatingSlot.index); - // 拍照检查是否存在消解完成的试管 - this.takeShotAndCheckFinishedTubes(); - // 将试管架放入异常处理区域 - device.transferArm.moveTubeRackToHeatingTurntable(this.heatingSlot.index); +// this.updateTaskStatus("ErrorRound", "移动异常试管架至加热区"); +// device.transferArm.moveTubeRackToHeatingTurntable(errorSlot.index); + // 等待放入空试管架 + device.door.open(); this.waitForEmptyTubeRackPutIn(); - // 取出消解完成的试管 + device.door.close(); + + String finishedTubeIndexListStr = String.join(",", this.finishedErrorTubeIndexes.stream().map(Object::toString).toArray(String[]::new)); + this.updateTaskStatus("ErrorRound", String.format("取出消解完成的试管 : %s", finishedTubeIndexListStr)); device.transferArm.takeOutTubesFromErrorSlot(this.finishedErrorTubeIndexes); + // 等待取出试管架 + device.door.open(); this.waitForTubeRackTakeOut(); + device.door.close(); + // 更新异常试管索引列表 this.errorTubeIndexes.removeAll(this.finishedErrorTubeIndexes); + + String remainTubeIndexListStr = String.join(",", this.errorTubeIndexes.stream().map(Object::toString).toArray(String[]::new)); + this.updateTaskStatus("ErrorRound", String.format("异常轮次执行结束, 异常试管剩余 : [%s]", remainTubeIndexListStr)); } // 等待放入试管架 @@ -435,7 +477,7 @@ public class DigestionTaskThread extends Thread { } catch (InterruptedException e) { throw new RuntimeException(e); } - } + } // @TODO : 这里记录下试管索引 this.updateTaskStatus("TubeCheck", "异常试管已确认"); } diff --git a/src/main/java/com/iflytop/digester/camera/.vs/baslerCamera/FileContentIndex/003a4049-43a8-4685-b725-0ef981a63d09.vsidx b/src/main/java/com/iflytop/digester/camera/.vs/baslerCamera/FileContentIndex/003a4049-43a8-4685-b725-0ef981a63d09.vsidx deleted file mode 100644 index 19e6464..0000000 Binary files a/src/main/java/com/iflytop/digester/camera/.vs/baslerCamera/FileContentIndex/003a4049-43a8-4685-b725-0ef981a63d09.vsidx and /dev/null differ diff --git a/src/main/java/com/iflytop/digester/camera/.vs/baslerCamera/FileContentIndex/32a71717-b8c7-4106-8f15-99bbd922817c.vsidx b/src/main/java/com/iflytop/digester/camera/.vs/baslerCamera/FileContentIndex/32a71717-b8c7-4106-8f15-99bbd922817c.vsidx new file mode 100644 index 0000000..93e160d Binary files /dev/null and b/src/main/java/com/iflytop/digester/camera/.vs/baslerCamera/FileContentIndex/32a71717-b8c7-4106-8f15-99bbd922817c.vsidx differ diff --git a/src/main/java/com/iflytop/digester/camera/.vs/baslerCamera/FileContentIndex/0c5d8c00-190b-4149-adea-d196cfb732c1.vsidx b/src/main/java/com/iflytop/digester/camera/.vs/baslerCamera/FileContentIndex/3ffb981f-6afa-4d2f-a956-f6e71b0a3ff7.vsidx similarity index 62% rename from src/main/java/com/iflytop/digester/camera/.vs/baslerCamera/FileContentIndex/0c5d8c00-190b-4149-adea-d196cfb732c1.vsidx rename to src/main/java/com/iflytop/digester/camera/.vs/baslerCamera/FileContentIndex/3ffb981f-6afa-4d2f-a956-f6e71b0a3ff7.vsidx index 2c73cc0..e6b3c59 100644 Binary files a/src/main/java/com/iflytop/digester/camera/.vs/baslerCamera/FileContentIndex/0c5d8c00-190b-4149-adea-d196cfb732c1.vsidx and b/src/main/java/com/iflytop/digester/camera/.vs/baslerCamera/FileContentIndex/3ffb981f-6afa-4d2f-a956-f6e71b0a3ff7.vsidx differ diff --git a/src/main/java/com/iflytop/digester/camera/.vs/baslerCamera/v17/.suo b/src/main/java/com/iflytop/digester/camera/.vs/baslerCamera/v17/.suo index d03924f..8147299 100644 Binary files a/src/main/java/com/iflytop/digester/camera/.vs/baslerCamera/v17/.suo and b/src/main/java/com/iflytop/digester/camera/.vs/baslerCamera/v17/.suo differ diff --git a/src/main/java/com/iflytop/digester/camera/.vs/baslerCamera/v17/Browse.VC.db b/src/main/java/com/iflytop/digester/camera/.vs/baslerCamera/v17/Browse.VC.db index a7cd360..cdb3d02 100644 Binary files a/src/main/java/com/iflytop/digester/camera/.vs/baslerCamera/v17/Browse.VC.db and b/src/main/java/com/iflytop/digester/camera/.vs/baslerCamera/v17/Browse.VC.db differ diff --git a/src/main/java/com/iflytop/digester/camera/DiComBaslerCamera.cpp b/src/main/java/com/iflytop/digester/camera/DiComBaslerCamera.cpp index 2ef7b04..2f3d5a2 100644 --- a/src/main/java/com/iflytop/digester/camera/DiComBaslerCamera.cpp +++ b/src/main/java/com/iflytop/digester/camera/DiComBaslerCamera.cpp @@ -246,7 +246,7 @@ JNIEXPORT jobject JNICALL CAMERA(deviceGrabSingleFrame)(JNIEnv* env, jobject, jl return nullptr; } - jclass javaGrabResultClass = env->FindClass("com/my/graphiteDigesterBg/diframe/component/baslerCamera/DiComBaslerCamera$GrabResult"); + jclass javaGrabResultClass = env->FindClass("com/iflytop/digester/camera/DiComBaslerCamera$GrabResult"); if (javaGrabResultClass == NULL) { throwException(env, "unable to find java grab result class"); return NULL; diff --git a/src/main/java/com/iflytop/digester/controller/CameraController.java b/src/main/java/com/iflytop/digester/controller/CameraController.java index 3e5a0ab..8e928d3 100644 --- a/src/main/java/com/iflytop/digester/controller/CameraController.java +++ b/src/main/java/com/iflytop/digester/controller/CameraController.java @@ -1,15 +1,42 @@ package com.iflytop.digester.controller; +import com.iflytop.digester.deviceinstance.Device; import com.iflytop.digester.underframework.controller.UfApiControllerBase; import com.iflytop.digester.underframework.controller.UfApiResponse; +import jakarta.annotation.Resource; +import org.opencv.core.Core; +import org.opencv.core.Mat; +import org.opencv.core.MatOfByte; +import org.opencv.core.Rect; +import org.opencv.imgcodecs.Imgcodecs; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.ResponseBody; + +import java.util.Base64; import java.util.Map; @Controller public class CameraController extends UfApiControllerBase { + @Resource + private Device device; + @ResponseBody @PostMapping("/api/camera/take-shot") public UfApiResponse takeShot() { - return this.success(Map.of("data", "https://avatars.githubusercontent.com/u/53512912?v=4")); + var srcImageMat = this.device.camera.grabToMat(); + + // 翻转图像 + Mat flippedImgMat = new Mat(); + Core.flip(srcImageMat, flippedImgMat, 1); + + // 裁剪图像 + Rect croppedRoi = new Rect(240, 120, 800, 800); + Mat croppedImgMat = new Mat(flippedImgMat, croppedRoi); + + MatOfByte imageMob = new MatOfByte(); + Imgcodecs.imencode(".png", croppedImgMat, imageMob); + byte[] imageBytes = imageMob.toArray(); + String base64Image = Base64.getEncoder().encodeToString(imageBytes); + String base64Data = "data:image/image/png;base64," + base64Image; + return this.success(Map.of("data",base64Data)); } } diff --git a/src/main/java/com/iflytop/digester/controller/TestController.java b/src/main/java/com/iflytop/digester/controller/TestController.java new file mode 100644 index 0000000..1dfce56 --- /dev/null +++ b/src/main/java/com/iflytop/digester/controller/TestController.java @@ -0,0 +1,25 @@ +package com.iflytop.digester.controller; +import com.iflytop.digester.deviceinstance.Device; +import com.iflytop.digester.underframework.controller.UfApiControllerBase; +import com.iflytop.digester.underframework.controller.UfApiResponse; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.ResponseBody; + +import java.util.List; +import java.util.Map; +@Controller +public class TestController extends UfApiControllerBase { + @Resource + private Device device; + + @ResponseBody + @PostMapping("/api/test/move-tube-from-error-slot-to-liquid-plate") + public UfApiResponse moveTubeFromErrorSlotToLiquidPlate(@RequestBody Map params) { + List indexes = (List)params.get("indexes"); + this.device.transferArm.takeOutTubesFromErrorSlot(indexes); + return this.success(); + } +} diff --git a/src/main/java/com/iflytop/digester/deviceinstance/LiquidAdditionInstance.java b/src/main/java/com/iflytop/digester/deviceinstance/LiquidAdditionInstance.java index 8ac0783..8187b52 100644 --- a/src/main/java/com/iflytop/digester/deviceinstance/LiquidAdditionInstance.java +++ b/src/main/java/com/iflytop/digester/deviceinstance/LiquidAdditionInstance.java @@ -117,4 +117,16 @@ public class LiquidAdditionInstance { } throw new RuntimeException("未找到对应的液体类型"); } + + // 摇匀 + public void shake( Integer count ) { + if ( 0 == count ) { + return ; + } + UfCmdSnippetExecutor.execute("LiquidAddShakeSetup"); + for ( int i=0; i(); snippetParams.put("LiquidPlatePos", UfMdbOption.getInteger("LiquidPlateTube." + tubeIndex, 0)); - snippetParams.put("TransLrSrcPos", UfMdbOption.getInteger("HeatPlateErrorSlotTube." + tubeIndex, 0)); - snippetParams.put("HeatingPlatePos", UfMdbOption.getInteger("TransLrMotorLiquidPlateTube." + tubeIndex, 0)); - snippetParams.put("TransLrDestPos", UfMdbOption.getInteger("TransLrMotorHeatingPlateTube." + tubeIndex, 0)); + snippetParams.put("HeatingPlatePos", UfMdbOption.getInteger("HeatPlateErrorSlotTube." + tubeIndex, 0)); + snippetParams.put("TransLrSrcPos", UfMdbOption.getInteger("TransLrMotorHeatingPlateTube." + tubeIndex, 0)); + snippetParams.put("TransLrDestPos", UfMdbOption.getInteger("TransLrMotorLiquidPlateTube." + tubeIndex, 0)); UfCmdSnippetExecutor.execute(snippetKey, snippetParams); } this.unlockArm(lock); diff --git a/src/main/java/com/iflytop/digester/model/MdbDigestionSolution.java b/src/main/java/com/iflytop/digester/model/MdbDigestionSolution.java index aeefdac..cf611c3 100644 --- a/src/main/java/com/iflytop/digester/model/MdbDigestionSolution.java +++ b/src/main/java/com/iflytop/digester/model/MdbDigestionSolution.java @@ -42,6 +42,7 @@ public class MdbDigestionSolution extends UfActiveRecord { liquid.volume = liquidNode.get("volume").asInt(); round.liquids.add(liquid); }); + round.shakingCount = roundNode.get("shaking").asInt(); // 加热配置 round.heatings = new ArrayList<>(); roundNode.get("heating").forEach(heatingNode -> { @@ -74,6 +75,7 @@ public class MdbDigestionSolution extends UfActiveRecord { liquid.volume = liquidNode.get("volume").asInt(); errorRound.liquids.add(liquid); }); + errorRound.shakingCount = errorRoundsJsonTree.get("shaking").asInt(); // 加热配置 errorRound.heatings = new ArrayList<>(); errorRoundsJsonTree.get("heating").forEach(heatingNode -> { @@ -104,6 +106,8 @@ public class MdbDigestionSolution extends UfActiveRecord { // 加液配置 public List liquids; + // 摇匀次数 + public Integer shakingCount; // 加热配置 public List heatings; // 加水定容 @@ -122,6 +126,8 @@ public class MdbDigestionSolution extends UfActiveRecord { // 加液配置 public List liquids; + // 摇匀次数 + public Integer shakingCount; // 加热配置 public List heatings; // 最大轮数 diff --git a/src/main/java/com/iflytop/digester/model/MdbDigestionTaskLog.java b/src/main/java/com/iflytop/digester/model/MdbDigestionTaskLog.java index 845c65f..a2d68e6 100644 --- a/src/main/java/com/iflytop/digester/model/MdbDigestionTaskLog.java +++ b/src/main/java/com/iflytop/digester/model/MdbDigestionTaskLog.java @@ -1,6 +1,10 @@ package com.iflytop.digester.model; import com.iflytop.digester.underframework.dao.record.UfActiveRecord; import com.iflytop.digester.underframework.dao.record.UfActiveRecordField; + +import java.text.SimpleDateFormat; +import java.util.Date; + public class MdbDigestionTaskLog extends UfActiveRecord { @UfActiveRecordField public String taskId; @@ -14,6 +18,9 @@ public class MdbDigestionTaskLog extends UfActiveRecord { @UfActiveRecordField public Long timestamp; + @UfActiveRecordField + public String time; + // get table name public static String getTableName() { return "app_digestion_task_logs"; @@ -26,6 +33,8 @@ public class MdbDigestionTaskLog extends UfActiveRecord { log.action = action; log.content = content; log.timestamp = System.currentTimeMillis(); + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + log.time = simpleDateFormat.format(new Date()); log.save(); } } diff --git a/src/main/java/com/iflytop/digester/underframework/connection/UfZcancmderWebsocket.java b/src/main/java/com/iflytop/digester/underframework/connection/UfZcancmderWebsocket.java index 2ae9146..d6a9e46 100644 --- a/src/main/java/com/iflytop/digester/underframework/connection/UfZcancmderWebsocket.java +++ b/src/main/java/com/iflytop/digester/underframework/connection/UfZcancmderWebsocket.java @@ -158,13 +158,7 @@ public class UfZcancmderWebsocket extends UfConnectionBase { UfMdbActuator actuator = UfMdbActuator.findOne(UfMdbActuator.class, actuatorCmd.actuatorId); LOG.info(" [Command-Executor:{}] {}({}) => {}", actuator.name, actuatorCmd.cmdKey, actuatorCmd.parameters, cmd); - if ( !this.client.isOpen() ) { - try { - this.client.connectBlocking(); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - } + this.reconnectIfClosed(); TimerTask task = new TimerTask() { @Override @@ -176,6 +170,36 @@ public class UfZcancmderWebsocket extends UfConnectionBase { timer.schedule(task, 10); } + // reconnect if closed + private void reconnectIfClosed() { + if ( this.client.isOpen() ) { + return ; + } + + var connectThread = new Thread(() -> { + do { + LOG.info("[Connection#{}] reconnecting ...", this.name); + try { + this.client.reconnectBlocking(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } while ( true ); + }); + + connectThread.start(); + try { + connectThread.join(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + // build command private String buildCommand(UfMdbActuatorCmd actuatorCmd) { String params = actuatorCmd.parameters.trim(); diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index 327d12d..28d6d86 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -34,7 +34,7 @@ mqtt-broker: app : errorSlotIndex : 4 - liquidPeristalticPumpPipeSetupEnable : true + liquidPeristalticPumpPipeSetupEnable : false liquidPipeVolumn : 1 opencv-library-path: D:/ProgramFiles/OpenCV/opencv/build/java/x64/opencv_java490.dll pylon-library-path: D:/ProgramFiles/Pylon5/Runtime/x64/PylonC_v5_2.dll diff --git a/web b/web index 4641118..dee1862 160000 --- a/web +++ b/web @@ -1 +1 @@ -Subproject commit 464111807ce66ce1d0f0652455cc17689d12ab7e +Subproject commit dee18622264b9391dedae06957d92d1c834b5c80