org.openiot.gsn.vsensor.RVirtualSensor.java Source code

Java tutorial

Introduction

Here is the source code for org.openiot.gsn.vsensor.RVirtualSensor.java

Source

/**
*    Copyright (c) 2011-2014, OpenIoT
*   
*    This file is part of OpenIoT.
*
*    OpenIoT is free software: you can redistribute it and/or modify
*    it under the terms of the GNU Lesser General Public License as published by
*    the Free Software Foundation, version 3 of the License.
*
*    OpenIoT is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*    GNU Lesser General Public License for more details.
*
*    You should have received a copy of the GNU Lesser General Public License
*    along with OpenIoT.  If not, see <http://www.gnu.org/licenses/>.
*
*     Contact: OpenIoT mailto: info@openiot.eu
 * @author sp3dy
 * @author Ali Salehi
 * @author Mehdi Riahi
*/

package org.openiot.gsn.vsensor;

import org.openiot.gsn.beans.DataField;
import org.openiot.gsn.beans.DataTypes;
import org.openiot.gsn.beans.StreamElement;

import java.io.File;
import java.io.Serializable;
import java.util.Hashtable;
import java.util.TreeMap;
import java.util.concurrent.ArrayBlockingQueue;

import org.apache.commons.io.FileUtils;
import org.apache.log4j.Logger;
import org.rosuda.REngine.REXP;
import org.rosuda.REngine.Rserve.RConnection;

public class RVirtualSensor extends AbstractVirtualSensor {

    private static final String WINDOW_SIZE = "window_size";
    private static final String STEP_SIZE = "step_size";
    private static final String OUTPUT_PLOT = "gsn_plot";
    private static final String SCRIPT = "script";
    private static final String SERVER = "server";
    private static final String PORT = "port";
    public String script = null;
    public String stype = null;

    private static transient Logger logger = Logger.getLogger(RVirtualSensor.class);

    private Hashtable<String, ArrayBlockingQueue<StreamElement>> circularBuffers;

    private int windowSize = -1;
    private int stepSize = -1;

    public RConnection rc;
    public REXP xp;

    public TreeMap<String, String> params = null;

    public boolean initialize() {
        params = getVirtualSensorConfiguration().getMainClassInitialParams();

        circularBuffers = new Hashtable<String, ArrayBlockingQueue<StreamElement>>();
        // Get the parameters from the XML configuration file

        String param = null;
        param = params.get(WINDOW_SIZE);

        if (param != null) {
            windowSize = Integer.parseInt(param);
        } else {
            logger.error("The required parameter: >" + WINDOW_SIZE
                    + "<+ is missing.from the virtual sensor configuration file.");
            return false;
        }

        param = params.get("script_type");
        if (param != null) {
            stype = param;
        } else {
            stype = "computation";
        }

        param = params.get(STEP_SIZE);

        if (param != null) {
            stepSize = Integer.parseInt(param);
        } else {
            logger.error("The required parameter: >" + STEP_SIZE
                    + "<+ is missing.from the virtual sensor configuration file.");
            return false;
        }

        if (windowSize < stepSize) {
            logger.error(
                    "The parameter " + WINDOW_SIZE + " must be greater or equal to the parameter " + STEP_SIZE);
            return false;
        }

        return true;
    }

    public void dataAvailable(String inputStreamName, StreamElement streamElement) {
        ArrayBlockingQueue<StreamElement> circularBuffer = circularBuffers.get(inputStreamName);

        // Get the circular buffer that matches the input stream. Create a new one
        // if none exists
        if (circularBuffer == null) {
            circularBuffer = new ArrayBlockingQueue<StreamElement>(windowSize);
            circularBuffers.put(inputStreamName, circularBuffer);
        }
        try {
            circularBuffer.put(streamElement);

            logger.debug(
                    "Window for " + inputStreamName + " contains: " + circularBuffer.size() + " of " + windowSize);

            if (circularBuffer.size() == windowSize) {
                logger.info("Window for " + inputStreamName + " contains: " + circularBuffer.size() + " of "
                        + windowSize);

                // Connect to Rserve and assign global variables
                try {
                    rc = new RConnection(params.get(SERVER), Integer.parseInt(params.get(PORT)));

                    logger.info("Connected to R server " + params.get(SERVER) + ":" + params.get(PORT));

                    String[] fieldname = streamElement.getFieldNames();

                    logger.info("Sending " + fieldname.length + " data attributes to R server.");

                    // Assign R vector variables prior the script
                    for (int n = 0; n < fieldname.length; n++) {
                        // Build the window
                        double[] values = new double[windowSize];
                        StreamElement elt = null;

                        // convert the circular buffer to an array
                        Object[] elts = circularBuffer.toArray();
                        for (int i = 0; i < elts.length; i++) {
                            elt = (StreamElement) elts[i];
                            values[i] = ((Number) elt.getData()[n]).doubleValue(); //
                        }

                        // assign vectors as R variables
                        rc.assign("gsn_" + fieldname[n].toLowerCase(), values);
                    }

                    logger.info("Done.");

                    // read the R script
                    // open the script file every time we do some processing (this can be
                    // improved).
                    File file = new File(params.get(SCRIPT).toString());
                    script = FileUtils.readFileToString(file, "UTF-8");

                    logger.info("Sending R script.");

                    // evaluate the R script
                    rc.voidEval(script);
                    logger.info("Done.");

                    // get the output timestamp
                    logger.info("Performing computation in R server (please wait).");

                    // collect vector values after computation
                    DataField[] outStructure = null;

                    outStructure = getVirtualSensorConfiguration().getOutputStructure();

                    String[] plotFieldName = new String[outStructure.length];
                    Byte[] plotFieldType = new Byte[outStructure.length];

                    for (int w = 0; w < outStructure.length; w++) {
                        plotFieldName[w] = outStructure[w].getName();
                        plotFieldType[w] = outStructure[w].getDataTypeID();
                    }

                    Serializable[] outputData = null;
                    StreamElement se = null;

                    Byte[] fieldType = streamElement.getFieldTypes();

                    // check if we have defined more attributes in the output structure
                    if (outStructure.length > fieldname.length) {
                        outputData = new Serializable[outStructure.length];
                    } else {
                        outputData = new Serializable[fieldname.length];
                    }

                    for (int n = 0; n < fieldname.length; n++) {
                        // evaluate/get attribute data from R server
                        xp = rc.parseAndEval(fieldname[n].toLowerCase());

                        if (fieldType[n] == DataTypes.DOUBLE) {
                            double[] b1 = xp.asDoubles();
                            outputData[n] = b1[b1.length - 1];
                        }

                        if (fieldType[n] == DataTypes.INTEGER) {
                            int[] b1 = xp.asIntegers();
                            outputData[n] = b1[b1.length - 1];
                        }

                        if (fieldType[n] == DataTypes.BIGINT) {
                            int[] b1 = xp.asIntegers();
                            outputData[n] = (long) b1[b1.length - 1];
                        }
                    }

                    int len1 = outStructure.length;
                    int len2 = fieldname.length;

                    // check if we have defined more attributes in the output structure
                    if (len1 > len2) {
                        if (stype.equals("plot")) {
                            xp = rc.parseAndEval("gsn_plot");
                            outputData[len2] = xp.asBytes();

                            se = new StreamElement(plotFieldName, plotFieldType, outputData);
                        }
                    } else {
                        se = new StreamElement(fieldname, fieldType, outputData);
                    }

                    logger.info("Computation finished.");

                    dataProduced(se);
                    logger.debug("Stream published: " + se.toString().toLowerCase());

                    // Close connection to R server
                    rc.close();
                    logger.info("Connection to R server closed.");

                } catch (Exception e) {
                    logger.warn(e);
                    // Close connection to R server
                    logger.info("Connection to R server closed.");
                    rc.close();
                }

                // Remove step size elements from the beginning of the buffer
                for (int i = 0; i < stepSize; i++) {
                    try {
                        circularBuffer.take();
                    } catch (InterruptedException e) {
                        logger.warn(e.getMessage(), e);
                    }
                }

            }

            // end if if for window
        } catch (InterruptedException e) {
            logger.warn(e.getMessage(), e);
        }

    }

    public void dispose() {

    }

    public int getPredicateValueAsIntWithException(String parameter) {
        String param = getVirtualSensorConfiguration().getMainClassInitialParams().get(parameter);
        if (param == null)
            throw new java.lang.RuntimeException("The required parameter: >" + parameter
                    + "<+ is missing.from the virtual sensor configuration file.");
        else
            return Integer.parseInt(param);
    }

}