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

org.bidib.jbidibc.ftdi.serial.debug.DebugReaderEventWindows Maven / Gradle / Ivy

There is a newer version: 2.0.25
Show newest version
package org.bidib.jbidibc.ftdi.serial.debug;

import java.io.ByteArrayOutputStream;
import java.util.EnumSet;

import org.bidib.jbidibc.debug.DebugMessageProcessor;
import org.bidib.jbidibc.messages.utils.ByteUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ftdi.DeviceStatus;
import com.ftdi.FTD2XX;
import com.ftdi.FTD2XXException;
import com.ftdi.FTDevice;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.WinBase;
import com.sun.jna.platform.win32.WinNT.HANDLE;

public class DebugReaderEventWindows extends AbstractDebugReader {

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

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

    static private final Kernel32 kernel32 = Kernel32.INSTANCE;

    private HANDLE hEvent;

    private byte[] inputBuffer = new byte[2048];

    private ByteArrayOutputStream output = new ByteArrayOutputStream();

    public DebugReaderEventWindows(DebugMessageProcessor messageReceiver) {
        super(messageReceiver);
    }

    @Override
    protected Thread createReceiverThread() {
        return new ReceiverThread();
    }

    public class ReceiverThread extends Thread {
        public ReceiverThread() {
            super("FTDI-Receiver");
        }

        @Override
        public void run() {
            receiverRunning.set(true);

            Thread.currentThread().setPriority(NORM_PRIORITY - 1);

            final FTDevice serialPort = getFTDevice();

            LOGGER.info("Started the receiver thread.");

            WinBase.SECURITY_ATTRIBUTES lpEventAttributes = null;
            final HANDLE hEvent = kernel32.CreateEvent(lpEventAttributes, false, false, "");

            DebugReaderEventWindows.this.hEvent = hEvent;

            int eventMask =
                FTD2XX.NotificationEvents.FT_EVENT_RXCHAR | FTD2XX.NotificationEvents.FT_EVENT_MODEM_STATUS
                    | FTD2XX.NotificationEvents.FT_EVENT_LINE_STATUS;

            while (receiverRunning.get()) {

                try {
                    int len = -1;

                    LOGGER.debug("Try to read data");

                    serialPort.SetEventNotification(hEvent.getPointer(), eventMask);
                    kernel32.WaitForSingleObject(hEvent, -1);

                    // LOGGER.info("After wait for read data");
                    int[] status = serialPort.getStatus();

                    if ((status[2]
                        & FTD2XX.NotificationEvents.FT_EVENT_MODEM_STATUS) == FTD2XX.NotificationEvents.FT_EVENT_MODEM_STATUS
                        || (status[2]
                            & FTD2XX.NotificationEvents.FT_EVENT_LINE_STATUS) == FTD2XX.NotificationEvents.FT_EVENT_LINE_STATUS) {
                        LOGGER.info("Received modem or line status event: {}", status[2]);

                        final EnumSet deviceStatusSet = serialPort.getDeviceStatus();

                        if (deviceStatusSet.contains(DeviceStatus.CTS)) {
                            LOGGER.info(">>>> CTS is high.");
                        }
                        else {
                            LOGGER.info(">>>> CTS is low.");
                        }

                        if (deviceStatusSet.contains(DeviceStatus.DSR)) {
                            LOGGER.info(">>>> DSR is high.");
                        }
                        else {
                            LOGGER.info(">>>> DSR is low.");
                        }

                    }
                    else {
                        // int available = serialPort.getQueueStatus();
                        int available = status[0];

                        // LOGGER.info("Queue status: {}", available);

                        if (available > 0) {
                            len = serialPort.read(inputBuffer, 0, available);

                            LOGGER.info("Read len: {}", len);
                        }
                    }

                    if (len < 0) {
                        // check if the port was closed.
                        boolean portClosed = !serialPort.isOpen();
                        LOGGER.info("Port closed: {}", portClosed);

                        if (portClosed) {
                            // say good-bye
                            LOGGER.info("The port is closed. Leave the receiver loop.");

                            receiverRunning.set(false);
                            continue;
                        }
                    }

                    if (len > 0) {
                        // receive(inputBuffer, len);
                        output.write(inputBuffer, 0, len);

                        if (MSG_RAW_LOGGER.isInfoEnabled()) {
                            MSG_RAW_LOGGER
                                .info("<<<< len: {}, data: {}", output.size(),
                                    ByteUtils.bytesToHex(output.toByteArray()));
                        }

                        addDataToReceiveQueue(output);

                        if (output != null && output.size() > 0) {

                            LOGGER.warn("Data in output: {}", output.toString());
                        }

                    }
                }
                catch (FTD2XXException ex) {
                    LOGGER.warn("Receive data failed with an exception!", ex);

                    receiverRunning.set(false);

                    if (serialPort == null || serialPort.isOpen()) {
                        triggerClosePort();
                    }
                }
                // catch (IOException ex) {
                // LOGGER.error("Receive data failed with an exception!", ex);
                //
                // receiverRunning.set(false);
                //
                // if (serialPort == null || serialPort.isOpen()) {
                // triggerClosePort();
                // }
                //
                // }
                catch (NullPointerException ex) {
                    LOGGER.error("Receive data failed with an NPE! The port might be closed.", ex);

                    receiverRunning.set(false);
                }
                catch (Exception ex) {
                    LOGGER.error("Message receiver returned from receive with an exception!", ex);
                }

            }

            // }

            closeHandle();

            LOGGER.info("Leaving receiver loop.");
        }

    }

    @Override
    protected void closeHandle() {
        LOGGER.info("Close the handle: {}", hEvent);

        if (hEvent != null) {
            kernel32.SetEvent(hEvent);

            kernel32.CloseHandle(hEvent);
            hEvent = null;
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy