feat():OPC UA环境
This commit is contained in:
@@ -47,12 +47,12 @@
|
|||||||
<artifactId>ruoyi-framework</artifactId>
|
<artifactId>ruoyi-framework</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- 加密解密工具-->
|
<!-- 加密解密工具 opc-->
|
||||||
<dependency>
|
<!-- <dependency>-->
|
||||||
<groupId>org.bouncycastle</groupId>
|
<!-- <groupId>org.bouncycastle</groupId>-->
|
||||||
<artifactId>bcprov-jdk15on</artifactId>
|
<!-- <artifactId>bcprov-jdk15on</artifactId>-->
|
||||||
<version>1.70</version>
|
<!-- <version>1.70</version>-->
|
||||||
</dependency>
|
<!-- </dependency>-->
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
@@ -108,6 +108,14 @@
|
|||||||
<artifactId>spring-boot-starter-websocket</artifactId>
|
<artifactId>spring-boot-starter-websocket</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- OPC UA 集成 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.kangaroohy</groupId>
|
||||||
|
<artifactId>milo-spring-boot-starter</artifactId>
|
||||||
|
<version>3.1.4.0.6.15</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
<!-- <dependency>-->
|
<!-- <dependency>-->
|
||||||
<!-- <groupId>com.alibaba</groupId>-->
|
<!-- <groupId>com.alibaba</groupId>-->
|
||||||
<!-- <artifactId>fastjson</artifactId>-->
|
<!-- <artifactId>fastjson</artifactId>-->
|
||||||
|
|||||||
@@ -36,14 +36,14 @@ public class AppMeasureEntryMessage extends OpcMessage {
|
|||||||
@Schema(description = "钢带速度 (m/min)")
|
@Schema(description = "钢带速度 (m/min)")
|
||||||
private BigDecimal stripSpeed;
|
private BigDecimal stripSpeed;
|
||||||
|
|
||||||
@Schema(description = "入口活套位置最大值 (m)")
|
@Schema(description = "入口活套位置(m)")
|
||||||
private BigDecimal entryLooperPositionMax;
|
private BigDecimal celLength;
|
||||||
|
|
||||||
@Schema(description = "入口活套位置最小值 (m)")
|
@Schema(description = "入口活套百分比(m)")
|
||||||
private BigDecimal entryLooperPositionMin;
|
private BigDecimal celCapacity;
|
||||||
|
|
||||||
@Schema(description = "当前实际活套位置 (m)")
|
@Schema(description = "入口活套张力(m)")
|
||||||
private BigDecimal entryLooperPositionCurrent;
|
private BigDecimal tensionCel ;
|
||||||
|
|
||||||
@Schema(description = "清洗电压 (V)")
|
@Schema(description = "清洗电压 (V)")
|
||||||
private BigDecimal cleaningVoltage;
|
private BigDecimal cleaningVoltage;
|
||||||
|
|||||||
@@ -21,17 +21,14 @@ public class AppMeasureExitMessage extends OpcMessage {
|
|||||||
@Schema(description = "钢带张力 BR8 – BR9 (daN)")
|
@Schema(description = "钢带张力 BR8 – BR9 (daN)")
|
||||||
private BigDecimal tensionBr8Br9;
|
private BigDecimal tensionBr8Br9;
|
||||||
|
|
||||||
@Schema(description = "出口活套位置 (m)")
|
@Schema(description = "入口活套位置(m)")
|
||||||
private BigDecimal deliveryLooperPosition;
|
private BigDecimal cxlLength;
|
||||||
|
|
||||||
@Schema(description = "出口活套最大可用百分比 (%)")
|
@Schema(description = "入口活套百分比(m)")
|
||||||
private BigDecimal exitLooperMaxPercent;
|
private BigDecimal cxlCapacity;
|
||||||
|
|
||||||
@Schema(description = "出口活套最小可用百分比 (%)")
|
@Schema(description = "入口活套张力(m)")
|
||||||
private BigDecimal exitLooperMinPercent;
|
private BigDecimal tensionCxl ;
|
||||||
|
|
||||||
@Schema(description = "出口活套当前百分比 (%)")
|
|
||||||
private BigDecimal exitLooperCurrentPercent;
|
|
||||||
|
|
||||||
@Schema(description = "涂油标志 (0=no, 1=yes)")
|
@Schema(description = "涂油标志 (0=no, 1=yes)")
|
||||||
private Integer oilingFlag;
|
private Integer oilingFlag;
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
11111
|
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
package com.fizz.business.scheduled;
|
||||||
|
|
||||||
|
import com.fizz.business.utils.RedisLockUtil;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.scheduling.annotation.Async;
|
||||||
|
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Async("threadPoolTaskExecutor")
|
||||||
|
@Component
|
||||||
|
@EnableScheduling
|
||||||
|
public abstract class BaseSchedule {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 默认key过期时间 1800秒
|
||||||
|
*/
|
||||||
|
private static final int DEFAULT_EXPIRE_SECONDS = 1800;
|
||||||
|
|
||||||
|
protected void execute(String taskName, int cacheSeconds, String cacheKey, Runnable func) {
|
||||||
|
// 执行完2分钟 删除键值
|
||||||
|
int delayedSeconds = Math.min(120, cacheSeconds / 10);
|
||||||
|
execute(taskName, cacheSeconds, delayedSeconds, cacheKey, k -> func.run());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 定时任务执行 多服务防止同时执行
|
||||||
|
*
|
||||||
|
* @param taskName: 任务名称
|
||||||
|
* @param cacheSeconds: <= 0时默认时间
|
||||||
|
* @param delayedSeconds: 任务执行完延时删除key; <0时默认 cacheSeconds/10
|
||||||
|
* @param cacheKey:
|
||||||
|
* @param func: 执行的任务 key: 处理后的cacheKey
|
||||||
|
*/
|
||||||
|
protected void execute(String taskName, int cacheSeconds, int delayedSeconds, String cacheKey, Consumer<String> func) {
|
||||||
|
String threadName = Thread.currentThread().getName();
|
||||||
|
cacheKey = "scheduling:" + cacheKey;
|
||||||
|
if (cacheSeconds <= 0) {
|
||||||
|
cacheSeconds = DEFAULT_EXPIRE_SECONDS;
|
||||||
|
}
|
||||||
|
if (delayedSeconds < 0) {
|
||||||
|
delayedSeconds = cacheSeconds / 10;
|
||||||
|
}
|
||||||
|
// 不存在键值时执行
|
||||||
|
String value = "1";
|
||||||
|
boolean success = RedisLockUtil.setIfAbsent(cacheKey, value, cacheSeconds);
|
||||||
|
if (!success) {
|
||||||
|
log.debug("定时任务: {}, 取消执行. {}", taskName, threadName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
log.debug("定时任务: {}, 开始执行. {}", taskName, threadName);
|
||||||
|
func.accept(cacheKey);
|
||||||
|
// 执行完后 延时时间内不可重复执行
|
||||||
|
if (delayedSeconds == 0) {
|
||||||
|
RedisLockUtil.delLock(cacheKey, value);
|
||||||
|
} else {
|
||||||
|
RedisLockUtil.setIfPresent(cacheKey, value, delayedSeconds);
|
||||||
|
}
|
||||||
|
log.debug("定时任务: {}, 执行结束. {}", taskName, threadName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void actionCatchException(Runnable func) {
|
||||||
|
String threadName = Thread.currentThread().getName();
|
||||||
|
try {
|
||||||
|
func.run();
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("定时任务执行出错 " + threadName, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package com.fizz.business.scheduled;
|
||||||
|
|
||||||
|
import cn.hutool.json.JSONUtil;
|
||||||
|
import com.kangaroohy.milo.model.ReadWriteEntity;
|
||||||
|
import com.kangaroohy.milo.service.MiloService;
|
||||||
|
import jdk.nashorn.internal.runtime.Debug;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
//@Component
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class LineMeasureSchedule extends BaseSchedule{
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
MiloService miloService;
|
||||||
|
@Scheduled(fixedDelay = 200)
|
||||||
|
public void L1L2LineMeasure() {
|
||||||
|
try {
|
||||||
|
ReadWriteEntity node = miloService.readFromOpcUa("ns=2;s=通道 2.LockStautsRead.lockStauts1");
|
||||||
|
log.debug(node.toString());
|
||||||
|
node.getValue();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
package com.fizz.business.utils;
|
||||||
|
|
||||||
|
import cn.hutool.core.lang.Pair;
|
||||||
|
import cn.hutool.core.util.IdUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.data.redis.core.script.DefaultRedisScript;
|
||||||
|
import org.springframework.data.redis.core.script.RedisScript;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class RedisLockUtil {
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(RedisLockUtil.class);
|
||||||
|
public static final RedisScript<Long> UNLOCK_SCRIPT = new DefaultRedisScript("if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end", Long.class);
|
||||||
|
private static final String UNLOCK_LUA = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
|
||||||
|
private static RedisTemplate<String, String> REDIS_TEMPLATE;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public void setRedisTemplate(RedisTemplate<String, String> redisTemplate) {
|
||||||
|
REDIS_TEMPLATE = redisTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
|
private RedisLockUtil() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean setIfAbsent(@NotNull String key, @NotNull String value, int seconds) {
|
||||||
|
Boolean result = REDIS_TEMPLATE.opsForValue().setIfAbsent(key, value, (long)seconds, TimeUnit.SECONDS);
|
||||||
|
return result != null && result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean setIfPresent(@NotNull String key, @NotNull String value, int seconds) {
|
||||||
|
Boolean result = REDIS_TEMPLATE.opsForValue().setIfPresent(key, value, (long)seconds, TimeUnit.SECONDS);
|
||||||
|
return result != null && result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void delLock(@NotNull String key, @NotNull String value) {
|
||||||
|
REDIS_TEMPLATE.execute(UNLOCK_SCRIPT, Collections.singletonList(key), new Object[]{value});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <V> Pair<Boolean, V> lockHandle(@NotNull String key, @NotNull Callable<V> callable, @NotNull Function<Exception, Pair<Boolean, V>> exceptionHandle) {
|
||||||
|
String threadName = Thread.currentThread().getName();
|
||||||
|
String msg = "RedisLockUtil " + threadName + " {}:" + key;
|
||||||
|
String value = IdUtil.simpleUUID();
|
||||||
|
boolean success = setIfAbsent(key, value, 6000);
|
||||||
|
if (!success) {
|
||||||
|
log.debug(msg, "锁获取失败");
|
||||||
|
return new Pair(false, (Object)null);
|
||||||
|
} else {
|
||||||
|
log.debug(msg, "锁获取成功");
|
||||||
|
|
||||||
|
Pair var8;
|
||||||
|
try {
|
||||||
|
V v = callable.call();
|
||||||
|
log.debug(msg, "执行完成");
|
||||||
|
var8 = new Pair(true, v);
|
||||||
|
return var8;
|
||||||
|
} catch (Exception var12) {
|
||||||
|
log.error(StrUtil.format(msg, new Object[]{"成功获取锁但执行失败"}), var12);
|
||||||
|
var8 = (Pair)exceptionHandle.apply(var12);
|
||||||
|
} finally {
|
||||||
|
delLock(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return var8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <V> Pair<Boolean, V> lockHandle(@NotNull String key, @NotNull Callable<V> callable) {
|
||||||
|
return lockHandle(key, callable, (e) -> {
|
||||||
|
throw new RuntimeException(key + " 成功获取锁但执行失败:" + e.getMessage());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
9
pom.xml
9
pom.xml
@@ -34,6 +34,9 @@
|
|||||||
<knife4j.version>4.5.0</knife4j.version>
|
<knife4j.version>4.5.0</knife4j.version>
|
||||||
<springdoc.version>1.7.0</springdoc.version>
|
<springdoc.version>1.7.0</springdoc.version>
|
||||||
<mybatis.version>3.5.2</mybatis.version>
|
<mybatis.version>3.5.2</mybatis.version>
|
||||||
|
<milo.version>0.6.3</milo.version>
|
||||||
|
<commons-pool2.version>2.12.0</commons-pool2.version>
|
||||||
|
<!-- 2.12.0-->
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<!-- 依赖声明 -->
|
<!-- 依赖声明 -->
|
||||||
@@ -212,6 +215,12 @@
|
|||||||
<!-- <version>3.5.2</version>-->
|
<!-- <version>3.5.2</version>-->
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.commons</groupId>
|
||||||
|
<artifactId>commons-pool2</artifactId>
|
||||||
|
<version>${commons-pool2.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</dependencyManagement>
|
</dependencyManagement>
|
||||||
|
|
||||||
|
|||||||
@@ -101,6 +101,10 @@ spring:
|
|||||||
enabled: true
|
enabled: true
|
||||||
max-attempts: 1
|
max-attempts: 1
|
||||||
max-interval: 200
|
max-interval: 200
|
||||||
|
task:
|
||||||
|
scheduling:
|
||||||
|
pool:
|
||||||
|
size: 8 #配置Scheduled定时任务为多线程
|
||||||
|
|
||||||
# token配置
|
# token配置
|
||||||
token:
|
token:
|
||||||
@@ -161,3 +165,32 @@ knife4j:
|
|||||||
enable-swagger-model: true # 显示模型
|
enable-swagger-model: true # 显示模型
|
||||||
enable-document-manage: true # 启用文档管理
|
enable-document-manage: true # 启用文档管理
|
||||||
cors: true # 允许跨域
|
cors: true # 允许跨域
|
||||||
|
|
||||||
|
kangaroohy:
|
||||||
|
milo:
|
||||||
|
primary: default
|
||||||
|
config:
|
||||||
|
default:
|
||||||
|
endpoint: opc.tcp://127.0.0.1:49320
|
||||||
|
security-policy: none
|
||||||
|
pool:
|
||||||
|
max-idle: 5
|
||||||
|
max-total: 20
|
||||||
|
min-idle: 2
|
||||||
|
initial-size: 3
|
||||||
|
|
||||||
|
|
||||||
|
#kangaroohy:
|
||||||
|
# milo:
|
||||||
|
# primary: default
|
||||||
|
# config:
|
||||||
|
# default:
|
||||||
|
# endpoint: opc.tcp://127.0.0.1:49320
|
||||||
|
# security-policy: basic256sha256
|
||||||
|
# username: OPCUA
|
||||||
|
# password: 123456
|
||||||
|
# test:
|
||||||
|
# endpoint: opc.tcp://127.0.0.1:49321
|
||||||
|
# security-policy: basic256sha256
|
||||||
|
# username: OPCUA
|
||||||
|
# password: 123456
|
||||||
@@ -149,8 +149,6 @@
|
|||||||
<artifactId>knife4j-openapi3-spring-boot-starter</artifactId>
|
<artifactId>knife4j-openapi3-spring-boot-starter</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!-- 防止进入swagger页面报类型转换错误,排除3.0.0中的引用,手动增加1.6.2版本 -->
|
<!-- 防止进入swagger页面报类型转换错误,排除3.0.0中的引用,手动增加1.6.2版本 -->
|
||||||
<!-- <dependency>-->
|
<!-- <dependency>-->
|
||||||
<!-- <groupId>io.swagger</groupId>-->
|
<!-- <groupId>io.swagger</groupId>-->
|
||||||
|
|||||||
Reference in New Issue
Block a user