sige 1 year ago
parent
commit
a38a0f9542
  1. BIN
      app.db
  2. BIN
      doc/MQTT.pdf
  3. 1
      emergency-stop.txt
  4. 80
      src/main/java/com/iflytop/digester/underframework/UfActuatorCmdExecutor.java
  5. 24
      src/main/java/com/iflytop/digester/underframework/UfCmdSnippetExecutor.java
  6. 13
      src/main/java/com/iflytop/digester/underframework/connection/UfZcancmderWebsocket.java
  7. 7
      src/main/resources/application-dev.yml
  8. 3
      src/main/resources/application-test.yml

BIN
app.db

BIN
doc/MQTT.pdf

1
emergency-stop.txt

@ -0,0 +1 @@
1

80
src/main/java/com/iflytop/digester/underframework/UfActuatorCmdExecutor.java

@ -1,11 +1,36 @@
package com.iflytop.digester.underframework; package com.iflytop.digester.underframework;
import com.iflytop.digester.underframework.dao.model.UfMdbActuator; import com.iflytop.digester.underframework.dao.model.UfMdbActuator;
import com.iflytop.digester.underframework.dao.model.UfMdbActuatorCmd; import com.iflytop.digester.underframework.dao.model.UfMdbActuatorCmd;
import com.iflytop.digester.underframework.dao.model.UfMdbNotification;
import com.iflytop.digester.underframework.dao.record.UfActiveRecord; import com.iflytop.digester.underframework.dao.record.UfActiveRecord;
import com.iflytop.digester.underframework.util.UfCommon;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.TimerTask;
public class UfActuatorCmdExecutor { public class UfActuatorCmdExecutor {
// logger
public static final Logger LOG = LoggerFactory.getLogger(UfActuatorCmdExecutor.class);
// emergency stop restore lock
private static final Object emergencyStopRestoreLock = new Object();
// execute command
public static String emergencyExecute(UfMdbActuatorCmd cmd) {
var con = UfApplication.getApp().connections.get(cmd.connectionKey);
return con.execute(cmd);
}
// execute cmd // execute cmd
public static String execute(UfMdbActuatorCmd cmd) { public static String execute(UfMdbActuatorCmd cmd) {
if ( UfActuatorCmdExecutor.hasEmergencyStopTriggered() ) {
throw new RuntimeException("触发紧急停止");
}
var con = UfApplication.getApp().connections.get(cmd.connectionKey); var con = UfApplication.getApp().connections.get(cmd.connectionKey);
return con.execute(cmd); return con.execute(cmd);
} }
@ -30,4 +55,59 @@ public class UfActuatorCmdExecutor {
public static String execute(String actuatorKey, String cmdKey) { public static String execute(String actuatorKey, String cmdKey) {
return execute(actuatorKey, cmdKey, null); return execute(actuatorKey, cmdKey, null);
} }
// check if emergency stop triggered
private static Boolean hasEmergencyStopTriggered() {
String filePath = UfApplication.getApp().getEnv().getProperty("app.emergency-stop-file-path");
if ( null == filePath ) {
return false;
}
// read all content from file as string
try {
String state = Files.readString(Path.of(filePath));
if ( "1".equals(state) ) {
return false; // not triggered
}
} catch (IOException e) {
throw new RuntimeException(e);
}
// triggered
LOG.warn("急停触发");
UfMdbNotification.action("EmergencyStop", new HashMap<>());
UfCmdSnippetExecutor.execute("EmergencyStop");
var restoreCheckThread = new Thread(UfActuatorCmdExecutor::emergencyStopRestoreCheck);
restoreCheckThread.start();
synchronized ( UfActuatorCmdExecutor.emergencyStopRestoreLock ) {
try {
UfActuatorCmdExecutor.emergencyStopRestoreLock.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
UfCmdSnippetExecutor.execute("EmergencyStopRestore");
return true;
}
// 急停恢复
public static void emergencyStopRestoreCheck() {
do {
UfCommon.delay(1000);
String filePath = UfApplication.getApp().getEnv().getProperty("app.emergency-stop-file-path");
assert filePath != null;
try {
String state = Files.readString(Path.of(filePath));
if ( "1".equals(state) ) {
break;
}
} catch (IOException e) {
throw new RuntimeException(e);
}
} while ( true );
LOG.warn("急停恢复");
synchronized ( UfActuatorCmdExecutor.emergencyStopRestoreLock ) {
UfActuatorCmdExecutor.emergencyStopRestoreLock.notify();
}
}
} }

24
src/main/java/com/iflytop/digester/underframework/UfCmdSnippetExecutor.java

@ -26,6 +26,25 @@ public class UfCmdSnippetExecutor {
private final UfMdbSnippet snippet; private final UfMdbSnippet snippet;
// params // params
private final Map<String, Object> params; private final Map<String, Object> params;
// emergency mode state
private Boolean emergencyModeEnable = false;
// 紧急模式运行
static public void emergencyExecute( String snippetKey ) {
Boolean logEnabled = UfMdbOption.getBoolean("DeviceCommandSnippetLogEnable", true);
if ( Boolean.TRUE.equals(logEnabled) ) {
LOG.info("*EMERGENCY* [Snippet Execute] : {}", snippetKey);
}
var snippet = UfActiveRecord.findOne(UfMdbSnippet.class, Map.of("key", snippetKey));
if (null == snippet) {
throw new RuntimeException("无效的片段KEY : " + snippetKey);
}
var executor = new UfCmdSnippetExecutor(snippet, new HashMap<>());
executor.setEmergencyModeEnable(true);
executor.run();
}
/** /**
* execute snippet * execute snippet
@ -61,6 +80,11 @@ public class UfCmdSnippetExecutor {
this.params = params; this.params = params;
} }
// set emergency mode
public void setEmergencyModeEnable( Boolean enable ) {
this.emergencyModeEnable = enable;
}
// execute snippet // execute snippet
public void run() { public void run() {
ObjectMapper jsonMapper = new ObjectMapper(); ObjectMapper jsonMapper = new ObjectMapper();

13
src/main/java/com/iflytop/digester/underframework/connection/UfZcancmderWebsocket.java

@ -119,15 +119,15 @@ public class UfZcancmderWebsocket extends UfConnectionBase {
} }
} }
if ( null != this.responseError ) {
throw new RuntimeException(this.responseError);
}
if ( null == this.response ) { if ( null == this.response ) {
var actuator = UfActiveRecord.findOne(UfMdbActuator.class, actuatorCmd.actuatorId); var actuator = UfActiveRecord.findOne(UfMdbActuator.class, actuatorCmd.actuatorId);
throw new RuntimeException(String.format("设备 [%s] 响应超时: %s", actuator.name, actuatorCmd.cmdKey)); throw new RuntimeException(String.format("设备 [%s] 响应超时: %s", actuator.name, actuatorCmd.cmdKey));
} }
if ( null != this.responseError ) {
throw new RuntimeException(this.responseError);
}
var responseLength = this.response.capacity(); var responseLength = this.response.capacity();
if ( 8 == responseLength ) { if ( 8 == responseLength ) {
return ""; return "";
@ -284,8 +284,9 @@ public class UfZcancmderWebsocket extends UfConnectionBase {
private void handleOnTextErrorMessage(ByteBuffer message) { private void handleOnTextErrorMessage(ByteBuffer message) {
Integer errorCode = message.getInt(8); Integer errorCode = message.getInt(8);
String errorMessage = switch (errorCode) { String errorMessage = switch (errorCode) {
case 3 -> "操作不支持";
case 14 -> "参数数量不匹配";
case 3 -> "操作不支持(koperation_not_support)";
case 11 -> "子设备超时(ksubdevice_overtime)";
case 14 -> "参数数量不匹配(kcmd_param_num_error)";
default -> "未知"; default -> "未知";
}; };

7
src/main/resources/application-dev.yml

@ -14,11 +14,11 @@ device:
key : zcancmder key : zcancmder
enable : true enable : true
type : ZcancmderWebsocket type : ZcancmderWebsocket
# uri: ws://192.168.8.10:19005
uri : ws://127.0.0.1:19005
uri: ws://192.168.8.10:19005
# uri : ws://127.0.0.1:19005
- name : modbus - name : modbus
key : modbus key : modbus
enable : false
enable : true
type : ModbusRTUOverTCP type : ModbusRTUOverTCP
host: 192.168.8.10 host: 192.168.8.10
port: 20000 port: 20000
@ -30,3 +30,4 @@ app :
opencv-library-path: D:/ProgramFiles/OpenCV/opencv/build/java/x64/opencv_java490.dll 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 pylon-library-path: D:/ProgramFiles/Pylon5/Runtime/x64/PylonC_v5_2.dll
pylon-wrapper-path: D:/Sige5193/digester/src/main/java/com/iflytop/digester/camera/x64/Debug/baslerCamera.dll pylon-wrapper-path: D:/Sige5193/digester/src/main/java/com/iflytop/digester/camera/x64/Debug/baslerCamera.dll
emergency-stop-file-path : D:/Sige5193/digester/emergency-stop.txt

3
src/main/resources/application-test.yml

@ -28,4 +28,5 @@ app :
bucketVolumeCheckEnable: false bucketVolumeCheckEnable: false
opencv-library-path: /userdata/rootfs_overlay/usr/lib/jni/libopencv_java420.so opencv-library-path: /userdata/rootfs_overlay/usr/lib/jni/libopencv_java420.so
pylon-library-path: /opt/pylon/lib/libpylonc.so.7.2 pylon-library-path: /opt/pylon/lib/libpylonc.so.7.2
pylon-wrapper-path: /app/basler-camera-java-wrapper/libpylonc-wrapper.so
pylon-wrapper-path: /app/basler-camera-java-wrapper/libpylonc-wrapper.so
emergency-stop-file-path: /sys/class/gpio/gpio102/value
Loading…
Cancel
Save