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

org.bidib.wizard.simulation.MotFuncSimulator Maven / Gradle / Ivy

package org.bidib.wizard.simulation;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.bidib.jbidibc.messages.BidibLibrary;
import org.bidib.jbidibc.messages.Feature;
import org.bidib.jbidibc.messages.StringData;
import org.bidib.jbidibc.messages.exception.ProtocolException;
import org.bidib.jbidibc.messages.message.BidibMessageInterface;
import org.bidib.jbidibc.messages.message.BidibRequestFactory;
import org.bidib.jbidibc.messages.message.StringGetMessage;
import org.bidib.jbidibc.messages.message.StringResponse;
import org.bidib.jbidibc.messages.message.StringSetMessage;
import org.bidib.jbidibc.messages.utils.ByteUtils;
import org.bidib.jbidibc.simulation.SimulationBidibMessageProcessor;
import org.bidib.jbidibc.simulation.annotation.BidibNodeSimulator;
import org.bidib.jbidibc.simulation.nodes.DefaultNodeSimulator;
import org.bushe.swing.event.annotation.AnnotationProcessor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@BidibNodeSimulator(vid = "13", pid = "149")
public class MotFuncSimulator extends DefaultNodeSimulator {

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

    private String[] stringValue = new String[] { "", "MotFunc_Sim" };

    public MotFuncSimulator(byte[] nodeAddress, long uniqueId, boolean autoAddFeature,
        SimulationBidibMessageProcessor messageReceiver, final BidibRequestFactory bidibRequestFactory) {
        super(nodeAddress, uniqueId, autoAddFeature, messageReceiver, bidibRequestFactory);
    }

    @Override
    protected void prepareFeatures() {
        LOGGER.info("Prepare the features.");
        super.prepareFeatures();

        features
            .add(new Feature(BidibLibrary.FEATURE_STRING_NAMESPACES_AVAILABLE,
                1 << BidibLibrary.BIDIB_STRING_NAMESPACE_RW_STORAGE));
    }

    private static final String PATTERN_WRITE_COMMAND_WITH_ADDRESS = "^W([0-9a-z]+)=(.*)";

    private static final String PATTERN_WRITE_COMMAND = "^W=(.*)";

    private static final String PATTERN_WRITE_COMMAND_FINISH = "^S=(.*)";

    private static final String PATTERN_READ_COMMAND_WITH_ADDRESS = "^R([0-9a-z]+)=";

    private Pattern pWriteCommandWithAddress;

    private Pattern pWriteCommand;

    private Pattern pWriteCommandFinish;

    private Pattern pReadCommandWithAddress;

    @Override
    public void postConstruct() {
        super.postConstruct();

        pWriteCommandWithAddress = Pattern.compile(PATTERN_WRITE_COMMAND_WITH_ADDRESS);
        pWriteCommand = Pattern.compile(PATTERN_WRITE_COMMAND);
        pWriteCommandFinish = Pattern.compile(PATTERN_WRITE_COMMAND_FINISH);
        pReadCommandWithAddress = Pattern.compile(PATTERN_READ_COMMAND_WITH_ADDRESS);
    }

    @Override
    public void start() {
        LOGGER.info("Start the simulator for address: {}", getAddress());

        AnnotationProcessor.process(this);

        super.start();
    }

    @Override
    public void stop() {
        AnnotationProcessor.unprocess(this);
        super.stop();
    }

    private final StringBuilder decoderConfig = new StringBuilder();

    private final StringBuilder motFuncConfig = new StringBuilder();

    private StorageTargetIndex storageTarget;

    private static final String CMD_RESULT_OK = "RES=OK";

    private static final String CMD_RESULT_NOK = "RES=NOK";

    private static final String CMD_END_OF_TRANSMISSION = "S=";

    @Override
    protected byte[] processStringSetRequest(BidibMessageInterface bidibMessage) {
        LOGGER.info("Process the stringSet request.");

        byte[] response = null;
        try {
            StringSetMessage stringSetMessage = (StringSetMessage) bidibMessage;
            int namespace = stringSetMessage.getNamespace();

            if (namespace == StringData.NAMESPACE_NODE) {

                response = super.processStringSetRequest(bidibMessage);
            }
            else if (namespace == StringData.NAMESPACE_3_RW_STORAGE) {
                int stringId = stringSetMessage.getStringId();
                String stringValue = stringSetMessage.getString();

                storageTarget = stringId == 0 ? StorageTargetIndex.target_decoder : StorageTargetIndex.target_motfuc;

                String returnValue = null;
                // process the command
                Matcher matcherWriteCommandWithAddress = pWriteCommandWithAddress.matcher(stringValue);
                if (matcherWriteCommandWithAddress.find()) {
                    // Write with address command
                    String addressString = matcherWriteCommandWithAddress.group(1);
                    String writeData = matcherWriteCommandWithAddress.group(2);

                    LOGGER.info("Found write with address command, address: {}, data: {}", addressString, writeData);

                    if (stringId >= 0 && stringId < 2) {
                        returnValue = CMD_RESULT_OK;

                        if (storageTarget == StorageTargetIndex.target_decoder) {
                            decoderConfig.setLength(0);
                            decoderConfig.append(writeData);
                        }
                        else {
                            motFuncConfig.setLength(0);
                            motFuncConfig.append(writeData);
                        }
                    }
                    else {
                        returnValue = CMD_RESULT_NOK;
                    }

                    StringResponse stringResponse =
                        new StringResponse(bidibMessage.getAddr(), getNextSendNum(),
                            ByteUtils.getLowByte(stringSetMessage.getNamespace()),
                            ByteUtils.getLowByte(stringSetMessage.getStringId()), returnValue);
                    LOGGER.info("Prepared the stringResponse: {}", stringResponse);
                    return stringResponse.getContent();
                }

                Matcher matcherWriteCommand = pWriteCommand.matcher(stringValue);
                if (matcherWriteCommand.find()) {
                    // Write command
                    String writeData = matcherWriteCommand.group(1);

                    LOGGER.info("Found write command, data: {}", writeData);

                    if (storageTarget == StorageTargetIndex.target_decoder) {
                        decoderConfig.append(writeData);
                    }
                    else {
                        motFuncConfig.append(writeData);
                    }

                    return null;
                }

                Matcher matcherWriteCommandFinish = pWriteCommandFinish.matcher(stringValue);
                if (matcherWriteCommandFinish.find()) {
                    // Write command
                    String writeData = matcherWriteCommandFinish.group(1);

                    LOGGER.info("Found write command finish, data: {}", writeData);

                    returnValue = CMD_RESULT_OK;

                    StringResponse stringResponse =
                        new StringResponse(bidibMessage.getAddr(), getNextSendNum(),
                            ByteUtils.getLowByte(stringSetMessage.getNamespace()),
                            ByteUtils.getLowByte(stringSetMessage.getStringId()), returnValue);
                    LOGGER.info("Prepared the stringResponse: {}", stringResponse);
                    return stringResponse.getContent();
                }

                Matcher matcherReadCommandWithAddress = pReadCommandWithAddress.matcher(stringValue);
                if (matcherReadCommandWithAddress.find()) {
                    // Write with address command
                    String addressString = matcherReadCommandWithAddress.group(1);

                    LOGGER.info("Found read with address command, address: {}", addressString);

                    if (stringId >= 0 && stringId < 2) {
                        returnValue = CMD_RESULT_OK;
                    }
                    else {
                        returnValue = CMD_RESULT_NOK;

                        StringResponse stringResponse =
                            new StringResponse(bidibMessage.getAddr(), getNextSendNum(),
                                ByteUtils.getLowByte(stringSetMessage.getNamespace()),
                                ByteUtils.getLowByte(stringSetMessage.getStringId()), returnValue);
                        LOGGER.info("Prepared the stringResponse: {}", stringResponse);

                        publishResponse(stringResponse.getContent());
                        return null;
                    }

                    StringResponse stringResponse =
                        new StringResponse(bidibMessage.getAddr(), getNextSendNum(),
                            ByteUtils.getLowByte(stringSetMessage.getNamespace()),
                            ByteUtils.getLowByte(stringSetMessage.getStringId()), returnValue);
                    LOGGER.info("Prepared the stringResponse: {}", stringResponse);

                    publishResponse(stringResponse.getContent());

                    final StringBuilder configSource;
                    if (storageTarget == StorageTargetIndex.target_decoder) {
                        configSource = decoderConfig;
                    }
                    else {
                        configSource = motFuncConfig;
                    }

                    // publish the data
                    if (configSource.length() > 0) {

                        final DccTestPacketizer packetizer = new DccTestPacketizer();
                        packetizer.setDataToTransfer(configSource.toString());

                        while (packetizer.hasNext()) {
                            returnValue = packetizer.getNextReadChunk();

                            stringResponse =
                                new StringResponse(bidibMessage.getAddr(), getNextSendNum(),
                                    ByteUtils.getLowByte(stringSetMessage.getNamespace()),
                                    ByteUtils.getLowByte(stringSetMessage.getStringId()), returnValue);
                            LOGGER.info("Prepared the stringResponse: {}", stringResponse);

                            publishResponse(stringResponse.getContent());
                        }
                    }

                    // publish end-of-transmission
                    returnValue = CMD_END_OF_TRANSMISSION;
                    stringResponse =
                        new StringResponse(bidibMessage.getAddr(), getNextSendNum(),
                            ByteUtils.getLowByte(stringSetMessage.getNamespace()),
                            ByteUtils.getLowByte(stringSetMessage.getStringId()), returnValue);
                    LOGGER.info("Prepared the stringResponse: {}", stringResponse);

                    publishResponse(stringResponse.getContent());
                }
            }
        }
        catch (ProtocolException ex) {
            LOGGER.warn("Create string response failed.", ex);
        }
        return response;
    }

    @Override
    protected byte[] processStringGetRequest(BidibMessageInterface bidibMessage) {
        LOGGER.info("Process the stringGet request.");

        byte[] response = null;
        try {
            StringGetMessage stringGetMessage = (StringGetMessage) bidibMessage;
            int stringId = stringGetMessage.getStringId();

            LOGGER.info("Get STRING[{}]: {}", stringId, stringValue[stringId]);

            StringResponse stringResponse =
                new StringResponse(bidibMessage.getAddr(), getNextSendNum(),
                    ByteUtils.getLowByte(stringGetMessage.getNamespace()),
                    ByteUtils.getLowByte(stringGetMessage.getStringId()), stringValue[stringId]);
            response = stringResponse.getContent();
        }
        catch (ProtocolException ex) {
            LOGGER.warn("Create string response failed.", ex);
        }
        return response;
    }

    private static class DccTestPacketizer {

        public static final int DEFAULT_CHUNK_SIZE = BidibMessageInterface.MAX_MESSAGE_LEN - 11;

        private String dataToTransfer;

        private int addressPointer;

        public static final String CMD_READ_CONTINUE = "H=";

        /**
         * Reset the addressPointer.
         */
        public void reset() {
            this.addressPointer = 0;
        }

        /**
         * Set the data to transfer and reset the address pointer.
         * 
         * @param dataToTransfer
         *            the dataToTransfer to set
         */
        public void setDataToTransfer(String dataToTransfer) {

            reset();

            this.dataToTransfer = dataToTransfer;
        }

        public boolean hasNext() {
            return dataToTransfer.length() > this.addressPointer;
        }

        public String getNextReadChunk() {
            return getNextDataChunk(CMD_READ_CONTINUE, DEFAULT_CHUNK_SIZE);
        }

        private String getNextDataChunk(String prefix, int chunkSize) {
            StringBuilder sb = new StringBuilder(prefix);
            sb.append(getNextChunk(chunkSize));
            return sb.toString();
        }

        protected String getNextChunk(int chunkSize) {

            int oldAddressPointer = this.addressPointer;
            // int chunkSize = this.chunkSize;

            if (dataToTransfer.length() < (oldAddressPointer + chunkSize)) {
                chunkSize = dataToTransfer.length() - oldAddressPointer;
                LOGGER.info("Reduced chunksize to: {}", chunkSize);
            }
            String chunk = dataToTransfer.substring(oldAddressPointer, oldAddressPointer + chunkSize);
            LOGGER.info("Return chunk: {}", chunk);

            // increment the junk index
            this.addressPointer += chunkSize;

            return chunk;
        }
    }

    private enum StorageTargetIndex {
        // @formatter:off
        target_decoder,
        target_motfuc;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy