package com.jwk.spring.boot.modbus4j;

import com.serotonin.modbus4j.ModbusFactory;
import com.serotonin.modbus4j.ModbusMaster;
import com.serotonin.modbus4j.exception.ModbusInitException;
import com.serotonin.modbus4j.ip.IpParameters;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.Executors;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;


/**
 * @author JWK
 * @version 1.0
 * @date 2022/9/7 17:00
 */
@Slf4j
@Data
public class ModbusTcpMaster {

    private ModbusMaster master = null;
    private ModbusFactory modbusFactory = null;
    private ModbusMasterUtil modbusMasterUtil = null;
    private Lock lock = new ReentrantLock();

    private String host;
    private Integer port;

    /**
     * 初始化
     *
     * @param host
     * @param port
     * @throws ModbusInitException
     */
    public ModbusTcpMaster(String host, Integer port) {
        this.host = host;
        this.port = port;
        modbusFactory = new ModbusFactory();

    }

    /**
     * 打开串口 异步
     *
     * @throws ModbusInitException
     */
    public void connectAsync() {
        Executors.newSingleThreadExecutor().execute(() -> this.connect());
    }

    /**
     * 连接
     *
     * @throws ModbusInitException
     */
    public void connect() {
        for (; ; ) {
            try {
                if (!lock.tryLock()) {
                    break;
                }
                IpParameters params = new IpParameters();
                params.setHost(host);
                params.setPort(port);
                master = modbusFactory.createTcpMaster(params, true);
                master.init();
                modbusMasterUtil = new ModbusMasterUtil(master);
                break;
            } catch (Exception e) {
                log.error("当前串口：{},打开失败！", getPort(), e);
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException ee) {

                }
            } finally {
                lock.unlock();
            }
        }
    }

    /**
     * 重新连接串口
     */
    public void reConnect() {
        try {
            master = null;
            connect();
            Thread.sleep(1000);
        } catch (Exception e) {

        }
        connect();
    }
}
