package com.zehong.system.modbus.util;

import com.serotonin.modbus4j.BatchRead;
import com.serotonin.modbus4j.BatchResults;
import com.serotonin.modbus4j.ModbusFactory;
import com.serotonin.modbus4j.ModbusMaster;
import com.serotonin.modbus4j.code.DataType;
import com.serotonin.modbus4j.exception.ErrorResponseException;
import com.serotonin.modbus4j.exception.ModbusInitException;
import com.serotonin.modbus4j.exception.ModbusTransportException;
import com.serotonin.modbus4j.ip.IpParameters;
import com.serotonin.modbus4j.locator.BaseLocator;
import com.serotonin.modbus4j.msg.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * modbus通讯工具类,采用modbus4j实现
 *
 */
@SuppressWarnings(value = "all")
public class Modbus4jUtils {

    private static final Logger log = LoggerFactory.getLogger(Modbus4jUtils.class);

    private static ModbusMaster master;

    private static final int START_ADDRESS = 0;  // 对应40001
    private static final int REGISTER_COUNT = 10; // 读取10个寄存器
    private static final int TARGET_VALUE = 1;   // 目标值（第二个寄存器的期望值）
    private static final int MAX_RETRIES = 3;    // 最大重试次数
    private static final int RETRY_DELAY = 500;  // 重试延迟(ms)// 监控参数
    private static final int MONITOR_INTERVAL = 5000; // 监控间隔(ms)

    // 监控控制标志
    private static final AtomicBoolean monitoring = new AtomicBoolean(false);

    /**
     * 工厂。
     */
    static ModbusFactory modbusFactory;
    static {
        if (modbusFactory == null) {
            modbusFactory = new ModbusFactory();
        }
    }

    /**
     * 获取master
     *
     * @return master
     * @throws ModbusInitException m
     */
    public static ModbusMaster getMaster() throws ModbusInitException {
        IpParameters params = new IpParameters();
        params.setHost("192.168.2.11");
        params.setPort(502);
        //
        // modbusFactory.createRtuMaster(wapper); //RTU 协议
        // modbusFactory.createUdpMaster(params);//UDP 协议
        // modbusFactory.createAsciiMaster(wrapper);//ASCII 协议
        if(master == null || !master.isConnected()) {
            master = modbusFactory.createTcpMaster(params, true);// TCP 协议
            master.setTimeout(5000); // 设置超时时间
            master.setRetries(3);    // 设置重试次数
            master.init();
        }

        return master;
    }

    /**
     * 动态获取 modubus master
     * @param ip ip
     * @param port port
     * @return r
     * @throws ModbusInitException m
     */
    public static ModbusMaster getMaster(String ip, int port) throws ModbusInitException {
        IpParameters params = new IpParameters();
        params.setHost(ip);
        params.setPort(port);
        ModbusMaster master = modbusFactory.createTcpMaster(params, false);// TCP 协议
        master.setTimeout(3000); // 设置超时时间
        master.setRetries(3);    // 设置重试次数
        master.init();
        return master;
    }

    /**
     * 读取[01 Coil Status 0x]类型 开关数据
     *
     * @param slaveId
     *            slaveId
     * @param offset
     *            位置
     * @return 读取值
     * @throws ModbusTransportException
     *             异常
     * @throws ErrorResponseException
     *             异常
     * @throws ModbusInitException
     *             异常
     */
    public static Boolean readCoilStatus(int slaveId, int offset)
            throws ModbusTransportException, ErrorResponseException, ModbusInitException {
        // 01 Coil Status
        BaseLocator<Boolean> loc = BaseLocator.coilStatus(slaveId, offset);
        Boolean value = getMaster().getValue(loc);
        return value;
    }

    /**
     * 读一下 开关数据
     * @param master
     * @param slaveId
     * @param offset
     * @return
     * @throws ModbusTransportException
     * @throws ErrorResponseException
     * @throws ModbusInitException
     */
    public static Boolean readCoilStatus(ModbusMaster master, int slaveId, int offset)
            throws ModbusTransportException, ErrorResponseException, ModbusInitException {
        // 01 Coil Status
        BaseLocator<Boolean> loc = BaseLocator.coilStatus(slaveId, offset);
        Boolean value = master.getValue(loc);
        return value;
    }

    /**
     * 读取[02 Input Status 1x]类型 开关数据
     *
     * @param slaveId
     * @param offset
     * @return
     * @throws ModbusTransportException
     * @throws ErrorResponseException
     * @throws ModbusInitException
     */
    public static Boolean readInputStatus(int slaveId, int offset)
            throws ModbusTransportException, ErrorResponseException, ModbusInitException {
        // 02 Input Status
        BaseLocator<Boolean> loc = BaseLocator.inputStatus(slaveId, offset);
        Boolean value = getMaster().getValue(loc);
        return value;
    }

    /**
     * 读取[02 Input Status 1x]类型 开关数据
     *
     * @param slaveId
     * @param offset
     * @return
     * @throws ModbusTransportException
     * @throws ErrorResponseException
     * @throws ModbusInitException
     */
    public static Boolean readInputStatus(ModbusMaster master,int slaveId, int offset)
            throws ModbusTransportException, ErrorResponseException, ModbusInitException {
        // 02 Input Status
        BaseLocator<Boolean> loc = BaseLocator.inputStatus(slaveId, offset);
        Boolean value = master.getValue(loc);
        return value;
    }

    /**
     * 机械臂入口传送带 0位置是 投入点，1位置是 末尾点
     * @param slaveId
     * @param registerOffsets
     * @return
     * @throws ModbusTransportException
     * @throws ErrorResponseException
     */
    public static boolean[] getRoboticArmEntryConveyorData(){

        ModbusMaster master = null;
        try {
            master = getMaster("192.168.2.11", 502);
            boolean[] booleans = readDiscreteInputs(master, 1, 0, 2);

            if(master != null) {
                master.destroy();
            }

            return booleans;
        } catch (ModbusTransportException | ModbusInitException e) {
            return  new boolean[]{false, false}; // 示例数据
        } finally {
            if(master != null) {
                master.destroy();
            }
        }
    }

    /**
     * 机械臂出库传送带 0位置是 投入点，1位置是 末尾点
     * @param slaveId
     * @param registerOffsets
     * @return
     * @throws ModbusTransportException
     * @throws ErrorResponseException
     */
    public static boolean[] getRoboticArmExitConveyorData() {
        ModbusMaster master = null;
        try {
            master = getMaster("192.168.2.12", 502);
            boolean[] booleans = readDiscreteInputs(master, 1, 0, 2);

            if(master != null) {
                master.destroy();
            }

            return booleans;
        } catch (ModbusTransportException | ModbusInitException e) {
            return  new boolean[]{false, false}; // 示例数据
        } finally {
            if(master != null) {
                master.destroy();
            }
        }
    }

    /**
     * 读取离散输入（功能码02）的兼容方法
     * 使用ReadDiscreteInputsRequest/Response，适配更多版本
     */
    private static boolean[] readDiscreteInputs(ModbusMaster master, int slaveId,
                                                int startAddress, int count) throws ModbusTransportException {
        // 创建功能码02对应的请求（ReadDiscreteInputsRequest）
        ModbusRequest request = new ReadDiscreteInputsRequest(slaveId, startAddress, count);

        // 发送请求并获取响应
        ModbusResponse response = master.send(request);

        // 转换为具体的响应类型
        if (response instanceof ReadDiscreteInputsResponse) {
            ReadDiscreteInputsResponse discreteResponse = (ReadDiscreteInputsResponse) response;
            return discreteResponse.getBooleanData();
        } else {
            throw new ModbusTransportException("无效的响应类型: " + response.getClass().getSimpleName());
        }
    }
    /**
     * 读取[03 Holding Register类型 2x]模拟量数据
     *
     * @param slaveId
     *            slave Id
     * @param offset
     *            位置
     * @param dataType
     *            数据类型,来自com.serotonin.modbus4j.code.DataType
     * @return
     * @throws ModbusTransportException
     *             异常
     * @throws ErrorResponseException
     *             异常
     * @throws ModbusInitException
     *             异常
     */
    public static Number readHoldingRegister(int slaveId, int offset, int dataType)
            throws ModbusTransportException, ErrorResponseException, ModbusInitException {
        // 03 Holding Register类型数据读取
        BaseLocator<Number> loc = BaseLocator.holdingRegister(slaveId, offset, dataType);
        Number value = getMaster().getValue(loc);
        return value;
    }

