# milo-spring-boot-starter
**Repository Path**: vampire001/milo-spring-boot-starter
## Basic Information
- **Project Name**: milo-spring-boot-starter
- **Description**: 基于eclipse milo实现的opc ua spring boot starter,支持读、写、订阅,使用连接池管理opc 连接
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 47
- **Forks**: 17
- **Created**: 2023-05-09
- **Last Updated**: 2025-06-12
## Categories & Tags
**Categories**: spring-boot-ext
**Tags**: opcua, SpringBoot, milo
## README
# milo-spring-boot-starter
milo 封装工具包,yml配置OPC UA地址,是否匿名等信息,即可连接OPC UA服务器
## maven
[](https://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22com.kangaroohy%22%20AND%20a%3A%milo-spring-boot-starter%22)
首次版本发布,适配 spring boot 3.x,也可在spring boot 2.x中使用
~~~
com.kangaroohy
milo-spring-boot-starter
${lastVersion}
~~~
## 配置
```yaml
kangaroohy:
milo:
primary: default
config:
default:
endpoint: opc.tcp://127.0.0.1:49320
security-policy: none
```
```yaml
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
```
特别提醒:
在kepware中,用户名/密码访问时,opcua配置,安全策略中三个策略全部勾选
同时kepware选项属性中的OPC UA配置,不允许匿名访问
此时,security-policy可选值:basic256sha256,basic256,basic128rsa15都可
同时配置上 用户名/密码 即可访问服务器
## 连接池
此封装自带了连接池配置,默认会生成3个连接,可配置
~~~yaml
kangaroohy:
milo:
pool:
max-idle: 5
max-total: 20
min-idle: 2
initial-size: 3
~~~
## 写
注入MiloService即可使用,支持:批量读、单个写(批量写,循环即可)
其中:写值时可能需要指定数据类型,视点位情况而定
Opc后边的字段对应Kepware中的tag数据类型(Ua除外,为通用类型)

### 通用类型
如Kep类型为:Boolean、LLong、Long、String、Float、Double,调用方法:`miloService.writeToOpcUa(ReadWriteEntity entity)`
```java
@SpringBootTest
@RunWith(SpringRunner.class)
public class MiloTest {
@Autowired
MiloService miloService;
@Test
public void writeToOpcUa() {
miloService.writeToOpcUa(
ReadWriteEntity.builder()
.identifier("GA.T1.Boolean")
//Kep中是Boolean类型
.value(true)
.build());
miloService.writeToOpcUa(
ReadWriteEntity.builder()
.identifier("GA.T1.LLong")
//Kep中是LLong类型,即:Int64,Java中的Long类型
.value(1235468L)
.build());
miloService.writeToOpcUa(
ReadWriteEntity.builder()
.identifier("GA.T1.Long")
//Kep中是Long类型,即:Int32,Java中的int类型
.value(123456)
.build());
miloService.writeToOpcUa(
ReadWriteEntity.builder()
.identifier("GA.T1.String")
.value("字符串")
.build());
miloService.writeToOpcUa(
ReadWriteEntity.builder()
.identifier("GA.T1.Float")
//Kep中是Float类型
.value(123.123F)
.build());
miloService.writeToOpcUa(
ReadWriteEntity.builder()
.identifier("GA.T1.Double")
//Kep中是Double类型
.value(123.123)
.build());
}
}
```
### 已提供方法的类型
如Kep类型为:Short、Word、Byte、Char,调用方法:`miloService.writeToOpcXXX(ReadWriteEntity entity)`,XXX对应kep类型
```java
@SpringBootTest
@RunWith(SpringRunner.class)
public class MiloTest {
@Autowired
MiloService miloService;
@Test
public void writeToOpcUa() {
miloService.writeToOpcShort(
ReadWriteEntity.builder()
.identifier("GA.T1.Short")
//Kep中是Short类型,即:Int16,带符号整数
.value(-123)
.build());
miloService.writeToOpcWord(
ReadWriteEntity.builder()
.identifier("GA.T1.Word")
//Kep中是Word类型,即:UInt16,无符号整数
.value(123)
.build());
miloService.writeToOpcByte(
ReadWriteEntity.builder()
.identifier("GA.BIT_8.Byte")
//Kep中是Byte类型,8位无符号整数
.value(123)
.build());
miloService.writeToOpcChar(
ReadWriteEntity.builder()
.identifier("GA.BIT_8.Char")
//Kep中是Char类型,8位带符号整数
.value(-123)
.build());
}
}
```
### 其他类型
其他的数据类型,则需要调用方法:`miloService.writeSpecifyType(WriteEntity entity)`,自行指定转换类型.variant(new Variant(xxx))
new Variant(xxx):
> new Variant(String[])
>
> new Variant(Unsigned.ushort("123"))
>
> ....
参数类型具体以标签数据类型为准,例如:
```java
@SpringBootTest
@RunWith(SpringRunner.class)
public class MiloTest {
@Autowired
MiloService miloService;
@Test
public void writeToOpcUa() {
UByte[] bytes = new UByte[10];
bytes[0] = UByte.valueOf(1);
bytes[1] = UByte.valueOf(2);
bytes[2] = UByte.valueOf(3);
bytes[3] = UByte.valueOf(4);
miloService.writeSpecifyType(
WriteEntity.builder()
.identifier("GA.BIT_8.Bytes")
//Kep中是Byte Array类型
.variant(new Variant(bytes))
.build());
}
}
```
## 读

读比较简单,传相应的TAG id数组即可,调用方法:readFromOpcUa(List ids)
id格式:通道名.设备名.TAG
如:GA.T1.T1001R_1
## 遍历节点

可遍历指定节点相关信息
## 订阅
这里使用的是实现`ApplicationRunner`接口,实现在项目启动时,自动订阅相关点位
当点位数值发生改变,则会触发回调,根据回调即可实现相应的逻辑
> 每新增一个订阅都会长期占用一个opc ua连接,不会释放
~~~java
@Component
@Slf4j
public class CustomRunner implements ApplicationRunner {
@Autowired
private MiloService miloService;
@Override
public void run(ApplicationArguments args) throws Exception {
sub();
}
private void sub() throws Exception {
List ids = new ArrayList<>();
ids.add("GA.T1.T1001R");
ids.add("GA.T1.String");
miloService.subscriptionFromOpcUa(ids, (id, value) -> log.info("subscription 点位:{} 订阅到消息:{}", id, value));
}
}
~~~
## 数据库动态加载连接
实现`MiloConfigProvider`,`@Component` 给spring管理即可
~~~java
@Component
public class MiloProvider implements MiloConfigProvider {
@Override
public Map config() {
Map configMap = new HashMap<>();
MiloProperties.Config config = new MiloProperties.Config();
config.setEndpoint("opc.tcp://192.168.68.134:49320");
config.setSecurityPolicy(SecurityPolicy.Basic256);
config.setUsername("OPCUA");
config.setPassword("123456");
configMap.put("dbConfig", config);
return configMap;
}
}
~~~