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