    /**
     * 读取[04 Input Registers 3x]类型 模拟量数据
     *
     * @param slaveId
     *            slaveId
     * @param offset
     *            位置
     * @param dataType
     *            数据类型,来自com.serotonin.modbus4j.code.DataType
     * @return 返回结果
     * @throws ModbusTransportException
     *             异常
     * @throws ErrorResponseException
     *             异常
     * @throws ModbusInitException
     *             异常
     */
    public static Number readInputRegisters(int slaveId, int offset, int dataType)
            throws ModbusTransportException, ErrorResponseException, ModbusInitException {
        // 04 Input Registers类型数据读取
        BaseLocator<Number> loc = BaseLocator.inputRegister(slaveId, offset, dataType);
        Number value = getMaster().getValue(loc);
        return value;
    }

    /**
     *
     * @param master
     * @param slaveId
     * @param offset
     * @param length
     * @return
     * @throws ModbusTransportException
     * @throws ErrorResponseException
     * @throws ModbusInitException
     */
    /**
     * 读取[04 Input Registers 3x]类型 模拟量数据
     *
     * @param master
     *          master
     * @param slaveId
     *            slaveId
     * @param offset
     *            位置
     * @param dataType
     *            数据类型,来自com.serotonin.modbus4j.code.DataType
     * @return 返回结果
     * @throws ModbusTransportException
     *             异常
     * @throws ErrorResponseException
     *             异常
     * @throws ModbusInitException
     *             异常
     */
    public static Number readInputRegisters(ModbusMaster master,int slaveId, int offset, int dataType)
            throws ModbusTransportException, ErrorResponseException, ModbusInitException {
        // 04 Input Registers类型数据读取
        BaseLocator<Number> loc = BaseLocator.inputRegister(slaveId, offset, dataType);
        Number value = master.getValue(loc);
        return value;
    }

    /**
     * 读老化柜的 10层数据
     * @param master
     * @return
     * @throws ModbusTransportException
     * @throws ErrorResponseException
     * @throws ModbusInitException
     */
    public static Map<Integer, Object>  readInputRegistersForAgeng(ModbusMaster master)
            throws ModbusTransportException, ErrorResponseException {
        // 10 层
        List<Integer> registerOffsets = Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
        Map<Integer, Object> result = new HashMap<>();
        for (Integer registerOffset : registerOffsets) {
            // 04 Input Registers类型数据读取
            BaseLocator<Number> loc = BaseLocator.inputRegister(1, registerOffset, DataType.TWO_BYTE_INT_UNSIGNED);
            Number value = master.getValue(loc);
            result.put(registerOffset, value);
        }
        return result;
    }

    /**
     * 批量读取使用方法
     *
     * @throws ModbusTransportException m
     * @throws ErrorResponseException e
     * @throws ModbusInitException m
     */
    public static void batchRead() throws ModbusTransportException, ErrorResponseException, ModbusInitException {

        BatchRead<Integer> batch = new BatchRead<Integer>();

        batch.addLocator(0, BaseLocator.holdingRegister(1, 1, DataType.FOUR_BYTE_FLOAT));
        batch.addLocator(1, BaseLocator.inputStatus(1, 0));

        ModbusMaster master = getMaster();

        batch.setContiguousRequests(false);
        BatchResults<Integer> results = master.send(batch);
        System.out.println(results.getValue(0));
        System.out.println(results.getValue(1));
    }

    public static Map<Integer,Object> batchReadHoldingRegister(ModbusMaster master,List<Integer> registerOffsets) throws ModbusTransportException, ErrorResponseException {
        BatchRead<Integer> batch = new BatchRead<Integer>();
        for (Integer registerOffset : registerOffsets) {
            batch.addLocator(registerOffset, BaseLocator.holdingRegister(1, registerOffset,DataType.EIGHT_BYTE_INT_UNSIGNED));
        }

        // 非连续地址也支持
        batch.setContiguousRequests(true);

        BatchResults<Integer> send = master.send(batch);
//
        Map<Integer, Object> result = new HashMap<>();
        for (Integer registerOffset : registerOffsets) {
            result.put(registerOffset, send.getValue(registerOffset));
        }
        return result;
    }


    /**
     * 批量读取使用方法
     *
     * @throws ModbusTransportException m
     * @throws ErrorResponseException e
     * @throws ModbusInitException m
     */
    public static Map<Integer, Object> batchReadAgingCabinetStatus(ModbusMaster master, List<Integer> registerOffsets) throws ModbusInitException, ModbusTransportException, ErrorResponseException {

        // 把设备集成到一个交换机上后 这个批量读取 不管用了。。
//        BatchRead<Integer> batch = new BatchRead<Integer>();
//        for (Integer registerOffset : registerOffsets) {
//            batch.addLocator(registerOffset, BaseLocator.inputStatus(1, registerOffset));
//        }
//
//        // 非连续地址也支持
//        batch.setContiguousRequests(true);
//
//        BatchResults<Integer> send = master.send(batch);
//        Map<Integer, Object> result = new HashMap<>();
//        for (Integer registerOffset : registerOffsets) {
//            result.put(registerOffset, send.getValue(registerOffset));
//        }
//        return result;

        Map<Integer, Object> result = new HashMap<>();
        for (Integer registerOffset : registerOffsets) {
            Boolean aBoolean = Modbus4jUtils.readCoilStatus(master, 1, registerOffset);
            result.put(registerOffset, aBoolean);
        }
        return result;
    }

    /**
     * 读取保持寄存器（16位无符号整数）
     *
     * @param slaveId  从站ID
     * @param offset   寄存器起始地址（0-based）
     * @param count    读取的寄存器数量
     * @return 无符号整数值数组
     * 请求格式解析：
     * 00 00 - 事务ID (0)
     * 00 00 - 协议ID (0)
     * 00 06 - 长度 (6字节)
     * 01 - 从站ID (1)
     * 03 - 功能码 (读保持寄存器)
     * 00 03 - 起始地址 (3)
     * 00 0A - 寄存器数量 (10)
     * 响应格式解析：
     * 00 00 00 00 00 17 - Modbus TCP头
     * 01 - 从站ID
     * 03 - 功能码
     * 14 - 数据字节数 (20字节 = 10寄存器 × 2字节)
     * 后续20字节为10个寄存器的数据
     * 关键处理逻辑：
     * 16位无符号转换：register.getValue() & 0xFFFF
     * 寄存器地址处理：modbus4j使用0-based地址，所以地址3对应设备手册中的40004寄存器
     * TCP连接管理：使用长连接提高效率
     */
    public static int[] readHoldingRegisters(int slaveId, int offset, int count)
            throws ModbusTransportException, ErrorResponseException {

        // 创建读取请求
        ReadHoldingRegistersRequest request = new ReadHoldingRegistersRequest(
                slaveId, offset, count
        );

        // 发送请求并获取响应
        ModbusResponse response = master.send(request);

        // 检查响应类型
        if (!(response instanceof ReadHoldingRegistersResponse)) {
            throw new IllegalArgumentException("Invalid response type: " + response.getClass().getName());
        }

        // 获取寄存器列表
        ReadHoldingRegistersResponse regResponse = (ReadHoldingRegistersResponse) response;
        short[] signedValues = regResponse.getShortData();
        // 转换为无符号整数
        int[] results = new int[signedValues.length];
        // 转为无符号整数并打印
        for (int i = 0; i < signedValues.length; i++) {
            int unsignedValue = signedValues[i] & 0xFFFF;
            results[i] = signedValues[i] & 0xFFFF;
            System.out.printf("寄存器 %d: %d (无符号) %n", i, unsignedValue);
        }
        return results;
    }

    /**
     * 写 [01 Coil Status(0x)]写一个 function ID = 5
     *
     * @param slaveId
     *            slave的ID
     * @param writeOffset
     *            位置
     * @param writeValue
     *            值
     * @return 是否写入成功
     * @throws ModbusTransportException m
     * @throws ModbusInitException m
     */
    public static boolean writeCoil(int slaveId, int writeOffset, boolean writeValue)
            throws ModbusTransportException, ModbusInitException {
        // 获取master
        ModbusMaster tcpMaster = getMaster();
        // 创建请求
        WriteCoilRequest request = new WriteCoilRequest(slaveId, writeOffset, writeValue);
        // 发送请求并获取响应对象
        WriteCoilResponse response = (WriteCoilResponse) tcpMaster.send(request);
        if (response.isException()) {
            return false;
        } else {
            return true;
        }
    }

    /**
     * 写[01 Coil Status(0x)] 写一个 function ID = 5
     * @param master
     * @param slaveId
     * @param writeOffset
     * @param writeValue
     * @return
     * @throws ModbusTransportException
     */
    public static boolean writeCoil(ModbusMaster master, int slaveId, int writeOffset, boolean writeValue) throws ModbusTransportException {
        // 创建请求
        WriteCoilRequest request = new WriteCoilRequest(slaveId, writeOffset, writeValue);
        // 发送请求并获取响应对象
        WriteCoilResponse response = (WriteCoilResponse) master.send(request);
        if (response.isException()) {
            return false;
        } else {
            return true;
        }
    }

    /**
     * 写[01 Coil Status(0x)] 写多个 function ID = 15
     *
     * @param slaveId
     *            slaveId
     * @param startOffset
     *            开始位置
     * @param bdata
     *            写入的数据
     * @return 是否写入成功
     * @throws ModbusTransportException m
     * @throws ModbusInitException m
     */
    public static boolean writeCoils(int slaveId, int startOffset, boolean[] bdata)
            throws ModbusTransportException, ModbusInitException {
        // 获取master
        ModbusMaster tcpMaster = getMaster();
        // 创建请求
        WriteCoilsRequest request = new WriteCoilsRequest(slaveId, startOffset, bdata);
        // 发送请求并获取响应对象
        WriteCoilsResponse response = (WriteCoilsResponse) tcpMaster.send(request);
        if (response.isException()) {
            return false;
        } else {
            return true;
        }

    }
    /**
     * 写入单个 Holding Register（功能码 6）
     *
     * @param slaveId     从站ID
     * @param writeOffset 寄存器偏移地址（如 0 表示地址 40001）
     * @param writeValue  要写入的值（short 类型）
     * @return 是否写入成功
     * @throws ModbusTransportException 如果传输失败
     * @throws ModbusInitException      如果初始化失败
     */
    public static boolean writeRegister(ModbusMaster master ,int slaveId, int writeOffset, short writeValue)
            throws ModbusTransportException, ModbusInitException {

        WriteRegisterRequest request = new WriteRegisterRequest(slaveId, writeOffset, writeValue);

        log.info("发送写入请求：从站={}, 地址={}, 值={}", slaveId, writeOffset, writeValue);

        WriteRegisterResponse response = null;
        synchronized (master) { // 多线程下保护主站资源
            response = (WriteRegisterResponse) master.send(request);
        }

        if (response == null) {
            log.error("未收到 Modbus 响应");
            return false;
        }

        if (response.isException()) {
            log.error("Modbus 异常响应: {}", response.getExceptionMessage());
            return false;
        }

        log.info("写入成功，响应确认");
        return true;
    }
    /**
     * 写入单个 Holding Register（功能码 6）
     *
     * @param slaveId     从站ID
     * @param writeOffset 寄存器偏移地址（如 0 表示地址 40001）
     * @param writeValue  要写入的值（short 类型）
     * @return 是否写入成功
     * @throws ModbusTransportException 如果传输失败
     * @throws ModbusInitException      如果初始化失败
     */
    public static boolean writeRegister(int slaveId, int writeOffset, short writeValue)
            throws ModbusTransportException, ModbusInitException {
        ModbusMaster master = getMaster();

        WriteRegisterRequest request = new WriteRegisterRequest(slaveId, writeOffset, writeValue);

        log.info("发送写入请求：从站={}, 地址={}, 值={}", slaveId, writeOffset, writeValue);

        WriteRegisterResponse response = null;
        synchronized (master) { // 多线程下保护主站资源
            response = (WriteRegisterResponse) master.send(request);
        }

        if (response == null) {
            log.error("未收到 Modbus 响应");
            return false;
        }

        if (response.isException()) {
            log.error("Modbus 异常响应: {}", response.getExceptionMessage());
            return false;
        }

        log.info("写入成功，响应确认");
        return true;
    }
    /***
     * 写[03 Holding Register(4x)] 写一个 function ID = 6
     *
     * @param slaveId s
     * @param writeOffset w
     * @param writeValue w
     * @return
     * @throws ModbusTransportException m
     * @throws ModbusInitException m
     */
//    public static boolean writeRegister(int slaveId, int writeOffset, short writeValue)
//            throws ModbusTransportException, ModbusInitException {
//        // 获取master
//        ModbusMaster tcpMaster = getMaster();
//        // 创建请求对象
//        WriteRegisterRequest request = new WriteRegisterRequest(slaveId, writeOffset, writeValue);
//        WriteRegisterResponse response = (WriteRegisterResponse) tcpMaster.send(request);
//        if (response.isException()) {
//            log.error(response.getExceptionMessage());
//            return false;
//        } else {
//            return true;
//        }
//
//    }

    /**
     *
     * 写入[03 Holding Register(4x)]写多个 function ID=16
     *
     * @param slaveId
     *            modbus的slaveID
     * @param startOffset
     *            起始位置偏移量值
     * @param sdata
     *            写入的数据
     * @return 返回是否写入成功
     * @throws ModbusTransportException m
     * @throws ModbusInitException m
     */
    public static boolean writeRegisters(int slaveId, int startOffset, short[] sdata)
            throws ModbusTransportException, ModbusInitException {
        // 获取master
        ModbusMaster tcpMaster = getMaster();
        // 创建请求对象
        WriteRegistersRequest request = new WriteRegistersRequest(slaveId, startOffset, sdata);
        // 发送请求并获取响应对象
        ModbusResponse response = tcpMaster.send(request);
        if (response.isException()) {
            log.error(response.getExceptionMessage());
            return false;
        } else {
            return true;
        }
    }



    /**
     * 写入数字类型的模拟量（如:写入Float类型的模拟量、Double类型模拟量、整数类型Short、Integer、Long）
     *
     * @param slaveId s
     * @param offset o
     * @param value
     *            写入值,Number的子类,例如写入Float浮点类型,Double双精度类型,以及整型short,int,long
     * @param dataType r
     *            ,com.serotonin.modbus4j.code.DataType
     * @throws ModbusTransportException m
     * @throws ErrorResponseException e
     * @throws ModbusInitException m
     */
    public static void writeHoldingRegister(int slaveId, int offset, Number value, int dataType)
            throws ModbusTransportException, ErrorResponseException, ModbusInitException {
        // 获取master
        ModbusMaster tcpMaster = getMaster();
        // 类型
        BaseLocator<Number> locator = BaseLocator.holdingRegister(slaveId, offset, dataType);
        tcpMaster.setValue(locator, value);
    }

    /**
     * 关闭Modbus连接
     */
    public static void destroyMaster() {
        if (master != null) {
            master.destroy();
            System.out.println("Modbus连接已关闭");
            master = null;
        }
    }

    /**
     * 获取读取Holding Register请求对象
     *
     * @param slaveId
     * @param offset
     * @param count
     * @return
     * @throws ModbusTransportException
     */
    public static ReadHoldingRegistersRequest getReadHoldingRegistersRequest(int slaveId, int offset, int count) throws ModbusTransportException {
        return new ReadHoldingRegistersRequest(slaveId, offset, count);
    }
    /**
     * 读取设备寄存器（线程安全版）
     */
    private static int[] readDeviceRegisters(int deviceId )
            throws ModbusTransportException, ModbusInitException {

        ModbusMaster master = getMaster();
        // 创建读取请求
        ReadHoldingRegistersRequest request = Modbus4jUtils.getReadHoldingRegistersRequest(deviceId,START_ADDRESS, REGISTER_COUNT);

        // 发送请求并获取响应
        ModbusResponse response = master.send(request);

        // 检查响应类型
        if (!(response instanceof ReadHoldingRegistersResponse)) {
            throw new IllegalArgumentException("Invalid response type: " + response.getClass().getName());
        }

        ReadHoldingRegistersResponse regResponse = (ReadHoldingRegistersResponse) response;
        short[] signedValues = regResponse.getShortData();

        // 转换为无符号整数
        int[] unsignedValues = new int[signedValues.length];
        for (int i = 0; i < signedValues.length; i++) {
            unsignedValues[i] = signedValues[i] & 0xFFFF;
        }

        return unsignedValues;
    }



    /**
     * 测试
     *
     * @param args a
     */
    public static void main(String[] args) {
        ModbusMaster modbusMaster = null;
        try {
            /* 5.写入时间，年、月、日、时、分 */
            // 示例：000100000006 设备地址01写时间06 寄存器地址0004（年04月05日06时07分08） 年/月/日/时/分数值07E9（2025）
//            Calendar cal = Calendar.getInstance();
//            // 当前年
//            int y = cal.get(Calendar.YEAR);
//            // 当前月
//            int m = cal.get(Calendar.MONTH) + 1;
//            // 当前日
//            int d = cal.get(Calendar.DATE);
//            // 当前小时
//            int h = cal.get(Calendar.HOUR_OF_DAY);
//            // 当前分钟
//            int mm = cal.get(Calendar.MINUTE);
//
//            boolean yearResult = writeRegister(1, 4, (short) y);
//            System.out.println(yearResult ? "写入成功" : "写入失败");
//            boolean mResult = writeRegister(1, 5, (short) m);
//            System.out.println(mResult ? "写入成功" : "写入失败");
//            boolean dResult = writeRegister(1, 6, (short) d);
//            System.out.println(dResult ? "写入成功" : "写入失败");
//            boolean hResult = writeRegister(1, 7, (short) h);
//            System.out.println(hResult ? "写入成功" : "写入失败");
//            boolean mmResult = writeRegister(1, 8, (short) mm);
//            System.out.println(mmResult ? "写入成功" : "写入失败");
//
//            int[] ints = readDeviceRegisters(1);
//            for (int i = 0; i < ints.length; i++) {
//                System.out.println(ints[i]);
//            }


////             01测试
//            modbusMaster = getMaster("192.168.2.12", 502);
//            这种方式 优势
//            Boolean aBoolean1 = Modbus4jUtils.readInputStatus(modbusMaster,1, 0);
//            Boolean aBoolean2 = Modbus4jUtils.readInputStatus(modbusMaster,1, 1);
//            System.out.println("aBoolean1 = " + aBoolean1);
//            System.out.println("aBoolean2 = " + aBoolean2);
//            System.out.println("v012:" + v012);
//            System.out.println("v013:" + v013);
//            // 02测试
//            Boolean v021 = readInputStatus(1, 0);
//            Boolean v022 = readInputStatus(1, 1);
//            System.out.println("v021:" + v021);
//            System.out.println("v022:" + v022);
//            int[] result = readDeviceRegisters(getMaster(),1);
//            master.destroy();
//            System.out.println("v023:" + v023);
//
////             03测试
//            Number v031 = readHoldingRegister(1, 0, DataType.FOUR_BYTE_FLOAT);// 注意,float
//            Number v032 = readHoldingRegister(1, 1, DataType.FOUR_BYTE_FLOAT);// 同上
//            System.out.println("v031:" + v031);
//            System.out.println("v032:" + v032);
//
//            // 04测试
//            Number v041 = readInputRegisters(1, 0, DataType.FOUR_BYTE_FLOAT);
//            Number v042 = readInputRegisters(1, 2, DataType.FOUR_BYTE_FLOAT);
//            System.out.println("v041:" + v041);
//            System.out.println("v042:" + v042);
//            // 批量读取
//            batchRead();

            modbusMaster = getMaster("192.168.2.11", 502);
            boolean[] booleans = readDiscreteInputs(modbusMaster, 1, 0, 2);

            // 输出结果
            for (int i = 0; i < booleans.length; i++) {
                System.out.println("离散输入 " + (0 + i) + ": " + booleans[i]);
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {

            if (modbusMaster != null) {
                modbusMaster.destroy();
                System.out.println("Modbus连接已关闭");
                modbusMaster = null;
            }
            if(master != null) {
                master.destroy();
                System.out.println("Modbus连接已关闭");
                master = null;
            }
        }
    }


    /**
     * 读取设备寄存器（线程安全版）
     */
    public static int[] readDeviceRegisters(ModbusMaster master, int deviceId )
            throws ModbusTransportException {

        // 创建读取请求
        ReadHoldingRegistersRequest request = Modbus4jUtils.getReadHoldingRegistersRequest(deviceId,START_ADDRESS, REGISTER_COUNT);

        // 发送请求并获取响应
        ModbusResponse response = master.send(request);

        // 检查响应类型
        if (!(response instanceof ReadHoldingRegistersResponse)) {
            throw new IllegalArgumentException("Invalid response type: " + response.getClass().getName());
        }

        ReadHoldingRegistersResponse regResponse = (ReadHoldingRegistersResponse) response;
        short[] signedValues = regResponse.getShortData();

        // 转换为无符号整数
        int[] unsignedValues = new int[signedValues.length];
        for (int i = 0; i < signedValues.length; i++) {
            unsignedValues[i] = signedValues[i] & 0xFFFF;
        }

        return unsignedValues;
    }
}
