All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bidib.jibidibc.jserialcomm.JSerialCommSerialConnector Maven / Gradle / Ivy

There is a newer version: 2.0.29
Show newest version
package org.bidib.jibidibc.jserialcomm;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.bidib.jbidibc.core.BidibLibrary;
import org.bidib.jbidibc.core.MessageReceiver;
import org.bidib.jbidibc.core.base.AbstractBaseBidib;
import org.bidib.jbidibc.core.exception.PortNotFoundException;
import org.bidib.jbidibc.core.exception.PortNotOpenedException;
import org.bidib.jbidibc.core.helpers.Context;
import org.bidib.jbidibc.core.utils.ByteUtils;
import org.bidib.jbidibc.serial.LineStatusListener;
import org.bidib.jbidibc.serial.SerialMessageEncoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fazecast.jSerialComm.SerialPort;
import com.fazecast.jSerialComm.SerialPortDataListener;
import com.fazecast.jSerialComm.SerialPortEvent;

public class JSerialCommSerialConnector extends AbstractBaseBidib {

    private static final Logger LOGGER = LoggerFactory.getLogger(JSerialCommSerialConnector.class);

    private static final Logger MSG_RAW_LOGGER = LoggerFactory.getLogger("RAW");

    private SerialPort comPort;

    private MessageReceiver messageReceiver;

    private LineStatusListener lineStatusListener;

    /**
     * @return the messageReceiver
     */
    public MessageReceiver getMessageReceiver() {
        return messageReceiver;
    }

    /**
     * @param messageReceiver
     *            the messageReceiver to set
     */
    public void setMessageReceiver(MessageReceiver messageReceiver) {
        this.messageReceiver = messageReceiver;
    }

    /**
     * @return the lineStatusListener
     */
    public LineStatusListener getLineStatusListener() {
        return lineStatusListener;
    }

    /**
     * @param lineStatusListener
     *            the lineStatusListener to set
     */
    public void setLineStatusListener(LineStatusListener lineStatusListener) {
        this.lineStatusListener = lineStatusListener;
    }

    protected boolean isImplAvaiable() {
        return (comPort != null);
    }

    @Override
    public boolean isOpened() {
        return comPort != null && comPort.isOpen();
    }

    @Override
    protected void internalOpen(String portName, Context context) throws PortNotFoundException, PortNotOpenedException {

        super.internalOpen(portName, context);

        Boolean useHardwareFlowControl = context.get("serial.useHardwareFlowControl", Boolean.class, Boolean.TRUE);

        LOGGER.info("Open port with portName: {}, useHardwareFlowControl: {}", portName, useHardwareFlowControl);

        final MessageReceiver serialMessageReceiver = getMessageReceiver();

        comPort = SerialPort.getCommPort(portName);

        if (useHardwareFlowControl) {
            comPort.setFlowControl(SerialPort.FLOW_CONTROL_RTS_ENABLED | SerialPort.FLOW_CONTROL_CTS_ENABLED);
        }
        else {
            comPort.setFlowControl(SerialPort.FLOW_CONTROL_DISABLED);
        }

        Integer baudRate = context.get("serial.baudrate", Integer.class, Integer.valueOf(115200));
        LOGGER.info("Open port with baudRate: {}", baudRate);

        comPort.setComPortParameters(baudRate, 8, SerialPort.ONE_STOP_BIT, SerialPort.NO_PARITY);
        boolean opened = comPort.openPort();

        if (!opened) {
            LOGGER.warn("Port was not opened: {}", portName);
            throw new PortNotOpenedException("Port was not opened: " + portName, "unknown");
        }

        startReceiverAndQueues(serialMessageReceiver, context);

        setConnected(true);

        comPort.addDataListener(new SerialPortDataListener() {
            @Override
            public int getListeningEvents() {
                return SerialPort.LISTENING_EVENT_DATA_AVAILABLE;
            }

            @Override
            public void serialEvent(SerialPortEvent event) {
                if (event.getEventType() != SerialPort.LISTENING_EVENT_DATA_AVAILABLE)
                    return;
                byte[] data = new byte[comPort.bytesAvailable()];
                int numRead = comPort.readBytes(data, data.length);
                LOGGER.debug("Read bytes count: {}", numRead);

                receive(data, data.length);
            }
        });

        if (useHardwareFlowControl) {
            // Activate DTR
            try {
                LOGGER.info("Activate DTR.");

                comPort.setDTR(); // pin 1 in DIN8; on main connector, this is DTR
            }
            catch (Exception e) {
                LOGGER.warn("Set DTR true failed.", e);
            }
        }

    }

