切换导航条
此项目
正在载入...
登录
钟来
/
Luhui
·
提交
转到一个项目
GitLab
转到仪表盘
项目
活动
文件
提交
管道
0
构建
0
图表
里程碑
问题
0
合并请求
0
成员
标记
维基
派生
网络
创建新的问题
下载为
邮件补丁
差异文件
浏览文件
作者
钟来
2025-12-11 14:04:11 +0800
提交
ead90f11bf87501c2bc1f34a694a6d5da76cd476
1 个父辈
84d10f6a
明牛协议解析完成
显示空白字符变更
内嵌
并排对比
正在显示
15 个修改的文件
包含
1400 行增加
和
675 行删除
lh-modules/lh-device-modbus-terminal/src/main/java/com/zhonglai/luhui/device/modbus/terminal/config/InitPlcConfig.java
lh-modules/lh-device-modbus-terminal/src/main/java/com/zhonglai/luhui/device/modbus/terminal/data/topic/PutTopic.java
lh-modules/lh-device-modbus-terminal/src/main/java/com/zhonglai/luhui/device/modbus/terminal/data/topic/ReadTopic.java
lh-modules/lh-device-modbus-terminal/src/main/java/com/zhonglai/luhui/device/modbus/terminal/modbus/EnhancedModbusTcpClientWithByteOrder.java
lh-modules/lh-device-modbus-terminal/src/main/java/com/zhonglai/luhui/device/modbus/terminal/modbus/Modbus4jRead.java
lh-modules/lh-device-modbus-terminal/src/main/java/com/zhonglai/luhui/device/modbus/terminal/modbus/Modbus4jWrite.java
lh-modules/lh-device-modbus-terminal/src/main/java/com/zhonglai/luhui/device/modbus/terminal/modbus/ModbusAddressParser.java
lh-modules/lh-device-modbus-terminal/src/main/java/com/zhonglai/luhui/device/modbus/terminal/modbus/ModbusConnectionManager.java
lh-modules/lh-device-modbus-terminal/src/main/java/com/zhonglai/luhui/device/modbus/terminal/modbus/ModbusMasterMessage.java
lh-modules/lh-device-modbus-terminal/src/main/java/com/zhonglai/luhui/device/modbus/terminal/modbus/dto/CachPlcConfig.java
lh-modules/lh-device-modbus-terminal/src/main/java/com/zhonglai/luhui/device/modbus/terminal/modbus/dto/PlcDataType.java
lh-modules/lh-device-modbus-terminal/src/main/java/com/zhonglai/luhui/device/modbus/terminal/modbus/dto/PlcSystem.java
lh-modules/lh-device-modbus-terminal/src/main/java/com/zhonglai/luhui/device/modbus/terminal/task/CollectPlcDataTask.java
lh-modules/lh-device-modbus-terminal/src/main/resources/configs/plcs _坤泰.json
lh-modules/lh-device-modbus-terminal/src/main/resources/configs/plcs.json
lh-modules/lh-device-modbus-terminal/src/main/java/com/zhonglai/luhui/device/modbus/terminal/config/InitPlcConfig.java
查看文件 @
ead90f1
...
...
@@ -48,6 +48,8 @@ public class InitPlcConfig {
cachPlcConfig
.
setProtocolType
(
plc
.
getProtocolType
());
cachPlcConfig
.
setConnectConfig
(
plc
.
getConnectConfig
());
cachPlcConfig
.
setPlcMap
(
new
HashMap
());
cachPlcConfig
.
setZeroBasedAddress
(
plc
.
getZeroBasedAddress
());
cachPlcConfig
.
setByteOrder
(
plc
.
getByteOrder
());
plcsConfigMap
.
put
(
plc
.
getId
(),
cachPlcConfig
);
}
...
...
lh-modules/lh-device-modbus-terminal/src/main/java/com/zhonglai/luhui/device/modbus/terminal/data/topic/PutTopic.java
查看文件 @
ead90f1
...
...
@@ -5,6 +5,7 @@ import com.zhonglai.luhui.device.modbus.terminal.config.InitPlcConfig;
import
com.zhonglai.luhui.device.modbus.terminal.data.TopicFactoryAdapter
;
import
com.zhonglai.luhui.device.modbus.terminal.modbus.Modbus4jWrite
;
import
com.zhonglai.luhui.device.modbus.terminal.modbus.ModbusMasterMessage
;
import
com.zhonglai.luhui.device.modbus.terminal.modbus.dto.CachPlcConfig
;
import
com.zhonglai.luhui.device.modbus.terminal.modbus.dto.Message
;
import
com.zhonglai.luhui.device.modbus.terminal.modbus.dto.PlcPoint
;
import
com.zhonglai.luhui.device.mqtt.terminal.jar.dto.Topic
;
...
...
@@ -31,15 +32,16 @@ public class PutTopic extends TopicFactoryAdapter {
{
JSONObject
plcCommand
=
jsonObject
.
getJSONObject
(
key
);
String
id
=
key
;
CachPlcConfig
cachPlcConfig
=
InitPlcConfig
.
getPlcsConfigMap
().
get
(
id
);
List
<
PlcPoint
>
plcPoints
=
getPlcPoints
(
id
,
plcCommand
);
Modbus4jWrite
modbus4jWrite
=
null
;
try
{
modbus4jWrite
=
new
Modbus4jWrite
(
id
);
modbus4jWrite
.
batchWrite
(
plcPoints
,
true
);
modbus4jWrite
.
batchWrite
(
plcPoints
,
cachPlcConfig
.
getZeroBasedAddress
()
);
}
catch
(
Exception
e
)
{
if
(
null
!=
modbus4jWrite
)
{
ModbusMasterMessage
.
closeMaster
(
id
);
// 销毁旧连接
ModbusMasterMessage
.
closeMaster
ByPlcId
(
id
);
// 销毁旧连接
}
logger
.
error
(
"写plc异常"
,
e
);
try
{
...
...
lh-modules/lh-device-modbus-terminal/src/main/java/com/zhonglai/luhui/device/modbus/terminal/data/topic/ReadTopic.java
查看文件 @
ead90f1
...
...
@@ -6,6 +6,7 @@ import com.zhonglai.luhui.device.modbus.terminal.data.TopicFactoryAdapter;
import
com.zhonglai.luhui.device.modbus.terminal.modbus.Modbus4jRead
;
import
com.zhonglai.luhui.device.modbus.terminal.modbus.Modbus4jWrite
;
import
com.zhonglai.luhui.device.modbus.terminal.modbus.ModbusMasterMessage
;
import
com.zhonglai.luhui.device.modbus.terminal.modbus.dto.CachPlcConfig
;
import
com.zhonglai.luhui.device.modbus.terminal.modbus.dto.PlcPoint
;
import
com.zhonglai.luhui.device.mqtt.terminal.jar.dto.Topic
;
import
com.zhonglai.luhui.device.mqtt.terminal.jar.mqtt.MqttService
;
...
...
@@ -34,16 +35,18 @@ public class ReadTopic extends TopicFactoryAdapter {
String
plcCommand
=
jsonObject
.
getString
(
key
);
String
id
=
key
;
List
<
PlcPoint
>
plcPoints
=
getPlcPoints
(
id
,
plcCommand
);
CachPlcConfig
cachPlcConfig
=
InitPlcConfig
.
getPlcsConfigMap
().
get
(
id
);
Modbus4jRead
modbus4jRead
=
null
;
try
{
modbus4jRead
=
new
Modbus4jRead
(
id
);
Map
<
String
,
Object
>
map
=
modbus4jRead
.
batchRead
(
plcPoints
,
true
);
Map
<
String
,
Object
>
map
=
modbus4jRead
.
batchRead
(
plcPoints
,
cachPlcConfig
.
getZeroBasedAddress
());
rJsonObject
.
put
(
key
,
map
);
}
catch
(
Exception
e
)
{
logger
.
error
(
"读plc异常"
,
e
);
if
(
null
!=
modbus4jRead
)
{
ModbusMasterMessage
.
closeMaster
(
id
);
// 销毁旧连接
ModbusMasterMessage
.
closeMaster
ByPlcId
(
id
);
// 销毁旧连接
}
return
;
}
...
...
lh-modules/lh-device-modbus-terminal/src/main/java/com/zhonglai/luhui/device/modbus/terminal/modbus/EnhancedModbusTcpClientWithByteOrder.java
0 → 100644
查看文件 @
ead90f1
package
com
.
zhonglai
.
luhui
.
device
.
modbus
.
terminal
.
modbus
;
import
com.serotonin.modbus4j.ModbusMaster
;
import
com.serotonin.modbus4j.exception.ModbusTransportException
;
import
com.serotonin.modbus4j.msg.*
;
import
com.zhonglai.luhui.device.modbus.terminal.modbus.dto.PlcDataType
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
java.nio.ByteBuffer
;
import
java.nio.ByteOrder
;
import
java.util.concurrent.*
;
import
java.util.concurrent.locks.ReentrantLock
;
/**
* 修正并重构后的增强版 Modbus TCP 客户端(字节序与功能码修复)
*/
public
class
EnhancedModbusTcpClientWithByteOrder
{
private
static
final
Logger
log
=
LoggerFactory
.
getLogger
(
EnhancedModbusTcpClientWithByteOrder
.
class
);
/** 浮点字节序 */
public
enum
ByteOrderType
{
ABCD
,
CDAB
,
BADC
,
DCBA
}
private
final
String
host
;
private
final
int
port
;
private
final
ExecutorService
executor
;
private
final
ReentrantLock
connectLock
=
new
ReentrantLock
();
// 配置 master 的参数
private
final
int
timeoutMillis
;
private
final
int
retries
;
private
final
boolean
encapsulated
;
public
static
class
ModbusAddress
{
private
final
int
startAddress
;
// 起始寄存器/线圈地址
private
final
int
bitIndex
;
// -1 表示不是位访问
private
final
int
length
;
// 连续寄存器/线圈长度
private
ModbusAddress
(
int
startAddress
,
int
bitIndex
,
int
length
)
{
this
.
startAddress
=
startAddress
;
this
.
bitIndex
=
bitIndex
;
this
.
length
=
length
;
}
public
int
getStartAddress
()
{
return
startAddress
;
}
public
int
getBitIndex
()
{
return
bitIndex
;
}
public
int
getLength
()
{
return
length
;
}
/**
* 支持格式:
* 40001
* 40001.01
* 40001-40003
*/
public
static
ModbusAddress
parse
(
String
addressStr
)
{
addressStr
=
addressStr
.
trim
();
if
(
addressStr
.
contains
(
"-"
))
{
String
[]
parts
=
addressStr
.
split
(
"-"
);
if
(
parts
.
length
!=
2
)
throw
new
IllegalArgumentException
(
"地址区间格式错误: "
+
addressStr
);
int
start
=
Integer
.
parseInt
(
parts
[
0
].
trim
());
int
end
=
Integer
.
parseInt
(
parts
[
1
].
trim
());
if
(
end
<
start
)
throw
new
IllegalArgumentException
(
"结束地址不能小于起始地址: "
+
addressStr
);
return
new
ModbusAddress
(
start
,
-
1
,
end
-
start
+
1
);
}
else
if
(
addressStr
.
contains
(
"."
))
{
String
[]
parts
=
addressStr
.
split
(
"\\."
);
if
(
parts
.
length
!=
2
)
throw
new
IllegalArgumentException
(
"位地址格式错误: "
+
addressStr
);
int
reg
=
Integer
.
parseInt
(
parts
[
0
].
trim
());
int
bit
=
Integer
.
parseInt
(
parts
[
1
].
trim
())
-
1
;
// 位从1开始
if
(
bit
<
0
||
bit
>
15
)
throw
new
IllegalArgumentException
(
"位索引必须在1-16: "
+
addressStr
);
return
new
ModbusAddress
(
reg
,
bit
,
1
);
}
else
{
int
reg
=
Integer
.
parseInt
(
addressStr
);
return
new
ModbusAddress
(
reg
,
-
1
,
1
);
}
}
}
public
EnhancedModbusTcpClientWithByteOrder
(
String
host
,
int
port
,
int
poolSize
)
{
this
(
host
,
port
,
poolSize
,
3000
,
1
,
true
);
}
public
EnhancedModbusTcpClientWithByteOrder
(
String
host
,
int
port
,
int
poolSize
,
int
timeoutMillis
,
int
retries
,
boolean
encapsulated
)
{
this
.
host
=
host
;
this
.
port
=
port
;
this
.
executor
=
Executors
.
newFixedThreadPool
(
poolSize
);
this
.
timeoutMillis
=
timeoutMillis
;
this
.
retries
=
retries
;
this
.
encapsulated
=
encapsulated
;
}
private
ModbusMaster
getMaster
()
throws
Exception
{
String
key
=
String
.
format
(
"tcp:%s:%d"
,
host
,
port
);
return
ModbusConnectionManager
.
getTcpMaster
(
host
,
port
,
timeoutMillis
,
retries
,
encapsulated
);
}
private
<
T
>
Future
<
T
>
submit
(
Callable
<
T
>
task
)
{
return
executor
.
submit
(
task
);
}
/**
* 将给定地址转换到 0..9999 的 offset。
* zeroBasedAddress == true 表示用户传入的是从 0 开始的地址(例如 0, 40000 等),
* 否则表示用户传入的是从 1 开始的地址(常见的 40001 表示 offset 0)。
*/
private
int
toOffset
(
int
address
,
boolean
zeroBasedAddress
)
{
if
(
zeroBasedAddress
)
{
// 例如 address=40000 -> offset = 40000 % 10000 = 0
int
off
=
address
%
10000
;
return
(
off
+
10000
)
%
10000
;
}
else
{
// one-based input (40001 -> offset 0)
int
off
=
(
address
-
1
)
%
10000
;
return
(
off
+
10000
)
%
10000
;
}
}
/**
* 基于经典 Modbus 地址段做判断:
* 0xxxx (1..9999) -> Coil (FC1 read)
* 1xxxx (10001..19999) -> Discrete Input (FC2 read)
* 3xxxx (30001..39999) -> Input Register (FC4 read)
* 4xxxx (40001..49999) -> Holding Register (FC3 read, write FC6/16)
*
* write 为 true 时,函数尝试返回合适的写功能码(单写/多写)
*/
private
int
getFunctionCode
(
int
address
,
boolean
write
,
Object
value
)
{
if
(
address
<=
0
)
throw
new
IllegalArgumentException
(
"地址必须为正数: "
+
address
);
int
prefix
=
address
/
10000
;
// 0 -> coils (1..9999), 1 -> discrete inputs, 3 -> input regs, 4 -> holding regs
switch
(
prefix
)
{
case
0
:
// 00001 - 09999 => coils
if
(
write
)
{
if
(
value
instanceof
boolean
[])
return
15
;
// Write Multiple Coils
return
5
;
// Write Single Coil
}
else
{
return
1
;
// Read Coils
}
case
1
:
// 10001 - 19999 => discrete input (read-only)
if
(
write
)
throw
new
IllegalArgumentException
(
"Discrete Input 为只读地址段,不能写: "
+
address
);
return
2
;
// Read Discrete Inputs
case
3
:
// 30001 - 39999 => input registers (read-only)
if
(
write
)
throw
new
IllegalArgumentException
(
"Input Register 为只读地址段,不能写: "
+
address
);
return
4
;
// Read Input Registers
case
4
:
// 40001 - 49999 => holding registers
if
(
write
)
{
// 16 = Write Multiple Registers, 6 = Write Single Register
if
(
value
instanceof
Number
)
{
// 无法仅凭 value 类型精确决定是否使用单寄存器还是多寄存器(例如 INT32 需要 2 寄存器)
// 所以这里默认多寄存器(16)以通用支持复杂类型;调用处可以选择适配单寄存器写(WriteRegisterRequest)。
return
16
;
}
else
if
(
value
instanceof
int
[]
||
value
instanceof
short
[]
||
value
instanceof
byte
[])
{
return
16
;
}
else
{
// For boolean writing to holding register bit - handled separately by API
return
16
;
}
}
else
{
return
3
;
// Read Holding Registers
}
default
:
throw
new
IllegalArgumentException
(
"地址超出支持范围: "
+
address
);
}
}
private
ModbusResponse
execute
(
ModbusRequest
req
,
Class
<?
extends
ModbusResponse
>
respType
)
throws
Exception
{
ModbusMaster
master
=
getMaster
();
ModbusResponse
response
=
master
.
send
(
req
);
if
(
response
==
null
)
throw
new
ModbusTransportException
(
"设备无响应"
);
if
(
response
.
isException
())
throw
new
ModbusTransportException
(
"异常响应: "
+
response
.
getExceptionMessage
());
return
respType
.
cast
(
response
);
}
// -------------------- 读接口 --------------------
public
Future
<
Object
>
read
(
int
slaveId
,
int
address
,
PlcDataType
dataType
,
boolean
zeroBasedAddress
,
ByteOrderType
floatByteOrder
)
{
return
submit
(()
->
{
int
offset
=
toOffset
(
address
,
zeroBasedAddress
);
final
ByteOrderType
effectiveByteOrder
=
(
floatByteOrder
==
null
)
?
ByteOrderType
.
CDAB
:
floatByteOrder
;
switch
(
dataType
)
{
case
BOOLEAN:
int
fcBool
=
getFunctionCode
(
address
,
false
,
null
);
if
(
fcBool
==
1
)
return
((
ReadCoilsResponse
)
execute
(
new
ReadCoilsRequest
(
slaveId
,
offset
,
1
),
ReadCoilsResponse
.
class
)).
getBooleanData
()[
0
];
if
(
fcBool
==
2
)
return
((
ReadDiscreteInputsResponse
)
execute
(
new
ReadDiscreteInputsRequest
(
slaveId
,
offset
,
1
),
ReadDiscreteInputsResponse
.
class
)).
getBooleanData
()[
0
];
throw
new
IllegalArgumentException
(
"BOOLEAN 类型无法读取地址:"
+
address
);
case
INT16:
short
[]
regs16
=
readRegisters
(
slaveId
,
offset
,
1
,
address
);
// 保持与之前兼容:返回 int(Java 没有 unsigned short,按 signed short 扩展)
return
(
int
)
regs16
[
0
];
case
INT32:
short
[]
regs32
=
readRegisters
(
slaveId
,
offset
,
2
,
address
);
return
toInt
(
regs32
,
effectiveByteOrder
);
case
INT64:
short
[]
regs64
=
readRegisters
(
slaveId
,
offset
,
4
,
address
);
return
toLong
(
regs64
,
effectiveByteOrder
);
case
FLOAT32:
short
[]
f32Regs
=
readRegisters
(
slaveId
,
offset
,
2
,
address
);
return
toFloat
(
f32Regs
,
effectiveByteOrder
);
case
FLOAT64:
short
[]
f64Regs
=
readRegisters
(
slaveId
,
offset
,
4
,
address
);
return
toDouble
(
f64Regs
,
effectiveByteOrder
);
default
:
throw
new
IllegalArgumentException
(
"未知 DataType:"
+
dataType
);
}
});
}
// -------------------- 写接口 --------------------
public
Future
<
Void
>
write
(
int
slaveId
,
int
address
,
PlcDataType
dataType
,
Object
value
,
boolean
zeroBasedAddress
,
ByteOrderType
floatByteOrder
)
{
return
submit
(()
->
{
int
offset
=
toOffset
(
address
,
zeroBasedAddress
);
final
ByteOrderType
effectiveByteOrder
=
(
floatByteOrder
==
null
)
?
ByteOrderType
.
CDAB
:
floatByteOrder
;
switch
(
dataType
)
{
case
BOOLEAN:
if
(
value
instanceof
Boolean
)
{
execute
(
new
WriteCoilRequest
(
slaveId
,
offset
,
(
Boolean
)
value
),
WriteCoilResponse
.
class
);
}
else
if
(
value
instanceof
boolean
[])
{
execute
(
new
WriteCoilsRequest
(
slaveId
,
offset
,
(
boolean
[])
value
),
WriteCoilsResponse
.
class
);
}
else
throw
new
IllegalArgumentException
(
"BOOLEAN 写入必须是 Boolean 或 boolean[]"
);
return
null
;
case
INT16:
// 写单个寄存器(用 WriteRegisterRequest -> FC6)
execute
(
new
WriteRegisterRequest
(
slaveId
,
offset
,
(
Long
.
valueOf
(
String
.
valueOf
(
value
))).
shortValue
()),
WriteRegisterResponse
.
class
);
return
null
;
case
INT32:
// 写 2 个寄存器(FC16)
execute
(
new
WriteRegistersRequest
(
slaveId
,
offset
,
toShorts
(
Integer
.
parseInt
(
String
.
valueOf
(
value
)),
effectiveByteOrder
)),
WriteRegistersResponse
.
class
);
return
null
;
case
INT64:
execute
(
new
WriteRegistersRequest
(
slaveId
,
offset
,
toShorts
(
Long
.
valueOf
(
String
.
valueOf
(
value
)),
effectiveByteOrder
)),
WriteRegistersResponse
.
class
);
return
null
;
case
FLOAT32:
execute
(
new
WriteRegistersRequest
(
slaveId
,
offset
,
fromFloat
(
Float
.
valueOf
(
String
.
valueOf
(
value
))
,
effectiveByteOrder
)),
WriteRegistersResponse
.
class
);
return
null
;
case
FLOAT64:
execute
(
new
WriteRegistersRequest
(
slaveId
,
offset
,
fromDouble
(
Double
.
valueOf
(
String
.
valueOf
(
value
)),
effectiveByteOrder
)),
WriteRegistersResponse
.
class
);
return
null
;
default
:
throw
new
IllegalArgumentException
(
"未知 DataType:"
+
dataType
);
}
});
}
/**
* 读取 Holding Register 中的某一位(支持 40001.01 格式)
*/
public
boolean
readBooleanFromRegisterBit
(
int
slaveId
,
String
addressStr
,
boolean
zeroBasedAddress
)
throws
Exception
{
ModbusAddress
addr
=
ModbusAddress
.
parse
(
addressStr
);
if
(
addr
.
getBitIndex
()
<
0
)
throw
new
IllegalArgumentException
(
"地址不是位访问: "
+
addressStr
);
int
offset
=
toOffset
(
addr
.
getStartAddress
(),
zeroBasedAddress
);
short
[]
regs
=
readRegisters
(
slaveId
,
offset
,
1
,
addr
.
getStartAddress
());
return
((
regs
[
0
]
>>
addr
.
getBitIndex
())
&
0x1
)
==
1
;
}
/**
* 写入 Holding Register 中的某一位(支持 40001.01 格式)
*/
public
void
writeBooleanToRegisterBit
(
int
slaveId
,
String
addressStr
,
boolean
value
,
boolean
zeroBasedAddress
)
throws
Exception
{
ModbusAddress
addr
=
ModbusAddress
.
parse
(
addressStr
);
if
(
addr
.
getBitIndex
()
<
0
)
throw
new
IllegalArgumentException
(
"地址不是位访问: "
+
addressStr
);
int
offset
=
toOffset
(
addr
.
getStartAddress
(),
zeroBasedAddress
);
// 读取原寄存器
short
[]
regs
=
readRegisters
(
slaveId
,
offset
,
1
,
addr
.
getStartAddress
());
// 修改对应 bit
if
(
value
)
regs
[
0
]
|=
(
1
<<
addr
.
getBitIndex
());
else
regs
[
0
]
&=
~(
1
<<
addr
.
getBitIndex
());
// 写回寄存器(用 WriteRegistersRequest)
execute
(
new
WriteRegistersRequest
(
slaveId
,
offset
,
regs
),
WriteRegistersResponse
.
class
);
}
private
short
[]
readRegisters
(
int
slaveId
,
int
offset
,
int
length
,
int
address
)
throws
Exception
{
int
fc
=
getFunctionCode
(
address
,
false
,
null
);
// 使用原始地址
if
(
fc
==
3
)
return
((
ReadHoldingRegistersResponse
)
execute
(
new
ReadHoldingRegistersRequest
(
slaveId
,
offset
,
length
),
ReadHoldingRegistersResponse
.
class
)).
getShortData
();
if
(
fc
==
4
)
return
((
ReadInputRegistersResponse
)
execute
(
new
ReadInputRegistersRequest
(
slaveId
,
offset
,
length
),
ReadInputRegistersResponse
.
class
)).
getShortData
();
throw
new
IllegalArgumentException
(
"寄存器类型无法读取,offset="
+
offset
+
" address="
+
address
);
}
// -------------------- 通用字节重排工具 --------------------
private
static
byte
[]
regsToRawBytes
(
short
[]
regs
)
{
byte
[]
raw
=
new
byte
[
regs
.
length
*
2
];
for
(
int
i
=
0
;
i
<
regs
.
length
;
i
++)
{
raw
[
i
*
2
]
=
(
byte
)
(
regs
[
i
]
>>
8
);
raw
[
i
*
2
+
1
]
=
(
byte
)
regs
[
i
];
}
return
raw
;
}
/**
* 根据目标字节长度(4 或 8)和字节序类型重排 bytes。
* 当 bytes.length == 4 或 8 时按表格重排;否则返回原数组拷贝。
*/
private
static
byte
[]
reorderBytesForType
(
byte
[]
src
,
ByteOrderType
boType
)
{
int
len
=
src
.
length
;
byte
[]
dst
=
new
byte
[
len
];
if
(
len
==
4
)
{
int
[]
map
;
switch
(
boType
)
{
case
ABCD:
map
=
new
int
[]{
0
,
1
,
2
,
3
};
break
;
case
CDAB:
map
=
new
int
[]{
2
,
3
,
0
,
1
};
break
;
case
BADC:
map
=
new
int
[]{
1
,
0
,
3
,
2
};
break
;
case
DCBA:
map
=
new
int
[]{
3
,
2
,
1
,
0
};
break
;
default
:
map
=
new
int
[]{
0
,
1
,
2
,
3
};
}
for
(
int
i
=
0
;
i
<
4
;
i
++)
dst
[
i
]
=
src
[
map
[
i
]];
return
dst
;
}
else
if
(
len
==
8
)
{
int
[]
map
;
switch
(
boType
)
{
case
ABCD:
map
=
new
int
[]{
0
,
1
,
2
,
3
,
4
,
5
,
6
,
7
};
break
;
case
CDAB:
map
=
new
int
[]{
2
,
3
,
0
,
1
,
6
,
7
,
4
,
5
};
break
;
// swap 2-word pairs
case
BADC:
map
=
new
int
[]{
1
,
0
,
3
,
2
,
5
,
4
,
7
,
6
};
break
;
// swap bytes in each word
case
DCBA:
map
=
new
int
[]{
7
,
6
,
5
,
4
,
3
,
2
,
1
,
0
};
break
;
// reverse
default
:
map
=
new
int
[]{
0
,
1
,
2
,
3
,
4
,
5
,
6
,
7
};
}
for
(
int
i
=
0
;
i
<
8
;
i
++)
dst
[
i
]
=
src
[
map
[
i
]];
return
dst
;
}
else
{
// 不支持的长度,返回原数组副本
System
.
arraycopy
(
src
,
0
,
dst
,
0
,
len
);
return
dst
;
}
}
private
static
byte
[]
reorderBytesForRead
(
byte
[]
src
,
ByteOrderType
type
)
{
int
len
=
src
.
length
;
byte
[]
dst
=
new
byte
[
len
];
int
[]
m
;
if
(
len
==
4
)
{
switch
(
type
)
{
case
ABCD:
m
=
new
int
[]{
0
,
1
,
2
,
3
};
break
;
case
CDAB:
m
=
new
int
[]{
2
,
3
,
0
,
1
};
break
;
case
BADC:
m
=
new
int
[]{
1
,
0
,
3
,
2
};
break
;
case
DCBA:
m
=
new
int
[]{
3
,
2
,
1
,
0
};
break
;
default
:
m
=
new
int
[]{
0
,
1
,
2
,
3
};
}
for
(
int
i
=
0
;
i
<
4
;
i
++)
dst
[
i
]
=
src
[
m
[
i
]];
}
else
if
(
len
==
8
)
{
switch
(
type
)
{
case
ABCD:
m
=
new
int
[]{
0
,
1
,
2
,
3
,
4
,
5
,
6
,
7
};
break
;
case
CDAB:
m
=
new
int
[]{
2
,
3
,
0
,
1
,
6
,
7
,
4
,
5
};
break
;
case
BADC:
m
=
new
int
[]{
1
,
0
,
3
,
2
,
5
,
4
,
7
,
6
};
break
;
case
DCBA:
m
=
new
int
[]{
7
,
6
,
5
,
4
,
3
,
2
,
1
,
0
};
break
;
default
:
m
=
new
int
[]{
0
,
1
,
2
,
3
,
4
,
5
,
6
,
7
};
}
for
(
int
i
=
0
;
i
<
8
;
i
++)
dst
[
i
]
=
src
[
m
[
i
]];
}
else
{
System
.
arraycopy
(
src
,
0
,
dst
,
0
,
len
);
}
return
dst
;
}
private
static
byte
[]
reorderBytesForWrite
(
byte
[]
src
,
ByteOrderType
type
)
{
int
len
=
src
.
length
;
byte
[]
dst
=
new
byte
[
len
];
int
[]
m
;
if
(
len
==
4
)
{
switch
(
type
)
{
case
ABCD:
m
=
new
int
[]{
0
,
1
,
2
,
3
};
break
;
case
CDAB:
m
=
new
int
[]{
2
,
3
,
0
,
1
};
break
;
case
BADC:
m
=
new
int
[]{
1
,
0
,
3
,
2
};
break
;
case
DCBA:
m
=
new
int
[]{
3
,
2
,
1
,
0
};
break
;
default
:
m
=
new
int
[]{
0
,
1
,
2
,
3
};
}
for
(
int
i
=
0
;
i
<
4
;
i
++)
dst
[
m
[
i
]]
=
src
[
i
];
}
else
if
(
len
==
8
)
{
switch
(
type
)
{
case
ABCD:
m
=
new
int
[]{
0
,
1
,
2
,
3
,
4
,
5
,
6
,
7
};
break
;
case
CDAB:
m
=
new
int
[]{
2
,
3
,
0
,
1
,
6
,
7
,
4
,
5
};
break
;
case
BADC:
m
=
new
int
[]{
1
,
0
,
3
,
2
,
5
,
4
,
7
,
6
};
break
;
case
DCBA:
m
=
new
int
[]{
7
,
6
,
5
,
4
,
3
,
2
,
1
,
0
};
break
;
default
:
m
=
new
int
[]{
0
,
1
,
2
,
3
,
4
,
5
,
6
,
7
};
}
for
(
int
i
=
0
;
i
<
8
;
i
++)
dst
[
m
[
i
]]
=
src
[
i
];
}
else
{
System
.
arraycopy
(
src
,
0
,
dst
,
0
,
len
);
}
return
dst
;
}
private
static
short
[]
rawBytesToRegs
(
byte
[]
raw
)
{
if
(
raw
.
length
%
2
!=
0
)
throw
new
IllegalArgumentException
(
"raw length must be even"
);
short
[]
regs
=
new
short
[
raw
.
length
/
2
];
for
(
int
i
=
0
;
i
<
regs
.
length
;
i
++)
{
regs
[
i
]
=
(
short
)
(((
raw
[
i
*
2
]
&
0
xFF
)
<<
8
)
|
(
raw
[
i
*
2
+
1
]
&
0
xFF
));
}
return
regs
;
}
// -------------------- 数值转换实现(统一、可维护) --------------------
private
int
toInt
(
short
[]
regs
,
ByteOrderType
boType
)
{
if
(
regs
.
length
==
1
)
{
return
regs
[
0
];
// 单寄存器,保留 signed short 扩展
}
if
(
regs
.
length
<
2
)
throw
new
IllegalArgumentException
(
"regs 长度必须 >= 2"
);
byte
[]
raw
=
regsToRawBytes
(
new
short
[]{
regs
[
0
],
regs
[
1
]});
byte
[]
reordered
=
reorderBytesForRead
(
raw
,
boType
);
return
ByteBuffer
.
wrap
(
reordered
).
order
(
ByteOrder
.
BIG_ENDIAN
).
getInt
();
}
private
long
toLong
(
short
[]
regs
,
ByteOrderType
boType
)
{
if
(
regs
.
length
!=
4
)
throw
new
IllegalArgumentException
(
"regs 长度必须为4"
);
byte
[]
raw
=
regsToRawBytes
(
regs
);
byte
[]
reordered
=
reorderBytesForRead
(
raw
,
boType
);
return
ByteBuffer
.
wrap
(
reordered
).
order
(
ByteOrder
.
BIG_ENDIAN
).
getLong
();
}
private
float
toFloat
(
short
[]
regs
,
ByteOrderType
boType
)
{
if
(
regs
.
length
<
2
)
throw
new
IllegalArgumentException
(
"regs 长度必须 >= 2"
);
byte
[]
raw
=
regsToRawBytes
(
new
short
[]{
regs
[
0
],
regs
[
1
]});
byte
[]
reordered
=
reorderBytesForRead
(
raw
,
boType
);
return
ByteBuffer
.
wrap
(
reordered
).
order
(
ByteOrder
.
BIG_ENDIAN
).
getFloat
();
}
private
double
toDouble
(
short
[]
regs
,
ByteOrderType
boType
)
{
if
(
regs
.
length
!=
4
)
throw
new
IllegalArgumentException
(
"regs 长度必须为4"
);
byte
[]
raw
=
regsToRawBytes
(
regs
);
byte
[]
reordered
=
reorderBytesForRead
(
raw
,
boType
);
return
ByteBuffer
.
wrap
(
reordered
).
order
(
ByteOrder
.
BIG_ENDIAN
).
getDouble
();
}
// 从基本类型生成寄存器(short[])
private
short
[]
fromFloat
(
float
value
,
ByteOrderType
boType
)
{
byte
[]
bytes
=
ByteBuffer
.
allocate
(
4
).
order
(
ByteOrder
.
BIG_ENDIAN
).
putFloat
(
value
).
array
();
// inverse: 根据字节序先获得 raw 字节,应当把 `bytes` 视为网络顺序(ABCD),
// 因此要把 `bytes` 按相反的 reordering 写回 regs:
byte
[]
raw
=
reorderBytesForWrite
(
bytes
,
boType
);
// 使其成为 "寄存器大端序" 的原始 bytes
return
rawBytesToRegs
(
raw
);
}
private
short
[]
fromDouble
(
double
value
,
ByteOrderType
boType
)
{
byte
[]
bytes
=
ByteBuffer
.
allocate
(
8
).
order
(
ByteOrder
.
BIG_ENDIAN
).
putDouble
(
value
).
array
();
byte
[]
raw
=
reorderBytesForWrite
(
bytes
,
boType
);
return
rawBytesToRegs
(
raw
);
}
private
short
[]
toShorts
(
int
value
,
ByteOrderType
boType
)
{
byte
[]
bytes
=
ByteBuffer
.
allocate
(
4
).
order
(
ByteOrder
.
BIG_ENDIAN
).
putInt
(
value
).
array
();
byte
[]
raw
=
reorderBytesForWrite
(
bytes
,
boType
);
return
rawBytesToRegs
(
raw
);
}
private
short
[]
toShorts
(
long
value
,
ByteOrderType
boType
)
{
byte
[]
bytes
=
ByteBuffer
.
allocate
(
8
).
order
(
ByteOrder
.
BIG_ENDIAN
).
putLong
(
value
).
array
();
byte
[]
raw
=
reorderBytesForWrite
(
bytes
,
boType
);
return
rawBytesToRegs
(
raw
);
}
/**
* 返回用于逆向重排的类型(因为我们上面 reorderBytesForType 的定义是“从 regs->字节->按字节序重排得到目标顺序”)。
* 当我们有一个按网络顺序(BIG_ENDIAN)的字节数组(例如 ByteBuffer.putInt 产生的),
* 为得到写入寄存器的 raw bytes(每个寄存器高字节在前),需要对这个数组做 inverse reorder。
*/
private
static
ByteOrderType
inverseOrder
(
ByteOrderType
boType
)
{
switch
(
boType
)
{
case
ABCD:
return
ByteOrderType
.
ABCD
;
case
CDAB:
return
ByteOrderType
.
CDAB
;
// 自反映射在 reorderBytesForType 中是对称的(因为 map 的逆映射与 map 本身一致)
case
BADC:
return
ByteOrderType
.
BADC
;
case
DCBA:
return
ByteOrderType
.
DCBA
;
default
:
return
ByteOrderType
.
CDAB
;
}
}
// -------------------- 关闭 --------------------
public
void
close
()
{
executor
.
shutdown
();
try
{
if
(!
executor
.
awaitTermination
(
3
,
TimeUnit
.
SECONDS
))
{
executor
.
shutdownNow
();
}
}
catch
(
InterruptedException
e
)
{
Thread
.
currentThread
().
interrupt
();
executor
.
shutdownNow
();
}
log
.
info
(
"EnhancedModbusTcpClientWithByteOrder closed"
);
}
// -------------------- 简单 main 测试示例 --------------------
public
static
void
main
(
String
[]
args
)
throws
Exception
{
EnhancedModbusTcpClientWithByteOrder
client
=
new
EnhancedModbusTcpClientWithByteOrder
(
"127.0.0.1"
,
2010
,
10
);
// // 示例:读取 10001 (coil) — 注意 zeroBasedAddress 参数语义
// Future<Object> bit1 = client.read(1, 10001, PlcDataType.BOOLEAN, false, ByteOrderType.CDAB);
// System.out.println("10001 = " + bit1.get());
//
// // 写入 FLOAT32
// client.write(1, 40001,PlcDataType.FLOAT32, 38.5f, false, ByteOrderType.CDAB);
// // 读取 FLOAT32
// Float temp = (Float) client.read(1, 40001,PlcDataType.FLOAT32, false, ByteOrderType.CDAB).get();
// System.out.println("40001 FLOAT32 = " + temp);
// // 写入 FLOAT64
// client.write(1, 40003,PlcDataType.FLOAT64, 102.23, false, ByteOrderType.CDAB);
// // 读取 FLOAT64
// Double pressure = (Double) client.read(1, 40003,PlcDataType.FLOAT64, false, ByteOrderType.CDAB).get();
// System.out.println("40003 FLOAT64 = " + pressure);
// // 写入 FLOAT32
// client.write(1, 40053, PlcDataType.FLOAT32, 56.5f, false, ByteOrderType.CDAB);
// Float one = (Float) client.read(1, 40053,PlcDataType.FLOAT32, false, ByteOrderType.CDAB).get();
// System.out.println("40008 INT16 = " + one);
// // 写入 40009 寄存器的第 2 位
client
.
writeBooleanToRegisterBit
(
1
,
"40051.13"
,
true
,
false
);
// // 读取 40009 寄存器的第 2 位
// boolean bitValue = client.readBooleanFromRegisterBit(1, "40009.02", false);
// System.out.println("40009.01 = " + bitValue);
// 写入 FLOAT32
// client.write(1, 40053,PlcDataType.FLOAT32, 9, false, ByteOrderType.ABCD);
// System.out.println(client.read(1, 40053, PlcDataType.FLOAT32, false, ByteOrderType.ABCD).get());
// System.out.println(client.read(1, 10001,PlcDataType.BOOLEAN, false, ByteOrderType.CDAB).get());
// System.out.println(client.read(1, 10002,PlcDataType.BOOLEAN, false, ByteOrderType.CDAB).get());
// System.out.println(client.read(1, 10003,PlcDataType.BOOLEAN, false, ByteOrderType.CDAB).get());
client
.
close
();
}
}
...
...
lh-modules/lh-device-modbus-terminal/src/main/java/com/zhonglai/luhui/device/modbus/terminal/modbus/Modbus4jRead.java
查看文件 @
ead90f1
...
...
@@ -8,6 +8,7 @@ import com.serotonin.modbus4j.exception.ErrorResponseException;
import
com.serotonin.modbus4j.exception.ModbusInitException
;
import
com.serotonin.modbus4j.exception.ModbusTransportException
;
import
com.serotonin.modbus4j.locator.BaseLocator
;
import
com.zhonglai.luhui.device.modbus.terminal.modbus.dto.PlcDataType
;
import
com.zhonglai.luhui.device.modbus.terminal.modbus.dto.PlcPoint
;
import
com.zhonglai.luhui.device.modbus.terminal.task.CollectPlcDataTask
;
import
org.slf4j.Logger
;
...
...
@@ -18,6 +19,7 @@ import java.io.IOException;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.concurrent.Future
;
/**
* modbus通讯工具类,采用modbus4j实现
...
...
@@ -46,94 +48,20 @@ public class Modbus4jRead {
/**
* 批量读取点位
*/
public
Map
<
String
,
Object
>
batchRead
(
List
<
PlcPoint
>
plcPoints
,
boolean
zeroBasedAddress
)
throws
ModbusTransportException
,
ErrorResponseException
{
BatchRead
<
String
>
batch
=
new
BatchRead
<>();
for
(
PlcPoint
plcPoint
:
plcPoints
)
{
String
key
=
plcPoint
.
getSystem
();
// 解析 Modbus 地址,生成 BaseLocator
BaseLocator
<?>
locator
=
ModbusAddressParser
.
parseLocator
(
plcPoint
.
getAddress
(),
plcPoint
.
getDataType
(),
plcPoint
.
getSlaveId
(),
zeroBasedAddress
,
plcPoint
.
getOrder
()
);
batch
.
addLocator
(
key
,
locator
);
}
batch
.
setContiguousRequests
(
false
);
// 发送批量请求
BatchResults
<
String
>
results
=
null
;
try
{
results
=
ModbusMasterMessage
.
getMaster
(
id
).
send
(
batch
);
}
catch
(
Exception
e
)
{
logger
.
error
(
"第一次批量读取异常,尝试一次"
,
e
);
if
(
e
instanceof
ModbusInitException
||
e
instanceof
ModbusTransportException
||
e
.
getCause
()
instanceof
IOException
)
{
ModbusMasterMessage
.
closeMaster
(
id
);
try
{
results
=
ModbusMasterMessage
.
getMaster
(
id
).
send
(
batch
);
}
catch
(
Exception
ex
)
{
logger
.
error
(
"第二次批量读取异常,不处理"
,
ex
);
return
null
;
}
}
else
{
logger
.
info
(
"第一次批量读不是联系异常,不尝试了"
);
return
null
;
}
}
// 转换成 JSON 对象
public
Map
<
String
,
Object
>
batchRead
(
List
<
PlcPoint
>
plcPoints
,
boolean
zeroBasedAddress
)
throws
Exception
{
EnhancedModbusTcpClientWithByteOrder
client
=
ModbusMasterMessage
.
getEnhancedModbusTcpClientWithByteOrder
(
id
);
Map
<
String
,
Object
>
jsonMap
=
new
HashMap
<>();
for
(
PlcPoint
plcPoint
:
plcPoints
)
{
// 输出所有结果
String
key
=
plcPoint
.
getSystem
();
Object
value
=
results
.
getValue
(
key
);
switch
(
plcPoint
.
getDataType
())
Object
value
;
String
addrStr
=
plcPoint
.
getAddress
();
EnhancedModbusTcpClientWithByteOrder
.
ModbusAddress
addr
=
EnhancedModbusTcpClientWithByteOrder
.
ModbusAddress
.
parse
(
addrStr
);
if
(
addr
.
getBitIndex
()>-
1
)
{
case
FLOAT32:
if
(
value
instanceof
Integer
)
{
int
raw
=
(
int
)
value
;
switch
(
plcPoint
.
getOrder
())
{
case
"ABCD"
:
value
=
ModbusAddressParser
.
intToFloatABCD
(
raw
);
break
;
case
"BADC"
:
value
=
ModbusAddressParser
.
intToFloatBADC
(
raw
);
break
;
case
"CDAB"
:
value
=
ModbusAddressParser
.
intToFloatCDAB
(
raw
);
break
;
case
"DCBA"
:
value
=
ModbusAddressParser
.
intToFloatDCBA
(
raw
);
break
;
}
}
break
;
case
INT32:
if
(
value
instanceof
Integer
)
{
int
raw
=
(
int
)
value
;
switch
(
plcPoint
.
getOrder
())
{
case
"ABCD"
:
value
=
ModbusAddressParser
.
int32ABCD
(
raw
);
break
;
case
"BADC"
:
value
=
ModbusAddressParser
.
int32BADC
(
raw
);
break
;
case
"CDAB"
:
value
=
ModbusAddressParser
.
int32CDAB
(
raw
);
break
;
case
"DCBA"
:
value
=
ModbusAddressParser
.
int32DCBA
(
raw
);
break
;
}
}
break
;
value
=
client
.
readBooleanFromRegisterBit
(
1
,
addrStr
,
zeroBasedAddress
);
}
else
{
value
=
client
.
read
(
1
,
addr
.
getStartAddress
(),
plcPoint
.
getDataType
(),
zeroBasedAddress
,
null
==
plcPoint
.
getOrder
()?
EnhancedModbusTcpClientWithByteOrder
.
ByteOrderType
.
ABCD
:
EnhancedModbusTcpClientWithByteOrder
.
ByteOrderType
.
valueOf
(
plcPoint
.
getOrder
())).
get
();
}
jsonMap
.
put
(
key
,
value
);
}
...
...
lh-modules/lh-device-modbus-terminal/src/main/java/com/zhonglai/luhui/device/modbus/terminal/modbus/Modbus4jWrite.java
查看文件 @
ead90f1
...
...
@@ -34,120 +34,24 @@ public class Modbus4jWrite {
public
Modbus4jWrite
(
String
id
)
throws
Exception
{
this
.
id
=
id
;
}
private
final
Object
writeLock
=
new
Object
();
// 全局串行化写锁
public
void
batchWrite
(
List
<
PlcPoint
>
points
,
boolean
zeroBasedAddress
)
throws
Exception
{
if
(
points
==
null
||
points
.
isEmpty
())
return
;
synchronized
(
writeLock
)
{
ModbusMaster
master
=
ModbusMasterMessage
.
getMaster
(
id
);
try
{
sendBatch
(
master
,
points
,
zeroBasedAddress
);
}
catch
(
Exception
e
)
{
log
.
info
(
"第一次批量写入异常,尝试重连后再写入"
,
e
);
if
(
e
instanceof
ModbusInitException
||
e
instanceof
ModbusTransportException
||
e
.
getCause
()
instanceof
IOException
)
{
ModbusMasterMessage
.
closeMaster
(
id
);
master
=
ModbusMasterMessage
.
getMaster
(
id
);
sendBatch
(
master
,
points
,
zeroBasedAddress
);
}
else
{
log
.
info
(
"第二次批量写入异常,不处理"
,
e
);
}
}
}
}
// 批量写入封装
private
void
sendBatch
(
ModbusMaster
master
,
List
<
PlcPoint
>
points
,
boolean
zeroBasedAddress
)
throws
Exception
{
for
(
PlcPoint
point
:
points
)
{
BaseLocator
<?>
locator
=
ModbusAddressParser
.
parseLocator
(
point
.
getAddress
(),
point
.
getDataType
(),
point
.
getSlaveId
(),
zeroBasedAddress
,
point
.
getOrder
()
);
Object
value
=
convertValue
(
point
);
if
(
point
.
getDataType
()
==
PlcDataType
.
BIT
&&
point
.
getAddress
().
contains
(
"."
))
{
// ⚡ 先读寄存器,再修改 bit 位,再写回
int
offset
=
ModbusAddressParser
.
parseOffset
(
point
.
getAddress
(),
zeroBasedAddress
);
int
bitIndex
=
ModbusAddressParser
.
parseBitIndex
(
point
.
getAddress
());
if
(
bitIndex
<
0
)
{
throw
new
IllegalArgumentException
(
"无效的 bit 地址: "
+
point
.
getAddress
());
}
// 读 holding register
int
rawValue
=
master
.
getValue
(
BaseLocator
.
holdingRegister
(
point
.
getSlaveId
(),
offset
,
DataType
.
TWO_BYTE_INT_UNSIGNED
)
).
intValue
();
// 修改 bit
boolean
bitVal
=
(
Boolean
)
value
;
if
(
bitVal
)
{
rawValue
=
rawValue
|
(
1
<<
bitIndex
);
// 置位
}
else
{
rawValue
=
rawValue
&
~(
1
<<
bitIndex
);
// 清位
}
// 写回
master
.
setValue
(
ModbusAddressParser
.
parseLocator
(
point
.
getAddress
().
split
(
"\\."
)[
0
],
PlcDataType
.
INT16
,
point
.
getSlaveId
(),
zeroBasedAddress
,
point
.
getOrder
()
),
rawValue
);
log
.
info
(
"写入成功(Bit): {}[{}] = {}"
,
point
.
getName
(),
point
.
getAddress
(),
value
);
}
else
{
// ⚡ 其它类型照旧
master
.
setValue
(
locator
,
value
);
log
.
info
(
"写入成功: {}[{}] = {}"
,
point
.
getName
(),
point
.
getAddress
(),
value
);
}
}
}
// 值转换逻辑沿用你的 writePoint
private
Object
convertValue
(
PlcPoint
point
)
{
Object
value
=
point
.
getValue
();
if
(
value
instanceof
String
)
{
String
strVal
=
(
String
)
value
;
switch
(
point
.
getDataType
())
{
case
BIT:
return
Boolean
.
parseBoolean
(
strVal
);
case
INT16:
return
Short
.
parseShort
(
strVal
);
case
UINT16:
return
Integer
.
parseInt
(
strVal
);
case
INT32:
int
raw
=
Integer
.
parseInt
(
strVal
);
switch
(
point
.
getOrder
())
{
case
"ABCD"
:
return
ModbusAddressParser
.
int32ToABCD
(
raw
);
case
"BADC"
:
return
ModbusAddressParser
.
int32ToBADC
(
raw
);
case
"CDAB"
:
return
ModbusAddressParser
.
int32ToCDAB
(
raw
);
case
"DCBA"
:
return
ModbusAddressParser
.
int32ToDCBA
(
raw
);
default
:
return
raw
;
}
case
INT64:
return
Long
.
parseLong
(
strVal
);
case
FLOAT32:
float
fvalue
=
Float
.
parseFloat
(
strVal
);
switch
(
point
.
getOrder
())
{
case
"ABCD"
:
return
ModbusAddressParser
.
floatToIntABCD
(
fvalue
);
case
"BADC"
:
return
ModbusAddressParser
.
floatToIntBADC
(
fvalue
);
case
"CDAB"
:
return
ModbusAddressParser
.
floatToIntCDAB
(
fvalue
);
case
"DCBA"
:
return
ModbusAddressParser
.
floatToIntDCBA
(
fvalue
);
default
:
return
fvalue
;
}
case
DOUBLE64:
return
Double
.
parseDouble
(
strVal
);
default
:
throw
new
IllegalArgumentException
(
"不支持的数据类型: "
+
point
.
getDataType
());
EnhancedModbusTcpClientWithByteOrder
client
=
ModbusMasterMessage
.
getEnhancedModbusTcpClientWithByteOrder
(
id
);
for
(
PlcPoint
plcPoint
:
points
)
{
EnhancedModbusTcpClientWithByteOrder
.
ModbusAddress
addr
=
EnhancedModbusTcpClientWithByteOrder
.
ModbusAddress
.
parse
(
plcPoint
.
getAddress
());
if
(
addr
.
getBitIndex
()>-
1
)
{
log
.
info
(
"BIT写入数据:addr {},plcPoint {}"
,
addr
,
plcPoint
);
client
.
writeBooleanToRegisterBit
(
1
,
plcPoint
.
getAddress
(),
Boolean
.
valueOf
(
String
.
valueOf
(
plcPoint
.
getValue
())),
zeroBasedAddress
);
}
else
{
log
.
info
(
plcPoint
.
getDataType
()+
"写入数据:addr {},plcPoint {}"
,
addr
,
plcPoint
);
client
.
write
(
1
,
addr
.
getStartAddress
(),
plcPoint
.
getDataType
(),
plcPoint
.
getValue
(),
zeroBasedAddress
,
null
==
plcPoint
.
getOrder
()?
EnhancedModbusTcpClientWithByteOrder
.
ByteOrderType
.
CDAB
:
EnhancedModbusTcpClientWithByteOrder
.
ByteOrderType
.
valueOf
(
plcPoint
.
getOrder
()));
}
}
return
value
;
}
}
\ No newline at end of file
...
...
lh-modules/lh-device-modbus-terminal/src/main/java/com/zhonglai/luhui/device/modbus/terminal/modbus/ModbusAddressParser.java
已删除
100644 → 0
查看文件 @
84d10f6
package
com
.
zhonglai
.
luhui
.
device
.
modbus
.
terminal
.
modbus
;
import
com.serotonin.modbus4j.locator.BaseLocator
;
import
com.serotonin.modbus4j.code.DataType
;
import
com.zhonglai.luhui.device.modbus.terminal.modbus.dto.PlcDataType
;
import
java.nio.ByteBuffer
;
import
java.nio.ByteOrder
;
public
class
ModbusAddressParser
{
/**
* 解析 Modbus 地址,生成 BaseLocator
* @param rawAddress 原始地址 (40001, 40001.01, 40003-40004)
* @param type 数据类型 (BIT, INT16, UINT16, INT32, INT64, FLOAT32, DOUBLE64)
* @param slaveId 从站ID
* @return BaseLocator 对象
*/
public
static
BaseLocator
<?>
parseLocator
(
String
rawAddress
,
PlcDataType
type
,
int
slaveId
,
boolean
zeroBasedAddress
,
String
order
)
{
int
offset
=
parseOffset
(
rawAddress
,
zeroBasedAddress
);
int
bitIndex
=
parseBitIndex
(
rawAddress
);
switch
(
type
)
{
case
BIT:
if
(
rawAddress
.
startsWith
(
"0"
))
{
// Coil (线圈输出)
return
BaseLocator
.
coilStatus
(
slaveId
,
offset
);
}
else
if
(
rawAddress
.
startsWith
(
"1"
))
{
// Discrete Input (离散量输入)
return
BaseLocator
.
inputStatus
(
slaveId
,
offset
);
}
else
if
(
rawAddress
.
startsWith
(
"3"
)
&&
bitIndex
>=
0
)
{
// Input Register 内部 bit 位
return
BaseLocator
.
inputRegisterBit
(
slaveId
,
offset
,
bitIndex
);
}
else
if
(
rawAddress
.
startsWith
(
"4"
)
&&
bitIndex
>=
0
)
{
// Holding Register 内部 bit 位
return
BaseLocator
.
holdingRegisterBit
(
slaveId
,
offset
,
bitIndex
);
}
else
{
throw
new
IllegalArgumentException
(
"地址不支持 BIT 类型: "
+
rawAddress
);
}
case
INT16:
if
(
rawAddress
.
startsWith
(
"3"
))
{
return
BaseLocator
.
inputRegister
(
slaveId
,
offset
,
DataType
.
TWO_BYTE_INT_SIGNED
);
}
else
if
(
rawAddress
.
startsWith
(
"4"
))
{
return
BaseLocator
.
holdingRegister
(
slaveId
,
offset
,
DataType
.
TWO_BYTE_INT_SIGNED
);
}
break
;
case
UINT16:
if
(
rawAddress
.
startsWith
(
"3"
))
{
return
BaseLocator
.
inputRegister
(
slaveId
,
offset
,
DataType
.
TWO_BYTE_INT_UNSIGNED
);
}
else
if
(
rawAddress
.
startsWith
(
"4"
))
{
return
BaseLocator
.
holdingRegister
(
slaveId
,
offset
,
DataType
.
TWO_BYTE_INT_UNSIGNED
);
}
break
;
case
INT32:
if
(
rawAddress
.
startsWith
(
"3"
))
{
return
BaseLocator
.
inputRegister
(
slaveId
,
offset
,
DataType
.
FOUR_BYTE_INT_SIGNED
);
}
else
if
(
rawAddress
.
startsWith
(
"4"
))
{
return
BaseLocator
.
holdingRegister
(
slaveId
,
offset
,
DataType
.
FOUR_BYTE_INT_SIGNED
);
}
break
;
case
INT64:
if
(
rawAddress
.
startsWith
(
"3"
))
{
return
BaseLocator
.
inputRegister
(
slaveId
,
offset
,
DataType
.
EIGHT_BYTE_INT_SIGNED
);
}
else
if
(
rawAddress
.
startsWith
(
"4"
))
{
return
BaseLocator
.
holdingRegister
(
slaveId
,
offset
,
DataType
.
EIGHT_BYTE_INT_SIGNED
);
}
break
;
case
FLOAT32:
if
(
order
==
null
)
{
order
=
"ABCD"
;
// 默认大端
}
int
floatDataType
=
DataType
.
FOUR_BYTE_FLOAT
;
switch
(
order
)
{
case
"ABCD"
:
// 大端 IEEE754
floatDataType
=
DataType
.
FOUR_BYTE_FLOAT
;
break
;
case
"CDAB"
:
// 寄存器交换
floatDataType
=
DataType
.
FOUR_BYTE_FLOAT_SWAPPED
;
break
;
case
"BADC"
:
// 字节交换
floatDataType
=
DataType
.
FOUR_BYTE_FLOAT_SWAPPED_INVERTED
;
break
;
case
"DCBA"
:
// 全反转
floatDataType
=
DataType
.
FOUR_BYTE_INT_SIGNED_SWAPPED_SWAPPED
;
// ⚠ modbus4j 没有直接 DCBA 的 float,可以用 int SWAP-SWAP 再手动转 float
break
;
}
if
(
rawAddress
.
startsWith
(
"3"
))
{
return
BaseLocator
.
inputRegister
(
slaveId
,
offset
,
floatDataType
);
}
else
if
(
rawAddress
.
startsWith
(
"4"
))
{
return
BaseLocator
.
holdingRegister
(
slaveId
,
offset
,
floatDataType
);
}
break
;
case
DOUBLE64:
if
(
rawAddress
.
startsWith
(
"3"
))
{
return
BaseLocator
.
inputRegister
(
slaveId
,
offset
,
DataType
.
EIGHT_BYTE_FLOAT
);
}
else
if
(
rawAddress
.
startsWith
(
"4"
))
{
return
BaseLocator
.
holdingRegister
(
slaveId
,
offset
,
DataType
.
EIGHT_BYTE_FLOAT
);
}
break
;
default
:
throw
new
IllegalArgumentException
(
"不支持的数据类型: "
+
type
);
}
throw
new
IllegalArgumentException
(
"地址和数据类型不匹配: "
+
rawAddress
+
" -> "
+
type
);
}
/**
* 解析寄存器地址(不包含小数点后的 bit 部分)
* @param addressStr e.g. "40050.06" 或 "40050"
* @param zeroBasedAddress 是否零基地址
* @return int registerAddress
*/
public
static
int
parseRegisterAddress
(
String
addressStr
,
boolean
zeroBasedAddress
)
{
String
[]
parts
=
addressStr
.
split
(
"\\."
);
int
baseAddr
=
Integer
.
parseInt
(
parts
[
0
]);
// 去掉40001/30001等逻辑前缀,Modbus4j用的是零基
if
(
baseAddr
>=
40001
&&
baseAddr
<=
49999
)
{
baseAddr
=
baseAddr
-
40001
;
}
else
if
(
baseAddr
>=
30001
&&
baseAddr
<=
39999
)
{
baseAddr
=
baseAddr
-
30001
;
}
else
if
(
baseAddr
>=
1
&&
baseAddr
<=
9999
)
{
baseAddr
=
baseAddr
-
1
;
}
if
(!
zeroBasedAddress
)
{
baseAddr
=
baseAddr
+
1
;
// 用户配置非零基,则+1
}
return
baseAddr
;
}
/** 解析寄存器偏移量 */
public
static
int
parseOffset
(
String
rawAddress
,
boolean
zeroBasedAddress
)
{
if
(
rawAddress
==
null
||
rawAddress
.
isEmpty
())
{
throw
new
IllegalArgumentException
(
"地址不能为空"
);
}
// 处理区间地址:40003-40004
if
(
rawAddress
.
contains
(
"-"
))
{
String
[]
parts
=
rawAddress
.
split
(
"-"
);
rawAddress
=
parts
[
0
];
// 取起始地址
}
// 去掉小数点后部分:40001.01 -> 40001
String
basePart
=
rawAddress
.
split
(
"\\."
)[
0
];
int
address
=
Integer
.
parseInt
(
basePart
);
int
offset
;
if
(
address
>=
1
&&
address
<=
9999
)
{
// Coil (0xxxx)
offset
=
address
-
1
;
}
else
if
(
address
>=
10001
&&
address
<=
19999
)
{
// Discrete Input (1xxxx)
offset
=
address
-
10001
;
}
else
if
(
address
>=
30001
&&
address
<=
39999
)
{
// Input Register (3xxxx)
offset
=
address
-
30001
;
}
else
if
(
address
>=
40001
&&
address
<=
49999
)
{
// Holding Register (4xxxx)
offset
=
address
-
40001
;
}
else
{
throw
new
IllegalArgumentException
(
"无效的Modbus地址: "
+
rawAddress
);
}
// 根据 zeroBasedAddress 参数调整偏移
if
(!
zeroBasedAddress
)
{
offset
+=
1
;
}
return
offset
;
}
/** 解析 bit 索引 */
public
static
int
parseBitIndex
(
String
rawAddress
)
{
if
(
rawAddress
.
contains
(
"."
))
{
String
[]
parts
=
rawAddress
.
split
(
"\\."
);
return
Integer
.
parseInt
(
parts
[
1
])
-
1
;
// 转成从0开始
}
return
-
1
;
// 没有 bit 位
}
public
static
float
intToFloatDCBA
(
int
value
)
{
byte
[]
bytes
=
new
byte
[
4
];
bytes
[
0
]
=
(
byte
)
(
value
&
0
xFF
);
bytes
[
1
]
=
(
byte
)
((
value
>>
8
)
&
0
xFF
);
bytes
[
2
]
=
(
byte
)
((
value
>>
16
)
&
0
xFF
);
bytes
[
3
]
=
(
byte
)
((
value
>>
24
)
&
0
xFF
);
// 反转成 DCBA
byte
tmp
;
tmp
=
bytes
[
0
];
bytes
[
0
]
=
bytes
[
3
];
bytes
[
3
]
=
tmp
;
tmp
=
bytes
[
1
];
bytes
[
1
]
=
bytes
[
2
];
bytes
[
2
]
=
tmp
;
return
ByteBuffer
.
wrap
(
bytes
).
order
(
ByteOrder
.
BIG_ENDIAN
).
getFloat
();
}
public
static
int
floatToIntDCBA
(
float
f
)
{
byte
[]
bytes
=
ByteBuffer
.
allocate
(
4
).
order
(
ByteOrder
.
BIG_ENDIAN
).
putFloat
(
f
).
array
();
// 反转成 DCBA
byte
tmp
;
tmp
=
bytes
[
0
];
bytes
[
0
]
=
bytes
[
3
];
bytes
[
3
]
=
tmp
;
tmp
=
bytes
[
1
];
bytes
[
1
]
=
bytes
[
2
];
bytes
[
2
]
=
tmp
;
return
ByteBuffer
.
wrap
(
bytes
).
order
(
ByteOrder
.
BIG_ENDIAN
).
getInt
();
}
public
static
float
intToFloatABCD
(
int
value
)
{
byte
[]
bytes
=
intToBytes
(
value
);
return
ByteBuffer
.
wrap
(
bytes
).
order
(
ByteOrder
.
BIG_ENDIAN
).
getFloat
();
}
public
static
float
intToFloatBADC
(
int
value
)
{
byte
[]
bytes
=
intToBytes
(
value
);
swap
(
bytes
,
0
,
1
);
swap
(
bytes
,
2
,
3
);
return
ByteBuffer
.
wrap
(
bytes
).
order
(
ByteOrder
.
BIG_ENDIAN
).
getFloat
();
}
public
static
float
intToFloatCDAB
(
int
value
)
{
byte
[]
bytes
=
intToBytes
(
value
);
swap
(
bytes
,
0
,
2
);
swap
(
bytes
,
1
,
3
);
return
ByteBuffer
.
wrap
(
bytes
).
order
(
ByteOrder
.
BIG_ENDIAN
).
getFloat
();
}
// ========== 32位整型的不同字节序 ==========
public
static
int
int32ABCD
(
int
value
)
{
return
value
;
// 默认就是ABCD
}
public
static
int
int32BADC
(
int
value
)
{
byte
[]
bytes
=
intToBytes
(
value
);
swap
(
bytes
,
0
,
1
);
swap
(
bytes
,
2
,
3
);
return
ByteBuffer
.
wrap
(
bytes
).
order
(
ByteOrder
.
BIG_ENDIAN
).
getInt
();
}
public
static
int
int32CDAB
(
int
value
)
{
byte
[]
bytes
=
intToBytes
(
value
);
swap
(
bytes
,
0
,
2
);
swap
(
bytes
,
1
,
3
);
return
ByteBuffer
.
wrap
(
bytes
).
order
(
ByteOrder
.
BIG_ENDIAN
).
getInt
();
}
public
static
int
int32DCBA
(
int
value
)
{
byte
[]
bytes
=
intToBytes
(
value
);
reverse
(
bytes
);
return
ByteBuffer
.
wrap
(
bytes
).
order
(
ByteOrder
.
BIG_ENDIAN
).
getInt
();
}
// ========== 通用工具 ==========
private
static
byte
[]
intToBytes
(
int
value
)
{
return
new
byte
[]
{
(
byte
)
((
value
>>
24
)
&
0
xFF
),
(
byte
)
((
value
>>
16
)
&
0
xFF
),
(
byte
)
((
value
>>
8
)
&
0
xFF
),
(
byte
)
(
value
&
0
xFF
)
};
}
private
static
void
swap
(
byte
[]
arr
,
int
i
,
int
j
)
{
byte
tmp
=
arr
[
i
];
arr
[
i
]
=
arr
[
j
];
arr
[
j
]
=
tmp
;
}
private
static
void
reverse
(
byte
[]
arr
)
{
for
(
int
i
=
0
,
j
=
arr
.
length
-
1
;
i
<
j
;
i
++,
j
--)
{
swap
(
arr
,
i
,
j
);
}
}
// ========== Float 写入 ==========
public
static
int
floatToIntABCD
(
float
f
)
{
byte
[]
bytes
=
ByteBuffer
.
allocate
(
4
).
order
(
ByteOrder
.
BIG_ENDIAN
).
putFloat
(
f
).
array
();
return
ByteBuffer
.
wrap
(
bytes
).
order
(
ByteOrder
.
BIG_ENDIAN
).
getInt
();
}
public
static
int
floatToIntBADC
(
float
f
)
{
byte
[]
bytes
=
ByteBuffer
.
allocate
(
4
).
order
(
ByteOrder
.
BIG_ENDIAN
).
putFloat
(
f
).
array
();
swap
(
bytes
,
0
,
1
);
swap
(
bytes
,
2
,
3
);
return
ByteBuffer
.
wrap
(
bytes
).
order
(
ByteOrder
.
BIG_ENDIAN
).
getInt
();
}
public
static
int
floatToIntCDAB
(
float
f
)
{
byte
[]
bytes
=
ByteBuffer
.
allocate
(
4
).
order
(
ByteOrder
.
BIG_ENDIAN
).
putFloat
(
f
).
array
();
swap
(
bytes
,
0
,
2
);
swap
(
bytes
,
1
,
3
);
return
ByteBuffer
.
wrap
(
bytes
).
order
(
ByteOrder
.
BIG_ENDIAN
).
getInt
();
}
// ========== Int32 写入 ==========
public
static
int
int32ToABCD
(
int
value
)
{
return
value
;
// 默认
}
public
static
int
int32ToBADC
(
int
value
)
{
byte
[]
bytes
=
intToBytes
(
value
);
swap
(
bytes
,
0
,
1
);
swap
(
bytes
,
2
,
3
);
return
ByteBuffer
.
wrap
(
bytes
).
order
(
ByteOrder
.
BIG_ENDIAN
).
getInt
();
}
public
static
int
int32ToCDAB
(
int
value
)
{
byte
[]
bytes
=
intToBytes
(
value
);
swap
(
bytes
,
0
,
2
);
swap
(
bytes
,
1
,
3
);
return
ByteBuffer
.
wrap
(
bytes
).
order
(
ByteOrder
.
BIG_ENDIAN
).
getInt
();
}
public
static
int
int32ToDCBA
(
int
value
)
{
byte
[]
bytes
=
intToBytes
(
value
);
reverse
(
bytes
);
return
ByteBuffer
.
wrap
(
bytes
).
order
(
ByteOrder
.
BIG_ENDIAN
).
getInt
();
}
private
short
[]
toRegisters
(
Object
value
,
PlcDataType
dataType
,
String
order
)
{
switch
(
dataType
)
{
case
INT16:
return
new
short
[]{(
Short
)
value
};
case
UINT16:
return
new
short
[]{((
Integer
)
value
).
shortValue
()};
case
INT32:
int
intVal
=
(
Integer
)
value
;
return
int32ToShorts
(
intVal
,
order
);
case
FLOAT32:
float
fVal
=
(
Float
)
value
;
return
floatToShorts
(
fVal
,
order
);
case
DOUBLE64:
double
dVal
=
(
Double
)
value
;
return
doubleToShorts
(
dVal
,
order
);
default
:
throw
new
IllegalArgumentException
(
"不支持的数据类型: "
+
dataType
);
}
}
// INT32 转 short[2]
private
short
[]
int32ToShorts
(
int
value
,
String
order
)
{
short
high
=
(
short
)
((
value
>>
16
)
&
0
xFFFF
);
short
low
=
(
short
)
(
value
&
0
xFFFF
);
if
(
"ABCD"
.
equals
(
order
))
return
new
short
[]{
high
,
low
};
if
(
"BADC"
.
equals
(
order
))
return
new
short
[]{(
short
)((
high
&
0
xFF
)
<<
8
|
(
high
>>
8
&
0
xFF
)),
(
short
)((
low
&
0
xFF
)
<<
8
|
(
low
>>
8
&
0
xFF
))};
if
(
"CDAB"
.
equals
(
order
))
return
new
short
[]{
low
,
high
};
if
(
"DCBA"
.
equals
(
order
))
return
new
short
[]{(
short
)((
low
&
0
xFF
)
<<
8
|
(
low
>>
8
&
0
xFF
)),
(
short
)((
high
&
0
xFF
)
<<
8
|
(
high
>>
8
&
0
xFF
))};
return
new
short
[]{
high
,
low
};
}
// FLOAT32 转 short[2]
private
short
[]
floatToShorts
(
float
f
,
String
order
)
{
int
bits
=
Float
.
floatToIntBits
(
f
);
return
int32ToShorts
(
bits
,
order
);
}
// DOUBLE64 转 short[4]
private
short
[]
doubleToShorts
(
double
d
,
String
order
)
{
long
bits
=
Double
.
doubleToLongBits
(
d
);
short
[]
regs
=
new
short
[
4
];
regs
[
0
]
=
(
short
)((
bits
>>
48
)
&
0
xFFFF
);
regs
[
1
]
=
(
short
)((
bits
>>
32
)
&
0
xFFFF
);
regs
[
2
]
=
(
short
)((
bits
>>
16
)
&
0
xFFFF
);
regs
[
3
]
=
(
short
)(
bits
&
0
xFFFF
);
switch
(
order
)
{
case
"ABCD"
:
return
regs
;
case
"BADC"
:
return
new
short
[]{
regs
[
1
],
regs
[
0
],
regs
[
3
],
regs
[
2
]};
case
"CDAB"
:
return
new
short
[]{
regs
[
2
],
regs
[
3
],
regs
[
0
],
regs
[
1
]};
case
"DCBA"
:
return
new
short
[]{
regs
[
3
],
regs
[
2
],
regs
[
1
],
regs
[
0
]};
default
:
return
regs
;
}
}
}
lh-modules/lh-device-modbus-terminal/src/main/java/com/zhonglai/luhui/device/modbus/terminal/modbus/ModbusConnectionManager.java
0 → 100644
查看文件 @
ead90f1
package
com
.
zhonglai
.
luhui
.
device
.
modbus
.
terminal
.
modbus
;
import
com.serotonin.modbus4j.ModbusFactory
;
import
com.serotonin.modbus4j.ModbusMaster
;
import
com.serotonin.modbus4j.ip.IpParameters
;
import
com.zhonglai.luhui.device.modbus.terminal.modbus.dto.JSerialCommWrapper
;
import
com.alibaba.fastjson.JSONObject
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
java.io.File
;
import
java.util.Objects
;
import
java.util.concurrent.ConcurrentHashMap
;
/**
* 统一管理 ModbusMaster 的连接池/缓存(按 key 缓存)
* key 建议:tcp -> "tcp:host:port" ; rtu/ascii/udp -> 使用 PLC id 或可序列化配置信息
*/
public
class
ModbusConnectionManager
{
private
static
final
Logger
log
=
LoggerFactory
.
getLogger
(
ModbusConnectionManager
.
class
);
private
static
final
ModbusFactory
factory
=
new
ModbusFactory
();
// key -> ModbusMaster
private
static
final
ConcurrentHashMap
<
String
,
ModbusMaster
>
masterCache
=
new
ConcurrentHashMap
<>();
// key -> lock object for double-check init
private
static
final
ConcurrentHashMap
<
String
,
Object
>
lockMap
=
new
ConcurrentHashMap
<>();
private
ModbusConnectionManager
()
{}
/**
* 获取或创建 TCP Master(host + port 作为 key)
*/
public
static
ModbusMaster
getTcpMaster
(
String
host
,
int
port
,
int
timeout
,
int
retries
,
boolean
encapsulated
)
throws
Exception
{
String
key
=
String
.
format
(
"tcp:%s:%d"
,
Objects
.
requireNonNull
(
host
),
port
);
ModbusMaster
m
=
masterCache
.
get
(
key
);
if
(
m
!=
null
)
return
m
;
Object
lock
=
lockMap
.
computeIfAbsent
(
key
,
k
->
new
Object
());
synchronized
(
lock
)
{
m
=
masterCache
.
get
(
key
);
if
(
m
!=
null
)
return
m
;
IpParameters
params
=
new
IpParameters
();
params
.
setHost
(
host
);
params
.
setPort
(
port
);
// encapsulated param controls MBAP or not (depends on device); keep configurable
m
=
factory
.
createTcpMaster
(
params
,
encapsulated
);
m
.
setTimeout
(
timeout
);
m
.
setRetries
(
retries
);
try
{
// set custom IO log file if needed
m
.
setIoLog
(
new
MyIOLog
(
new
File
(
"logs/modbus.log"
)));
}
catch
(
Exception
e
)
{
// 忽略日志初始化失败
}
m
.
init
();
masterCache
.
put
(
key
,
m
);
log
.
info
(
"Created TCP ModbusMaster [{}]"
,
key
);
return
m
;
}
}
/**
* 通用创建接口 —— 通过传入 protocolType 与 connectConfig(用于兼容 InitPlcConfig)
* 支持:TCP / RTU / ASCII / UDP (与原 createMaster 保持一致)
*
* protocolType: "TCP" / "RTU" / "ASCII" / "UDP"
* connectConfig: JSONObject(与原代码互操作)
*/
public
static
ModbusMaster
getOrCreateMaster
(
String
key
,
String
protocolType
,
JSONObject
connectConfig
,
int
timeout
,
int
retries
)
throws
Exception
{
ModbusMaster
m
=
masterCache
.
get
(
key
);
if
(
m
!=
null
)
return
m
;
Object
lock
=
lockMap
.
computeIfAbsent
(
key
,
k
->
new
Object
());
synchronized
(
lock
)
{
m
=
masterCache
.
get
(
key
);
if
(
m
!=
null
)
return
m
;
ModbusMaster
created
;
switch
(
protocolType
)
{
case
"TCP"
:
{
IpParameters
parameters
=
JSONObject
.
parseObject
(
connectConfig
.
toJSONString
(),
IpParameters
.
class
);
created
=
factory
.
createTcpMaster
(
parameters
,
true
);
break
;
}
case
"RTU"
:
{
JSerialCommWrapper
wrapper
=
JSONObject
.
parseObject
(
connectConfig
.
toJSONString
(),
JSerialCommWrapper
.
class
);
created
=
factory
.
createRtuMaster
(
wrapper
);
break
;
}
case
"ASCII"
:
{
JSerialCommWrapper
wrapper
=
JSONObject
.
parseObject
(
connectConfig
.
toJSONString
(),
JSerialCommWrapper
.
class
);
created
=
factory
.
createAsciiMaster
(
wrapper
);
break
;
}
case
"UDP"
:
{
IpParameters
parameters
=
JSONObject
.
parseObject
(
connectConfig
.
toJSONString
(),
IpParameters
.
class
);
created
=
factory
.
createUdpMaster
(
parameters
);
break
;
}
default
:
throw
new
IllegalArgumentException
(
"不支持的协议类型: "
+
protocolType
);
}
created
.
setTimeout
(
timeout
);
created
.
setRetries
(
retries
);
try
{
created
.
setIoLog
(
new
MyIOLog
(
new
File
(
"logs/modbus.log"
)));
}
catch
(
Exception
ignored
)
{}
created
.
init
();
masterCache
.
put
(
key
,
created
);
log
.
info
(
"Created ModbusMaster [{}] protocol={}"
,
key
,
protocolType
);
return
created
;
}
}
/**
* 关闭并移除指定 key 的 master
*/
public
static
void
closeMaster
(
String
key
)
{
Object
lock
=
lockMap
.
computeIfAbsent
(
key
,
k
->
new
Object
());
synchronized
(
lock
)
{
ModbusMaster
m
=
masterCache
.
remove
(
key
);
if
(
m
!=
null
)
{
try
{
m
.
destroy
();
log
.
info
(
"Closed ModbusMaster [{}]"
,
key
);
}
catch
(
Exception
e
)
{
log
.
warn
(
"Close ModbusMaster [{}] failed: {}"
,
key
,
e
.
getMessage
());
}
}
lockMap
.
remove
(
key
);
}
}
/**
* 关闭所有 master
*/
public
static
void
closeAll
()
{
masterCache
.
forEach
((
k
,
v
)
->
{
try
{
v
.
destroy
();
}
catch
(
Exception
ignored
)
{}
});
masterCache
.
clear
();
lockMap
.
clear
();
log
.
info
(
"Closed all ModbusMaster instances"
);
}
}
...
...
lh-modules/lh-device-modbus-terminal/src/main/java/com/zhonglai/luhui/device/modbus/terminal/modbus/ModbusMasterMessage.java
查看文件 @
ead90f1
package
com
.
zhonglai
.
luhui
.
device
.
modbus
.
terminal
.
modbus
;
import
com.serotonin.modbus4j.ModbusFactory
;
import
com.serotonin.modbus4j.ModbusMaster
;
import
com.alibaba.fastjson.JSONObject
;
import
com.serotonin.modbus4j.ip.IpParameters
;
import
com.serotonin.modbus4j.msg.ReadHoldingRegistersRequest
;
import
com.serotonin.modbus4j.msg.ReadHoldingRegistersResponse
;
import
com.serotonin.modbus4j.ModbusMaster
;
import
com.zhonglai.luhui.device.modbus.terminal.config.InitPlcConfig
;
import
com.zhonglai.luhui.device.modbus.terminal.modbus.dto.CachPlcConfig
;
import
com.zhonglai.luhui.device.modbus.terminal.modbus.dto.JSerialCommWrapper
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
java.io.File
;
import
java.util.concurrent.ConcurrentHashMap
;
/**
* 通过 PLC ID 获取 ModbusMaster 或增强的 Modbus TCP Client。
* 所有 ModbusMaster 交由 ModbusConnectionManager 管理生命周期。
*
* 支持:
* - PLC ID 生成唯一 key
* - 安全缓存 Enhanced 客户端
* - 自动加载字节序
*/
public
class
ModbusMasterMessage
{
private
static
final
Logger
log
=
LoggerFactory
.
getLogger
(
ModbusMasterMessage
.
class
);
private
static
final
ConcurrentHashMap
<
String
,
ModbusMaster
>
masterCache
=
new
ConcurrentHashMap
<>();
private
static
final
ConcurrentHashMap
<
String
,
Object
>
lockMap
=
new
ConcurrentHashMap
<>();
private
static
final
ModbusFactory
factory
=
new
ModbusFactory
();
/** 获取或创建 ModbusMaster,不做连接性检测 */
public
static
ModbusMaster
getMaster
(
String
id
)
throws
Exception
{
ModbusMaster
master
=
masterCache
.
get
(
id
);
if
(
master
!=
null
)
{
/**
* 记录 key 与 plcId 的映射(目前主要用于 debug,可扩展)
*/
private
static
final
ConcurrentHashMap
<
String
,
String
>
keyToPlcId
=
new
ConcurrentHashMap
<>();
/**
* 缓存增强版 TCP 客户端,避免多次创建造成连接池重复。
*/
private
static
final
ConcurrentHashMap
<
String
,
EnhancedModbusTcpClientWithByteOrder
>
enhancedCache
=
new
ConcurrentHashMap
<>();
/**
* 根据 PLC ID 获取 ModbusMaster,如不存在则由 ConnectionManager 创建。
*/
public
static
ModbusMaster
getMaster
(
String
plcId
)
throws
Exception
{
CachPlcConfig
config
=
InitPlcConfig
.
getPlcSystems
(
plcId
);
if
(
config
==
null
)
{
throw
new
IllegalArgumentException
(
"未找到 PLC 配置: "
+
plcId
);
}
String
key
=
"modbus:master:"
+
plcId
;
ModbusMaster
master
=
ModbusConnectionManager
.
getOrCreateMaster
(
key
,
config
.
getProtocolType
().
name
(),
config
.
getConnectConfig
(),
3000
,
1
);
keyToPlcId
.
put
(
key
,
plcId
);
return
master
;
}
// double-check locking 保证只创建一次
Object
lock
=
lockMap
.
computeIfAbsent
(
id
,
k
->
new
Object
());
synchronized
(
lock
)
{
master
=
masterCache
.
get
(
id
);
if
(
master
==
null
)
{
CachPlcConfig
config
=
InitPlcConfig
.
getPlcSystems
(
id
);
/**
* 获取或创建 EnhancedModbusTcpClientWithByteOrder(带缓存)
*/
public
static
EnhancedModbusTcpClientWithByteOrder
getEnhancedModbusTcpClientWithByteOrder
(
String
plcId
)
throws
Exception
{
return
enhancedCache
.
computeIfAbsent
(
plcId
,
id
->
{
try
{
CachPlcConfig
config
=
InitPlcConfig
.
getPlcSystems
(
plcId
);
if
(
config
==
null
)
{
throw
new
IllegalArgumentException
(
"未找到
PLC配置: "
+
i
d
);
throw
new
IllegalArgumentException
(
"未找到
PLC 配置: "
+
plcI
d
);
}
master
=
createMaster
(
config
);
master
.
setIoLog
(
new
MyIOLog
(
new
File
(
"logs/modbus.log"
)));
master
.
init
();
masterCache
.
put
(
id
,
master
);
log
.
info
(
"ModbusMaster[{}] 已创建"
,
id
);
JSONObject
conn
=
config
.
getConnectConfig
();
String
host
=
conn
.
getString
(
"host"
);
// 修复 bug:原代码误写为 "post"
Integer
portObj
=
conn
.
getInteger
(
"port"
);
if
(
portObj
==
null
)
{
throw
new
IllegalArgumentException
(
"PLC "
+
plcId
+
" 缺少 port 字段"
);
}
int
port
=
portObj
;
int
poolSize
=
conn
.
getInteger
(
"poolSize"
)
!=
null
&&
conn
.
getInteger
(
"poolSize"
)
>
0
?
conn
.
getInteger
(
"poolSize"
)
:
10
;
EnhancedModbusTcpClientWithByteOrder
client
=
new
EnhancedModbusTcpClientWithByteOrder
(
host
,
port
,
poolSize
);
// 处理字节序设置
if
(
config
.
getByteOrder
()
!=
null
)
{
try
{
EnhancedModbusTcpClientWithByteOrder
.
ByteOrderType
order
=
EnhancedModbusTcpClientWithByteOrder
.
ByteOrderType
.
valueOf
(
config
.
getByteOrder
().
toUpperCase
()
);
}
catch
(
Exception
e
)
{
log
.
warn
(
"PLC {} 字节序配置不正确: {},使用默认字节序"
,
plcId
,
config
.
getByteOrder
());
}
return
master
;
}
/**
* 创建 Master
*/
private
static
ModbusMaster
createMaster
(
CachPlcConfig
config
)
throws
Exception
{
System
.
out
.
println
(
"config:"
+
JSONObject
.
toJSONString
(
config
));
JSONObject
connectConfig
=
config
.
getConnectConfig
();
switch
(
config
.
getProtocolType
())
{
case
TCP:
IpParameters
parameters
=
JSONObject
.
parseObject
(
connectConfig
.
toJSONString
(),
IpParameters
.
class
);
// parameters.setEncapsulated(false);
return
factory
.
createTcpMaster
(
parameters
,
true
);
case
RTU:
return
factory
.
createRtuMaster
(
JSONObject
.
parseObject
(
connectConfig
.
toJSONString
(),
JSerialCommWrapper
.
class
));
case
ASCII:
return
factory
.
createAsciiMaster
(
JSONObject
.
parseObject
(
connectConfig
.
toJSONString
(),
JSerialCommWrapper
.
class
));
case
UDP:
return
factory
.
createUdpMaster
(
JSONObject
.
parseObject
(
connectConfig
.
toJSONString
(),
IpParameters
.
class
));
default
:
throw
new
Exception
(
"不支持协议"
);
log
.
info
(
"为 PLC {} 创建并缓存 EnhancedModbusTcpClientWithByteOrder: {}:{} (poolSize={})"
,
plcId
,
host
,
port
,
poolSize
);
return
client
;
}
catch
(
Exception
e
)
{
log
.
error
(
"创建 EnhancedModbusTcpClientWithByteOrder 失败 (PLC {}): {}"
,
plcId
,
e
.
getMessage
(),
e
);
throw
new
RuntimeException
(
e
);
}
});
}
/**
* 关闭
Master
* 关闭
指定 PLC 的 Modbus
Master
*/
public
static
void
closeMaster
(
String
id
)
{
Object
lock
=
lockMap
.
computeIfAbsent
(
id
,
k
->
new
Object
());
synchronized
(
lock
)
{
ModbusMaster
master
=
masterCache
.
remove
(
id
);
if
(
master
!=
null
)
master
.
destroy
();
lockMap
.
remove
(
id
);
}
public
static
void
closeMasterByPlcId
(
String
plcId
)
{
String
key
=
"modbus:master:"
+
plcId
;
ModbusConnectionManager
.
closeMaster
(
key
);
keyToPlcId
.
remove
(
key
);
}
/**
* 关闭所有 M
aster
* 关闭所有 M
odbusMaster,同时清空映射缓存
*/
public
static
void
closeAll
()
{
if
(
null
!=
masterCache
)
{
masterCache
.
values
().
forEach
(
ModbusMaster:
:
destroy
);
masterCache
.
clear
();
}
if
(
null
!=
lockMap
)
{
lockMap
.
clear
();
}
ModbusConnectionManager
.
closeAll
();
keyToPlcId
.
clear
();
}
}
...
...
lh-modules/lh-device-modbus-terminal/src/main/java/com/zhonglai/luhui/device/modbus/terminal/modbus/dto/CachPlcConfig.java
查看文件 @
ead90f1
...
...
@@ -8,10 +8,20 @@ import java.util.Map;
public
class
CachPlcConfig
{
private
String
id
;
private
String
systemName
;
private
String
byteOrder
;
private
Boolean
zeroBasedAddress
;
private
ProtocolType
protocolType
;
private
JSONObject
connectConfig
;
private
Map
<
String
,
PlcPoint
>
plcMap
;
public
Boolean
getZeroBasedAddress
()
{
return
zeroBasedAddress
;
}
public
void
setZeroBasedAddress
(
Boolean
zeroBasedAddress
)
{
this
.
zeroBasedAddress
=
zeroBasedAddress
;
}
public
String
getSystemName
()
{
return
systemName
;
}
...
...
@@ -51,4 +61,12 @@ public class CachPlcConfig {
public
void
setId
(
String
id
)
{
this
.
id
=
id
;
}
public
String
getByteOrder
()
{
return
byteOrder
;
}
public
void
setByteOrder
(
String
byteOrder
)
{
this
.
byteOrder
=
byteOrder
;
}
}
...
...
lh-modules/lh-device-modbus-terminal/src/main/java/com/zhonglai/luhui/device/modbus/terminal/modbus/dto/PlcDataType.java
查看文件 @
ead90f1
...
...
@@ -3,14 +3,12 @@ package com.zhonglai.luhui.device.modbus.terminal.modbus.dto;
import
com.fasterxml.jackson.annotation.JsonCreator
;
public
enum
PlcDataType
{
BIT
,
// 线圈/开关量
INPUT_BIT
,
// 输入离散量
BOOLEAN
,
INT16
,
UINT16
,
INT32
,
INT64
,
INT32
,
// 新增
INT64
,
// 新增
FLOAT32
,
DOUBLE
64
;
FLOAT
64
;
//忽略大小写
@JsonCreator
...
...
@@ -18,13 +16,11 @@ public enum PlcDataType {
if
(
value
==
null
)
return
null
;
switch
(
value
.
toUpperCase
())
{
case
"BIT"
:
return
B
IT
;
return
B
OOLEAN
;
case
"INT"
:
return
INT16
;
case
"INT16"
:
return
INT16
;
case
"UINT"
:
case
"UINT16"
:
return
UINT16
;
case
"LONG"
:
// 兼容 long
return
INT32
;
case
"INT32"
:
...
...
@@ -32,14 +28,15 @@ public enum PlcDataType {
case
"INT64"
:
return
INT64
;
case
"FLOAT"
:
return
FLOAT32
;
case
"FLOAT32"
:
return
FLOAT32
;
case
"DOUBLE"
:
case
"DOUBLE64"
:
return
DOUBLE64
;
case
"INPUT_BIT"
:
case
"INPUT"
:
return
INPUT_BIT
;
return
FLOAT32
;
case
"BOOLEAN"
:
return
BOOLEAN
;
case
"FLOAT64"
:
return
FLOAT64
;
default
:
throw
new
IllegalArgumentException
(
"未知的枚举值: "
+
value
);
}
...
...
lh-modules/lh-device-modbus-terminal/src/main/java/com/zhonglai/luhui/device/modbus/terminal/modbus/dto/PlcSystem.java
查看文件 @
ead90f1
...
...
@@ -6,9 +6,25 @@ import java.util.List;
public
class
PlcSystem
{
private
String
id
;
private
String
systemName
;
private
String
byteOrder
;
private
Boolean
zeroBasedAddress
;
private
ProtocolType
protocolType
;
private
JSONObject
connectConfig
;
private
List
<
PlcPoint
>
points
;
public
Boolean
getZeroBasedAddress
()
{
return
zeroBasedAddress
;
}
public
void
setZeroBasedAddress
(
Boolean
zeroBasedAddress
)
{
this
.
zeroBasedAddress
=
zeroBasedAddress
;
}
public
String
getByteOrder
()
{
return
byteOrder
;
}
public
void
setByteOrder
(
String
byteOrder
)
{
this
.
byteOrder
=
byteOrder
;
}
public
String
getSystemName
()
{
return
systemName
;
...
...
lh-modules/lh-device-modbus-terminal/src/main/java/com/zhonglai/luhui/device/modbus/terminal/task/CollectPlcDataTask.java
查看文件 @
ead90f1
...
...
@@ -62,7 +62,7 @@ public class CollectPlcDataTask {
count
++;
if
(
count
==
maxDataLenth
)
{
boolean
success
=
subMqttData
(
mqttService
,
plcId
,
plcPoints
);
boolean
success
=
subMqttData
(
mqttService
,
plcId
,
plcPoints
,
cachPlcConfig
.
getZeroBasedAddress
()
);
System
.
out
.
println
(
"plc "
+
plcId
+
" 发送数据 "
+
plcPoints
.
size
()
+
" 条"
);
if
(!
success
)
{
...
...
@@ -85,7 +85,7 @@ public class CollectPlcDataTask {
// 处理剩余未满一批的数据
if
(!
plcPoints
.
isEmpty
())
{
boolean
success
=
subMqttData
(
mqttService
,
plcId
,
plcPoints
);
boolean
success
=
subMqttData
(
mqttService
,
plcId
,
plcPoints
,
cachPlcConfig
.
getZeroBasedAddress
()
);
logger
.
info
(
"plc "
+
plcId
+
" 发送数据 "
+
plcPoints
.
size
()
+
" 条"
);
if
(!
success
)
{
logger
.
info
(
"plc "
+
plcId
+
" 数据发送失败,本批次丢弃"
);
...
...
@@ -94,11 +94,11 @@ public class CollectPlcDataTask {
}
private
boolean
subMqttData
(
MqttService
mqttService
,
String
plcId
,
List
<
PlcPoint
>
plcPoints
)
private
boolean
subMqttData
(
MqttService
mqttService
,
String
plcId
,
List
<
PlcPoint
>
plcPoints
,
boolean
zeroBasedAddress
)
{
//通知
try
{
Map
<
String
,
Object
>
datMap
=
new
Modbus4jRead
(
plcId
).
batchRead
(
plcPoints
,
true
);
Map
<
String
,
Object
>
datMap
=
new
Modbus4jRead
(
plcId
).
batchRead
(
plcPoints
,
zeroBasedAddress
);
JSONObject
mqttSendData
=
new
JSONObject
();
mqttSendData
.
put
(
plcId
+
""
,
datMap
);
String
rdata
=
JSONObject
.
toJSONString
(
mqttSendData
);
...
...
@@ -107,7 +107,7 @@ public class CollectPlcDataTask {
if
(
e
instanceof
ModbusTransportException
)
{
logger
.
error
(
"plc通讯超时:"
+
plcId
);
ModbusMasterMessage
.
closeMaster
(
plcId
);
// 销毁旧连接
ModbusMasterMessage
.
closeMaster
ByPlcId
(
plcId
);
// 销毁旧连接
return
false
;
}
else
if
(
e
instanceof
MqttException
)
...
...
@@ -117,7 +117,7 @@ public class CollectPlcDataTask {
if
(
e
instanceof
ErrorResponseException
)
{
logger
.
error
(
"plc返回指令异常"
,
e
);
ModbusMasterMessage
.
closeMaster
(
plcId
);
// 销毁旧连接
ModbusMasterMessage
.
closeMaster
ByPlcId
(
plcId
);
// 销毁旧连接
return
false
;
}
else
{
throw
new
RuntimeException
(
e
);
...
...
lh-modules/lh-device-modbus-terminal/src/main/resources/configs/plcs _坤泰.json
0 → 100644
查看文件 @
ead90f1
{
"plcs"
:
[
{
"id"
:
"2_1"
,
"systemName"
:
"成鱼系统1"
,
"protocolType"
:
"TCP"
,
"byteOrder"
:
"CBAD"
,
"connectConfig"
:
{
"host"
:
"192.168.2.11"
,
"port"
:
2010
,
"poolSize"
:
10
},
"points"
:
[
{
"name"
:
"自动"
,
"system"
:
"zd"
,
"address"
:
"10001"
,
"dataType"
:
"bit"
},
{
"name"
:
"远程"
,
"system"
:
"yc"
,
"address"
:
"10002"
,
"dataType"
:
"bit"
},
{
"name"
:
"补水泵启动"
,
"system"
:
"bsbqd"
,
"address"
:
"10003"
,
"dataType"
:
"bit"
},
{
"name"
:
"水泵1运行"
,
"system"
:
"sb1"
,
"address"
:
"10004"
,
"dataType"
:
"bit"
},
{
"name"
:
"水泵2运行"
,
"system"
:
"sb2"
,
"address"
:
"10005"
,
"dataType"
:
"bit"
},
{
"name"
:
"氧锥泵1运行"
,
"system"
:
"yzb1yx"
,
"address"
:
"10006"
,
"dataType"
:
"bit"
},
{
"name"
:
"氧锥泵2运行"
,
"system"
:
"yzb2yx"
,
"address"
:
"10007"
,
"dataType"
:
"bit"
},
{
"name"
:
"氧锥泵3运行"
,
"system"
:
"yzb3yx"
,
"address"
:
"10008"
,
"dataType"
:
"bit"
},
{
"name"
:
"氧锥泵4运行"
,
"system"
:
"yzb4yx"
,
"address"
:
"10009"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污泵运行"
,
"system"
:
"pwb"
,
"address"
:
"10010"
,
"dataType"
:
"bit"
},
{
"name"
:
"微滤机电源合闸"
,
"system"
:
"wlj"
,
"address"
:
"10011"
,
"dataType"
:
"bit"
},
{
"name"
:
"紫外灯电源合闸"
,
"system"
:
"zwd"
,
"address"
:
"10012"
,
"dataType"
:
"bit"
},
{
"name"
:
"微滤池高液位"
,
"system"
:
"wlq"
,
"address"
:
"10013"
,
"dataType"
:
"bit"
},
{
"name"
:
"微滤池低液位"
,
"system"
:
"wld"
,
"address"
:
"10014"
,
"dataType"
:
"bit"
},
{
"name"
:
"蝶阀1开到位"
,
"system"
:
"df1kdw"
,
"address"
:
"10015"
,
"dataType"
:
"bit"
},
{
"name"
:
"蝶阀1关到位"
,
"system"
:
"df1gdw"
,
"address"
:
"10016"
,
"dataType"
:
"bit"
},
{
"name"
:
"蝶阀2开到位"
,
"system"
:
"df2kdw"
,
"address"
:
"10017"
,
"dataType"
:
"bit"
},
{
"name"
:
"蝶阀2关到位"
,
"system"
:
"df2gdw"
,
"address"
:
"10018"
,
"dataType"
:
"bit"
},
{
"name"
:
"蝶阀3开到位"
,
"system"
:
"df3kdw"
,
"address"
:
"10019"
,
"dataType"
:
"bit"
},
{
"name"
:
"蝶阀3关到位"
,
"system"
:
"df3gdw"
,
"address"
:
"10020"
,
"dataType"
:
"bit"
},
{
"name"
:
"蝶阀4开到位"
,
"system"
:
"df4kdw"
,
"address"
:
"10021"
,
"dataType"
:
"bit"
},
{
"name"
:
"蝶阀4关到位"
,
"system"
:
"df4gdw"
,
"address"
:
"10022"
,
"dataType"
:
"bit"
},
{
"name"
:
"蝶阀5开到位"
,
"system"
:
"df5kdw"
,
"address"
:
"10023"
,
"dataType"
:
"bit"
},
{
"name"
:
"蝶阀5关到位"
,
"system"
:
"df5gdw"
,
"address"
:
"10024"
,
"dataType"
:
"bit"
},
{
"name"
:
"蝶阀6开到位"
,
"system"
:
"df6kdw"
,
"address"
:
"10025"
,
"dataType"
:
"bit"
},
{
"name"
:
"蝶阀6关到位"
,
"system"
:
"df6gdw"
,
"address"
:
"10026"
,
"dataType"
:
"bit"
},
{
"name"
:
"蝶阀7开到位"
,
"system"
:
"df7kdw"
,
"address"
:
"10027"
,
"dataType"
:
"bit"
},
{
"name"
:
"蝶阀7关到位"
,
"system"
:
"df7gdw"
,
"address"
:
"10028"
,
"dataType"
:
"bit"
},
{
"name"
:
"蝶阀8开到位"
,
"system"
:
"df8kdw"
,
"address"
:
"10029"
,
"dataType"
:
"bit"
},
{
"name"
:
"蝶阀8关到位"
,
"system"
:
"df8gdw"
,
"address"
:
"10030"
,
"dataType"
:
"bit"
},
{
"name"
:
"循环水泵运行"
,
"system"
:
"xhsbyx"
,
"address"
:
"10031"
,
"dataType"
:
"bit"
},
{
"name"
:
"系统报警"
,
"system"
:
"xtbj"
,
"address"
:
"00001"
,
"dataType"
:
"bit"
},
{
"name"
:
"水泵1故障"
,
"system"
:
"sb1gz"
,
"address"
:
"40001.09"
,
"dataType"
:
"bit"
},
{
"name"
:
"水泵2故障"
,
"system"
:
"sb2gz"
,
"address"
:
"40001.10"
,
"dataType"
:
"bit"
},
{
"name"
:
"氧锥泵1故障"
,
"system"
:
"yzb1gz"
,
"address"
:
"40001.11"
,
"dataType"
:
"bit"
},
{
"name"
:
"氧锥泵2故障"
,
"system"
:
"yzb2gz"
,
"address"
:
"40001.12"
,
"dataType"
:
"bit"
},
{
"name"
:
"氧锥泵3故障"
,
"system"
:
"yzb3gz"
,
"address"
:
"40001.13"
,
"dataType"
:
"bit"
},
{
"name"
:
"氧锥泵4故障"
,
"system"
:
"yzb4gz"
,
"address"
:
"40001.14"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污泵故障"
,
"system"
:
"pwb_gz"
,
"address"
:
"40001.15"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀1开不到位"
,
"system"
:
"pwf1kbdw"
,
"address"
:
"40001.01"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀1关不到位"
,
"system"
:
"pwf1gbdw"
,
"address"
:
"40001.02"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀2开不到位"
,
"system"
:
"pwf2kbdw"
,
"address"
:
"40001.03"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀2关不到位"
,
"system"
:
"pwf2gbdw"
,
"address"
:
"40001.04"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀3开不到位"
,
"system"
:
"pwf3kbdw"
,
"address"
:
"40001.05"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀3关不到位"
,
"system"
:
"pwf3gbdw"
,
"address"
:
"40001.06"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀4开不到位"
,
"system"
:
"pwf4kbdw"
,
"address"
:
"40001.07"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀4关不到位"
,
"system"
:
"pwf4gbdw"
,
"address"
:
"40001.08"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀5开不到位"
,
"system"
:
"pwf5kbdw"
,
"address"
:
"40002.09"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀5关不到位"
,
"system"
:
"pwf5gbdw"
,
"address"
:
"40002.10"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀6开不到位"
,
"system"
:
"pwf6kbdw"
,
"address"
:
"40002.11"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀6关不到位"
,
"system"
:
"pwf6gbdw"
,
"address"
:
"40002.12"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀7开不到位"
,
"system"
:
"pwf7kbdw"
,
"address"
:
"40002.13"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀7关不到位"
,
"system"
:
"pwf7gbdw"
,
"address"
:
"40002.14"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀8开不到位"
,
"system"
:
"pwf8kbdw"
,
"address"
:
"40002.15"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀8关不到位"
,
"system"
:
"pwf8gbdw"
,
"address"
:
"40002.16"
,
"dataType"
:
"bit"
},
{
"name"
:
"补水高液位超时"
,
"system"
:
"bsgywdcs"
,
"address"
:
"40002.03"
,
"dataType"
:
"bit"
},
{
"name"
:
"微滤池高液位超时"
,
"system"
:
"wlcgywdcs"
,
"address"
:
"40002.04"
,
"dataType"
:
"bit"
},
{
"name"
:
"微滤机跳闸"
,
"system"
:
"wljtz"
,
"address"
:
"40002.05"
,
"dataType"
:
"bit"
},
{
"name"
:
"紫外杀菌灯跳闸故障"
,
"system"
:
"zwsjdtz"
,
"address"
:
"40002.06"
,
"dataType"
:
"bit"
},
{
"name"
:
"溶氧超限报警"
,
"system"
:
"rycxbj"
,
"address"
:
"40002.07"
,
"dataType"
:
"bit"
},
{
"name"
:
"微滤池低液位长时间不消失报警"
,
"system"
:
"wlcdywbcsbj"
,
"address"
:
"40002.08"
,
"dataType"
:
"bit"
},
{
"name"
:
"溶氧值"
,
"system"
:
"ryz"
,
"address"
:
"40003-40004"
,
"order"
:
"ABCD"
,
"dataType"
:
"float32"
},
{
"name"
:
"温度值"
,
"system"
:
"wdz"
,
"address"
:
"40005-40006"
,
"order"
:
"ABCD"
,
"dataType"
:
"float32"
},
{
"name"
:
"电能值"
,
"system"
:
"dnz"
,
"address"
:
"40007-40008"
,
"order"
:
"ABCD"
,
"dataType"
:
"float32"
},
{
"name"
:
"当前氧锥泵运行台数"
,
"system"
:
"dqyzb"
,
"address"
:
"40009"
,
"dataType"
:
"int"
},
{
"name"
:
"氧锥泵1运行时间"
,
"system"
:
"yzb1_sj"
,
"address"
:
"40011-40012"
,
"order"
:
"ABCD"
,
"dataType"
:
"int32"
},
{
"name"
:
"氧锥泵2运行时间"
,
"system"
:
"yzb2_sj"
,
"address"
:
"40013-40014"
,
"order"
:
"ABCD"
,
"dataType"
:
"int32"
},
{
"name"
:
"氧锥泵3运行时间"
,
"system"
:
"yzb3_sj"
,
"address"
:
"40015-40016"
,
"order"
:
"ABCD"
,
"dataType"
:
"int32"
},
{
"name"
:
"氧锥泵4运行时间"
,
"system"
:
"yzb4_sj"
,
"address"
:
"40017-40018"
,
"order"
:
"ABCD"
,
"dataType"
:
"int32"
},
{
"name"
:
"生化池水温"
,
"system"
:
"shcsw"
,
"address"
:
"40019-40020"
,
"order"
:
"ABCD"
,
"dataType"
:
"float32"
},
{
"name"
:
"循环水泵故障"
,
"system"
:
"xhsb_gz"
,
"address"
:
"40021.09"
,
"dataType"
:
"bit"
},
{
"name"
:
"生化池水温低限报警"
,
"system"
:
"shcsw_dx_bj"
,
"address"
:
"40021.10"
,
"dataType"
:
"bit"
},
{
"name"
:
"生化池水温高限报警"
,
"system"
:
"shcsw_gx_bj"
,
"address"
:
"40021.11"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀1开OR关"
,
"system"
:
"pwf1_or"
,
"address"
:
"40051.01"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀2开OR关"
,
"system"
:
"pwf2_or"
,
"address"
:
"40051.02"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀3开OR关"
,
"system"
:
"pwf3_or"
,
"address"
:
"40051.03"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀4开OR关"
,
"system"
:
"pwf4_or"
,
"address"
:
"40051.04"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀5开OR关"
,
"system"
:
"pwf5_or"
,
"address"
:
"40051.05"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀6开OR关"
,
"system"
:
"pwf6_or"
,
"address"
:
"40051.06"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀7开OR关"
,
"system"
:
"pwf7_or"
,
"address"
:
"40051.07"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀8开OR关"
,
"system"
:
"pwf8_or"
,
"address"
:
"40051.08"
,
"dataType"
:
"bit"
},
{
"name"
:
"水泵1启动"
,
"system"
:
"sb1start"
,
"address"
:
"40051.09"
,
"dataType"
:
"bit"
},
{
"name"
:
"水泵2启动"
,
"system"
:
"sb2start"
,
"address"
:
"40051.10"
,
"dataType"
:
"bit"
},
{
"name"
:
"氧锥泵1启动"
,
"system"
:
"yzb1_qd"
,
"address"
:
"40051.11"
,
"dataType"
:
"bit"
},
{
"name"
:
"氧锥泵2启动"
,
"system"
:
"yzb2_qd"
,
"address"
:
"40051.12"
,
"dataType"
:
"bit"
},
{
"name"
:
"氧锥泵3启动"
,
"system"
:
"yzb3_qd"
,
"address"
:
"40051.13"
,
"dataType"
:
"bit"
},
{
"name"
:
"氧锥泵4启动"
,
"system"
:
"yzb4_qd"
,
"address"
:
"40051.14"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污泵启动"
,
"system"
:
"pwb_qd"
,
"address"
:
"40051.15"
,
"dataType"
:
"bit"
},
{
"name"
:
"水泵1停止"
,
"system"
:
"sb1stop"
,
"address"
:
"40052.01"
,
"dataType"
:
"bit"
},
{
"name"
:
"水泵2停止"
,
"system"
:
"sb2stop"
,
"address"
:
"40052.02"
,
"dataType"
:
"bit"
},
{
"name"
:
"氧锥泵1停止"
,
"system"
:
"yzb1_tz"
,
"address"
:
"40052.03"
,
"dataType"
:
"bit"
},
{
"name"
:
"氧锥泵2停止"
,
"system"
:
"yzb2_tz"
,
"address"
:
"40052.04"
,
"dataType"
:
"bit"
},
{
"name"
:
"氧锥泵3停止"
,
"system"
:
"yzb3_tz"
,
"address"
:
"40052.05"
,
"dataType"
:
"bit"
},
{
"name"
:
"氧锥泵4停止"
,
"system"
:
"yzb4_tz"
,
"address"
:
"40052.06"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污泵停止"
,
"system"
:
"pwb_tz"
,
"address"
:
"40052.07"
,
"dataType"
:
"bit"
},
{
"name"
:
"清报警"
,
"system"
:
"qbj"
,
"address"
:
"40052.09"
,
"dataType"
:
"bit"
},
{
"name"
:
"累计时间清零"
,
"system"
:
"ljtq"
,
"address"
:
"40052.10"
,
"dataType"
:
"bit"
},
{
"name"
:
"溶氧上限报警设定值"
,
"system"
:
"rysjup"
,
"address"
:
"40053-40054"
,
"order"
:
"ABCD"
,
"dataType"
:
"float32"
},
{
"name"
:
"溶氧下限报警设定值"
,
"system"
:
"rysjdown"
,
"address"
:
"40055-40056"
,
"order"
:
"ABCD"
,
"dataType"
:
"float32"
}
]
},
{
"id"
:
"2_2"
,
"systemName"
:
"成鱼系统2"
,
"protocolType"
:
"TCP"
,
"byteOrder"
:
"CBAD"
,
"connectConfig"
:
{
"host"
:
"192.168.2.2"
,
"port"
:
2001
,
"poolSize"
:
10
},
"points"
:
[
{
"name"
:
"自动"
,
"system"
:
"zd"
,
"address"
:
"10001"
,
"dataType"
:
"bit"
},
{
"name"
:
"远程"
,
"system"
:
"yc"
,
"address"
:
"10002"
,
"dataType"
:
"bit"
},
{
"name"
:
"补水泵启动"
,
"system"
:
"bsbqd"
,
"address"
:
"10003"
,
"dataType"
:
"bit"
},
{
"name"
:
"水泵1运行"
,
"system"
:
"sb1"
,
"address"
:
"10004"
,
"dataType"
:
"bit"
},
{
"name"
:
"水泵2运行"
,
"system"
:
"sb2"
,
"address"
:
"10005"
,
"dataType"
:
"bit"
},
{
"name"
:
"氧锥泵1运行"
,
"system"
:
"yzb1yx"
,
"address"
:
"10006"
,
"dataType"
:
"bit"
},
{
"name"
:
"氧锥泵2运行"
,
"system"
:
"yzb2yx"
,
"address"
:
"10007"
,
"dataType"
:
"bit"
},
{
"name"
:
"氧锥泵3运行"
,
"system"
:
"yzb3yx"
,
"address"
:
"10008"
,
"dataType"
:
"bit"
},
{
"name"
:
"氧锥泵4运行"
,
"system"
:
"yzb4yx"
,
"address"
:
"10009"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污泵运行"
,
"system"
:
"pwb"
,
"address"
:
"10010"
,
"dataType"
:
"bit"
},
{
"name"
:
"微滤机电源合闸"
,
"system"
:
"wlj"
,
"address"
:
"10011"
,
"dataType"
:
"bit"
},
{
"name"
:
"紫外灯电源合闸"
,
"system"
:
"zwd"
,
"address"
:
"10012"
,
"dataType"
:
"bit"
},
{
"name"
:
"微滤池高液位"
,
"system"
:
"wlq"
,
"address"
:
"10013"
,
"dataType"
:
"bit"
},
{
"name"
:
"微滤池低液位"
,
"system"
:
"wld"
,
"address"
:
"10014"
,
"dataType"
:
"bit"
},
{
"name"
:
"蝶阀1开到位"
,
"system"
:
"df1kdw"
,
"address"
:
"10015"
,
"dataType"
:
"bit"
},
{
"name"
:
"蝶阀1关到位"
,
"system"
:
"df1gdw"
,
"address"
:
"10016"
,
"dataType"
:
"bit"
},
{
"name"
:
"蝶阀2开到位"
,
"system"
:
"df2kdw"
,
"address"
:
"10017"
,
"dataType"
:
"bit"
},
{
"name"
:
"蝶阀2关到位"
,
"system"
:
"df2gdw"
,
"address"
:
"10018"
,
"dataType"
:
"bit"
},
{
"name"
:
"蝶阀3开到位"
,
"system"
:
"df3kdw"
,
"address"
:
"10019"
,
"dataType"
:
"bit"
},
{
"name"
:
"蝶阀3关到位"
,
"system"
:
"df3gdw"
,
"address"
:
"10020"
,
"dataType"
:
"bit"
},
{
"name"
:
"蝶阀4开到位"
,
"system"
:
"df4kdw"
,
"address"
:
"10021"
,
"dataType"
:
"bit"
},
{
"name"
:
"蝶阀4关到位"
,
"system"
:
"df4gdw"
,
"address"
:
"10022"
,
"dataType"
:
"bit"
},
{
"name"
:
"蝶阀5开到位"
,
"system"
:
"df5kdw"
,
"address"
:
"10023"
,
"dataType"
:
"bit"
},
{
"name"
:
"蝶阀5关到位"
,
"system"
:
"df5gdw"
,
"address"
:
"10024"
,
"dataType"
:
"bit"
},
{
"name"
:
"蝶阀6开到位"
,
"system"
:
"df6kdw"
,
"address"
:
"10025"
,
"dataType"
:
"bit"
},
{
"name"
:
"蝶阀6关到位"
,
"system"
:
"df6gdw"
,
"address"
:
"10026"
,
"dataType"
:
"bit"
},
{
"name"
:
"蝶阀7开到位"
,
"system"
:
"df7kdw"
,
"address"
:
"10027"
,
"dataType"
:
"bit"
},
{
"name"
:
"蝶阀7关到位"
,
"system"
:
"df7gdw"
,
"address"
:
"10028"
,
"dataType"
:
"bit"
},
{
"name"
:
"蝶阀8开到位"
,
"system"
:
"df8kdw"
,
"address"
:
"10029"
,
"dataType"
:
"bit"
},
{
"name"
:
"蝶阀8关到位"
,
"system"
:
"df8gdw"
,
"address"
:
"10030"
,
"dataType"
:
"bit"
},
{
"name"
:
"循环水泵运行"
,
"system"
:
"xhsbyx"
,
"address"
:
"10031"
,
"dataType"
:
"bit"
},
{
"name"
:
"系统报警"
,
"system"
:
"xtbj"
,
"address"
:
"00001"
,
"dataType"
:
"bit"
},
{
"name"
:
"水泵1故障"
,
"system"
:
"sb1gz"
,
"address"
:
"40001.09"
,
"dataType"
:
"bit"
},
{
"name"
:
"水泵2故障"
,
"system"
:
"sb2gz"
,
"address"
:
"40001.10"
,
"dataType"
:
"bit"
},
{
"name"
:
"氧锥泵1故障"
,
"system"
:
"yzb1gz"
,
"address"
:
"40001.11"
,
"dataType"
:
"bit"
},
{
"name"
:
"氧锥泵2故障"
,
"system"
:
"yzb2gz"
,
"address"
:
"40001.12"
,
"dataType"
:
"bit"
},
{
"name"
:
"氧锥泵3故障"
,
"system"
:
"yzb3gz"
,
"address"
:
"40001.13"
,
"dataType"
:
"bit"
},
{
"name"
:
"氧锥泵4故障"
,
"system"
:
"yzb4gz"
,
"address"
:
"40001.14"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污泵故障"
,
"system"
:
"pwb_gz"
,
"address"
:
"40001.15"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀1开不到位"
,
"system"
:
"pwf1kbdw"
,
"address"
:
"40001.01"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀1关不到位"
,
"system"
:
"pwf1gbdw"
,
"address"
:
"40001.02"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀2开不到位"
,
"system"
:
"pwf2kbdw"
,
"address"
:
"40001.03"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀2关不到位"
,
"system"
:
"pwf2gbdw"
,
"address"
:
"40001.04"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀3开不到位"
,
"system"
:
"pwf3kbdw"
,
"address"
:
"40001.05"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀3关不到位"
,
"system"
:
"pwf3gbdw"
,
"address"
:
"40001.06"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀4开不到位"
,
"system"
:
"pwf4kbdw"
,
"address"
:
"40001.07"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀4关不到位"
,
"system"
:
"pwf4gbdw"
,
"address"
:
"40001.08"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀5开不到位"
,
"system"
:
"pwf5kbdw"
,
"address"
:
"40002.09"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀5关不到位"
,
"system"
:
"pwf5gbdw"
,
"address"
:
"40002.10"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀6开不到位"
,
"system"
:
"pwf6kbdw"
,
"address"
:
"40002.11"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀6关不到位"
,
"system"
:
"pwf6gbdw"
,
"address"
:
"40002.12"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀7开不到位"
,
"system"
:
"pwf7kbdw"
,
"address"
:
"40002.13"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀7关不到位"
,
"system"
:
"pwf7gbdw"
,
"address"
:
"40002.14"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀8开不到位"
,
"system"
:
"pwf8kbdw"
,
"address"
:
"40002.15"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀8关不到位"
,
"system"
:
"pwf8gbdw"
,
"address"
:
"40002.16"
,
"dataType"
:
"bit"
},
{
"name"
:
"补水高液位超时"
,
"system"
:
"bsgywdcs"
,
"address"
:
"40002.03"
,
"dataType"
:
"bit"
},
{
"name"
:
"微滤池高液位超时"
,
"system"
:
"wlcgywdcs"
,
"address"
:
"40002.04"
,
"dataType"
:
"bit"
},
{
"name"
:
"微滤机跳闸"
,
"system"
:
"wljtz"
,
"address"
:
"40002.05"
,
"dataType"
:
"bit"
},
{
"name"
:
"紫外杀菌灯跳闸故障"
,
"system"
:
"zwsjdtz"
,
"address"
:
"40002.06"
,
"dataType"
:
"bit"
},
{
"name"
:
"溶氧超限报警"
,
"system"
:
"rycxbj"
,
"address"
:
"40002.07"
,
"dataType"
:
"bit"
},
{
"name"
:
"微滤池低液位长时间不消失报警"
,
"system"
:
"wldc"
,
"address"
:
"40002.08"
,
"dataType"
:
"bit"
},
{
"name"
:
"溶氧值"
,
"system"
:
"ryz"
,
"address"
:
"40003-40004"
,
"order"
:
"ABCD"
,
"dataType"
:
"float32"
},
{
"name"
:
"温度值"
,
"system"
:
"wdz"
,
"address"
:
"40005-40006"
,
"order"
:
"ABCD"
,
"dataType"
:
"float32"
},
{
"name"
:
"电能值"
,
"system"
:
"dnz"
,
"address"
:
"40007-40008"
,
"order"
:
"ABCD"
,
"dataType"
:
"float32"
},
{
"name"
:
"当前氧锥泵运行台数"
,
"system"
:
"dqyzb"
,
"address"
:
"40009"
,
"dataType"
:
"int"
},
{
"name"
:
"氧锥泵1运行时间"
,
"system"
:
"yzb1_sj"
,
"address"
:
"40011-40012"
,
"order"
:
"ABCD"
,
"dataType"
:
"int32"
},
{
"name"
:
"氧锥泵2运行时间"
,
"system"
:
"yzb2_sj"
,
"address"
:
"40013-40014"
,
"order"
:
"ABCD"
,
"dataType"
:
"int32"
},
{
"name"
:
"氧锥泵3运行时间"
,
"system"
:
"yzb3_sj"
,
"address"
:
"40015-40016"
,
"order"
:
"ABCD"
,
"dataType"
:
"int32"
},
{
"name"
:
"氧锥泵4运行时间"
,
"system"
:
"yzb4_sj"
,
"address"
:
"40017-40018"
,
"order"
:
"ABCD"
,
"dataType"
:
"int32"
},
{
"name"
:
"生化池水温"
,
"system"
:
"shcsw"
,
"address"
:
"40019-40020"
,
"order"
:
"ABCD"
,
"dataType"
:
"float32"
},
{
"name"
:
"循环水泵故障"
,
"system"
:
"xhsb_gz"
,
"address"
:
"40021.09"
,
"dataType"
:
"bit"
},
{
"name"
:
"生化池水温低限报警"
,
"system"
:
"shcsw_dx_bj"
,
"address"
:
"40021.10"
,
"dataType"
:
"bit"
},
{
"name"
:
"生化池水温高限报警"
,
"system"
:
"shcsw_gx_bj"
,
"address"
:
"40021.11"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀1开OR关"
,
"system"
:
"pwf1_or"
,
"address"
:
"40051.01"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀2开OR关"
,
"system"
:
"pwf2_or"
,
"address"
:
"40051.02"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀3开OR关"
,
"system"
:
"pwf3_or"
,
"address"
:
"40051.03"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀4开OR关"
,
"system"
:
"pwf4_or"
,
"address"
:
"40051.04"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀5开OR关"
,
"system"
:
"pwf5_or"
,
"address"
:
"40051.05"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀6开OR关"
,
"system"
:
"pwf6_or"
,
"address"
:
"40051.06"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀7开OR关"
,
"system"
:
"pwf7_or"
,
"address"
:
"40051.07"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀8开OR关"
,
"system"
:
"pwf8_or"
,
"address"
:
"40051.08"
,
"dataType"
:
"bit"
},
{
"name"
:
"水泵1启动"
,
"system"
:
"sb1start"
,
"address"
:
"40051.09"
,
"dataType"
:
"bit"
},
{
"name"
:
"水泵2启动"
,
"system"
:
"sb2start"
,
"address"
:
"40051.10"
,
"dataType"
:
"bit"
},
{
"name"
:
"氧锥泵1启动"
,
"system"
:
"yzb1_qd"
,
"address"
:
"40051.11"
,
"dataType"
:
"bit"
},
{
"name"
:
"氧锥泵2启动"
,
"system"
:
"yzb2_qd"
,
"address"
:
"40051.12"
,
"dataType"
:
"bit"
},
{
"name"
:
"氧锥泵3启动"
,
"system"
:
"yzb3_qd"
,
"address"
:
"40051.13"
,
"dataType"
:
"bit"
},
{
"name"
:
"氧锥泵4启动"
,
"system"
:
"yzb4_qd"
,
"address"
:
"40051.14"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污泵启动"
,
"system"
:
"pwb_qd"
,
"address"
:
"40051.15"
,
"dataType"
:
"bit"
},
{
"name"
:
"水泵1停止"
,
"system"
:
"sb1stop"
,
"address"
:
"40052.01"
,
"dataType"
:
"bit"
},
{
"name"
:
"水泵2停止"
,
"system"
:
"sb2stop"
,
"address"
:
"40052.02"
,
"dataType"
:
"bit"
},
{
"name"
:
"氧锥泵1停止"
,
"system"
:
"yzb1_tz"
,
"address"
:
"40052.03"
,
"dataType"
:
"bit"
},
{
"name"
:
"氧锥泵2停止"
,
"system"
:
"yzb2_tz"
,
"address"
:
"40052.04"
,
"dataType"
:
"bit"
},
{
"name"
:
"氧锥泵3停止"
,
"system"
:
"yzb3_tz"
,
"address"
:
"40052.05"
,
"dataType"
:
"bit"
},
{
"name"
:
"氧锥泵4停止"
,
"system"
:
"yzb4_tz"
,
"address"
:
"40052.06"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污泵停止"
,
"system"
:
"pwb_tz"
,
"address"
:
"40052.07"
,
"dataType"
:
"bit"
},
{
"name"
:
"清报警"
,
"system"
:
"qbj"
,
"address"
:
"40052.09"
,
"dataType"
:
"bit"
},
{
"name"
:
"累计时间清零"
,
"system"
:
"ljtq"
,
"address"
:
"40052.10"
,
"dataType"
:
"bit"
},
{
"name"
:
"溶氧上限报警设定值"
,
"system"
:
"rysjup"
,
"address"
:
"40053-40054"
,
"order"
:
"ABCD"
,
"dataType"
:
"float32"
},
{
"name"
:
"溶氧下限报警设定值"
,
"system"
:
"rysjdown"
,
"address"
:
"40055-40056"
,
"order"
:
"ABCD"
,
"dataType"
:
"float32"
}
]
},
{
"id"
:
"2_3"
,
"systemName"
:
"源水处理区"
,
"protocolType"
:
"TCP"
,
"byteOrder"
:
"CBAD"
,
"connectConfig"
:
{
"host"
:
"192.168.2.5"
,
"port"
:
2004
,
"poolSize"
:
10
},
"points"
:
[
{
"name"
:
"自动"
,
"system"
:
"zd"
,
"address"
:
"10001"
,
"dataType"
:
"bit"
},
{
"name"
:
"远程"
,
"system"
:
"yc"
,
"address"
:
"10002"
,
"dataType"
:
"bit"
},
{
"name"
:
"水源泵1启动"
,
"system"
:
"syp1"
,
"address"
:
"10003"
,
"dataType"
:
"bit"
},
{
"name"
:
"水源泵2启动"
,
"system"
:
"syp2"
,
"address"
:
"10004"
,
"dataType"
:
"bit"
},
{
"name"
:
"水源泵3启动"
,
"system"
:
"syp3"
,
"address"
:
"10005"
,
"dataType"
:
"bit"
},
{
"name"
:
"风机1启动"
,
"system"
:
"fj1"
,
"address"
:
"10006"
,
"dataType"
:
"bit"
},
{
"name"
:
"风机2启动"
,
"system"
:
"fj2"
,
"address"
:
"10007"
,
"dataType"
:
"bit"
},
{
"name"
:
"紫外灯电源合闸"
,
"system"
:
"zwd"
,
"address"
:
"10008"
,
"dataType"
:
"bit"
},
{
"name"
:
"生化池高液位"
,
"system"
:
"shg"
,
"address"
:
"10009"
,
"dataType"
:
"bit"
},
{
"name"
:
"生化池低液位"
,
"system"
:
"shd"
,
"address"
:
"10010"
,
"dataType"
:
"bit"
},
{
"name"
:
"系统报警"
,
"system"
:
"xtbj"
,
"address"
:
"00001"
,
"dataType"
:
"bit"
},
{
"name"
:
"电能值"
,
"system"
:
"dnz"
,
"address"
:
"40007-40008"
,
"order"
:
"ABCD"
,
"dataType"
:
"float"
},
{
"name"
:
"当前水源泵启动台数"
,
"system"
:
"dqsy"
,
"address"
:
"40009"
,
"dataType"
:
"int"
},
{
"name"
:
"当前风机运行台数"
,
"system"
:
"dqfj"
,
"address"
:
"40010"
,
"dataType"
:
"int"
},
{
"name"
:
"水源泵1运行时间"
,
"system"
:
"syp1sj"
,
"address"
:
"40011-40012"
,
"order"
:
"ABCD"
,
"dataType"
:
"long"
},
{
"name"
:
"水源泵2运行时间"
,
"system"
:
"syp2sj"
,
"address"
:
"40013-40014"
,
"order"
:
"ABCD"
,
"dataType"
:
"long"
},
{
"name"
:
"水源泵3运行时间"
,
"system"
:
"syp3sj"
,
"address"
:
"40015-40016"
,
"order"
:
"ABCD"
,
"dataType"
:
"long"
},
{
"name"
:
"风机1运行时间"
,
"system"
:
"fj1t"
,
"address"
:
"40017-40018"
,
"order"
:
"ABCD"
,
"dataType"
:
"long"
},
{
"name"
:
"风机2运行时间"
,
"system"
:
"fj2t"
,
"address"
:
"40019-40020"
,
"order"
:
"ABCD"
,
"dataType"
:
"long"
},
{
"name"
:
"水源泵1故障"
,
"system"
:
"syp1g"
,
"address"
:
"40001.09"
,
"dataType"
:
"bit"
},
{
"name"
:
"水源泵2故障"
,
"system"
:
"syp2g"
,
"address"
:
"40001.10"
,
"dataType"
:
"bit"
},
{
"name"
:
"水源泵3故障"
,
"system"
:
"syp3g"
,
"address"
:
"40001.11"
,
"dataType"
:
"bit"
},
{
"name"
:
"风机1故障"
,
"system"
:
"fj1g"
,
"address"
:
"40001.12"
,
"dataType"
:
"bit"
},
{
"name"
:
"风机2故障"
,
"system"
:
"fj2g"
,
"address"
:
"40001.13"
,
"dataType"
:
"bit"
},
{
"name"
:
"紫外杀菌灯跳闸故障"
,
"system"
:
"zwsjdtz"
,
"address"
:
"40001.14"
,
"dataType"
:
"bit"
},
{
"name"
:
"水源泵1启动"
,
"system"
:
"syp1s"
,
"address"
:
"40051.01"
,
"dataType"
:
"bit"
},
{
"name"
:
"水源泵2启动"
,
"system"
:
"syp2s"
,
"address"
:
"40051.02"
,
"dataType"
:
"bit"
},
{
"name"
:
"水源泵3启动"
,
"system"
:
"syp3s"
,
"address"
:
"40051.03"
,
"dataType"
:
"bit"
},
{
"name"
:
"风机1启动"
,
"system"
:
"fj1s"
,
"address"
:
"40051.04"
,
"dataType"
:
"bit"
},
{
"name"
:
"风机2启动"
,
"system"
:
"fj2s"
,
"address"
:
"40051.05"
,
"dataType"
:
"bit"
},
{
"name"
:
"水源泵1停止"
,
"system"
:
"syp1t"
,
"address"
:
"40051.09"
,
"dataType"
:
"bit"
},
{
"name"
:
"水源泵2停止"
,
"system"
:
"syp2t"
,
"address"
:
"40051.10"
,
"dataType"
:
"bit"
},
{
"name"
:
"水源泵3停止"
,
"system"
:
"syp3t"
,
"address"
:
"40051.11"
,
"dataType"
:
"bit"
},
{
"name"
:
"风机1停止"
,
"system"
:
"fj1p"
,
"address"
:
"40051.12"
,
"dataType"
:
"bit"
},
{
"name"
:
"风机2停止"
,
"system"
:
"fj2p"
,
"address"
:
"40051.13"
,
"dataType"
:
"bit"
},
{
"name"
:
"清报警"
,
"system"
:
"qbj"
,
"address"
:
"40052.01"
,
"dataType"
:
"bit"
},
{
"name"
:
"累计时间清零"
,
"system"
:
"ljtq"
,
"address"
:
"40052.02"
,
"dataType"
:
"bit"
}
]
},
{
"id"
:
"2_4"
,
"systemName"
:
"育苗系统"
,
"protocolType"
:
"TCP"
,
"byteOrder"
:
"CBAD"
,
"connectConfig"
:
{
"host"
:
"192.168.2.4"
,
"port"
:
2002
,
"poolSize"
:
10
},
"points"
:
[
{
"name"
:
"手动/自动"
,
"system"
:
"sdz"
,
"address"
:
"10001"
,
"dataType"
:
"bit"
},
{
"name"
:
"本地/远程"
,
"system"
:
"bdyy"
,
"address"
:
"10002"
,
"dataType"
:
"bit"
},
{
"name"
:
"水泵1运行"
,
"system"
:
"sb1"
,
"address"
:
"10004"
,
"dataType"
:
"bit"
},
{
"name"
:
"水泵2运行"
,
"system"
:
"sb2"
,
"address"
:
"10005"
,
"dataType"
:
"bit"
},
{
"name"
:
"风机1运行"
,
"system"
:
"fj1"
,
"address"
:
"10006"
,
"dataType"
:
"bit"
},
{
"name"
:
"风机2运行"
,
"system"
:
"fj2"
,
"address"
:
"10007"
,
"dataType"
:
"bit"
},
{
"name"
:
"热源泵1电源合闸"
,
"system"
:
"ryb1"
,
"address"
:
"10008"
,
"dataType"
:
"bit"
},
{
"name"
:
"热源泵2电源合闸"
,
"system"
:
"ryb2"
,
"address"
:
"10009"
,
"dataType"
:
"bit"
},
{
"name"
:
"微滤机电源合闸"
,
"system"
:
"wlj"
,
"address"
:
"10010"
,
"dataType"
:
"bit"
},
{
"name"
:
"紫外灯电源合闸"
,
"system"
:
"zwd"
,
"address"
:
"10011"
,
"dataType"
:
"bit"
},
{
"name"
:
"补水池高液位"
,
"system"
:
"bsc"
,
"address"
:
"10012"
,
"dataType"
:
"bit"
},
{
"name"
:
"微滤池高液位"
,
"system"
:
"wlq"
,
"address"
:
"10013"
,
"dataType"
:
"bit"
},
{
"name"
:
"微滤池低液位"
,
"system"
:
"wld"
,
"address"
:
"10015"
,
"dataType"
:
"bit"
},
{
"name"
:
"系统报警"
,
"system"
:
"xtbj"
,
"address"
:
"00001"
,
"dataType"
:
"bit"
},
{
"name"
:
"溶氧值"
,
"system"
:
"ryz"
,
"address"
:
"40003-40004"
,
"order"
:
"ABCD"
,
"dataType"
:
"float32"
},
{
"name"
:
"温度值"
,
"system"
:
"wdz"
,
"address"
:
"40005-40006"
,
"order"
:
"ABCD"
,
"dataType"
:
"float32"
},
{
"name"
:
"电能值"
,
"system"
:
"dnz"
,
"address"
:
"40007-40008"
,
"order"
:
"ABCD"
,
"dataType"
:
"float32"
},
{
"name"
:
"当前风机运行台数"
,
"system"
:
"dqfj"
,
"address"
:
"40009"
,
"dataType"
:
"int"
},
{
"name"
:
"风机1运行时间"
,
"system"
:
"fj1t"
,
"address"
:
"40011-40012"
,
"order"
:
"ABCD"
,
"dataType"
:
"long"
},
{
"name"
:
"风机2运行时间"
,
"system"
:
"fj2t"
,
"address"
:
"40013-40014"
,
"order"
:
"ABCD"
,
"dataType"
:
"long"
},
{
"name"
:
"水泵1故障"
,
"system"
:
"sb1gz"
,
"address"
:
"40001.10"
,
"dataType"
:
"bit"
},
{
"name"
:
"水泵2故障"
,
"system"
:
"sb2gz"
,
"address"
:
"40001.11"
,
"dataType"
:
"bit"
},
{
"name"
:
"风机1故障"
,
"system"
:
"fj1g"
,
"address"
:
"40001.12"
,
"dataType"
:
"bit"
},
{
"name"
:
"风机2故障"
,
"system"
:
"fj2g"
,
"address"
:
"40001.13"
,
"dataType"
:
"bit"
},
{
"name"
:
"热泵1跳闸"
,
"system"
:
"rb1tz"
,
"address"
:
"40001.16"
,
"dataType"
:
"bit"
},
{
"name"
:
"热泵2跳闸"
,
"system"
:
"rb2tz"
,
"address"
:
"40001.01"
,
"dataType"
:
"bit"
},
{
"name"
:
"微滤机跳闸"
,
"system"
:
"wljtz"
,
"address"
:
"40001.02"
,
"dataType"
:
"bit"
},
{
"name"
:
"紫外杀菌灯跳闸故障"
,
"system"
:
"zwsjdtz"
,
"address"
:
"40001.03"
,
"dataType"
:
"bit"
},
{
"name"
:
"补水上液位超时"
,
"system"
:
"bssywcs"
,
"address"
:
"40001.04"
,
"dataType"
:
"bit"
},
{
"name"
:
"微滤池上液位超时"
,
"system"
:
"wlcsywcs"
,
"address"
:
"40001.05"
,
"dataType"
:
"bit"
},
{
"name"
:
"溶氧超限报警"
,
"system"
:
"rycxbj"
,
"address"
:
"40001.06"
,
"dataType"
:
"bit"
},
{
"name"
:
"补水泵3故障(没有)"
,
"system"
:
"bsb3g"
,
"address"
:
"40001.07"
,
"dataType"
:
"bit"
},
{
"name"
:
"微滤池低液位长时间不消失报警"
,
"system"
:
"wldc"
,
"address"
:
"40001.08"
,
"dataType"
:
"bit"
},
{
"name"
:
"水泵1启动"
,
"system"
:
"sb1start"
,
"address"
:
"40051.01"
,
"dataType"
:
"bit"
},
{
"name"
:
"水泵2启动"
,
"system"
:
"sb2start"
,
"address"
:
"40051.02"
,
"dataType"
:
"bit"
},
{
"name"
:
"风机1启动"
,
"system"
:
"fj1s"
,
"address"
:
"40051.03"
,
"dataType"
:
"bit"
},
{
"name"
:
"风机2启动"
,
"system"
:
"fj2s"
,
"address"
:
"40051.04"
,
"dataType"
:
"bit"
},
{
"name"
:
"补水泵3启动"
,
"system"
:
"bsb3s"
,
"address"
:
"40051.05"
,
"dataType"
:
"bit"
},
{
"name"
:
"水泵1停止"
,
"system"
:
"sb1stop"
,
"address"
:
"40051.09"
,
"dataType"
:
"bit"
},
{
"name"
:
"水泵2停止"
,
"system"
:
"sb2stop"
,
"address"
:
"40051.10"
,
"dataType"
:
"bit"
},
{
"name"
:
"风机1停止"
,
"system"
:
"fj1p"
,
"address"
:
"40051.11"
,
"dataType"
:
"bit"
},
{
"name"
:
"风机2停止"
,
"system"
:
"fj2p"
,
"address"
:
"40051.12"
,
"dataType"
:
"bit"
},
{
"name"
:
"补水泵3停止"
,
"system"
:
"bsb3p"
,
"address"
:
"40051.13"
,
"dataType"
:
"bit"
},
{
"name"
:
"清报警"
,
"system"
:
"qbj"
,
"address"
:
"40052.01"
,
"dataType"
:
"bit"
},
{
"name"
:
"累计时间清零"
,
"system"
:
"ljtq"
,
"address"
:
"40052.02"
,
"dataType"
:
"bit"
},
{
"name"
:
"溶氧上限报警设定值"
,
"system"
:
"rysjup"
,
"address"
:
"40053-40054"
,
"order"
:
"ABCD"
,
"dataType"
:
"float32"
},
{
"name"
:
"溶氧下限报警设定值"
,
"system"
:
"rysjdown"
,
"address"
:
"40055-40056"
,
"order"
:
"ABCD"
,
"dataType"
:
"float32"
}
]
},
{
"id"
:
"2_5"
,
"systemName"
:
"设备房系统"
,
"protocolType"
:
"TCP"
,
"byteOrder"
:
"CBAD"
,
"connectConfig"
:
{
"host"
:
"192.168.2.3"
,
"port"
:
2003
,
"poolSize"
:
10
},
"points"
:
[
{
"name"
:
"自动"
,
"system"
:
"zd"
,
"address"
:
"10001"
,
"dataType"
:
"bit"
},
{
"name"
:
"远程"
,
"system"
:
"yc"
,
"address"
:
"10002"
,
"dataType"
:
"bit"
},
{
"name"
:
"风机1运行"
,
"system"
:
"fj1"
,
"address"
:
"10003"
,
"dataType"
:
"bit"
},
{
"name"
:
"风机2运行"
,
"system"
:
"fj2"
,
"address"
:
"10004"
,
"dataType"
:
"bit"
},
{
"name"
:
"风机3运行"
,
"system"
:
"fj3"
,
"address"
:
"10005"
,
"dataType"
:
"bit"
},
{
"name"
:
"风机4运行"
,
"system"
:
"fj4"
,
"address"
:
"10006"
,
"dataType"
:
"bit"
},
{
"name"
:
"补水泵1运行"
,
"system"
:
"bsb1"
,
"address"
:
"10007"
,
"dataType"
:
"bit"
},
{
"name"
:
"补水泵2运行"
,
"system"
:
"bsb2"
,
"address"
:
"10008"
,
"dataType"
:
"bit"
},
{
"name"
:
"热泵1电源合闸"
,
"system"
:
"rb1"
,
"address"
:
"10010"
,
"dataType"
:
"bit"
},
{
"name"
:
"热泵2电源合闸"
,
"system"
:
"rb2"
,
"address"
:
"10011"
,
"dataType"
:
"bit"
},
{
"name"
:
"空压机电源合闸"
,
"system"
:
"kyj"
,
"address"
:
"10012"
,
"dataType"
:
"bit"
},
{
"name"
:
"补水阀1开到位"
,
"system"
:
"bsf1"
,
"address"
:
"10013"
,
"dataType"
:
"bit"
},
{
"name"
:
"补水阀2开到位"
,
"system"
:
"bsf2"
,
"address"
:
"10014"
,
"dataType"
:
"bit"
},
{
"name"
:
"补水阀1关到位"
,
"system"
:
"bsf1g"
,
"address"
:
"10016"
,
"dataType"
:
"bit"
},
{
"name"
:
"补水阀2关到位"
,
"system"
:
"bsf2g"
,
"address"
:
"10017"
,
"dataType"
:
"bit"
},
{
"name"
:
"补水1高液位"
,
"system"
:
"bsg1"
,
"address"
:
"10019"
,
"dataType"
:
"bit"
},
{
"name"
:
"补水2高液位"
,
"system"
:
"bsg2"
,
"address"
:
"10020"
,
"dataType"
:
"bit"
},
{
"name"
:
"系统报警"
,
"system"
:
"xtbj"
,
"address"
:
"00001"
,
"dataType"
:
"bit"
},
{
"name"
:
"电能值"
,
"system"
:
"dnz"
,
"address"
:
"40007-40008"
,
"order"
:
"ABCD"
,
"dataType"
:
"float"
},
{
"name"
:
"当前风机运行台数"
,
"system"
:
"dqfj"
,
"address"
:
"40009"
,
"dataType"
:
"int"
},
{
"name"
:
"风机1运行时间"
,
"system"
:
"fj1t"
,
"address"
:
"40011-40012"
,
"order"
:
"ABCD"
,
"dataType"
:
"long"
},
{
"name"
:
"风机2运行时间"
,
"system"
:
"fj2t"
,
"address"
:
"40013-40014"
,
"order"
:
"ABCD"
,
"dataType"
:
"long"
},
{
"name"
:
"风机3运行时间"
,
"system"
:
"fj3t"
,
"address"
:
"40015-40016"
,
"order"
:
"ABCD"
,
"dataType"
:
"long"
},
{
"name"
:
"风机4运行时间"
,
"system"
:
"fj4t"
,
"address"
:
"40017-40018"
,
"order"
:
"ABCD"
,
"dataType"
:
"long"
},
{
"name"
:
"风机1故障"
,
"system"
:
"fj1g"
,
"address"
:
"40001.09"
,
"dataType"
:
"bit"
},
{
"name"
:
"风机2故障"
,
"system"
:
"fj2g"
,
"address"
:
"40001.10"
,
"dataType"
:
"bit"
},
{
"name"
:
"风机3故障"
,
"system"
:
"fj3g"
,
"address"
:
"40001.11"
,
"dataType"
:
"bit"
},
{
"name"
:
"风机4故障"
,
"system"
:
"fj4g"
,
"address"
:
"40001.12"
,
"dataType"
:
"bit"
},
{
"name"
:
"补水泵1故障"
,
"system"
:
"bsb1g"
,
"address"
:
"40001.13"
,
"dataType"
:
"bit"
},
{
"name"
:
"补水泵2故障"
,
"system"
:
"bsb2g"
,
"address"
:
"40001.14"
,
"dataType"
:
"bit"
},
{
"name"
:
"热泵1跳闸故障"
,
"system"
:
"rb1g"
,
"address"
:
"40001.16"
,
"dataType"
:
"bit"
},
{
"name"
:
"热泵2跳闸故障"
,
"system"
:
"rb2g"
,
"address"
:
"40001.01"
,
"dataType"
:
"bit"
},
{
"name"
:
"补水阀1开不到位"
,
"system"
:
"bsf1b"
,
"address"
:
"40001.02"
,
"dataType"
:
"bit"
},
{
"name"
:
"补水阀1关不到位"
,
"system"
:
"bsf1bg"
,
"address"
:
"40001.03"
,
"dataType"
:
"bit"
},
{
"name"
:
"补水阀2开不到位"
,
"system"
:
"bsf2b"
,
"address"
:
"40001.04"
,
"dataType"
:
"bit"
},
{
"name"
:
"补水阀2关不到位"
,
"system"
:
"bsf2bg"
,
"address"
:
"40001.05"
,
"dataType"
:
"bit"
},
{
"name"
:
"空压机跳闸故障"
,
"system"
:
"kyjg"
,
"address"
:
"40001.08"
,
"dataType"
:
"bit"
},
{
"name"
:
"补水阀1开OR关"
,
"system"
:
"bsf1c"
,
"address"
:
"40051.01"
,
"dataType"
:
"bit"
},
{
"name"
:
"补水阀2开OR关"
,
"system"
:
"bsf2c"
,
"address"
:
"40051.02"
,
"dataType"
:
"bit"
},
{
"name"
:
"风机1启动"
,
"system"
:
"fj1s"
,
"address"
:
"40051.09"
,
"dataType"
:
"bit"
},
{
"name"
:
"风机2启动"
,
"system"
:
"fj2s"
,
"address"
:
"40051.10"
,
"dataType"
:
"bit"
},
{
"name"
:
"风机3启动"
,
"system"
:
"fj3s"
,
"address"
:
"40051.11"
,
"dataType"
:
"bit"
},
{
"name"
:
"风机4启动"
,
"system"
:
"fj4s"
,
"address"
:
"40051.12"
,
"dataType"
:
"bit"
},
{
"name"
:
"补水泵1启动"
,
"system"
:
"bsb1s"
,
"address"
:
"40051.13"
,
"dataType"
:
"bit"
},
{
"name"
:
"补水泵2启动"
,
"system"
:
"bsb2s"
,
"address"
:
"40051.14"
,
"dataType"
:
"bit"
},
{
"name"
:
"风机1停止"
,
"system"
:
"fj1p"
,
"address"
:
"40052.01"
,
"dataType"
:
"bit"
},
{
"name"
:
"风机2停止"
,
"system"
:
"fj2p"
,
"address"
:
"40052.02"
,
"dataType"
:
"bit"
},
{
"name"
:
"风机3停止"
,
"system"
:
"fj3p"
,
"address"
:
"40052.03"
,
"dataType"
:
"bit"
},
{
"name"
:
"风机4停止"
,
"system"
:
"fj4p"
,
"address"
:
"40052.04"
,
"dataType"
:
"bit"
},
{
"name"
:
"补水泵1停止"
,
"system"
:
"bsb1p"
,
"address"
:
"40052.05"
,
"dataType"
:
"bit"
},
{
"name"
:
"补水泵2停止"
,
"system"
:
"bsb2p"
,
"address"
:
"40052.06"
,
"dataType"
:
"bit"
},
{
"name"
:
"清报警"
,
"system"
:
"qbj"
,
"address"
:
"40052.09"
,
"dataType"
:
"bit"
},
{
"name"
:
"累计时间清零"
,
"system"
:
"ljtq"
,
"address"
:
"40052.10"
,
"dataType"
:
"bit"
}
]
}
]
}
...
...
lh-modules/lh-device-modbus-terminal/src/main/resources/configs/plcs.json
查看文件 @
ead90f1
{}
\ No newline at end of file
{
"plcs"
:
[
{
"id"
:
"2_1"
,
"systemName"
:
"成鱼系统1"
,
"protocolType"
:
"TCP"
,
"byteOrder"
:
"CBAD"
,
"zeroBasedAddress"
:
false
,
"connectConfig"
:
{
"host"
:
"127.0.0.1"
,
"port"
:
2010
,
"poolSize"
:
10
},
"points"
:
[
{
"name"
:
"自动"
,
"system"
:
"zd"
,
"address"
:
"10001"
,
"dataType"
:
"bit"
},
{
"name"
:
"远程"
,
"system"
:
"yc"
,
"address"
:
"10002"
,
"dataType"
:
"bit"
},
{
"name"
:
"补水泵启动"
,
"system"
:
"bsbqd"
,
"address"
:
"10003"
,
"dataType"
:
"bit"
},
{
"name"
:
"水泵1运行"
,
"system"
:
"sb1"
,
"address"
:
"10004"
,
"dataType"
:
"bit"
},
{
"name"
:
"水泵2运行"
,
"system"
:
"sb2"
,
"address"
:
"10005"
,
"dataType"
:
"bit"
},
{
"name"
:
"氧锥泵1运行"
,
"system"
:
"yzb1yx"
,
"address"
:
"10006"
,
"dataType"
:
"bit"
},
{
"name"
:
"氧锥泵2运行"
,
"system"
:
"yzb2yx"
,
"address"
:
"10007"
,
"dataType"
:
"bit"
},
{
"name"
:
"氧锥泵3运行"
,
"system"
:
"yzb3yx"
,
"address"
:
"10008"
,
"dataType"
:
"bit"
},
{
"name"
:
"氧锥泵4运行"
,
"system"
:
"yzb4yx"
,
"address"
:
"10009"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污泵运行"
,
"system"
:
"pwb"
,
"address"
:
"10010"
,
"dataType"
:
"bit"
},
{
"name"
:
"微滤机电源合闸"
,
"system"
:
"wlj"
,
"address"
:
"10011"
,
"dataType"
:
"bit"
},
{
"name"
:
"紫外灯电源合闸"
,
"system"
:
"zwd"
,
"address"
:
"10012"
,
"dataType"
:
"bit"
},
{
"name"
:
"微滤池高液位"
,
"system"
:
"wlq"
,
"address"
:
"10013"
,
"dataType"
:
"bit"
},
{
"name"
:
"微滤池低液位"
,
"system"
:
"wld"
,
"address"
:
"10014"
,
"dataType"
:
"bit"
},
{
"name"
:
"蝶阀1开到位"
,
"system"
:
"df1kdw"
,
"address"
:
"10015"
,
"dataType"
:
"bit"
},
{
"name"
:
"蝶阀1关到位"
,
"system"
:
"df1gdw"
,
"address"
:
"10016"
,
"dataType"
:
"bit"
},
{
"name"
:
"蝶阀2开到位"
,
"system"
:
"df2kdw"
,
"address"
:
"10017"
,
"dataType"
:
"bit"
},
{
"name"
:
"蝶阀2关到位"
,
"system"
:
"df2gdw"
,
"address"
:
"10018"
,
"dataType"
:
"bit"
},
{
"name"
:
"蝶阀3开到位"
,
"system"
:
"df3kdw"
,
"address"
:
"10019"
,
"dataType"
:
"bit"
},
{
"name"
:
"蝶阀3关到位"
,
"system"
:
"df3gdw"
,
"address"
:
"10020"
,
"dataType"
:
"bit"
},
{
"name"
:
"蝶阀4开到位"
,
"system"
:
"df4kdw"
,
"address"
:
"10021"
,
"dataType"
:
"bit"
},
{
"name"
:
"蝶阀4关到位"
,
"system"
:
"df4gdw"
,
"address"
:
"10022"
,
"dataType"
:
"bit"
},
{
"name"
:
"蝶阀5开到位"
,
"system"
:
"df5kdw"
,
"address"
:
"10023"
,
"dataType"
:
"bit"
},
{
"name"
:
"蝶阀5关到位"
,
"system"
:
"df5gdw"
,
"address"
:
"10024"
,
"dataType"
:
"bit"
},
{
"name"
:
"蝶阀6开到位"
,
"system"
:
"df6kdw"
,
"address"
:
"10025"
,
"dataType"
:
"bit"
},
{
"name"
:
"蝶阀6关到位"
,
"system"
:
"df6gdw"
,
"address"
:
"10026"
,
"dataType"
:
"bit"
},
{
"name"
:
"蝶阀7开到位"
,
"system"
:
"df7kdw"
,
"address"
:
"10027"
,
"dataType"
:
"bit"
},
{
"name"
:
"蝶阀7关到位"
,
"system"
:
"df7gdw"
,
"address"
:
"10028"
,
"dataType"
:
"bit"
},
{
"name"
:
"蝶阀8开到位"
,
"system"
:
"df8kdw"
,
"address"
:
"10029"
,
"dataType"
:
"bit"
},
{
"name"
:
"蝶阀8关到位"
,
"system"
:
"df8gdw"
,
"address"
:
"10030"
,
"dataType"
:
"bit"
},
{
"name"
:
"循环水泵运行"
,
"system"
:
"xhsbyx"
,
"address"
:
"10031"
,
"dataType"
:
"bit"
},
{
"name"
:
"系统报警"
,
"system"
:
"xtbj"
,
"address"
:
"00001"
,
"dataType"
:
"bit"
},
{
"name"
:
"水泵1故障"
,
"system"
:
"sb1gz"
,
"address"
:
"40001.09"
,
"dataType"
:
"bit"
},
{
"name"
:
"水泵2故障"
,
"system"
:
"sb2gz"
,
"address"
:
"40001.10"
,
"dataType"
:
"bit"
},
{
"name"
:
"氧锥泵1故障"
,
"system"
:
"yzb1gz"
,
"address"
:
"40001.11"
,
"dataType"
:
"bit"
},
{
"name"
:
"氧锥泵2故障"
,
"system"
:
"yzb2gz"
,
"address"
:
"40001.12"
,
"dataType"
:
"bit"
},
{
"name"
:
"氧锥泵3故障"
,
"system"
:
"yzb3gz"
,
"address"
:
"40001.13"
,
"dataType"
:
"bit"
},
{
"name"
:
"氧锥泵4故障"
,
"system"
:
"yzb4gz"
,
"address"
:
"40001.14"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污泵故障"
,
"system"
:
"pwb_gz"
,
"address"
:
"40001.15"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀1开不到位"
,
"system"
:
"pwf1kbdw"
,
"address"
:
"40001.01"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀1关不到位"
,
"system"
:
"pwf1gbdw"
,
"address"
:
"40001.02"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀2开不到位"
,
"system"
:
"pwf2kbdw"
,
"address"
:
"40001.03"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀2关不到位"
,
"system"
:
"pwf2gbdw"
,
"address"
:
"40001.04"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀3开不到位"
,
"system"
:
"pwf3kbdw"
,
"address"
:
"40001.05"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀3关不到位"
,
"system"
:
"pwf3gbdw"
,
"address"
:
"40001.06"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀4开不到位"
,
"system"
:
"pwf4kbdw"
,
"address"
:
"40001.07"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀4关不到位"
,
"system"
:
"pwf4gbdw"
,
"address"
:
"40001.08"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀5开不到位"
,
"system"
:
"pwf5kbdw"
,
"address"
:
"40002.09"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀5关不到位"
,
"system"
:
"pwf5gbdw"
,
"address"
:
"40002.10"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀6开不到位"
,
"system"
:
"pwf6kbdw"
,
"address"
:
"40002.11"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀6关不到位"
,
"system"
:
"pwf6gbdw"
,
"address"
:
"40002.12"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀7开不到位"
,
"system"
:
"pwf7kbdw"
,
"address"
:
"40002.13"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀7关不到位"
,
"system"
:
"pwf7gbdw"
,
"address"
:
"40002.14"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀8开不到位"
,
"system"
:
"pwf8kbdw"
,
"address"
:
"40002.15"
,
"dataType"
:
"bit"
},
{
"name"
:
"排污阀8关不到位"
,
"system"
:
"pwf8gbdw"
,
"address"
:
"40002.16"
,
"dataType"
:
"bit"
},
{
"name"
:
"补水高液位超时"
,
"system"
:
"bsgywdcs"
,
"address"
:
"40002.03"
,
"dataType"
:
"bit"
},
{
"name"
:
"微滤池高液位超时"
,
"system"
:
"wlcgywdcs"
,
"address"
:
"40002.04"
,
"dataType"
:
"bit"
},
{
"name"
:
"微滤机跳闸"
,
"system"
:
"wljtz"
,
"address"
:
"40002.05"
,
"dataType"
:
"bit"
},
{
"name"
:
"紫外杀菌灯跳闸故障"
,
"system"
:
"zwsjdtz"
,
"address"
:
"40002.06"
,
"dataType"
:
"bit"
},
{
"name"
:
"溶氧超限报警"
,
"system"
:
"rycxbj"
,
"address"
:
"40002.07"
,
"dataType"
:
"bit"
},
{
"name"
:
"微滤池低液位长时间不消失报警"
,
"system"
:
"wlcdywbcsbj"
,
"address"
:
"40002.08"
,
"dataType"
:
"bit"
},
{
"name"
:
"溶氧值"
,
"system"
:
"ryz"
,
"address"
:
"40003-40004"
,
"order"
:
"ABCD"
,
"dataType"
:
"float32"
},
{
"name"
:
"温度值"
,
"system"
:
"wdz"
,
"address"
:
"40005-40006"
,
"order"
:
"ABCD"
,
"dataType"
:
"float32"
},
{
"name"
:
"电能值"
,
"system"
:
"dnz"
,
"address"
:
"40007-40008"
,
"order"
:
"ABCD"
,
"dataType"
:
"float32"
},
{
"name"
:
"当前氧锥泵运行台数"
,
"system"
:
"dqyzb"
,
"address"
:
"40009"
,
"dataType"
:
"int"
},
{
"name"
:
"氧锥泵1运行时间"
,
"system"
:
"yzb1_sj"
,
"address"
:
"40011-40012"
,
"order"
:
"ABCD"
,
"dataType"
:
"int32"
},
{
"name"
:
"氧锥泵2运行时间"
,
"system"
:
"yzb2_sj"
,
"address"
:
"40013-40014"
,
"order"
:
"ABCD"
,
"dataType"
:
"int32"
},
{
"name"
:
"氧锥泵3运行时间"
,
"system"
:
"yzb3_sj"
,
"address"
:
"40015-40016"
,
"order"
:
"ABCD"
,
"dataType"
:
"int32"
},
{
"name"
:
"氧锥泵4运行时间"
,
"system"
:
"yzb4_sj"
,
"address"
:
"40017-40018"
,
"order"
:
"ABCD"
,
"dataType"
:
"int32"
},
{
"name"
:
"生化池水温"
,
"system"
:
"shcsw"
,
"address"
:
"40019-40020"
,
"order"
:
"ABCD"
,
"dataType"
:
"float32"
},
{
"name"
:
"循环水泵故障"
,
"system"
:
"xhsb_gz"
,
"address"
:
"40021.09"
,
"dataType"
:
"bit"
},
{
"name"
:
"生化池水温低限报警"
,
"system"
:
"shcsw_dx_bj"
,
"address"
:
"40021.10"
,
"dataType"
:
"bit"
},
{
"name"
:
"生化池水温高限报警"
,
"system"
:
"shcsw_gx_bj"
,
"address"
:
"40021.11"
,
"dataType"
:
"bit"
}
]
}
]
}
...
...
请
注册
或
登录
后发表评论