Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
Z
zhmes-agecal
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
耿迪迪
zhmes-agecal
Commits
1c3cf716
Commit
1c3cf716
authored
Jun 09, 2025
by
wanghao
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
1 使用 modbus4j + juc 实现 读取老化柜和老化层状态--测试中
parent
5179d8fe
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
743 additions
and
43 deletions
+743
-43
EquipmentDataCollection.java
...ong/web/controller/equipment/EquipmentDataCollection.java
+36
-43
AgingCabinetInspectionAndPowerCheckTask.java
...ong/web/task/AgingCabinetInspectionAndPowerCheckTask.java
+143
-0
pom.xml
zhmes-agecal-common/pom.xml
+6
-0
Modbus4jUtils.java
...ain/java/com/zehong/framework/modbus4j/Modbus4jUtils.java
+425
-0
ModbusDeviceData.java
.../java/com/zehong/framework/modbus4j/ModbusDeviceData.java
+29
-0
ModbusTcpTask.java
...ain/java/com/zehong/framework/modbus4j/ModbusTcpTask.java
+47
-0
ModbusDeviceData.java
...ava/com/zehong/system/domain/modbus/ModbusDeviceData.java
+29
-0
ITEquipmentInfoService.java
...ava/com/zehong/system/service/ITEquipmentInfoService.java
+5
-0
TEquipmentInfoServiceImpl.java
...zehong/system/service/impl/TEquipmentInfoServiceImpl.java
+23
-0
No files found.
zhmes-agecal-admin/src/main/java/com/zehong/web/controller/equipment/EquipmentDataCollection.java
View file @
1c3cf716
...
...
@@ -13,13 +13,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import
org.springframework.web.bind.annotation.GetMapping
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RestController
;
import
java.sql.Timestamp
;
import
java.text.SimpleDateFormat
;
import
java.util.ArrayList
;
import
java.util.Calendar
;
import
java.util.Date
;
import
java.util.List
;
import
java.util.*
;
/**
* 生产设备数据采集
...
...
@@ -37,19 +31,18 @@ public class EquipmentDataCollection {
private
ITStoreyInfoService
tStoreyInfoService
;
@Autowired
private
ITEquipmentAlarmDataService
tEquipmentAlarmDataService
;
/**
* 1.老化柜、标定柜巡查
* 2.老化层断电
*/
@GetMapping
(
"/equipmentPatrol"
)
public
void
equipmentPatrol
(){
public
void
equipmentPatrol
()
{
List
<
String
>
type
=
new
ArrayList
<>();
type
.
add
(
"1"
);
type
.
add
(
"2"
);
List
<
TEquipmentInfo
>
equipmentInfos
=
tEquipmentInfoService
.
selectTEquipmentList
(
type
);
try
{
if
(
equipmentInfos
.
size
()
==
0
)
{
try
{
if
(
equipmentInfos
.
size
()
==
0
)
{
log
.
error
(
"设备列表查询结果为空"
);
throw
new
Exception
(
"无设备信息!"
);
}
...
...
@@ -58,9 +51,9 @@ public class EquipmentDataCollection {
String
sendMsg1
=
"00010000000601040000000A"
;
String
receiveMsg1
=
null
;
TEquipmentAlarmData
alarmData
=
new
TEquipmentAlarmData
();
for
(
TEquipmentInfo
info
:
equipmentInfos
)
{
for
(
TEquipmentInfo
info
:
equipmentInfos
)
{
receiveMsg1
=
agingCabinetCommunication
(
info
,
sendMsg1
);
if
(
receiveMsg1
==
null
||
receiveMsg1
.
length
()
!=
58
)
{
if
(
receiveMsg1
==
null
||
receiveMsg1
.
length
()
!=
58
)
{
// 记录异常数据
alarmData
.
setfAlarmType
(
"01"
);
// 01.老化柜 02.标定柜 03.机械臂 04.老化层 05.点位
alarmData
.
setfEquipmentCode
(
info
.
getfEquipmentCode
());
...
...
@@ -73,7 +66,7 @@ public class EquipmentDataCollection {
// 解析服务器返回信息
// 示例:00 01 00 00 00 17 01 04 14 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
String
flag
=
receiveMsg1
.
substring
(
18
,
58
);
if
(
"0000000000000000000000000000000000000000"
.
equals
(
flag
)
&&
!
"0"
.
equals
(
info
.
getfStatus
()))
{
if
(
"0000000000000000000000000000000000000000"
.
equals
(
flag
)
&&
!
"0"
.
equals
(
info
.
getfStatus
()))
{
// 更新老化柜状态(“0”空闲,“1”运行,“2”故障)
info
.
setfStatus
(
"0"
);
info
.
setfUpdateTime
(
new
Date
());
...
...
@@ -82,7 +75,7 @@ public class EquipmentDataCollection {
info
.
setfStatus
(
"1"
);
info
.
setfUpdateTime
(
new
Date
());
tEquipmentInfoService
.
updateTEquipmentInfo
(
info
);
}
else
if
(
"0000000000000000000000000000000000000000"
.
equals
(
flag
)){
}
else
if
(
"0000000000000000000000000000000000000000"
.
equals
(
flag
))
{
// 解析层状态,根据层编号修改状态
int
startIndex
;
int
endIndex
;
...
...
@@ -90,11 +83,11 @@ public class EquipmentDataCollection {
String
status
;
TStoreyInfo
storeyInfo
=
new
TStoreyInfo
();
String
storeyCode
;
for
(
startIndex
=
18
,
endIndex
=
22
,
code
=
1
;
endIndex
<=
receiveMsg1
.
length
();
startIndex
+=
4
,
endIndex
+=
4
,
code
++)
{
for
(
startIndex
=
18
,
endIndex
=
22
,
code
=
1
;
endIndex
<=
receiveMsg1
.
length
();
startIndex
+=
4
,
endIndex
+=
4
,
code
++)
{
status
=
receiveMsg1
.
substring
(
startIndex
,
endIndex
);
storeyCode
=
info
.
getfEquipmentCode
()
+
"-"
+
code
;
storeyInfo
=
tStoreyInfoService
.
selectTStoreyInfoByCode
(
storeyCode
);
if
(
storeyInfo
==
null
)
{
if
(
storeyInfo
==
null
)
{
// 记录异常数据
alarmData
.
setfAlarmType
(
"01"
);
// 01.老化柜 02.标定柜 03.机械臂 04.老化层 05.点位
alarmData
.
setfEquipmentCode
(
info
.
getfEquipmentCode
());
...
...
@@ -102,13 +95,13 @@ public class EquipmentDataCollection {
tEquipmentAlarmDataService
.
insertTEquipmentAlarmData
(
alarmData
);
continue
;
}
if
(
"0000"
.
equals
(
status
))
{
if
(
"0000"
.
equals
(
status
))
{
/* 2.老化层断电 */
// 示例:000100000006 01 功能码05 寄存器地址0000 断电0000
String
addr
=
Integer
.
toHexString
(
code
-
1
).
length
()<
2
?
"0"
+
Integer
.
toHexString
(
code
-
1
):
Integer
.
toHexString
(
code
-
1
);
String
addr
=
Integer
.
toHexString
(
code
-
1
).
length
()
<
2
?
"0"
+
Integer
.
toHexString
(
code
-
1
)
:
Integer
.
toHexString
(
code
-
1
);
String
sendMsg2
=
"000100000006010500"
+
addr
+
"0000"
;
String
receiveMsg2
=
storeyCommunication
(
storeyInfo
,
sendMsg2
);
if
(
sendMsg2
.
equals
(
receiveMsg2
))
{
if
(
sendMsg2
.
equals
(
receiveMsg2
))
{
// 更新老化层状态
storeyInfo
.
setfStatus
(
"3"
);
//断电
tStoreyInfoService
.
updateTStoreyInfo
(
storeyInfo
);
...
...
@@ -171,20 +164,20 @@ public class EquipmentDataCollection {
// 解析服务器返回信息
// 示例:00 01 00 00 00 17 01 04 14 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
String
storeyCode
=
storeyInfo
.
getfStoreyCode
();
int
code
=
Integer
.
parseInt
(
storeyCode
.
substring
(
storeyCode
.
indexOf
(
"-"
)
+
1
));
int
code
=
Integer
.
parseInt
(
storeyCode
.
substring
(
storeyCode
.
indexOf
(
"-"
)
+
1
));
int
startIndex
;
int
endIndex
;
String
status
;
int
flag
=
1
;
for
(
startIndex
=
18
,
endIndex
=
22
,
code
=
1
;
endIndex
<=
receiveMsg1
.
length
();
startIndex
+=
4
,
endIndex
+=
4
,
flag
++)
{
for
(
startIndex
=
18
,
endIndex
=
22
,
code
=
1
;
endIndex
<=
receiveMsg1
.
length
();
startIndex
+=
4
,
endIndex
+=
4
,
flag
++)
{
status
=
receiveMsg1
.
substring
(
startIndex
,
endIndex
);
if
(
flag
==
code
&&
"0001"
.
equals
(
status
))
{
if
(
flag
==
code
&&
"0001"
.
equals
(
status
))
{
/* 3.老化层上电 */
// 示例:000100000006 01 功能码05 寄存器地址0000 上电FF00
String
addr
=
Integer
.
toHexString
(
flag
-
1
).
length
()<
2
?
"0"
+
Integer
.
toHexString
(
flag
-
1
):
Integer
.
toHexString
(
flag
-
1
);
String
addr
=
Integer
.
toHexString
(
flag
-
1
).
length
()
<
2
?
"0"
+
Integer
.
toHexString
(
flag
-
1
)
:
Integer
.
toHexString
(
flag
-
1
);
String
sendMsg2
=
"000100000006010500"
+
addr
+
"FF00"
;
String
receiveMsg2
=
storeyCommunication
(
storeyInfo
,
sendMsg2
);
if
(!
sendMsg2
.
equals
(
receiveMsg2
)
||
receiveMsg2
==
null
)
{
if
(!
sendMsg2
.
equals
(
receiveMsg2
)
||
receiveMsg2
==
null
)
{
// 记录异常数据
alarmData
.
setfAlarmType
(
"04"
);
//01.老化柜 02.标定柜 03.机械臂 04.老化层 05.点位
alarmData
.
setfEquipmentCode
(
storeyInfo
.
getfStoreyCode
());
...
...
@@ -200,7 +193,7 @@ public class EquipmentDataCollection {
// 示例:000100000006 点位地址01 功能码03 起始位置0000 终止位置000A
String
sendMsg3
=
"00010000000601030000000A"
;
String
receiveMsg3
=
storeyCommunication
(
storeyInfo
,
sendMsg3
);
if
(
receiveMsg3
==
null
)
{
if
(
receiveMsg3
==
null
)
{
// 记录异常数据
alarmData
.
setfAlarmType
(
"04"
);
//01.老化柜 02.标定柜 03.机械臂 04.老化层 05.点位
alarmData
.
setfEquipmentCode
(
storeyInfo
.
getfStoreyCode
());
...
...
@@ -210,11 +203,11 @@ public class EquipmentDataCollection {
// 解析服务器返回信息
// 示例:000100000017010314 浓度0000 状态0001 AD值01F7 标定AD值01F7 年07E9 月0005 日0004 时000E 分000F 秒0015
String
value
=
receiveMsg3
.
substring
(
22
,
26
);
//板子状态
if
(
"0001"
.
equals
(
value
))
{
if
(
"0001"
.
equals
(
value
))
{
/* 5.写入时间,年、月、日、时、分 */
// 示例:000100000006 设备地址01写时间06 寄存器地址0004(年04月05日06时07分08) 年/月/日/时/分数值07E9(2025)
Calendar
cal
=
Calendar
.
getInstance
();
Calendar
cal
=
Calendar
.
getInstance
();
// 当前年
int
y
=
cal
.
get
(
Calendar
.
YEAR
);
// 当前月
...
...
@@ -225,15 +218,15 @@ public class EquipmentDataCollection {
int
h
=
cal
.
get
(
Calendar
.
HOUR_OF_DAY
);
// 当前分钟
int
mm
=
cal
.
get
(
Calendar
.
MINUTE
);
String
minutes
=
Integer
.
toHexString
(
mm
).
length
()
<
2
?
"000"
+
Integer
.
toHexString
(
mm
):
"00"
+
Integer
.
toHexString
(
mm
);
String
hours
=
Integer
.
toHexString
(
h
).
length
()
<
2
?
"000"
+
Integer
.
toHexString
(
h
):
"00"
+
Integer
.
toHexString
(
h
);
String
date
=
Integer
.
toHexString
(
d
).
length
()
<
2
?
"000"
+
Integer
.
toHexString
(
d
):
"00"
+
Integer
.
toHexString
(
d
);
String
month
=
Integer
.
toHexString
(
m
).
length
()
<
2
?
"000"
+
Integer
.
toHexString
(
m
):
"00"
+
Integer
.
toHexString
(
m
);
String
year
=
Integer
.
toHexString
(
y
).
length
()
<
4
?
"0"
+
Integer
.
toHexString
(
y
):
Integer
.
toHexString
(
y
);
String
minutes
=
Integer
.
toHexString
(
mm
).
length
()
<
2
?
"000"
+
Integer
.
toHexString
(
mm
)
:
"00"
+
Integer
.
toHexString
(
mm
);
String
hours
=
Integer
.
toHexString
(
h
).
length
()
<
2
?
"000"
+
Integer
.
toHexString
(
h
)
:
"00"
+
Integer
.
toHexString
(
h
);
String
date
=
Integer
.
toHexString
(
d
).
length
()
<
2
?
"000"
+
Integer
.
toHexString
(
d
)
:
"00"
+
Integer
.
toHexString
(
d
);
String
month
=
Integer
.
toHexString
(
m
).
length
()
<
2
?
"000"
+
Integer
.
toHexString
(
m
)
:
"00"
+
Integer
.
toHexString
(
m
);
String
year
=
Integer
.
toHexString
(
y
).
length
()
<
4
?
"0"
+
Integer
.
toHexString
(
y
)
:
Integer
.
toHexString
(
y
);
String
sendMsgYear
=
"0001000000060"
+
code
+
"060004"
+
year
;
String
receiveMsgYear
=
storeyCommunication
(
storeyInfo
,
sendMsgYear
);
if
(!
sendMsgYear
.
equals
(
receiveMsgYear
)
||
receiveMsgYear
==
null
)
{
if
(!
sendMsgYear
.
equals
(
receiveMsgYear
)
||
receiveMsgYear
==
null
)
{
// 记录异常数据
alarmData
.
setfAlarmType
(
"05"
);
//01.老化柜 02.标定柜 03.机械臂 04.老化层 05.点位
alarmData
.
setfEquipmentCode
(
storeyInfo
.
getfStoreyCode
());
...
...
@@ -251,45 +244,45 @@ public class EquipmentDataCollection {
String
ip
=
null
;
Integer
port
=
null
;
int
num
=
1
;
try
{
try
{
ip
=
equipment
.
getfIp
();
port
=
equipment
.
getfPort
();
if
(
ip
==
null
||
port
==
null
)
{
if
(
ip
==
null
||
port
==
null
)
{
receiveMsg
=
equipment
.
getfEquipmentCode
();
}
else
{
// 若通讯失败将再次通讯,最多通讯3次
while
((
receiveMsg
==
null
||
receiveMsg
.
length
()
!=
58
)
&&
num
<=
3
)
{
while
((
receiveMsg
==
null
||
receiveMsg
.
length
()
!=
58
)
&&
num
<=
3
)
{
// 发送并接收数据
receiveMsg
=
TCPClient
.
PLCConnect
(
ip
,
port
,
sendMsg
);
num
++;
}
}
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
throw
new
RuntimeException
(
e
);
}
return
receiveMsg
;
}
//老化层通讯
private
String
storeyCommunication
(
TStoreyInfo
storey
,
String
sendMsg
){
private
String
storeyCommunication
(
TStoreyInfo
storey
,
String
sendMsg
)
{
String
ip
=
null
;
Integer
port
=
null
;
String
receiveMsg
=
null
;
int
num
=
1
;
try
{
try
{
ip
=
storey
.
getfIp
();
port
=
storey
.
getfPort
();
if
(
ip
==
null
||
port
==
null
)
{
if
(
ip
==
null
||
port
==
null
)
{
receiveMsg
=
storey
.
getfStoreyCode
();
}
// 若通讯失败将再次通讯,最多通讯3次
while
((!
sendMsg
.
equals
(
receiveMsg
)
||
receiveMsg
==
null
)
&&
num
<=
3
)
{
while
((!
sendMsg
.
equals
(
receiveMsg
)
||
receiveMsg
==
null
)
&&
num
<=
3
)
{
// 发送并接收数据
receiveMsg
=
TCPClient
.
PLCConnect
(
ip
,
port
,
sendMsg
);
num
++;
}
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
throw
new
RuntimeException
(
e
);
}
return
receiveMsg
;
...
...
zhmes-agecal-admin/src/main/java/com/zehong/web/task/AgingCabinetInspectionAndPowerCheckTask.java
0 → 100644
View file @
1c3cf716
package
com
.
zehong
.
web
.
task
;
import
com.serotonin.modbus4j.ModbusMaster
;
import
com.serotonin.modbus4j.exception.ErrorResponseException
;
import
com.serotonin.modbus4j.exception.ModbusInitException
;
import
com.serotonin.modbus4j.exception.ModbusTransportException
;
import
com.zehong.framework.modbus4j.Modbus4jUtils
;
import
com.zehong.system.domain.TEquipmentInfo
;
import
com.zehong.system.domain.modbus.ModbusDeviceData
;
import
com.zehong.system.service.ITEquipmentInfoService
;
import
com.zehong.web.controller.equipment.EquipmentDataCollection
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.stereotype.Component
;
import
org.springframework.web.context.request.async.DeferredResult
;
import
javax.annotation.Resource
;
import
java.util.*
;
import
java.util.concurrent.CompletableFuture
;
import
java.util.concurrent.ExecutorService
;
import
java.util.concurrent.Executors
;
import
java.util.stream.Collectors
;
/**
* @author lenovo
* @date 2025/6/9
* @description 老化柜巡查 + 老化层断电检测
*/
@Component
(
"agingCabinetInspectionAndPowerCheckTask"
)
public
class
AgingCabinetInspectionAndPowerCheckTask
{
private
static
final
Logger
log
=
LoggerFactory
.
getLogger
(
AgingCabinetInspectionAndPowerCheckTask
.
class
);
private
final
ExecutorService
executor
=
Executors
.
newFixedThreadPool
(
10
);
@Resource
private
ITEquipmentInfoService
tEquipmentInfoService
;
/**
* 五分钟一次
* 1.老化柜、标定柜巡查
* 2.老化层断电
* 这种方式先注释掉
// for (TEquipmentInfo equipmentInfo : equipmentInfos) {
// Future<Map<Integer, Object>> future = executor.submit(new ModbusTcpTask(equipmentInfo, registerOffset));
// futures.add(future);
// }
// List<ModbusDeviceData> results = new ArrayList<>();
//
// for (int i = 0; i < futures.size(); i++) {
// Map<Integer, Object> data = futures.get(i).get();
// ModbusDeviceData deviceData = new ModbusDeviceData();
// deviceData.setDeviceId(equipmentInfos.get(i).getfEquipmentId().toString());
// deviceData.setRegisterValues(data.entrySet().stream()
// .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().toString())));
// results.add(deviceData);
// }
*/
public
void
ryCheck
()
{
List
<
String
>
type
=
new
ArrayList
<>();
type
.
add
(
"1"
);
type
.
add
(
"2"
);
List
<
TEquipmentInfo
>
equipmentInfos
=
tEquipmentInfoService
.
selectTEquipmentList
(
type
);
try
{
if
(
equipmentInfos
.
size
()
==
0
)
{
log
.
error
(
"设备列表查询结果为空"
);
throw
new
Exception
(
"无设备信息!"
);
}
// 10 层
// List<Integer> registerOffset = Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
//
// List<CompletableFuture<ModbusDeviceData>> futures = equipmentInfos.stream().map(equipmentInfo -> CompletableFuture.supplyAsync(() -> {
// ModbusMaster master = null;
// try {
// master = Modbus4jUtils.getMaster(equipmentInfo.getfIp(), equipmentInfo.getfPort());
// Map<Integer, Object> integerObjectMap = Modbus4jUtils.batchReadAgingCabinet(master, registerOffset);
// // 构造结果对象
// ModbusDeviceData deviceData = new ModbusDeviceData();
// deviceData.setDeviceId(equipmentInfo.getfEquipmentId().toString());
// deviceData.setRegisterValues(integerObjectMap.entrySet().stream()
// .collect(Collectors.toMap(
// Map.Entry::getKey,
// e -> e.getValue() != null ? e.getValue().toString() : "NULL"
// )));
//
// return deviceData;
//
// } catch (ModbusInitException e) {
//
// // 初始化失败
// Map<Integer, String> errorMap = new HashMap<>();
//
// ModbusDeviceData deviceData = new ModbusDeviceData();
// deviceData.setDeviceId("");
// deviceData.setRegisterValues(errorMap);
//
// return deviceData;
// } catch (ModbusTransportException | ErrorResponseException e) {
// // 返回错误信息
// Map<Integer, String> errorMap = new HashMap<>();
// registerOffset.forEach(offset -> errorMap.put(offset, "ERROR: " + e.getMessage()));
//
// ModbusDeviceData deviceData = new ModbusDeviceData();
// deviceData.setDeviceId(equipmentInfo.getfEquipmentId().toString());
// deviceData.setRegisterValues(errorMap);
//
// return deviceData;
// } finally {
// if (master != null) {
// master.destroy();
// }
// }
// }, executor)).collect(Collectors.toList());
//
// // 等待所有任务完成并收集结果
// CompletableFuture<List<ModbusDeviceData>> listCompletableFuture = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
// .thenApply(v -> futures.stream()
// .map(CompletableFuture::join)
// .collect(Collectors.toList()));
//
// DeferredResult<List<ModbusDeviceData>> deferredResult = new DeferredResult<>();
//
// listCompletableFuture.whenComplete((result, ex) -> {
// if (ex != null) {
// deferredResult.setErrorResult(Collections.singletonList(createErrorData(ex)));
// } else {
// deferredResult.setResult(result);
// }
// });
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
}
private
ModbusDeviceData
createErrorData
(
Throwable
ex
)
{
ModbusDeviceData
errorData
=
new
ModbusDeviceData
();
errorData
.
setDeviceId
(
"error"
);
errorData
.
setRegisterValues
(
Collections
.
singletonMap
(
0
,
"系统错误:"
+
ex
.
getMessage
()));
return
errorData
;
}
}
zhmes-agecal-common/pom.xml
View file @
1c3cf716
...
...
@@ -118,6 +118,12 @@
<groupId>
javax.servlet
</groupId>
<artifactId>
javax.servlet-api
</artifactId>
</dependency>
<!-- modbus4j-->
<dependency>
<groupId>
com.infiniteautomation
</groupId>
<artifactId>
modbus4j
</artifactId>
<version>
3.0.3
</version>
</dependency>
</dependencies>
...
...
zhmes-agecal-framework/src/main/java/com/zehong/framework/modbus4j/Modbus4jUtils.java
0 → 100644
View file @
1c3cf716
package
com
.
zehong
.
framework
.
modbus4j
;
import
com.serotonin.modbus4j.BatchRead
;
import
com.serotonin.modbus4j.BatchResults
;
import
com.serotonin.modbus4j.ModbusFactory
;
import
com.serotonin.modbus4j.ModbusMaster
;
import
com.serotonin.modbus4j.code.DataType
;
import
com.serotonin.modbus4j.exception.ErrorResponseException
;
import
com.serotonin.modbus4j.exception.ModbusInitException
;
import
com.serotonin.modbus4j.exception.ModbusTransportException
;
import
com.serotonin.modbus4j.ip.IpParameters
;
import
com.serotonin.modbus4j.locator.BaseLocator
;
import
com.serotonin.modbus4j.msg.*
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
/**
* modbus通讯工具类,采用modbus4j实现
*
*/
public
class
Modbus4jUtils
{
private
static
final
Logger
log
=
LoggerFactory
.
getLogger
(
Modbus4jUtils
.
class
);
/**
* 工厂。
*/
static
ModbusFactory
modbusFactory
;
static
{
if
(
modbusFactory
==
null
)
{
modbusFactory
=
new
ModbusFactory
();
}
}
/**
* 获取master
*
* @return master
* @throws ModbusInitException m
*/
public
static
ModbusMaster
getMaster
()
throws
ModbusInitException
{
IpParameters
params
=
new
IpParameters
();
params
.
setHost
(
"localhost"
);
params
.
setPort
(
502
);
//
// modbusFactory.createRtuMaster(wapper); //RTU 协议
// modbusFactory.createUdpMaster(params);//UDP 协议
// modbusFactory.createAsciiMaster(wrapper);//ASCII 协议
ModbusMaster
master
=
modbusFactory
.
createTcpMaster
(
params
,
false
);
// TCP 协议
master
.
init
();
return
master
;
}
/**
* 动态获取 modubus master
* @param ip ip
* @param port port
* @return r
* @throws ModbusInitException m
*/
public
static
ModbusMaster
getMaster
(
String
ip
,
int
port
)
throws
ModbusInitException
{
IpParameters
params
=
new
IpParameters
();
params
.
setHost
(
ip
);
params
.
setPort
(
port
);
ModbusMaster
master
=
modbusFactory
.
createTcpMaster
(
params
,
false
);
// TCP 协议
master
.
init
();
return
master
;
}
/**
* 读取[01 Coil Status 0x]类型 开关数据
*
* @param slaveId
* slaveId
* @param offset
* 位置
* @return 读取值
* @throws ModbusTransportException
* 异常
* @throws ErrorResponseException
* 异常
* @throws ModbusInitException
* 异常
*/
public
static
Boolean
readCoilStatus
(
int
slaveId
,
int
offset
)
throws
ModbusTransportException
,
ErrorResponseException
,
ModbusInitException
{
// 01 Coil Status
BaseLocator
<
Boolean
>
loc
=
BaseLocator
.
coilStatus
(
slaveId
,
offset
);
Boolean
value
=
getMaster
().
getValue
(
loc
);
return
value
;
}
/**
* 读取[02 Input Status 1x]类型 开关数据
*
* @param slaveId
* @param offset
* @return
* @throws ModbusTransportException
* @throws ErrorResponseException
* @throws ModbusInitException
*/
public
static
Boolean
readInputStatus
(
int
slaveId
,
int
offset
)
throws
ModbusTransportException
,
ErrorResponseException
,
ModbusInitException
{
// 02 Input Status
BaseLocator
<
Boolean
>
loc
=
BaseLocator
.
inputStatus
(
slaveId
,
offset
);
Boolean
value
=
getMaster
().
getValue
(
loc
);
return
value
;
}
/**
* 读取[03 Holding Register类型 2x]模拟量数据
*
* @param slaveId
* slave Id
* @param offset
* 位置
* @param dataType
* 数据类型,来自com.serotonin.modbus4j.code.DataType
* @return
* @throws ModbusTransportException
* 异常
* @throws ErrorResponseException
* 异常
* @throws ModbusInitException
* 异常
*/
public
static
Number
readHoldingRegister
(
int
slaveId
,
int
offset
,
int
dataType
)
throws
ModbusTransportException
,
ErrorResponseException
,
ModbusInitException
{
// 03 Holding Register类型数据读取
BaseLocator
<
Number
>
loc
=
BaseLocator
.
holdingRegister
(
slaveId
,
offset
,
dataType
);
Number
value
=
getMaster
().
getValue
(
loc
);
return
value
;
}
/**
* 读取[04 Input Registers 3x]类型 模拟量数据
*
* @param slaveId
* slaveId
* @param offset
* 位置
* @param dataType
* 数据类型,来自com.serotonin.modbus4j.code.DataType
* @return 返回结果
* @throws ModbusTransportException
* 异常
* @throws ErrorResponseException
* 异常
* @throws ModbusInitException
* 异常
*/
public
static
Number
readInputRegisters
(
int
slaveId
,
int
offset
,
int
dataType
)
throws
ModbusTransportException
,
ErrorResponseException
,
ModbusInitException
{
// 04 Input Registers类型数据读取
BaseLocator
<
Number
>
loc
=
BaseLocator
.
inputRegister
(
slaveId
,
offset
,
dataType
);
Number
value
=
getMaster
().
getValue
(
loc
);
return
value
;
}
/**
*
* @param master
* @param slaveId
* @param offset
* @param length
* @return
* @throws ModbusTransportException
* @throws ErrorResponseException
* @throws ModbusInitException
*/
/**
* 读取[04 Input Registers 3x]类型 模拟量数据
*
* @param master
* master
* @param slaveId
* slaveId
* @param offset
* 位置
* @param dataType
* 数据类型,来自com.serotonin.modbus4j.code.DataType
* @return 返回结果
* @throws ModbusTransportException
* 异常
* @throws ErrorResponseException
* 异常
* @throws ModbusInitException
* 异常
*/
public
static
Number
readInputRegisters
(
ModbusMaster
master
,
int
slaveId
,
int
offset
,
int
dataType
)
throws
ModbusTransportException
,
ErrorResponseException
,
ModbusInitException
{
// 04 Input Registers类型数据读取
BaseLocator
<
Number
>
loc
=
BaseLocator
.
inputRegister
(
slaveId
,
offset
,
dataType
);
Number
value
=
getMaster
().
getValue
(
loc
);
return
value
;
}
/**
* 批量读取使用方法
*
* @throws ModbusTransportException m
* @throws ErrorResponseException e
* @throws ModbusInitException m
*/
public
static
void
batchRead
()
throws
ModbusTransportException
,
ErrorResponseException
,
ModbusInitException
{
BatchRead
<
Integer
>
batch
=
new
BatchRead
<
Integer
>();
batch
.
addLocator
(
0
,
BaseLocator
.
holdingRegister
(
1
,
1
,
DataType
.
FOUR_BYTE_FLOAT
));
batch
.
addLocator
(
1
,
BaseLocator
.
inputStatus
(
1
,
0
));
ModbusMaster
master
=
getMaster
();
batch
.
setContiguousRequests
(
false
);
BatchResults
<
Integer
>
results
=
master
.
send
(
batch
);
System
.
out
.
println
(
results
.
getValue
(
0
));
System
.
out
.
println
(
results
.
getValue
(
1
));
}
/**
* 批量读取使用方法
*
* @throws ModbusTransportException m
* @throws ErrorResponseException e
* @throws ModbusInitException m
*/
public
static
Map
<
Integer
,
Object
>
batchReadAgingCabinet
(
ModbusMaster
master
,
List
<
Integer
>
registerOffsets
)
throws
ModbusTransportException
,
ErrorResponseException
{
BatchRead
<
Integer
>
batch
=
new
BatchRead
<
Integer
>();
for
(
Integer
registerOffset
:
registerOffsets
)
{
batch
.
addLocator
(
registerOffset
,
BaseLocator
.
holdingRegister
(
1
,
registerOffset
,
DataType
.
FOUR_BYTE_FLOAT
));
}
// 非连续地址也支持
batch
.
setContiguousRequests
(
false
);
BatchResults
<
Integer
>
send
=
master
.
send
(
batch
);
Map
<
Integer
,
Object
>
result
=
new
HashMap
<>();
for
(
Integer
registerOffset
:
registerOffsets
)
{
result
.
put
(
registerOffset
,
send
.
getValue
(
registerOffset
));
}
return
result
;
}
/**
* 写 [01 Coil Status(0x)]写一个 function ID = 5
*
* @param slaveId
* slave的ID
* @param writeOffset
* 位置
* @param writeValue
* 值
* @return 是否写入成功
* @throws ModbusTransportException m
* @throws ModbusInitException m
*/
public
static
boolean
writeCoil
(
int
slaveId
,
int
writeOffset
,
boolean
writeValue
)
throws
ModbusTransportException
,
ModbusInitException
{
// 获取master
ModbusMaster
tcpMaster
=
getMaster
();
// 创建请求
WriteCoilRequest
request
=
new
WriteCoilRequest
(
slaveId
,
writeOffset
,
writeValue
);
// 发送请求并获取响应对象
WriteCoilResponse
response
=
(
WriteCoilResponse
)
tcpMaster
.
send
(
request
);
if
(
response
.
isException
())
{
return
false
;
}
else
{
return
true
;
}
}
/**
* 写[01 Coil Status(0x)] 写多个 function ID = 15
*
* @param slaveId
* slaveId
* @param startOffset
* 开始位置
* @param bdata
* 写入的数据
* @return 是否写入成功
* @throws ModbusTransportException m
* @throws ModbusInitException m
*/
public
static
boolean
writeCoils
(
int
slaveId
,
int
startOffset
,
boolean
[]
bdata
)
throws
ModbusTransportException
,
ModbusInitException
{
// 获取master
ModbusMaster
tcpMaster
=
getMaster
();
// 创建请求
WriteCoilsRequest
request
=
new
WriteCoilsRequest
(
slaveId
,
startOffset
,
bdata
);
// 发送请求并获取响应对象
WriteCoilsResponse
response
=
(
WriteCoilsResponse
)
tcpMaster
.
send
(
request
);
if
(
response
.
isException
())
{
return
false
;
}
else
{
return
true
;
}
}
/***
* 写[03 Holding Register(4x)] 写一个 function ID = 6
*
* @param slaveId s
* @param writeOffset w
* @param writeValue w
* @return
* @throws ModbusTransportException m
* @throws ModbusInitException m
*/
public
static
boolean
writeRegister
(
int
slaveId
,
int
writeOffset
,
short
writeValue
)
throws
ModbusTransportException
,
ModbusInitException
{
// 获取master
ModbusMaster
tcpMaster
=
getMaster
();
// 创建请求对象
WriteRegisterRequest
request
=
new
WriteRegisterRequest
(
slaveId
,
writeOffset
,
writeValue
);
WriteRegisterResponse
response
=
(
WriteRegisterResponse
)
tcpMaster
.
send
(
request
);
if
(
response
.
isException
())
{
log
.
error
(
response
.
getExceptionMessage
());
return
false
;
}
else
{
return
true
;
}
}
/**
*
* 写入[03 Holding Register(4x)]写多个 function ID=16
*
* @param slaveId
* modbus的slaveID
* @param startOffset
* 起始位置偏移量值
* @param sdata
* 写入的数据
* @return 返回是否写入成功
* @throws ModbusTransportException m
* @throws ModbusInitException m
*/
public
static
boolean
writeRegisters
(
int
slaveId
,
int
startOffset
,
short
[]
sdata
)
throws
ModbusTransportException
,
ModbusInitException
{
// 获取master
ModbusMaster
tcpMaster
=
getMaster
();
// 创建请求对象
WriteRegistersRequest
request
=
new
WriteRegistersRequest
(
slaveId
,
startOffset
,
sdata
);
// 发送请求并获取响应对象
ModbusResponse
response
=
tcpMaster
.
send
(
request
);
if
(
response
.
isException
())
{
log
.
error
(
response
.
getExceptionMessage
());
return
false
;
}
else
{
return
true
;
}
}
/**
* 写入数字类型的模拟量(如:写入Float类型的模拟量、Double类型模拟量、整数类型Short、Integer、Long)
*
* @param slaveId s
* @param offset o
* @param value
* 写入值,Number的子类,例如写入Float浮点类型,Double双精度类型,以及整型short,int,long
* @param dataType r
* ,com.serotonin.modbus4j.code.DataType
* @throws ModbusTransportException m
* @throws ErrorResponseException e
* @throws ModbusInitException m
*/
public
static
void
writeHoldingRegister
(
int
slaveId
,
int
offset
,
Number
value
,
int
dataType
)
throws
ModbusTransportException
,
ErrorResponseException
,
ModbusInitException
{
// 获取master
ModbusMaster
tcpMaster
=
getMaster
();
// 类型
BaseLocator
<
Number
>
locator
=
BaseLocator
.
holdingRegister
(
slaveId
,
offset
,
dataType
);
tcpMaster
.
setValue
(
locator
,
value
);
}
/**
* 测试
*
* @param args a
*/
public
static
void
main
(
String
[]
args
)
{
try
{
// 01测试
Boolean
v011
=
readCoilStatus
(
1
,
0
);
Boolean
v012
=
readCoilStatus
(
1
,
1
);
Boolean
v013
=
readCoilStatus
(
1
,
6
);
System
.
out
.
println
(
"v011:"
+
v011
);
System
.
out
.
println
(
"v012:"
+
v012
);
System
.
out
.
println
(
"v013:"
+
v013
);
// 02测试
Boolean
v021
=
readInputStatus
(
1
,
0
);
Boolean
v022
=
readInputStatus
(
1
,
1
);
Boolean
v023
=
readInputStatus
(
1
,
2
);
System
.
out
.
println
(
"v021:"
+
v021
);
System
.
out
.
println
(
"v022:"
+
v022
);
System
.
out
.
println
(
"v023:"
+
v023
);
// 03测试
Number
v031
=
readHoldingRegister
(
1
,
1
,
DataType
.
FOUR_BYTE_FLOAT
);
// 注意,float
Number
v032
=
readHoldingRegister
(
1
,
3
,
DataType
.
FOUR_BYTE_FLOAT
);
// 同上
System
.
out
.
println
(
"v031:"
+
v031
);
System
.
out
.
println
(
"v032:"
+
v032
);
// 04测试
Number
v041
=
readInputRegisters
(
1
,
0
,
DataType
.
FOUR_BYTE_FLOAT
);
//
Number
v042
=
readInputRegisters
(
1
,
2
,
DataType
.
FOUR_BYTE_FLOAT
);
//
System
.
out
.
println
(
"v041:"
+
v041
);
System
.
out
.
println
(
"v042:"
+
v042
);
// 批量读取
batchRead
();
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
}
}
zhmes-agecal-framework/src/main/java/com/zehong/framework/modbus4j/ModbusDeviceData.java
0 → 100644
View file @
1c3cf716
package
com
.
zehong
.
framework
.
modbus4j
;
import
java.util.Map
;
/**
* @author lenovo
* @date 2025/6/9
* @description TODO
*/
public
class
ModbusDeviceData
{
private
String
deviceId
;
private
Map
<
Integer
,
String
>
registerValues
;
// key: 寄存器地址, value: 读取结果
public
String
getDeviceId
()
{
return
deviceId
;
}
public
void
setDeviceId
(
String
deviceId
)
{
this
.
deviceId
=
deviceId
;
}
public
Map
<
Integer
,
String
>
getRegisterValues
()
{
return
registerValues
;
}
public
void
setRegisterValues
(
Map
<
Integer
,
String
>
registerValues
)
{
this
.
registerValues
=
registerValues
;
}
}
zhmes-agecal-framework/src/main/java/com/zehong/framework/modbus4j/ModbusTcpTask.java
0 → 100644
View file @
1c3cf716
package
com
.
zehong
.
framework
.
modbus4j
;
import
com.serotonin.modbus4j.ModbusMaster
;
import
com.serotonin.modbus4j.exception.ModbusInitException
;
import
com.zehong.system.domain.TEquipmentInfo
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.concurrent.Callable
;
/**
* @author lenovo
* @date 2025/6/9
* @description 读取数据多线程封装
*/
public
class
ModbusTcpTask
implements
Callable
<
Map
<
Integer
,
Object
>>
{
private
final
TEquipmentInfo
equipmentInfo
;
private
final
List
<
Integer
>
registerOffsets
;
public
ModbusTcpTask
(
TEquipmentInfo
equipmentInfo
,
List
<
Integer
>
registerOffset
)
{
this
.
equipmentInfo
=
equipmentInfo
;
this
.
registerOffsets
=
registerOffset
;
}
@Override
public
Map
<
Integer
,
Object
>
call
(){
ModbusMaster
master
=
null
;
try
{
master
=
Modbus4jUtils
.
getMaster
(
equipmentInfo
.
getfIp
(),
equipmentInfo
.
getfPort
());
return
Modbus4jUtils
.
batchReadAgingCabinet
(
master
,
registerOffsets
);
}
catch
(
ModbusInitException
e
)
{
Map
<
Integer
,
Object
>
errorMap
=
new
HashMap
<>();
errorMap
.
put
(
1
,-
1
);
return
errorMap
;
}
catch
(
Exception
e
)
{
Map
<
Integer
,
Object
>
errorMap
=
new
HashMap
<>();
registerOffsets
.
forEach
(
offset
->
errorMap
.
put
(
offset
,
"ERROR: "
+
e
.
getMessage
()));
return
errorMap
;
}
finally
{
if
(
master
!=
null
)
{
master
.
destroy
();
}
}
}
}
zhmes-agecal-system/src/main/java/com/zehong/system/domain/modbus/ModbusDeviceData.java
0 → 100644
View file @
1c3cf716
package
com
.
zehong
.
system
.
domain
.
modbus
;
import
java.util.Map
;
/**
* @author lenovo
* @date 2025/6/9
* @description TODO
*/
public
class
ModbusDeviceData
{
private
String
deviceId
;
private
Map
<
Integer
,
String
>
registerValues
;
// key: 寄存器地址, value: 读取结果
public
String
getDeviceId
()
{
return
deviceId
;
}
public
void
setDeviceId
(
String
deviceId
)
{
this
.
deviceId
=
deviceId
;
}
public
Map
<
Integer
,
String
>
getRegisterValues
()
{
return
registerValues
;
}
public
void
setRegisterValues
(
Map
<
Integer
,
String
>
registerValues
)
{
this
.
registerValues
=
registerValues
;
}
}
zhmes-agecal-system/src/main/java/com/zehong/system/service/ITEquipmentInfoService.java
View file @
1c3cf716
package
com
.
zehong
.
system
.
service
;
import
java.util.List
;
import
java.util.concurrent.CompletableFuture
;
import
com.zehong.system.domain.TEquipmentInfo
;
import
com.zehong.system.domain.modbus.ModbusDeviceData
;
/**
* 生产设备信息Service接口
...
...
@@ -35,6 +38,8 @@ public interface ITEquipmentInfoService
*/
public
List
<
TEquipmentInfo
>
selectTEquipmentList
(
List
<
String
>
types
);
CompletableFuture
<
List
<
ModbusDeviceData
>>
readAllDevicesRegistersAsync
(
List
<
Integer
>
registerOffsets
);
/**
* 新增生产设备信息
*
...
...
zhmes-agecal-system/src/main/java/com/zehong/system/service/impl/TEquipmentInfoServiceImpl.java
View file @
1c3cf716
package
com
.
zehong
.
system
.
service
.
impl
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.concurrent.CompletableFuture
;
import
com.zehong.system.domain.modbus.ModbusDeviceData
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Service
;
import
com.zehong.system.mapper.TEquipmentInfoMapper
;
...
...
@@ -102,4 +106,23 @@ public class TEquipmentInfoServiceImpl implements ITEquipmentInfoService
{
return
tEquipmentInfoMapper
.
deleteTEquipmentInfoById
(
fEquipmentId
);
}
/**
* 批量查询设备寄存器数据
*
* @param registerOffsets 设备寄存器地址
* @return 设备寄存器数据
*/
@Override
public
CompletableFuture
<
List
<
ModbusDeviceData
>>
readAllDevicesRegistersAsync
(
List
<
Integer
>
registerOffsets
)
{
List
<
String
>
type
=
new
ArrayList
<>();
type
.
add
(
"1"
);
type
.
add
(
"2"
);
List
<
TEquipmentInfo
>
tEquipmentInfos
=
tEquipmentInfoMapper
.
selectTEquipmentList
(
type
);
return
null
;
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment