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

org.bidib.jbidibc.gateway.GatewayMessageReceiver Maven / Gradle / Ivy

package org.bidib.jbidibc.gateway;

import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

import org.apache.commons.collections4.CollectionUtils;
import org.bidib.jbidibc.core.BidibLibrary;
import org.bidib.jbidibc.core.MessageReceiver;
import org.bidib.jbidibc.core.exception.ProtocolException;
import org.bidib.jbidibc.core.message.BidibCommand;
import org.bidib.jbidibc.core.message.BidibMessage;
import org.bidib.jbidibc.core.message.RequestFactory;
import org.bidib.jbidibc.core.node.BidibNode;
import org.bidib.jbidibc.core.node.NodeRegistry;
import org.bidib.jbidibc.core.utils.ByteUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class GatewayMessageReceiver extends MessageReceiver {

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

    private AtomicBoolean escapeHot = new AtomicBoolean();

    private ByteArrayOutputStream output = new ByteArrayOutputStream(2048);

    private RequestFactory requestFactory;

    private GatewayMessagePeer gatewayMessagePeer;

    public GatewayMessageReceiver(NodeRegistry nodeRegistry) {
        super(nodeRegistry, false);
    }

    private synchronized RequestFactory getRequestFactory() {
        if (requestFactory == null) {
            requestFactory = new RequestFactory();
        }

        return requestFactory;
    }

    public void setGatewayMessagePeer(final GatewayMessagePeer gatewayMessagePeer) {
        LOGGER.info("Set the gatewayMessagePeer: {}", gatewayMessagePeer);
        this.gatewayMessagePeer = gatewayMessagePeer;
    }

    @Override
    public void enable() {
        LOGGER.info("enable is called.");
        escapeHot.set(false);

        MSG_RAW_LOGGER.info("++++ Enable the message receiver.");

        try {
            output.reset();
        }
        catch (Exception ex) {
            LOGGER.warn("Reset buffered received data failed.", ex);
        }

        super.enable();
    }

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

        MSG_RAW_LOGGER.info("++++ Disable the message receiver.");

        escapeHot.set(false);
    }

    /**
     * Receive messages from the configured port
     * 
     * @param data
     *            the received data
     */
    @Override
    public void receive(final ByteArrayOutputStream data) {

        if (!running.get()) {
            LOGGER.info("The receiver is not running. Skip processing of messages.");
            try {
                byte[] rawdata = data.toByteArray();
                LOGGER.info("Receiver is stopped, number of bytes read: {}, buffer: {}", rawdata.length,
                    ByteUtils.bytesToHex(rawdata));
            }
            catch (Exception ex) {
                LOGGER.warn("Read data from input stream to buffer failed.", ex);
            }
            return;
        }

        MSG_RAW_LOGGER.info("<<<< start parse input");

        try {
            byte[] rawdata = data.toByteArray();
            LOGGER.info("Received data: {}", ByteUtils.bytesToHex(rawdata));
            parseInput(rawdata, rawdata.length);
        }
        catch (Exception e) {
            LOGGER.warn("Exception detected in message receiver!", e);

            // reset the escapeHot flag
            if (escapeHot.get()) {
                LOGGER.warn("Reset the escapeHot to false.");
                escapeHot.set(false);
            }
            throw new RuntimeException(e);
        }
        finally {
            MSG_RAW_LOGGER.info("<<<< finished parse input");
        }
    }

    /**
     * Parse the received data to process the received bidib packets.
     * 
     * @param receivedData
     *            the received data
     * @param len
     *            the len of the recevided data packet
     * @throws ProtocolException
     */
    protected void parseInput(final byte[] receivedData, int len) throws ProtocolException {
        if (receivedData != null) {
            int data = 0;
            StringBuilder logRecord = new StringBuilder();

            // LOGGER.debug("Number of bytes read: {}", len);
            MSG_RAW_LOGGER.info("<<<< len: {}, data: {}", len, ByteUtils.bytesToHex(receivedData, len));

            for (int index = 0; index < len; index++) {
                data = (receivedData[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) {

                    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 {
                        if (output.size() > 0) {
                            processMessages(output);
                        }
                        else {
                            LOGGER.warn("No data in output buffer.");
                        }
                    }
                    catch (ProtocolException ex) {
                        LOGGER.warn("Process messages failed.", ex);
                        // reset the escape hot flag
                        escapeHot.set(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.set(true);
                }
                else {
                    if (escapeHot.get()) {
                        data ^= 0x20;
                        escapeHot.set(false);
                    }
                    // append data to output array
                    output.write(ByteUtils.getLowByte(data));
                }
            }

            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.");
        }
    }

    @Override
    public synchronized void processMessages(ByteArrayOutputStream output) throws ProtocolException {
        LOGGER.info("Received messages to process: {}", ByteUtils.bytesToHex(output.toByteArray()));

        // This is a shortcut to forward the message to the peer. The message numbers are not checked currently.

        // if a CRC error is detected in splitMessages the reading loop will terminate ...
        try {
            List bidibMessages = new ArrayList();
            getRequestFactory().createFromRaw(output.toByteArray(), bidibMessages);

            if (CollectionUtils.isNotEmpty(bidibMessages)) {

                for (BidibCommand bidibCommand : bidibMessages) {
                    LOGGER.info("Process the current bidibCommand: {}", bidibCommand);

                    // TODO forward message
                    if (gatewayMessagePeer != null) {
                        gatewayMessagePeer.forwardMessage(bidibCommand);
                    }

                }
            }
            else {
                LOGGER.warn("No commands in packet received.");
            }
        }
        catch (ProtocolException ex) {
            LOGGER.warn("Create BiDiB message failed.", ex);
        }

        // clear the content in the outputStream because the message is processed
        output.reset();
        // super.processMessages(output);
    }

    @Override
    protected void evaluateMessage(final BidibNode bidibNode, final BidibMessage message) throws ProtocolException {
        // TODO Auto-generated method stub
        LOGGER.info("Received message to evaluate: {}", message);

        super.evaluateMessage(bidibNode, message);
    }

    // public static void evaluateMessage(GatewayMessageReceiver messageReceiver, BidibMessage message)
    // throws ProtocolException {
    // messageReceiver.evaluateMessage(message);
    // }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy