/**
* 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 Sofiane Sarni
*/
package org.openiot.gsn.wrappers;
import org.openiot.gsn.beans.DataField;
import org.openiot.gsn.beans.AddressBean;
import org.openiot.gsn.beans.StreamElement;
import java.io.*;
import java.util.Arrays;
import java.util.Vector;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import org.apache.log4j.Logger;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.DateTimeFormat;
/*
* This wrapper searches in a local directory for images
* that match the file-mask (given as regular expression)
* with the defined rate (rate parameter).
* The timestamp for the image is created from the file name following the time-format parameter
* See ./virtual-sensors/samples/imagefileexample.xml for an example
* */
public class ImageFileWrapper extends AbstractWrapper {
private static final transient Logger logger = Logger.getLogger(ImageFileWrapper.class);
private int threadCounter;
private String imagesDirectory;
private String fileExtension;
private String timeFormat;
private String fileMask;
private long rate;
private long latestProcessedTimestamp;
private static final String PARAM_DIRECTORY = "directory";
private static final String PARAM_FILE_MASK = "file-mask";
private static final String PARAM_TIME_FORMAT = "time-format";
private static final String PARAM_EXTENSION = "extension";
private static final String PARAM_RATE = "rate";
public DataField[] getOutputFormat() {
return new DataField[]{
new DataField("image", "binary:image/"+fileExtension, fileExtension+" image")};
}
public boolean initialize() {
setName(getWrapperName() + "-" + (++threadCounter));
AddressBean addressBean = getActiveAddressBean();
fileExtension = addressBean.getPredicateValue(PARAM_EXTENSION);
if (fileExtension == null) {
logger.warn("The > "+PARAM_EXTENSION+" < parameter is missing from the wrapper for VS " + this.getActiveAddressBean().getVirtualSensorName());
return false;
}
timeFormat = addressBean.getPredicateValue(PARAM_TIME_FORMAT);
if (timeFormat == null) {
logger.warn("The > "+PARAM_TIME_FORMAT+" < parameter is missing from the wrapper for VS " + this.getActiveAddressBean().getVirtualSensorName());
return false;
}
fileMask = addressBean.getPredicateValue(PARAM_FILE_MASK);
if (fileMask == null) {
logger.warn("The > "+PARAM_FILE_MASK+" < parameter is missing from the wrapper for VS " + this.getActiveAddressBean().getVirtualSensorName());
return false;
}
imagesDirectory = addressBean.getPredicateValue(PARAM_DIRECTORY);
if (imagesDirectory == null) {
logger.warn("The > "+PARAM_DIRECTORY+" < parameter is missing from the wrapper for VS " + this.getActiveAddressBean().getVirtualSensorName());
return false;
}
String rateStr = addressBean.getPredicateValue(PARAM_RATE);
if (rateStr != null) {
try {
rate = Integer.parseInt(rateStr);
} catch (NumberFormatException e) {
logger.warn("The > "+PARAM_RATE+" < parameter is invalid for wrapper in VS " + this.getActiveAddressBean().getVirtualSensorName());
return false;
}
} else {
logger.warn("The > "+PARAM_RATE+" < parameter is missing from the wrapper in VS " + this.getActiveAddressBean().getVirtualSensorName());
return false;
}
latestProcessedTimestamp=-1;
return true;
}
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
logger.error(e.getMessage(), e);
}
while (isActive()) {
try {
listOfNewFiles(imagesDirectory,fileMask);
Thread.sleep(rate);
} catch (InterruptedException e) {
logger.error(e.getMessage(), e);
}
}
}
public void dispose() {
threadCounter--;
}
public String getWrapperName() {
return "ImageFileWrapper";
}
/* converts time from string to long
* returns -1 if not successful
* */
private long strTime2Long(String s, String timeFormat) {
long l = -1;
try {
DateTimeFormatter fmt = DateTimeFormat.forPattern(timeFormat);
l = fmt.parseDateTime(s).getMillis();
}
catch (java.lang.IllegalArgumentException e) {
logger.warn(e.getMessage(), e);
}
return l;
}
private String getTimeStampFromFileName(String fileName, String regexMask) {
Pattern pattern = Pattern.compile(regexMask);
Matcher matcher = pattern.matcher(fileName);
if (matcher.find()) {
logger.debug("Date => "+matcher.group(1));
return matcher.group(1);
}
else {
logger.debug("Date => null");
return null;
}
}
/*
* posts new image files to database
* returns a list of file names in a directory,
* which match a fileMask (given as regular expression)
* */
private Vector<String> listOfNewFiles(String dir, String regexFileMask) {
File f = new File(dir);
String[] files = f.list();
Arrays.sort(files);
Vector <String> v = new Vector<String>();
logger.debug("*** found "+files.length+" files ***");
for (int i=0;i<files.length;i++) {
String file = files[i];
Pattern pattern = Pattern.compile(regexFileMask);
Matcher matcher = pattern.matcher(file);
logger.debug("("+i+") Testing... " + file);
if (matcher.find()) {
String date = getTimeStampFromFileName(file,regexFileMask);
long epoch = strTime2Long(date,timeFormat);
logger.debug("Matching => "+file + " date = "+ date + " epoch = "+epoch);
if (epoch>latestProcessedTimestamp) {
logger.debug("New image => "+epoch);
latestProcessedTimestamp = epoch;
v.add(file);
postData(dir+"/"+file,epoch);
}
}
}
return v;
}
/*
* Posting data to database
* */
private boolean postData(String imagePath, long timed) {
logger.debug("trying to post... " + imagePath);
boolean success = true;
Serializable[] stream = new Serializable[1];
try {
FileInputStream fileinputstream = new FileInputStream(imagePath);
int numberBytes = fileinputstream.available();
logger.debug("Image file has size: " + numberBytes + " bytes");
byte bytearray[] = new byte[numberBytes];
fileinputstream.read(bytearray);
fileinputstream.close();
stream[0] = bytearray;
} catch (FileNotFoundException e) {
logger.warn("Couldn't find image file: " + imagePath);
logger.warn(e.getMessage(), e);
success = false;
} catch (IOException e) {
logger.warn("Couldn't read image file: " + imagePath);
logger.warn(e.getMessage(), e);
success = false;
}
StreamElement se = new StreamElement(getOutputFormat(), stream, timed);
if (success) {
success = postStreamElement(se);
}
return success;
}
}