    @Override
    public boolean close() {

        if (comPort != null) {

            long start = System.currentTimeMillis();

            LOGGER.info("Close the port, comPort: {}", comPort);

            comPort.removeDataListener();
            comPort.closePort();

            final MessageReceiver serialMessageReceiver = getMessageReceiver();
            stopReceiverAndQueues(serialMessageReceiver);

            long end = System.currentTimeMillis();
            LOGGER.info("Closed the port. duration: {}", end - start);

            fireCtsChanged(false);
            setConnected(false);

            comPort = null;

            return true;
        }
        else {
            LOGGER.info("No port to close available.");
        }
        return false;
    }

    public List getPortIdentifiers() {

        List portIdentifiers = new ArrayList<>();
        for (SerialPort serialPort : SerialPort.getCommPorts()) {
            portIdentifiers.add(serialPort.getSystemPortName());
        }

        return portIdentifiers;
    }

    protected void fireCtsChanged(boolean ready) {
        LOGGER.info("CTS has changed, ready: {}", ready);

        // signal changed line status to the bidib implementation
        if (lineStatusListener != null) {
            lineStatusListener.notifyLineStatusChanged(ready);
        }
    }

    private ByteArrayOutputStream sendBuffer = new ByteArrayOutputStream(100);

    @Override
    protected void sendData(ByteArrayOutputStream data) {

        if (comPort != null && data != null) {

            try {
                if (!firstPacketSent) {
                    LOGGER.info("Send initial sequence.");

                    try {
                        byte[] initialSequence = new byte[] { (byte) BidibLibrary.BIDIB_PKT_MAGIC };
                        if (MSG_RAW_LOGGER.isInfoEnabled()) {
                            MSG_RAW_LOGGER
                                .info(">> [{}] - {}", initialSequence.length, ByteUtils.bytesToHex(initialSequence));
                        }
                        comPort.writeBytes(initialSequence, initialSequence.length);
                        Thread.sleep(10);
                        if (MSG_RAW_LOGGER.isInfoEnabled()) {
                            MSG_RAW_LOGGER
                                .info(">> [{}] - {}", initialSequence.length, ByteUtils.bytesToHex(initialSequence));
                        }
                        comPort.writeBytes(initialSequence, initialSequence.length);

                        firstPacketSent = true;

                        LOGGER.info("Send initial sequence passed.");
                    }
                    catch (Exception ex) {
                        LOGGER.warn("Send initial sequence failed.", ex);
                    }
                }

                sendBuffer.reset();
                SerialMessageEncoder.encodeMessage(data, sendBuffer);

                if (MSG_RAW_LOGGER.isInfoEnabled()) {
                    MSG_RAW_LOGGER
                        .info(">> [{}] - {}", sendBuffer.toByteArray().length,
                            ByteUtils.bytesToHex(sendBuffer.toByteArray()));
                }

                int sent = comPort.writeBytes(sendBuffer.toByteArray(), sendBuffer.size());
                if (sent == 0) {
                    MSG_RAW_LOGGER.warn(">> sent bytes: {}", sent);

                    byte[] bytes = data.toByteArray();
                    LOGGER
                        .error("The message has not been sent to comPort: {}, message: {}", comPort,
                            ByteUtils.bytesToHex(bytes));

                    throw new RuntimeException("Write message to output failed: " + ByteUtils.bytesToHex(bytes));
                }
                else {
                    MSG_RAW_LOGGER.info(">> sent bytes: {}", sent);
                }
            }
            catch (IOException ex) {
                byte[] bytes = data.toByteArray();
                LOGGER
                    .warn("Send message to output stream failed: [{}] - {}", bytes.length, ByteUtils.bytesToHex(bytes));

                throw new RuntimeException("Send message to output stream failed: " + ByteUtils.bytesToHex(bytes), ex);
            }
            finally {
                sendBuffer.reset();
            }
        }

    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy