no message

main
暴炳林 2025-04-15 14:38:27 +08:00
parent 36a3e4f24e
commit edade7cc3c
25 changed files with 1914 additions and 9 deletions

View File

@ -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));

View File

@ -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>

View File

@ -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 配置。";
}
}

View File

@ -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);
}
}

View File

@ -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")

View File

@ -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));
}
}

View File

@ -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> {
}

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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> {
}

View File

@ -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());
}
}

View File

@ -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));
}
}

View File

@ -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> {
}

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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> {
}

View File

@ -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
# 最小连接数