/**
* 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
*/
package org.openiot.gsn.wrappers.sbox;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.Serializable;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
import org.apache.commons.lang.ArrayUtils;
import org.apache.log4j.Logger;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
import org.openiot.gsn.beans.AddressBean;
import org.openiot.gsn.beans.DataField;
import org.openiot.gsn.beans.DataTypes;
import org.openiot.gsn.wrappers.AbstractWrapper;
public class SboxWrapper extends AbstractWrapper {
private final transient Logger logger = Logger.getLogger(SboxWrapper.class);
// Instance params
private static int instanceCounter = 0;
// Sampling rate
private static final int DEFAULT_SAMPLING_RATE = 30000; // 30sec
private long samplingRate = DEFAULT_SAMPLING_RATE;
// Connection params
private String sensorServerHost;
private int sensorServerPort;
private String sensorUID;
// Field descriptions
private DataField[] fields;
public boolean initialize() {
AddressBean params = getActiveAddressBean();
if (params.getPredicateValue("rate") != null) {
samplingRate = (long) Integer.parseInt(params.getPredicateValue("rate"));
logger.info("Sampling rate set to " + samplingRate + " msec.");
}
if (params.getPredicateValue("host") != null) {
sensorServerHost = params.getPredicateValue("host");
} else {
logger.warn("Missing predicate >host<. Initialization failed");
return false;
}
if (params.getPredicateValue("port") != null) {
sensorServerPort = Integer.parseInt(params.getPredicateValue("port"));
} else {
logger.warn("Missing predicate >port<. Initialization failed");
return false;
}
if (params.getPredicateValue("sensorUID") != null) {
sensorUID = params.getPredicateValue("sensorUID");
} else {
logger.warn("Missing predicate >sensorUID<. Initialization failed");
return false;
}
// Connect to server to lookup field definitions
JSONArray fieldDefinitions = sendCommand("fields");
if (fieldDefinitions == null) {
logger.warn("Could not retrieve field definitions from server. Initialization failed");
return false;
}
initializeFields(fieldDefinitions);
// Setup wrapper name
setName(SboxWrapper.class.getSimpleName() + "[" + sensorServerHost + ":" + sensorServerPort + "][" + sensorUID + "]-TID_" + instanceCounter++);
return true;
}
public void run() {
while (isActive()) {
try {
// delay
Thread.sleep(samplingRate);
} catch (InterruptedException e) {
logger.error(e.getMessage(), e);
}
// Retrieve data from server
JSONArray state = sendCommand("state");
if (state == null) {
logger.error("Bad response from server");
} else {
Serializable[] dataPacket = new Serializable[fields.length];
for (int fieldIndex = 0; fieldIndex < fields.length; fieldIndex++) {
DataField fieldDefinition = this.fields[fieldIndex];
JSONObject dataMatch = null;
for (int dataIndex = 0; dataIndex < fields.length; dataIndex++) {
JSONObject fieldData = (JSONObject) state.get(dataIndex);
if (fieldDefinition.getName().equalsIgnoreCase((String) fieldData.get("name"))) {
dataMatch = fieldData;
break;
}
}
Object value = null;
if (dataMatch != null) {
value = dataMatch.get("value");
if (fieldDefinition.getDataTypeID() == DataTypes.BIGINT) {
value = Long.valueOf(value.toString());
} else if (fieldDefinition.getDataTypeID() == DataTypes.DOUBLE) {
value = Double.valueOf(value.toString());
} else if (fieldDefinition.getDataTypeID() == DataTypes.INTEGER) {
value = Integer.valueOf(value.toString());
} else if (fieldDefinition.getDataTypeID() == DataTypes.SMALLINT) {
value = Short.valueOf(value.toString());
} else if (fieldDefinition.getDataTypeID() == DataTypes.TINYINT) {
value = Byte.valueOf(value.toString());
} else if (fieldDefinition.getDataTypeID() == DataTypes.VARCHAR) {
value = value.toString();
}
}
dataPacket[fieldIndex] = (Serializable) value;
}
logger.debug("Sending new data packet for sensor " + sensorUID + ": " + ArrayUtils.toString(dataPacket));
// post the data to GSN
postStreamElement(dataPacket);
}
}
}
public DataField[] getOutputFormat() {
return fields;
}
public String getWrapperName() {
return "SBOX wrapper";
}
public void dispose() {
instanceCounter--;
}
protected void initializeFields(JSONArray fieldDefinitions) {
this.fields = new DataField[fieldDefinitions.size()];
for (int fieldIndex = 0; fieldIndex < fieldDefinitions.size(); fieldIndex++) {
JSONObject fieldDefinition = (JSONObject) fieldDefinitions.get(fieldIndex);
String fieldName = (String) fieldDefinition.get("name");
String fieldType = (String) fieldDefinition.get("type");
String fieldDescription = (String) fieldDefinition.get("description");
this.fields[fieldIndex] = new DataField(fieldName, fieldType, fieldDescription);
}
}
protected JSONArray sendCommand(String commandName) {
JSONObject request = new JSONObject();
request.put("command", commandName);
request.put("sensorUID", sensorUID);
Socket serverConnection = null;
try {
serverConnection = new Socket(sensorServerHost, sensorServerPort);
PrintWriter serverOutput = new PrintWriter(serverConnection.getOutputStream(), true);
BufferedReader serverInput = new BufferedReader(new InputStreamReader(serverConnection.getInputStream()));
// Send command
serverOutput.write(request.toJSONString() + "\n");
serverOutput.flush();
// Read output
String output = serverInput.readLine();
if (output == null || output.isEmpty()) {
return null;
}
Object response = JSONValue.parse(output);
if (response instanceof JSONArray) {
return (JSONArray) response;
}
logger.warn("Invalid response from server");
return null;
} catch (UnknownHostException ex) {
logger.warn("Unkown host >" + sensorServerHost + "<; connection attempt aborted");
return null;
} catch (IOException ex) {
logger.warn("IO exception connecting to host >" + sensorServerHost + "<; connection attempt aborted");
return null;
} finally {
if (serverConnection != null) {
try {
serverConnection.close();
} catch (Exception ex) {
logger.warn("Caught exception while disconnecting from host >" + sensorServerHost + "<");
return null;
}
}
}
}
}