no message
parent
36a3e4f24e
commit
edade7cc3c
|
|
@ -88,9 +88,9 @@ public class GeneratorController {
|
|||
@ApiOperation("生成代码")
|
||||
@PostMapping(value = "/{tableName}/{type}")
|
||||
public ResponseEntity<Object> generatorCode(@PathVariable String tableName, @PathVariable Integer type, HttpServletRequest request, HttpServletResponse response){
|
||||
if(!generatorEnabled && type == 0){
|
||||
/*if(!generatorEnabled && type == 0){
|
||||
throw new BadRequestException("此环境不允许生成代码,请选择预览或者下载查看!");
|
||||
}
|
||||
}*/
|
||||
switch (type){
|
||||
// 生成代码
|
||||
case 0: generatorService.generator(genConfigService.find(tableName), generatorService.getColumns(tableName));
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -19,6 +19,11 @@
|
|||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>net.wimpi</groupId>
|
||||
<artifactId>jamod</artifactId>
|
||||
<version>1.2</version>
|
||||
</dependency>
|
||||
<!--jlibmodbus-->
|
||||
<dependency>
|
||||
<groupId>com.intelligt.modbus</groupId>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,666 @@
|
|||
package com.youchain.Netty;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.youchain.annotation.AnonymousAccess;
|
||||
import com.youchain.exception.BadRequestException;
|
||||
import com.youchain.exception.handler.ApiResult;
|
||||
import io.swagger.annotations.Api;
|
||||
import lombok.Data;
|
||||
import net.wimpi.modbus.ModbusException;
|
||||
import net.wimpi.modbus.ModbusIOException;
|
||||
import net.wimpi.modbus.io.ModbusTCPTransaction;
|
||||
import net.wimpi.modbus.msg.ReadMultipleRegistersRequest;
|
||||
import net.wimpi.modbus.msg.ReadMultipleRegistersResponse;
|
||||
import net.wimpi.modbus.msg.WriteMultipleRegistersRequest;
|
||||
import net.wimpi.modbus.msg.WriteMultipleRegistersResponse;
|
||||
import net.wimpi.modbus.net.TCPMasterConnection;
|
||||
import net.wimpi.modbus.procimg.Register;
|
||||
import net.wimpi.modbus.procimg.SimpleRegister;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
// 自定义类来存储每个 IP 的配置信息和读取结果
|
||||
@Data
|
||||
class ModbusWrite {
|
||||
Long id;
|
||||
int modbusConfigId;
|
||||
int address;
|
||||
int values;
|
||||
public static List<ModbusWrite> convertToModbusWriteList(List<Map<String, Object>> queryResult) {
|
||||
List<ModbusWrite> modbusWriteList = new ArrayList<>();
|
||||
for (Map<String, Object> row : queryResult) {
|
||||
ModbusWrite modbusWrite = new ModbusWrite();
|
||||
// 从 Map 中获取 id 并转换为 Long 类型
|
||||
Object idObj = row.get("id");
|
||||
if (idObj != null) {
|
||||
modbusWrite.setId(Long.valueOf(idObj.toString()));
|
||||
}
|
||||
// 从 Map 中获取 modbusInfoId 并转换为 int 类型
|
||||
Object modbusConfigIdObj = row.get("modbusInfoId");
|
||||
if (modbusConfigIdObj != null) {
|
||||
modbusWrite.setModbusConfigId(Integer.parseInt(modbusConfigIdObj.toString()));
|
||||
}
|
||||
// 从 Map 中获取 address 并转换为 int 类型
|
||||
Object addressObj = row.get("address");
|
||||
if (addressObj != null) {
|
||||
modbusWrite.setAddress(Integer.parseInt(addressObj.toString()));
|
||||
}
|
||||
// 从 Map 中获取 value 并转换为 int 类型
|
||||
Object valuesObj = row.get("value");
|
||||
if (valuesObj != null) {
|
||||
modbusWrite.setValues(Integer.parseInt(valuesObj.toString()));
|
||||
}
|
||||
modbusWriteList.add(modbusWrite);
|
||||
}
|
||||
return modbusWriteList;
|
||||
}
|
||||
}
|
||||
@Data
|
||||
class ModbusConfig {
|
||||
Long id;
|
||||
// 报错原因
|
||||
public String description;
|
||||
// 设备的 IP 地址
|
||||
String ip;
|
||||
// 设备的端口号
|
||||
int port;
|
||||
// 起始寄存器地址
|
||||
int startAddress;
|
||||
// 要读取的寄存器数量
|
||||
int numberOfRegisters;
|
||||
// 连接失败时的最大重试次数
|
||||
int maxRetries;
|
||||
// 存储读取到的寄存器值
|
||||
List<Integer> dataValues;
|
||||
// 数据的状态,normal 表示正常,abnormal 表示异常,warning 表示警告,maintenance 表示维护中
|
||||
String dataStatus="normal";
|
||||
// 用于存储要写入的值
|
||||
List<ModbusWrite> modbusWriteList;
|
||||
// 新增连接状态标记
|
||||
boolean isConnected = false;
|
||||
|
||||
/**
|
||||
* 构造函数,用于初始化 Modbus 设备的配置信息。
|
||||
*
|
||||
* @param ip 设备的 IP 地址
|
||||
* @param port 设备的端口号
|
||||
* @param startAddress 起始寄存器地址
|
||||
* @param numberOfRegisters 要读取的寄存器数量
|
||||
* @param maxRetries 最大重试次数
|
||||
*/
|
||||
public ModbusConfig(Long id,String ip, int port, int startAddress, int numberOfRegisters, int maxRetries, List<Integer> dataValues) {
|
||||
this.id = id;
|
||||
this.ip = ip;
|
||||
this.port = port;
|
||||
this.startAddress = startAddress;
|
||||
this.numberOfRegisters = numberOfRegisters;
|
||||
this.maxRetries = maxRetries;
|
||||
// 初始化存储寄存器值的列表
|
||||
this.dataValues =dataValues;
|
||||
}
|
||||
|
||||
public ModbusConfig() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空当前存储的结果,以便存储新的读取数据。
|
||||
*/
|
||||
public void clearData() {
|
||||
dataValues.clear();
|
||||
}
|
||||
/* 处理jdbc查询结果*/
|
||||
public static List<ModbusConfig> convertToModbusConfigList(List<Map<String, Object>> queryResult) {
|
||||
List<ModbusConfig> configList = new ArrayList<>();
|
||||
for (Map<String, Object> row : queryResult) {
|
||||
Long id = Long.valueOf(row.get("id")+"");
|
||||
String ip = (String) row.get("ip");
|
||||
Object portObj = row.get("port");
|
||||
int port = 0;
|
||||
if (portObj instanceof Number) {
|
||||
port = ((Number) portObj).intValue();
|
||||
}
|
||||
Object startAddressObj = row.get("startAddress");
|
||||
int startAddress = 0;
|
||||
if (startAddressObj instanceof Number) {
|
||||
startAddress = ((Number) startAddressObj).intValue();
|
||||
}
|
||||
Object numberOfRegistersObj = row.get("numberOfRegisters");
|
||||
int numberOfRegisters = 0;
|
||||
if (numberOfRegistersObj instanceof Number) {
|
||||
numberOfRegisters = ((Number) numberOfRegistersObj).intValue();
|
||||
}
|
||||
Object maxRetriesObj = row.get("maxRetries");
|
||||
int maxRetries = 0;
|
||||
if (maxRetriesObj instanceof Number) {
|
||||
maxRetries = ((Number) maxRetriesObj).intValue();
|
||||
}
|
||||
// 处理 dataValues 字段
|
||||
Object dataValuesObj = row.get("dataValues");
|
||||
List<Integer> dataValues = new ArrayList<>();
|
||||
if (dataValuesObj != null && dataValuesObj instanceof String) {
|
||||
String dataValuesStr = (String) dataValuesObj;
|
||||
if (!dataValuesStr.isEmpty()) {
|
||||
try {
|
||||
// 使用 fastjson 解析 JSON 数组
|
||||
JSONArray jsonArray = JSON.parseArray(dataValuesStr);
|
||||
for (int i = 0; i < jsonArray.size(); i++) {
|
||||
dataValues.add(jsonArray.getInteger(i));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.err.println("无法解析 dataValues 中的值: " + dataValuesStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
ModbusConfig config = new ModbusConfig(id,ip, port, startAddress, numberOfRegisters, maxRetries,dataValues);
|
||||
configList.add(config);
|
||||
}
|
||||
return configList;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* JamodReadModbusTCP 类用于通过 Modbus TCP 协议从多个设备读取寄存器数据。
|
||||
* 支持为每个设备配置不同的端口、起始地址、数据长度和重试次数,
|
||||
* 并将读取到的数据存储在对应的 ModbusConfig 对象中。
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/jamod")
|
||||
@Api(tags = "jamod测试")
|
||||
public class JamodReadModbusTCP {
|
||||
// 存储每个 Modbus 设备的配置信息
|
||||
private static List<ModbusConfig> CONFIG_LIST = new ArrayList<>();
|
||||
@Autowired
|
||||
private JdbcQueryExample jdbcQueryExample;
|
||||
|
||||
// Modbus 从站 ID
|
||||
private static final int SLAVE_ID = 1;
|
||||
|
||||
// 存储所有 Modbus TCP 连接的线程安全列表
|
||||
private static CopyOnWriteArrayList<TCPMasterConnection> connections = new CopyOnWriteArrayList<>();
|
||||
// 用于定时执行读取任务的调度执行器
|
||||
private static ScheduledExecutorService executorService;
|
||||
// 用于同步连接操作的锁对象
|
||||
private final Object connectionLock = new Object();
|
||||
/**
|
||||
* 向 Modbus TCP 服务写入值
|
||||
* @param connection 要使用的 TCPMasterConnection 对象
|
||||
* @param config 设备的配置信息
|
||||
* @param slaveId Modbus 从站 ID
|
||||
*/
|
||||
private void writeRegisters(TCPMasterConnection connection, ModbusConfig config, int slaveId) {
|
||||
synchronized (connectionLock) {
|
||||
if (!connection.isConnected()) {
|
||||
try {
|
||||
connectWithRetries(connection, config);
|
||||
} catch (Exception e) {
|
||||
System.err.println("重新连接到 " + config.ip + " 失败 - " + translateExceptionMessage(e.getMessage()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
List<ModbusWrite> modbusWriteList = config.modbusWriteList;
|
||||
for (ModbusWrite modbusWrite : modbusWriteList){
|
||||
try {
|
||||
/* 写入值*/
|
||||
List<Integer> writeValues = Collections.singletonList(modbusWrite.getValues());
|
||||
/* 写入地址*/
|
||||
int writeAddress = modbusWrite.getAddress();
|
||||
if (writeValues == null || writeValues.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
SimpleRegister[] registers = new SimpleRegister[writeValues.size()];
|
||||
for (int i = 0; i < writeValues.size(); i++) {
|
||||
registers[i] = new SimpleRegister(writeValues.get(i));
|
||||
}
|
||||
|
||||
WriteMultipleRegistersRequest request = new WriteMultipleRegistersRequest(writeAddress, registers);
|
||||
request.setUnitID(slaveId);
|
||||
|
||||
ModbusTCPTransaction transaction = new ModbusTCPTransaction(connection);
|
||||
transaction.setRequest(request);
|
||||
transaction.execute();
|
||||
|
||||
WriteMultipleRegistersResponse response = (WriteMultipleRegistersResponse) transaction.getResponse();
|
||||
if (response != null) {
|
||||
String updateSql=" UPDATE modbus_write_log "
|
||||
+" SET "
|
||||
+" `status` = 'success',failure_reason='', "
|
||||
+" execution_time = ROUND( "
|
||||
+" (UNIX_TIMESTAMP(NOW()) - UNIX_TIMESTAMP(write_time)), "
|
||||
+" 3 "
|
||||
+" ) "
|
||||
+" WHERE id = "+modbusWrite.id+";";
|
||||
jdbcQueryExample.executeUpdate(updateSql);
|
||||
System.out.println("成功向 " + config.ip + " 写入值");
|
||||
}
|
||||
} catch (ModbusIOException e) {
|
||||
synchronized (connectionLock) {
|
||||
System.err.println("Modbus IO 异常,针对 " + config.ip + " - " + translateExceptionMessage(e.getMessage()));
|
||||
}
|
||||
} catch (ModbusException e) {
|
||||
String updateSql=" UPDATE modbus_write_log "
|
||||
+" SET "
|
||||
+" `status` = 'retrying',retry_count = retry_count + 1 "
|
||||
+" WHERE id ="+modbusWrite.id+";";
|
||||
jdbcQueryExample.executeUpdate(updateSql);
|
||||
System.err.println("Modbus 事务异常,针对 " + config.ip + " - " + translateExceptionMessage(e.getMessage()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动定时任务
|
||||
*/
|
||||
@PostMapping("/start")
|
||||
@AnonymousAccess
|
||||
public void startTask() {
|
||||
// 初始化配置列表
|
||||
String sql = "SELECT id 'id',device_name, device_ip 'ip', device_port 'port', " +
|
||||
"start_address 'startAddress', data_length 'numberOfRegisters', " +
|
||||
"max_retries 'maxRetries', data_values 'dataValues' " +
|
||||
"FROM modbus_info WHERE enabled = ?";
|
||||
List<Map<String, Object>> queryResult = jdbcQueryExample.sqlQuery(sql, 1);
|
||||
CONFIG_LIST = ModbusConfig.convertToModbusConfigList(queryResult);
|
||||
// 初始化连接
|
||||
initializeConnections();
|
||||
|
||||
// 注册关闭钩子
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(this::shutdown));
|
||||
|
||||
// 启动定时任务
|
||||
executorService = Executors.newScheduledThreadPool(1);
|
||||
executorService.scheduleAtFixedRate(() -> {
|
||||
System.out.println("开始读取数据...");
|
||||
for (ModbusConfig config : CONFIG_LIST) {
|
||||
TCPMasterConnection connection = getConnectionByIp(config.ip);
|
||||
if (connection != null) {
|
||||
config.clearData();
|
||||
ModbusConfig updatedConfig = readRegisters(connection, config, SLAVE_ID);
|
||||
if (updatedConfig != null) {
|
||||
// 处理数据更新逻辑(原有读取后的处理逻辑)
|
||||
if ("warning".equals(updatedConfig.dataStatus)) {
|
||||
String updateSql = "update modbus_info set data_status='warning',description='"
|
||||
+ updatedConfig.description + "',last_read_time=NOW() where id="
|
||||
+ updatedConfig.id + ";";
|
||||
jdbcQueryExample.executeUpdate(updateSql);
|
||||
} else if ("normal".equals(updatedConfig.dataStatus)) {
|
||||
String updateSql = "update modbus_info set data_status='normal',data_values='"
|
||||
+ updatedConfig.dataValues + "',description='',last_read_time=NOW() where id="
|
||||
+ updatedConfig.id + ";";
|
||||
jdbcQueryExample.executeUpdate(updateSql);
|
||||
|
||||
// 读取成功后处理写入逻辑
|
||||
String sqlWrite = "select id,modbus_info_id 'modbusInfoId',register_address 'address',data_values 'value' " +
|
||||
"from modbus_write_log where `status` in ('unprocessed','retrying') and modbus_info_id=?";
|
||||
List<Map<String, Object>> queryWrite = jdbcQueryExample.sqlQuery(sqlWrite, updatedConfig.id);
|
||||
List<ModbusWrite> modbusWriteList = ModbusWrite.convertToModbusWriteList(queryWrite);
|
||||
config.modbusWriteList = modbusWriteList;
|
||||
writeRegisters(connection, config, SLAVE_ID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 0, 1, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭定时任务
|
||||
*/
|
||||
@PostMapping("/stop")
|
||||
@AnonymousAccess
|
||||
public void stopTask() {
|
||||
if (executorService != null && !executorService.isShutdown()) {
|
||||
executorService.shutdown();
|
||||
try {
|
||||
if (!executorService.awaitTermination(5, TimeUnit.SECONDS)) {
|
||||
executorService.shutdownNow();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
System.err.println("等待定时任务执行器终止时被中断。");
|
||||
}
|
||||
}
|
||||
|
||||
// 关闭所有连接
|
||||
for (TCPMasterConnection connection : connections) {
|
||||
if (connection.isConnected()) {
|
||||
try {
|
||||
connection.close();
|
||||
System.out.println("已关闭 " + connection.getAddress() + " 的连接。");
|
||||
} catch (Exception e) {
|
||||
System.err.println("关闭 " + connection.getAddress() + " 的连接时出错: " + translateExceptionMessage(e.getMessage()));
|
||||
}
|
||||
}
|
||||
}
|
||||
// 清空配置信息
|
||||
CONFIG_LIST.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 IP 地址从连接列表中查找对应的 TCPMasterConnection 对象。
|
||||
*
|
||||
* @param ipAddress 要查找的 IP 地址
|
||||
* @return 对应的 TCPMasterConnection 对象,如果未找到则返回 null
|
||||
*/
|
||||
private static TCPMasterConnection getConnectionByIp(String ipAddress) {
|
||||
for (TCPMasterConnection connection : connections) {
|
||||
if (connection.getAddress().getHostAddress().equals(ipAddress)) {
|
||||
return connection;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化与所有配置的 Modbus 设备的连接。
|
||||
* 遍历 CONFIG_LIST 中的每个设备配置信息,创建连接并尝试建立连接。
|
||||
*/
|
||||
private void initializeConnections() {
|
||||
for (ModbusConfig config : CONFIG_LIST) {
|
||||
try {
|
||||
InetAddress inetAddress = InetAddress.getByName(config.ip);
|
||||
TCPMasterConnection connection = new TCPMasterConnection(inetAddress);
|
||||
connection.setPort(config.port);
|
||||
|
||||
// 尝试连接,成功则标记状态并添加连接
|
||||
connectWithRetries(connection, config);
|
||||
|
||||
config.isConnected = true;
|
||||
connections.add(connection);
|
||||
} catch (Exception e) {
|
||||
// 初始化连接失败,标记状态为未连接
|
||||
config.isConnected = false;
|
||||
|
||||
String des="初始化连接失败,后续将重试 - IP: " + config.ip + ",错误: " + translateExceptionMessage(e.getMessage());
|
||||
System.err.println(des);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 尝试连接到 Modbus 设备,若连接失败则进行重试,最多重试 maxRetries 次。
|
||||
*
|
||||
* @param connection 要连接的 TCPMasterConnection 对象
|
||||
* @param config 设备的配置信息
|
||||
* @throws Exception 如果尝试 maxRetries 次后仍无法连接
|
||||
*/
|
||||
private void connectWithRetries(TCPMasterConnection connection, ModbusConfig config) throws Exception {
|
||||
int retries = 0;
|
||||
while (retries < config.maxRetries) {
|
||||
try {
|
||||
// 尝试建立连接
|
||||
connection.connect();
|
||||
System.out.println("已连接到 " + config.ip);
|
||||
/*连接成功修改状态*/
|
||||
String updateSql = "update modbus_info set is_connected=0 where id="
|
||||
+ config.id + ";";
|
||||
jdbcQueryExample.executeUpdate(updateSql);
|
||||
return;
|
||||
} catch (Exception e) {
|
||||
retries++;
|
||||
System.err.println("第 " + retries + " 次尝试连接到 " + config.ip + " 失败: " + translateExceptionMessage(e.getMessage()));
|
||||
if (retries == config.maxRetries) {
|
||||
// 达到最大重试次数,抛出异常
|
||||
String updateSql = "update modbus_info set is_connected=1,data_values='"
|
||||
+ "',description='"+"尝试 " + config.maxRetries + " 次后仍无法连接到 " + config.ip + "。"+e.getMessage()+"' where id="
|
||||
+ config.id + ";";
|
||||
jdbcQueryExample.executeUpdate(updateSql);
|
||||
throw new Exception("尝试 " + config.maxRetries + " 次后仍无法连接到 " + config.ip + "。");
|
||||
}
|
||||
try {
|
||||
// 重试前暂停 1 秒
|
||||
TimeUnit.SECONDS.sleep(1);
|
||||
} catch (InterruptedException ie) {
|
||||
Thread.currentThread().interrupt();
|
||||
System.err.println("连接重试期间睡眠被中断。");
|
||||
throw new Exception("连接重试被中断。");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从指定的 Modbus 设备读取寄存器数据。
|
||||
* 如果连接断开,会尝试重新连接。
|
||||
* 读取到的数据会存储在对应的 ModbusConfig 对象中。
|
||||
*
|
||||
* @param connection 要使用的 TCPMasterConnection 对象
|
||||
* @param config 设备的配置信息
|
||||
* @param slaveId Modbus 从站 ID
|
||||
* @return 读取到的寄存器数据列表,如果读取失败则返回 null
|
||||
*/
|
||||
private ModbusConfig readRegisters(TCPMasterConnection connection, ModbusConfig config, int slaveId) {
|
||||
// 同步操作,确保同一时间只有一个线程可以检查和修改连接状态
|
||||
synchronized (connectionLock) {
|
||||
if (!connection.isConnected()) {
|
||||
try {
|
||||
// 尝试重新连接到设备
|
||||
connectWithRetries(connection, config);
|
||||
} catch (Exception e) {
|
||||
System.err.println("重新连接到 " + config.ip + " 失败 - " + translateExceptionMessage(e.getMessage()));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
// 创建一个读取多个寄存器的请求
|
||||
ReadMultipleRegistersRequest request = new ReadMultipleRegistersRequest(config.startAddress, config.numberOfRegisters);
|
||||
// 设置从站 ID
|
||||
request.setUnitID(slaveId);
|
||||
|
||||
// 创建一个 Modbus TCP 事务
|
||||
ModbusTCPTransaction transaction = new ModbusTCPTransaction(connection);
|
||||
// 设置请求到事务中
|
||||
transaction.setRequest(request);
|
||||
// 执行事务
|
||||
transaction.execute();
|
||||
|
||||
// 获取事务的响应
|
||||
ReadMultipleRegistersResponse response = (ReadMultipleRegistersResponse) transaction.getResponse();
|
||||
if (response != null) {
|
||||
// 获取响应中的寄存器数组
|
||||
Register[] registers = response.getRegisters();
|
||||
// 用于临时存储读取到的寄存器值
|
||||
List<Integer> values = new ArrayList<>();
|
||||
for (Register register : registers) {
|
||||
// 将每个寄存器的值添加到临时列表中
|
||||
values.add(register.getValue());
|
||||
}
|
||||
// 更新配置中的数据
|
||||
config.dataValues = values;
|
||||
config.dataStatus="normal";// 数据正常
|
||||
}
|
||||
} catch (ModbusIOException e) {
|
||||
// 同步操作,确保同一时间只有一个线程可以处理连接异常
|
||||
synchronized (connectionLock) {
|
||||
System.err.println("Modbus IO 异常,针对 " + config.ip + " - " + translateExceptionMessage(e.getMessage()));
|
||||
try {
|
||||
// 关闭当前连接
|
||||
connection.close();
|
||||
// 尝试重新连接到设备
|
||||
connectWithRetries(connection, config);
|
||||
} catch (Exception re) {
|
||||
System.err.println("重新连接到 " + config.ip + " 失败 - " + translateExceptionMessage(re.getMessage()));
|
||||
}
|
||||
}
|
||||
} catch (ModbusException e) {
|
||||
config.dataStatus="warning";// 数据报错
|
||||
config.description="Modbus 事务异常,针对 " + config.ip + " - " + translateExceptionMessage(e.getMessage());
|
||||
// System.err.println("Modbus 事务异常,针对 " + config.ip + " - " + translateExceptionMessage(e.getMessage()));
|
||||
}
|
||||
/* 修改表值*/
|
||||
|
||||
return config;
|
||||
}
|
||||
/**
|
||||
* 程序关闭时的清理操作。
|
||||
* 关闭定时任务执行器和所有 Modbus TCP 连接。
|
||||
*/
|
||||
private void shutdown() {
|
||||
if (executorService != null && !executorService.isShutdown()) {
|
||||
// 发起关闭定时任务执行器的请求
|
||||
executorService.shutdown();
|
||||
try {
|
||||
// 等待执行器在 5 秒内正常关闭
|
||||
if (!executorService.awaitTermination(5, TimeUnit.SECONDS)) {
|
||||
// 若 5 秒内未关闭,则强制关闭
|
||||
executorService.shutdownNow();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
System.err.println("等待定时任务执行器终止时被中断。");
|
||||
}
|
||||
}
|
||||
|
||||
// 关闭所有连接
|
||||
for (TCPMasterConnection connection : connections) {
|
||||
if (connection.isConnected()) {
|
||||
try {
|
||||
// 关闭连接
|
||||
connection.close();
|
||||
System.out.println("已关闭 " + connection.getAddress() + " 的连接。");
|
||||
} catch (Exception e) {
|
||||
System.err.println("关闭 " + connection.getAddress() + " 的连接时出错: " + translateExceptionMessage(e.getMessage()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将异常信息翻译成中文,目前只是简单返回原信息。
|
||||
* 可根据实际情况添加更多翻译规则。
|
||||
*
|
||||
* @param message 原始异常信息
|
||||
* @return 翻译后的异常信息
|
||||
*/
|
||||
private String translateExceptionMessage(String message) {
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定 IP 地址对应的设备的最新读取数据。
|
||||
*
|
||||
* @param ipAddress 要获取数据的设备的 IP 地址
|
||||
* @return 存储最新读取数据的列表,如果 IP 地址对应的配置不存在则返回 null
|
||||
*/
|
||||
public List<Integer> getLatestData(String ipAddress) {
|
||||
// 遍历配置列表,查找对应 IP 的配置信息
|
||||
for (ModbusConfig config : CONFIG_LIST) {
|
||||
if (config.ip.equals(ipAddress)) {
|
||||
// 返回配置中存储的数据的副本
|
||||
return new ArrayList<>(config.dataValues);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
// 添加新配置的方法
|
||||
@PostMapping("/addConFig")
|
||||
@AnonymousAccess
|
||||
public synchronized ResponseEntity<Object> addModbusConfig(@RequestBody Long id) {
|
||||
String sql = "SELECT id 'id',device_name, device_ip 'ip', device_port 'port', " +
|
||||
"start_address 'startAddress', data_length 'numberOfRegisters', " +
|
||||
"max_retries 'maxRetries', data_values 'dataValues' " +
|
||||
"FROM modbus_info WHERE id=?";
|
||||
List<Map<String, Object>> queryResult = jdbcQueryExample.sqlQuery(sql, id);
|
||||
if (queryResult.size()>0){
|
||||
ModbusConfig newConfig = ModbusConfig.convertToModbusConfigList(queryResult).get(0);
|
||||
// 检查是否已存在相同配置(示例:根据IP和端口判断)
|
||||
if (CONFIG_LIST.stream().anyMatch(c ->
|
||||
c.getIp().equals(newConfig.getIp()) &&
|
||||
c.getPort() == newConfig.getPort())) {
|
||||
System.err.println("配置已存在,跳过添加: " + newConfig.getIp() + ":" + newConfig.getPort());
|
||||
// return;
|
||||
}else {
|
||||
// 添加新配置
|
||||
CONFIG_LIST.add(newConfig);
|
||||
}
|
||||
if (getConnectionByIp(newConfig.ip)==null){
|
||||
// 初始化连接
|
||||
initializeConnection(newConfig);
|
||||
}
|
||||
}else {throw new BadRequestException("未查询到配置信息");}
|
||||
ApiResult apiResult=new ApiResult();
|
||||
return new ResponseEntity<>(apiResult.success("添加成功"), HttpStatus.OK);
|
||||
}
|
||||
// 初始化单个配置的连接
|
||||
private void initializeConnection(ModbusConfig config) {
|
||||
try {
|
||||
// 创建连接对象
|
||||
TCPMasterConnection connection = new TCPMasterConnection(
|
||||
InetAddress.getByName(config.getIp())
|
||||
);
|
||||
connection.setPort(config.getPort());
|
||||
|
||||
// 尝试连接
|
||||
connectWithRetries(connection, config);
|
||||
|
||||
// 保存连接
|
||||
connections.add(connection);
|
||||
config.setConnected(true);
|
||||
System.out.println("成功连接新设备: " + config.getIp() + ":" + config.getPort());
|
||||
} catch (Exception e) {
|
||||
config.setConnected(false);
|
||||
throw new RuntimeException("异常: " + config.getIp() + ":" + config.getPort(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加写入操作
|
||||
* @param ip IP
|
||||
* @param address 地址
|
||||
* @param values 数据
|
||||
*/
|
||||
public synchronized void addWrite(String ip, int address, int values) {
|
||||
String sql = "SELECT id " +
|
||||
"FROM modbus_info WHERE device_ip= '"+ip+"'";
|
||||
List<Map<String, Object>> modbusInfos = jdbcQueryExample.sqlQuery(sql);
|
||||
if (modbusInfos.size()>0){
|
||||
Long modbus_info_id = Long.valueOf(modbusInfos.get(0).get("id").toString());
|
||||
// 如果已有任务,直接跳过
|
||||
String sqlWrite = "select id,modbus_info_id 'modbusInfoId',register_address 'address',data_values 'value' " +
|
||||
"from modbus_write_log where `status` in ('unprocessed','retrying') " +
|
||||
"and modbus_info_id=? " +
|
||||
"and register_address=? " +
|
||||
"and data_values=?";
|
||||
List<Map<String, Object>> queryWrite = jdbcQueryExample.sqlQuery(sqlWrite, modbus_info_id,address,values);
|
||||
if (queryWrite.size()<1) {
|
||||
String insertSql = "INSERT INTO `wms`.`modbus_write_log` ( `modbus_info_id`, `register_address`, `data_values`, `write_time`, `status`,`failure_reason`) " +
|
||||
"VALUES ( ?,? , ?, NOW(), 'unprocessed', '');";
|
||||
// 添加写入操作
|
||||
jdbcQueryExample.executeUpdate(insertSql, modbus_info_id, address, values);
|
||||
}
|
||||
}
|
||||
}
|
||||
public String getRead(String ip,int address) {
|
||||
for (ModbusConfig config : CONFIG_LIST) {
|
||||
if (config.getIp().equals(ip)) {
|
||||
if (config.getDataValues() != null && config.getDataValues().size() >= (address-1)) {
|
||||
return config.getDataValues().get(address)+""; // 索引从0开始
|
||||
} else {
|
||||
System.err.println("dataValues 集合中没有足够的数据。");
|
||||
return "dataValues 集合中没有足够的数据。";
|
||||
}
|
||||
}
|
||||
}
|
||||
System.err.println("未找到 IP 地址为 " + ip + " 的 ModbusConfig 配置。");
|
||||
return "未找到 IP 地址为 " + ip + " 的 ModbusConfig 配置。";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
package com.youchain.Netty;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Component
|
||||
@Service
|
||||
public class JdbcQueryExample {
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
|
||||
@Autowired
|
||||
public JdbcQueryExample(JdbcTemplate jdbcTemplate) {
|
||||
this.jdbcTemplate = jdbcTemplate;
|
||||
}
|
||||
|
||||
public List<Map<String, Object>> sqlQuery(String sql, Object... params) {
|
||||
return jdbcTemplate.queryForList(sql, params);
|
||||
}
|
||||
public List<Map<String, Object>> sqlQuery(String sql) {
|
||||
return jdbcTemplate.queryForList(sql);
|
||||
}
|
||||
public int executeUpdate(String sql, Object... params) {
|
||||
return jdbcTemplate.update(sql, params);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -16,6 +16,7 @@
|
|||
package com.youchain.basicdata.domain;
|
||||
|
||||
import com.youchain.base.BaseEntity;
|
||||
import com.youchain.jamod.domain.ModbusInfo;
|
||||
import com.youchain.modules.system.domain.Dept;
|
||||
import lombok.Data;
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
|
|
@ -84,6 +85,16 @@ public class Box extends BaseEntity implements Serializable {
|
|||
@Column(name = "`sort`")
|
||||
@ApiModelProperty(value = "排序")
|
||||
private int sort=0;
|
||||
@Column(name = "`work_code`")
|
||||
@ApiModelProperty(value = "业务代码")
|
||||
private String workCode;
|
||||
@Column(name = "`work_type`")
|
||||
@ApiModelProperty(value = "业务类型")
|
||||
private String workType;
|
||||
@OneToOne
|
||||
@JoinColumn(name = "`modbus_id`")
|
||||
@ApiModelProperty(value = "关联modbus")
|
||||
private ModbusInfo modbusInfo;
|
||||
|
||||
@Column(name = "`IP`")
|
||||
@ApiModelProperty(value = "IP")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.youchain.basicdata.domain;
|
||||
|
||||
import com.youchain.base.BaseEntity;
|
||||
import com.youchain.modules.system.domain.Dept;
|
||||
import lombok.Data;
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import cn.hutool.core.bean.copier.CopyOptions;
|
||||
import javax.persistence.*;
|
||||
import javax.validation.constraints.*;
|
||||
import java.sql.Timestamp;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @website https://eladmin.vip
|
||||
* @description /
|
||||
* @author admin
|
||||
* @date 2025-04-11
|
||||
**/
|
||||
@Entity
|
||||
@Data
|
||||
@Table(name="base_point_item")
|
||||
public class PointItem extends BaseEntity implements Serializable {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "`id`")
|
||||
@ApiModelProperty(value = "ID")
|
||||
private Long id;
|
||||
|
||||
@Column(name = "`code`")
|
||||
@ApiModelProperty(value = "编号")
|
||||
private String code;
|
||||
|
||||
@Column(name = "`name`")
|
||||
@ApiModelProperty(value = "名称")
|
||||
private String name;
|
||||
|
||||
@OneToOne
|
||||
@JoinColumn(name = "`item_id`",nullable = false)
|
||||
@ApiModelProperty(value = "物料")
|
||||
private Item item;
|
||||
@OneToOne
|
||||
@JoinColumn(name = "`point_id`",nullable = false)
|
||||
@ApiModelProperty(value = "点位")
|
||||
private Point point;
|
||||
@Column(name = "`enabled`")
|
||||
@ApiModelProperty(value = "状态:1启用、0禁用")
|
||||
private Boolean enabled=true;
|
||||
|
||||
@Column(name = "`order_Number`")
|
||||
@ApiModelProperty(value = "工单号")
|
||||
private String orderNumber;
|
||||
|
||||
@Column(name = "`create_by`")
|
||||
@ApiModelProperty(value = "创建人")
|
||||
private String createBy;
|
||||
|
||||
@Column(name = "`update_by`")
|
||||
@ApiModelProperty(value = "修改人")
|
||||
private String updateBy;
|
||||
|
||||
@Column(name = "`create_time`")
|
||||
@ApiModelProperty(value = "创建时间")
|
||||
private Timestamp createTime;
|
||||
|
||||
@Column(name = "`update_time`")
|
||||
@ApiModelProperty(value = "修改时间")
|
||||
private Timestamp updateTime;
|
||||
|
||||
public void copy(PointItem source){
|
||||
BeanUtil.copyProperties(source,this, CopyOptions.create().setIgnoreNullValue(true));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.youchain.basicdata.repository;
|
||||
|
||||
import com.youchain.basicdata.domain.PointItem;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
|
||||
/**
|
||||
* @website https://eladmin.vip
|
||||
* @author admin
|
||||
* @date 2025-04-11
|
||||
**/
|
||||
public interface PointItemRepository extends JpaRepository<PointItem, Long>, JpaSpecificationExecutor<PointItem> {
|
||||
}
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.youchain.basicdata.rest;
|
||||
|
||||
import com.youchain.annotation.Log;
|
||||
import com.youchain.basicdata.domain.PointItem;
|
||||
import com.youchain.basicdata.service.PointItemService;
|
||||
import com.youchain.basicdata.service.dto.PointItemQueryCriteria;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import io.swagger.annotations.*;
|
||||
import java.io.IOException;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* @website https://eladmin.vip
|
||||
* @author admin
|
||||
* @date 2025-04-11
|
||||
**/
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@Api(tags = "pointItem管理")
|
||||
@RequestMapping("/api/pointItem")
|
||||
public class PointItemController {
|
||||
|
||||
private final PointItemService pointItemService;
|
||||
|
||||
@Log("导出数据")
|
||||
@ApiOperation("导出数据")
|
||||
@GetMapping(value = "/download")
|
||||
@PreAuthorize("@el.check('pointItem:list')")
|
||||
public void exportPointItem(HttpServletResponse response, PointItemQueryCriteria criteria) throws IOException {
|
||||
pointItemService.download(pointItemService.queryAll(criteria), response);
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
@Log("查询pointItem")
|
||||
@ApiOperation("查询pointItem")
|
||||
@PreAuthorize("@el.check('pointItem:list')")
|
||||
public ResponseEntity<Object> queryPointItem(PointItemQueryCriteria criteria, Pageable pageable){
|
||||
return new ResponseEntity<>(pointItemService.queryAll(criteria,pageable),HttpStatus.OK);
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
@Log("新增pointItem")
|
||||
@ApiOperation("新增pointItem")
|
||||
@PreAuthorize("@el.check('pointItem:add')")
|
||||
public ResponseEntity<Object> createPointItem(@Validated @RequestBody PointItem resources){
|
||||
return new ResponseEntity<>(pointItemService.create(resources),HttpStatus.CREATED);
|
||||
}
|
||||
|
||||
@PutMapping
|
||||
@Log("修改pointItem")
|
||||
@ApiOperation("修改pointItem")
|
||||
@PreAuthorize("@el.check('pointItem:edit')")
|
||||
public ResponseEntity<Object> updatePointItem(@Validated @RequestBody PointItem resources){
|
||||
pointItemService.update(resources);
|
||||
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
|
||||
}
|
||||
|
||||
@DeleteMapping
|
||||
@Log("删除pointItem")
|
||||
@ApiOperation("删除pointItem")
|
||||
@PreAuthorize("@el.check('pointItem:del')")
|
||||
public ResponseEntity<Object> deletePointItem(@RequestBody Long[] ids) {
|
||||
pointItemService.deleteAll(ids);
|
||||
return new ResponseEntity<>(HttpStatus.OK);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.youchain.basicdata.service;
|
||||
|
||||
import com.youchain.basicdata.domain.PointItem;
|
||||
import com.youchain.basicdata.service.dto.PointItemDto;
|
||||
import com.youchain.basicdata.service.dto.PointItemQueryCriteria;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import java.util.Map;
|
||||
import java.util.List;
|
||||
import java.io.IOException;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* @website https://eladmin.vip
|
||||
* @description 服务接口
|
||||
* @author admin
|
||||
* @date 2025-04-11
|
||||
**/
|
||||
public interface PointItemService {
|
||||
|
||||
/**
|
||||
* 查询数据分页
|
||||
* @param criteria 条件
|
||||
* @param pageable 分页参数
|
||||
* @return Map<String,Object>
|
||||
*/
|
||||
Map<String,Object> queryAll(PointItemQueryCriteria criteria, Pageable pageable);
|
||||
|
||||
/**
|
||||
* 查询所有数据不分页
|
||||
* @param criteria 条件参数
|
||||
* @return List<PointItemDto>
|
||||
*/
|
||||
List<PointItemDto> queryAll(PointItemQueryCriteria criteria);
|
||||
|
||||
/**
|
||||
* 根据ID查询
|
||||
* @param id ID
|
||||
* @return PointItemDto
|
||||
*/
|
||||
PointItemDto findById(Long id);
|
||||
|
||||
/**
|
||||
* 创建
|
||||
* @param resources /
|
||||
* @return PointItemDto
|
||||
*/
|
||||
PointItemDto create(PointItem resources);
|
||||
|
||||
/**
|
||||
* 编辑
|
||||
* @param resources /
|
||||
*/
|
||||
void update(PointItem resources);
|
||||
|
||||
/**
|
||||
* 多选删除
|
||||
* @param ids /
|
||||
*/
|
||||
void deleteAll(Long[] ids);
|
||||
|
||||
/**
|
||||
* 导出数据
|
||||
* @param all 待导出的数据
|
||||
* @param response /
|
||||
* @throws IOException /
|
||||
*/
|
||||
void download(List<PointItemDto> all, HttpServletResponse response) throws IOException;
|
||||
}
|
||||
|
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
package com.youchain.basicdata.service.dto;
|
||||
|
||||
import com.youchain.jamod.domain.ModbusInfo;
|
||||
import com.youchain.modules.system.domain.Dept;
|
||||
import lombok.Data;
|
||||
import java.sql.Timestamp;
|
||||
|
|
@ -53,7 +54,9 @@ public class BoxDto implements Serializable {
|
|||
|
||||
/** 排序*/
|
||||
private String sort;
|
||||
|
||||
private String workCode;
|
||||
private String workType;
|
||||
private ModbusInfo modbusInfo;
|
||||
/** 仓库*/
|
||||
private Dept dept;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.youchain.basicdata.service.dto;
|
||||
|
||||
import com.youchain.basicdata.domain.Item;
|
||||
import com.youchain.basicdata.domain.Point;
|
||||
import com.youchain.modules.system.domain.Dept;
|
||||
import lombok.Data;
|
||||
import java.sql.Timestamp;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @website https://eladmin.vip
|
||||
* @description /
|
||||
* @author admin
|
||||
* @date 2025-04-11
|
||||
**/
|
||||
@Data
|
||||
public class PointItemDto implements Serializable {
|
||||
|
||||
/** ID */
|
||||
private Long id;
|
||||
|
||||
/** 编号 */
|
||||
private String code;
|
||||
|
||||
/** 名称 */
|
||||
private String name;
|
||||
|
||||
/** 物料ID */
|
||||
private Item item;
|
||||
|
||||
/** 点位ID */
|
||||
private Point point;
|
||||
|
||||
|
||||
/** 状态:1启用、0禁用 */
|
||||
private Boolean enabled=true;
|
||||
|
||||
/** 工单号 */
|
||||
private String orderNumber;
|
||||
|
||||
/** 创建人 */
|
||||
private String createBy;
|
||||
|
||||
/** 修改人 */
|
||||
private String updateBy;
|
||||
|
||||
/** 创建时间 */
|
||||
private Timestamp createTime;
|
||||
|
||||
/** 修改时间 */
|
||||
private Timestamp updateTime;
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.youchain.basicdata.service.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import java.util.List;
|
||||
import com.youchain.annotation.Query;
|
||||
|
||||
/**
|
||||
* @website https://eladmin.vip
|
||||
* @author admin
|
||||
* @date 2025-04-11
|
||||
**/
|
||||
@Data
|
||||
public class PointItemQueryCriteria{
|
||||
|
||||
/** 模糊 */
|
||||
@Query(type = Query.Type.INNER_LIKE)
|
||||
private String code;
|
||||
|
||||
/** 模糊 */
|
||||
@Query(type = Query.Type.INNER_LIKE)
|
||||
private Long itemId;
|
||||
|
||||
/** 模糊 */
|
||||
@Query(type = Query.Type.INNER_LIKE)
|
||||
private Long pointId;
|
||||
|
||||
/** 精确 */
|
||||
@Query
|
||||
private Boolean enabled;
|
||||
}
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.youchain.basicdata.service.impl;
|
||||
|
||||
import com.youchain.basicdata.domain.PointItem;
|
||||
import com.youchain.utils.FileUtil;
|
||||
import com.youchain.utils.PageUtil;
|
||||
import com.youchain.utils.QueryHelp;
|
||||
import com.youchain.utils.ValidationUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import com.youchain.basicdata.repository.PointItemRepository;
|
||||
import com.youchain.basicdata.service.PointItemService;
|
||||
import com.youchain.basicdata.service.dto.PointItemDto;
|
||||
import com.youchain.basicdata.service.dto.PointItemQueryCriteria;
|
||||
import com.youchain.basicdata.service.mapstruct.PointItemMapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.io.IOException;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
/**
|
||||
* @website https://eladmin.vip
|
||||
* @description 服务实现
|
||||
* @author admin
|
||||
* @date 2025-04-11
|
||||
**/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class PointItemServiceImpl implements PointItemService {
|
||||
|
||||
private final PointItemRepository pointItemRepository;
|
||||
private final PointItemMapper pointItemMapper;
|
||||
|
||||
@Override
|
||||
public Map<String,Object> queryAll(PointItemQueryCriteria criteria, Pageable pageable){
|
||||
Page<PointItem> page = pointItemRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable);
|
||||
return PageUtil.toPage(page.map(pointItemMapper::toDto));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PointItemDto> queryAll(PointItemQueryCriteria criteria){
|
||||
return pointItemMapper.toDto(pointItemRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder)));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public PointItemDto findById(Long id) {
|
||||
PointItem pointItem = pointItemRepository.findById(id).orElseGet(PointItem::new);
|
||||
ValidationUtil.isNull(pointItem.getId(),"PointItem","id",id);
|
||||
return pointItemMapper.toDto(pointItem);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public PointItemDto create(PointItem resources) {
|
||||
resources.setCode(resources.getPoint().getCode()+":"+resources.getItem().getCode());
|
||||
resources.setEnabled(true);
|
||||
return pointItemMapper.toDto(pointItemRepository.save(resources));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void update(PointItem resources) {
|
||||
PointItem pointItem = pointItemRepository.findById(resources.getId()).orElseGet(PointItem::new);
|
||||
ValidationUtil.isNull( pointItem.getId(),"PointItem","id",resources.getId());
|
||||
pointItem.copy(resources);
|
||||
pointItemRepository.save(pointItem);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteAll(Long[] ids) {
|
||||
for (Long id : ids) {
|
||||
pointItemRepository.deleteById(id);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void download(List<PointItemDto> all, HttpServletResponse response) throws IOException {
|
||||
List<Map<String, Object>> list = new ArrayList<>();
|
||||
for (PointItemDto pointItem : all) {
|
||||
Map<String,Object> map = new LinkedHashMap<>();
|
||||
map.put("编号", pointItem.getCode());
|
||||
map.put("名称", pointItem.getName());
|
||||
map.put("物料ID", pointItem.getItem().getCode());
|
||||
map.put("点位ID", pointItem.getPoint().getCode());
|
||||
map.put("状态:1启用、0禁用", pointItem.getEnabled());
|
||||
map.put("工单号", pointItem.getOrderNumber());
|
||||
map.put("创建人", pointItem.getCreateBy());
|
||||
map.put("修改人", pointItem.getUpdateBy());
|
||||
map.put("创建时间", pointItem.getCreateTime());
|
||||
map.put("修改时间", pointItem.getUpdateTime());
|
||||
list.add(map);
|
||||
}
|
||||
FileUtil.downloadExcel(list, response);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.youchain.basicdata.service.mapstruct;
|
||||
|
||||
import com.youchain.base.BaseMapper;
|
||||
import com.youchain.basicdata.domain.PointItem;
|
||||
import com.youchain.basicdata.service.dto.PointItemDto;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.ReportingPolicy;
|
||||
|
||||
/**
|
||||
* @website https://eladmin.vip
|
||||
* @author admin
|
||||
* @date 2025-04-11
|
||||
**/
|
||||
@Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE)
|
||||
public interface PointItemMapper extends BaseMapper<PointItemDto, PointItem> {
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
package com.youchain.dropdown;
|
||||
|
||||
import com.youchain.annotation.AnonymousAccess;
|
||||
import com.youchain.annotation.Log;
|
||||
import com.youchain.basicdata.domain.Item;
|
||||
import com.youchain.basicdata.domain.Point;
|
||||
import com.youchain.basicdata.repository.ItemRepository;
|
||||
import com.youchain.basicdata.repository.PointRepository;
|
||||
import com.youchain.exception.handler.ApiResult;
|
||||
import com.youchain.jamod.domain.ModbusInfo;
|
||||
import com.youchain.jamod.service.ModbusInfoService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@Api(tags = "下拉框加载")
|
||||
@RequestMapping("/api/dropdown")
|
||||
public class DropdownController {
|
||||
private final PointRepository pointRepository;
|
||||
private final ItemRepository itemRepository;
|
||||
@PostMapping("/pointData")
|
||||
@ApiOperation("全部点位")
|
||||
@AnonymousAccess
|
||||
public ResponseEntity<Object> pointData(){
|
||||
List<Point> pointList=pointRepository.findAll();
|
||||
ApiResult apiResult=ApiResult.fail(200,"成功",pointList);
|
||||
return new ResponseEntity<>(apiResult,apiResult.getStatus());
|
||||
}
|
||||
@PostMapping("/itemData")
|
||||
@ApiOperation("全部物料")
|
||||
@AnonymousAccess
|
||||
public ResponseEntity<Object> itemData(){
|
||||
List<Item> itemList=itemRepository.findAll();
|
||||
ApiResult apiResult=ApiResult.fail(200,"成功",itemList);
|
||||
return new ResponseEntity<>(apiResult,apiResult.getStatus());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.youchain.jamod.domain;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.bean.copier.CopyOptions;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.persistence.*;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.io.Serializable;
|
||||
import java.sql.Timestamp;
|
||||
|
||||
/**
|
||||
* @website https://eladmin.vip
|
||||
* @description /
|
||||
* @author huojin
|
||||
* @date 2025-03-21
|
||||
**/
|
||||
@Entity
|
||||
@Data
|
||||
@Table(name="modbus_info")
|
||||
public class ModbusInfo implements Serializable {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "`id`")
|
||||
@ApiModelProperty(value = "自增主键,唯一标识每条记录")
|
||||
private Integer id;
|
||||
|
||||
@Column(name = "`device_name`",nullable = false)
|
||||
@NotBlank
|
||||
@ApiModelProperty(value = "Modbus 设备的名称,用于直观识别设备")
|
||||
private String deviceName;
|
||||
|
||||
@Column(name = "`device_ip`",nullable = false)
|
||||
@NotBlank
|
||||
@ApiModelProperty(value = "Modbus 设备的 IP 地址")
|
||||
private String deviceIp;
|
||||
|
||||
@Column(name = "`device_port`",nullable = false)
|
||||
@NotNull
|
||||
@ApiModelProperty(value = "Modbus 设备的端口号")
|
||||
private Integer devicePort;
|
||||
|
||||
@Column(name = "`device_description`")
|
||||
@ApiModelProperty(value = "Modbus 设备的详细描述信息,如设备用途、型号等")
|
||||
private String deviceDescription;
|
||||
|
||||
@Column(name = "`data_type`",nullable = false)
|
||||
@NotNull
|
||||
@ApiModelProperty(value = "Modbus 数据的类型")
|
||||
private String dataType;
|
||||
|
||||
@Column(name = "`start_address`",nullable = false)
|
||||
@NotNull
|
||||
@ApiModelProperty(value = "批量读取数据的起始地址")
|
||||
private Integer startAddress;
|
||||
|
||||
@Column(name = "`data_length`",nullable = false)
|
||||
@NotNull
|
||||
@ApiModelProperty(value = "批量读取的数据长度")
|
||||
private Integer dataLength;
|
||||
|
||||
@Column(name = "`data_values`")
|
||||
@ApiModelProperty(value = "批量读取的数据值集合,以特定格式存储,如逗号分隔的字符串")
|
||||
private String dataValues;
|
||||
|
||||
@Column(name = "`last_read_time`")
|
||||
@ApiModelProperty(value = "最后一次读取该数据的时间")
|
||||
private Timestamp lastReadTime;
|
||||
|
||||
@Column(name = "`last_modify_time`")
|
||||
@ApiModelProperty(value = "最后一次修改该数据的时间")
|
||||
private Timestamp lastModifyTime;
|
||||
|
||||
@Column(name = "`data_version`")
|
||||
@ApiModelProperty(value = "数据的版本号,每次数据修改时版本号递增,用于数据追溯")
|
||||
private Integer dataVersion;
|
||||
|
||||
@Column(name = "`data_status`")
|
||||
@ApiModelProperty(value = "数据的状态,normal 表示正常,abnormal 表示异常,warning 表示警告,maintenance 表示维护中")
|
||||
private String dataStatus;
|
||||
|
||||
@Column(name = "`alarm_status`")
|
||||
@ApiModelProperty(value = "是否触发报警,TRUE 表示触发,FALSE 表示未触发")
|
||||
private Integer alarmStatus;
|
||||
|
||||
@Column(name = "`is_connected`")
|
||||
@ApiModelProperty(value = "记录设备连接状态,TRUE 表示连接成功,FALSE 表示连接失败")
|
||||
private Integer isConnected;
|
||||
|
||||
@Column(name = "`max_retries`")
|
||||
@ApiModelProperty(value = "异常重试次数")
|
||||
private Integer maxRetries;
|
||||
|
||||
@Column(name = "`enabled`")
|
||||
@ApiModelProperty(value = "状态:1启用、0禁用")
|
||||
private Boolean enabled;
|
||||
|
||||
@Column(name = "`description`")
|
||||
@ApiModelProperty(value = "报错原因")
|
||||
private String description;
|
||||
|
||||
public void copy(ModbusInfo source){
|
||||
BeanUtil.copyProperties(source,this, CopyOptions.create().setIgnoreNullValue(true));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.youchain.jamod.repository;
|
||||
|
||||
import com.youchain.jamod.domain.ModbusInfo;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
|
||||
/**
|
||||
* @website https://eladmin.vip
|
||||
* @author huojin
|
||||
* @date 2025-03-21
|
||||
**/
|
||||
public interface ModbusInfoRepository extends JpaRepository<ModbusInfo, Integer>, JpaSpecificationExecutor<ModbusInfo> {
|
||||
}
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.youchain.jamod.rest;
|
||||
|
||||
import com.youchain.annotation.Log;
|
||||
import com.youchain.jamod.domain.ModbusInfo;
|
||||
import com.youchain.jamod.service.ModbusInfoService;
|
||||
import com.youchain.jamod.service.dto.ModbusInfoQueryCriteria;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @website https://eladmin.vip
|
||||
* @author huojin
|
||||
* @date 2025-03-21
|
||||
**/
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@Api(tags = "modbusInfo管理")
|
||||
@RequestMapping("/api/modbusInfo")
|
||||
public class ModbusInfoController {
|
||||
|
||||
private final ModbusInfoService modbusInfoService;
|
||||
|
||||
@Log("导出数据")
|
||||
@ApiOperation("导出数据")
|
||||
@GetMapping(value = "/download")
|
||||
@PreAuthorize("@el.check('modbusInfo:list')")
|
||||
public void exportModbusInfo(HttpServletResponse response, ModbusInfoQueryCriteria criteria) throws IOException {
|
||||
modbusInfoService.download(modbusInfoService.queryAll(criteria), response);
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
@Log("查询modbusInfo")
|
||||
@ApiOperation("查询modbusInfo")
|
||||
@PreAuthorize("@el.check('modbusInfo:list')")
|
||||
public ResponseEntity<Object> queryModbusInfo(ModbusInfoQueryCriteria criteria, Pageable pageable){
|
||||
return new ResponseEntity<>(modbusInfoService.queryAll(criteria,pageable),HttpStatus.OK);
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
@Log("新增modbusInfo")
|
||||
@ApiOperation("新增modbusInfo")
|
||||
@PreAuthorize("@el.check('modbusInfo:add')")
|
||||
public ResponseEntity<Object> createModbusInfo(@Validated @RequestBody ModbusInfo resources){
|
||||
return new ResponseEntity<>(modbusInfoService.create(resources),HttpStatus.CREATED);
|
||||
}
|
||||
|
||||
@PutMapping
|
||||
@Log("修改modbusInfo")
|
||||
@ApiOperation("修改modbusInfo")
|
||||
@PreAuthorize("@el.check('modbusInfo:edit')")
|
||||
public ResponseEntity<Object> updateModbusInfo(@Validated @RequestBody ModbusInfo resources){
|
||||
modbusInfoService.update(resources);
|
||||
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
|
||||
}
|
||||
|
||||
@DeleteMapping
|
||||
@Log("删除modbusInfo")
|
||||
@ApiOperation("删除modbusInfo")
|
||||
@PreAuthorize("@el.check('modbusInfo:del')")
|
||||
public ResponseEntity<Object> deleteModbusInfo(@RequestBody Integer[] ids) {
|
||||
modbusInfoService.deleteAll(ids);
|
||||
return new ResponseEntity<>(HttpStatus.OK);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.youchain.jamod.service;
|
||||
|
||||
import com.youchain.jamod.domain.ModbusInfo;
|
||||
import com.youchain.jamod.service.dto.ModbusInfoDto;
|
||||
import com.youchain.jamod.service.dto.ModbusInfoQueryCriteria;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @website https://eladmin.vip
|
||||
* @description 服务接口
|
||||
* @author huojin
|
||||
* @date 2025-03-21
|
||||
**/
|
||||
public interface ModbusInfoService {
|
||||
|
||||
/**
|
||||
* 查询数据分页
|
||||
* @param criteria 条件
|
||||
* @param pageable 分页参数
|
||||
* @return Map<String,Object>
|
||||
*/
|
||||
Map<String,Object> queryAll(ModbusInfoQueryCriteria criteria, Pageable pageable);
|
||||
|
||||
/**
|
||||
* 查询所有数据不分页
|
||||
* @param criteria 条件参数
|
||||
* @return List<ModbusInfoDto>
|
||||
*/
|
||||
List<ModbusInfoDto> queryAll(ModbusInfoQueryCriteria criteria);
|
||||
|
||||
/**
|
||||
* 根据ID查询
|
||||
* @param id ID
|
||||
* @return ModbusInfoDto
|
||||
*/
|
||||
ModbusInfoDto findById(Integer id);
|
||||
|
||||
/**
|
||||
* 创建
|
||||
* @param resources /
|
||||
* @return ModbusInfoDto
|
||||
*/
|
||||
ModbusInfoDto create(ModbusInfo resources);
|
||||
|
||||
/**
|
||||
* 编辑
|
||||
* @param resources /
|
||||
*/
|
||||
void update(ModbusInfo resources);
|
||||
|
||||
/**
|
||||
* 多选删除
|
||||
* @param ids /
|
||||
*/
|
||||
void deleteAll(Integer[] ids);
|
||||
|
||||
/**
|
||||
* 导出数据
|
||||
* @param all 待导出的数据
|
||||
* @param response /
|
||||
* @throws IOException /
|
||||
*/
|
||||
void download(List<ModbusInfoDto> all, HttpServletResponse response) throws IOException;
|
||||
}
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.youchain.jamod.service.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.sql.Timestamp;
|
||||
|
||||
/**
|
||||
* @website https://eladmin.vip
|
||||
* @description /
|
||||
* @author huojin
|
||||
* @date 2025-03-21
|
||||
**/
|
||||
@Data
|
||||
public class ModbusInfoDto implements Serializable {
|
||||
|
||||
/** 自增主键,唯一标识每条记录 */
|
||||
private Integer id;
|
||||
|
||||
/** Modbus 设备的名称,用于直观识别设备 */
|
||||
private String deviceName;
|
||||
|
||||
/** Modbus 设备的 IP 地址 */
|
||||
private String deviceIp;
|
||||
|
||||
/** Modbus 设备的端口号 */
|
||||
private Integer devicePort;
|
||||
|
||||
/** Modbus 设备的详细描述信息,如设备用途、型号等 */
|
||||
private String deviceDescription;
|
||||
|
||||
/** Modbus 数据的类型 */
|
||||
private String dataType;
|
||||
|
||||
/** 批量读取数据的起始地址 */
|
||||
private Integer startAddress;
|
||||
|
||||
/** 批量读取的数据长度 */
|
||||
private Integer dataLength;
|
||||
|
||||
/** 批量读取的数据值集合,以特定格式存储,如逗号分隔的字符串 */
|
||||
private String dataValues;
|
||||
|
||||
/** 最后一次读取该数据的时间 */
|
||||
private Timestamp lastReadTime;
|
||||
|
||||
/** 最后一次修改该数据的时间 */
|
||||
private Timestamp lastModifyTime;
|
||||
|
||||
/** 数据的版本号,每次数据修改时版本号递增,用于数据追溯 */
|
||||
private Integer dataVersion;
|
||||
|
||||
/** 数据的状态,normal 表示正常,abnormal 表示异常,warning 表示警告,maintenance 表示维护中 */
|
||||
private String dataStatus;
|
||||
|
||||
/** 是否触发报警,TRUE 表示触发,FALSE 表示未触发 */
|
||||
private Integer alarmStatus;
|
||||
|
||||
/** 记录设备连接状态,TRUE 表示连接成功,FALSE 表示连接失败 */
|
||||
private Integer isConnected;
|
||||
|
||||
/** 异常重试次数 */
|
||||
private Integer maxRetries;
|
||||
|
||||
/** 状态:1启用、0禁用 */
|
||||
private Boolean enabled;
|
||||
|
||||
/** 报错原因 */
|
||||
private String description;
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.youchain.jamod.service.dto;
|
||||
|
||||
import com.youchain.annotation.Query;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @website https://eladmin.vip
|
||||
* @author huojin
|
||||
* @date 2025-03-21
|
||||
**/
|
||||
@Data
|
||||
public class ModbusInfoQueryCriteria{
|
||||
|
||||
/** 模糊 */
|
||||
@Query(type = Query.Type.INNER_LIKE)
|
||||
private String deviceName;
|
||||
|
||||
/** 模糊 */
|
||||
@Query(type = Query.Type.INNER_LIKE)
|
||||
private String deviceIp;
|
||||
}
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.youchain.jamod.service.impl;
|
||||
|
||||
import com.youchain.jamod.domain.ModbusInfo;
|
||||
import com.youchain.jamod.repository.ModbusInfoRepository;
|
||||
import com.youchain.jamod.service.ModbusInfoService;
|
||||
import com.youchain.jamod.service.dto.ModbusInfoDto;
|
||||
import com.youchain.jamod.service.dto.ModbusInfoQueryCriteria;
|
||||
import com.youchain.jamod.service.mapstruct.ModbusInfoMapper;
|
||||
import com.youchain.utils.FileUtil;
|
||||
import com.youchain.utils.PageUtil;
|
||||
import com.youchain.utils.QueryHelp;
|
||||
import com.youchain.utils.ValidationUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @website https://eladmin.vip
|
||||
* @description 服务实现
|
||||
* @author huojin
|
||||
* @date 2025-03-21
|
||||
**/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class ModbusInfoServiceImpl implements ModbusInfoService {
|
||||
|
||||
private final ModbusInfoRepository modbusInfoRepository;
|
||||
private final ModbusInfoMapper modbusInfoMapper;
|
||||
|
||||
@Override
|
||||
public Map<String,Object> queryAll(ModbusInfoQueryCriteria criteria, Pageable pageable){
|
||||
Page<ModbusInfo> page = modbusInfoRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable);
|
||||
return PageUtil.toPage(page.map(modbusInfoMapper::toDto));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ModbusInfoDto> queryAll(ModbusInfoQueryCriteria criteria){
|
||||
return modbusInfoMapper.toDto(modbusInfoRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder)));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public ModbusInfoDto findById(Integer id) {
|
||||
ModbusInfo modbusInfo = modbusInfoRepository.findById(id).orElseGet(ModbusInfo::new);
|
||||
ValidationUtil.isNull(modbusInfo.getId(),"ModbusInfo","id",id);
|
||||
return modbusInfoMapper.toDto(modbusInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public ModbusInfoDto create(ModbusInfo resources) {
|
||||
return modbusInfoMapper.toDto(modbusInfoRepository.save(resources));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void update(ModbusInfo resources) {
|
||||
ModbusInfo modbusInfo = modbusInfoRepository.findById(resources.getId()).orElseGet(ModbusInfo::new);
|
||||
ValidationUtil.isNull( modbusInfo.getId(),"ModbusInfo","id",resources.getId());
|
||||
modbusInfo.copy(resources);
|
||||
modbusInfoRepository.save(modbusInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteAll(Integer[] ids) {
|
||||
for (Integer id : ids) {
|
||||
modbusInfoRepository.deleteById(id);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void download(List<ModbusInfoDto> all, HttpServletResponse response) throws IOException {
|
||||
List<Map<String, Object>> list = new ArrayList<>();
|
||||
for (ModbusInfoDto modbusInfo : all) {
|
||||
Map<String,Object> map = new LinkedHashMap<>();
|
||||
map.put("Modbus 设备的名称,用于直观识别设备", modbusInfo.getDeviceName());
|
||||
map.put("Modbus 设备的 IP 地址", modbusInfo.getDeviceIp());
|
||||
map.put("Modbus 设备的端口号", modbusInfo.getDevicePort());
|
||||
map.put("Modbus 设备的详细描述信息,如设备用途、型号等", modbusInfo.getDeviceDescription());
|
||||
map.put("Modbus 数据的类型", modbusInfo.getDataType());
|
||||
map.put("批量读取数据的起始地址", modbusInfo.getStartAddress());
|
||||
map.put("批量读取的数据长度", modbusInfo.getDataLength());
|
||||
map.put("批量读取的数据值集合,以特定格式存储,如逗号分隔的字符串", modbusInfo.getDataValues());
|
||||
map.put("最后一次读取该数据的时间", modbusInfo.getLastReadTime());
|
||||
map.put("最后一次修改该数据的时间", modbusInfo.getLastModifyTime());
|
||||
map.put("数据的版本号,每次数据修改时版本号递增,用于数据追溯", modbusInfo.getDataVersion());
|
||||
map.put("数据的状态,normal 表示正常,abnormal 表示异常,warning 表示警告,maintenance 表示维护中", modbusInfo.getDataStatus());
|
||||
map.put("是否触发报警,TRUE 表示触发,FALSE 表示未触发", modbusInfo.getAlarmStatus());
|
||||
map.put("记录设备连接状态,TRUE 表示连接成功,FALSE 表示连接失败", modbusInfo.getIsConnected());
|
||||
map.put("异常重试次数", modbusInfo.getMaxRetries());
|
||||
map.put("状态:1启用、0禁用", modbusInfo.getEnabled());
|
||||
map.put("报错原因", modbusInfo.getDescription());
|
||||
list.add(map);
|
||||
}
|
||||
FileUtil.downloadExcel(list, response);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.youchain.jamod.service.mapstruct;
|
||||
|
||||
import com.youchain.base.BaseMapper;
|
||||
import com.youchain.jamod.domain.ModbusInfo;
|
||||
import com.youchain.jamod.service.dto.ModbusInfoDto;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.ReportingPolicy;
|
||||
|
||||
/**
|
||||
* @website https://eladmin.vip
|
||||
* @author huojin
|
||||
* @date 2025-03-21
|
||||
**/
|
||||
@Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE)
|
||||
public interface ModbusInfoMapper extends BaseMapper<ModbusInfoDto, ModbusInfo> {
|
||||
|
||||
}
|
||||
|
|
@ -14,13 +14,9 @@ spring:
|
|||
druid:
|
||||
db-type: com.alibaba.druid.pool.DruidDataSource
|
||||
driverClassName: net.sf.log4jdbc.sql.jdbcapi.DriverSpy
|
||||
# url: jdbc:log4jdbc:mysql://${DB_HOST:47.100.54.81}:${DB_PORT:53306}/${DB_NAME:hefeihvac_wms}?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false
|
||||
url: jdbc:log4jdbc:mysql://${DB_HOST:localhost}:${DB_PORT:3306}/${DB_NAME:hefeihvac_wms}?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false
|
||||
# url: jdbc:log4jdbc:mysql://${DB_HOST:10.175.163.49}:${DB_PORT:3306}/${DB_NAME:hefeihvac_wms}?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false
|
||||
# url: jdbc:log4jdbc:mysql://${DB_HOST:10.173.188.206}:${DB_PORT:53306}/${DB_NAME:wms}?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false
|
||||
url: jdbc:log4jdbc:mysql://${DB_HOST:47.103.100.52}:${DB_PORT:53306}/${DB_NAME:hefeihvac_wms}?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false
|
||||
username: ${DB_USER:root}
|
||||
# password: ${DB_PWD:Youchain@56}
|
||||
password: ${DB_PWD:123456}
|
||||
password: ${DB_PWD:Youchain@56}
|
||||
# 初始连接数
|
||||
initial-size: 5
|
||||
# 最小连接数
|
||||
|
|
|
|||
Loading…
Reference in New Issue