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

org.bidib.jbidibc.serial.SerialMessageReceiver Maven / Gradle / Ivy

There is a newer version: 2.0.29
Show newest version
package org.bidib.jbidibc.serial;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.nio.charset.UnsupportedCharsetException;

import org.bidib.jbidibc.core.BidibLibrary;
import org.bidib.jbidibc.core.MessageReceiver;
import org.bidib.jbidibc.core.exception.InvalidConfigurationException;
import org.bidib.jbidibc.core.exception.ProtocolException;
import org.bidib.jbidibc.core.node.NodeFactory;
import org.bidib.jbidibc.core.utils.ByteUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SerialMessageReceiver extends MessageReceiver {
    private static final Logger LOGGER = LoggerFactory.getLogger(SerialMessageReceiver.class);

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

    boolean escapeHot = false;

    private final Object accessLock = new Object();

    private ByteArrayOutputStream output = new ByteArrayOutputStream(1024);

    public SerialMessageReceiver(NodeFactory nodeFactory) {
        super(nodeFactory);
    }

    public void enable() {
        LOGGER.info("enable is called.");
        synchronized (accessLock) {
            escapeHot = false;
        }
        super.enable();
    }

    public void disable() {
        LOGGER.info("Disable is called.");
        super.disable();

        synchronized (accessLock) {
            escapeHot = false;
        }
    }

    @Override
    public String getErrorInformation() {
        if (output != null && output.size() > 0) {

            byte[] remaining = output.toByteArray();
            return new String(remaining);
        }

        return null;
    }

    public void purgeOutputStream() {
        synchronized (accessLock) {
            LOGGER.info("Purge the output stream. Current escapeHot: {}", escapeHot);

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

                try {
                    byte[] remaining = output.toByteArray();

                    String remainingValue = new String(remaining, Charset.forName("UTF-8"));

                    LOGGER.info("Cleared remaining data from message output buffer: {}, text: {}",
                        ByteUtils.bytesToHex(remaining), remainingValue);

                    if (remainingValue.indexOf("I=") > -1) {
                        // This is the detection of the debug interface active
                        InvalidConfigurationException ice =
                            new InvalidConfigurationException("An active debug interface configuration was detected.");
                        ice.setReason("debug-interface-active");
                        throw ice;
                    }
                }
                catch (UnsupportedCharsetException ex) {
                    LOGGER.warn("Clear remaining data from message output buffer failed.", ex);
                }
                finally {
                    output.reset();
                }
            }
        }
    }

    /**
     * Receive messages from the configured port
     */
    public void receive(final InputStream input) {
        LOGGER.debug("Start receiving messages from port.");

        if (!running.get()) {
            LOGGER.info("The receiver is not running. Skip processing of messages.");
            return;
        }

        synchronized (accessLock) {
            LOGGER.debug("Start processing input stream.");
            // InputStream input = null;
            try {
                if (input != null) {
                    // input = port.getInputStream();
                    parseInput(input);
                }
                else {
                    LOGGER.warn("Inside receive, port is not available");
                }
            }
            catch (Exception e) {
                LOGGER.warn("Exception detected in message receiver!", e);

                // reset the escapeHot flag
                if (escapeHot) {
                    LOGGER.warn("Reset the escapeHot to false.");
                    escapeHot = false;
                }
                throw new RuntimeException(e);
            }
        }
    }

    protected void parseInput(final InputStream input) throws IOException, ProtocolException {
        if (input != null) {
            int data = 0;
            StringBuilder logRecord = new StringBuilder();

            // read the values from in the port
            int len = 0;
            while (running.get() && (len = input.read(inputBuffer, 0, inputBuffer.length)) > 0) {

                LOGGER.debug("Number of bytes read: {}", len);
                MSG_RAW_LOGGER.info("<<<< len: {}", len);

                for (int index = 0; index < len; index++) {
                    data = (inputBuffer[index] & 0xFF);
                    if (LOGGER.isTraceEnabled()) {
                        LOGGER.trace("received data: {}", ByteUtils.byteToHex(data));
                    }
                    // append data to log record
                    logRecord.append(ByteUtils.byteToHex(data)).append(" ");

                    // check if the current is the end of a packet
                    if (data == BidibLibrary.BIDIB_PKT_MAGIC && output.size() > 0) {

                        LOGGER.debug("Received raw message: {}", logRecord);
                        if (MSG_RAW_LOGGER.isInfoEnabled()) {
                            MSG_RAW_LOGGER.info("<< [{}] - {}", logRecord.length() / 3, logRecord);
                        }
                        logRecord.setLength(0);

                        // if a CRC error is detected in splitMessages the reading loop will terminate ...
                        try {
                            processMessages(output);
                        }
                        catch (ProtocolException ex) {
                            LOGGER.warn("Process messages failed.", ex);
                            // reset the escape hot flag
                            escapeHot = false;
                        }

                        // after process messages there could be more data in the stream that will be continued with
                        // the next packet
                    }
                    else {
                        if (data == BidibLibrary.BIDIB_PKT_ESCAPE) {
                            escapeHot = true;
                        }
                        else if (data != BidibLibrary.BIDIB_PKT_MAGIC) {
                            if (escapeHot) {
                                data ^= 0x20;
                                escapeHot = false;
                            }
                            // append data to output array
                            output.write(ByteUtils.getLowByte(data));
                        }
                    }

                    // if (!running.get()) {
                    // LOGGER.warn("Abort processing input because the receiver was stopped.");
                    // break;
                    // }
                }
            }
            LOGGER.debug("Leaving receive loop, RUNNING: {}", running);

            if (output != null && output.size() > 0) {
                byte[] remaining = output.toByteArray();
                String remainingString = ByteUtils.bytesToHex(remaining);
                LOGGER.debug("Data remaining in output: {}", remainingString);
            }
            if (logRecord != null && logRecord.length() > 0) {
                LOGGER.debug("Data remaining in logRecord: {}", logRecord);
            }

        }
        else {
            LOGGER.error("No input available.");
        }

    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy