/**
* Global Sensor Networks (GSN) Source Code
* Copyright (c) 2006-2014, Ecole Polytechnique Federale de Lausanne (EPFL)
* <p/>
* This file is part of GSN.
* <p/>
* GSN is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* <p/>
* GSN 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 General Public License for more details.
* <p/>
* You should have received a copy of the GNU General Public License
* along with GSN. If not, see <http://www.gnu.org/licenses/>.
* <p/>
* File: gsn-tiny/src/tinygsn/model/wrappers/AbstractWrapper.java
*
* @author Do Ngoc Hoan
*/
package tinygsn.model.wrappers;
import android.annotation.TargetApi;
import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.content.Intent;
import android.content.pm.FeatureInfo;
import android.content.pm.PackageManager;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import org.epfl.locationprivacy.util.Utils;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import java.util.Properties;
import tinygsn.beans.DataField;
import tinygsn.beans.StaticData;
import tinygsn.beans.StreamElement;
import tinygsn.beans.StreamSource;
import tinygsn.beans.WrapperConfig;
import tinygsn.model.utils.Parameter;
import tinygsn.services.WrapperService;
import tinygsn.storage.db.SqliteStorageManager;
import tinygsn.utils.Logging;
import tinygsn.utils.ToastUtils;
public abstract class AbstractWrapper {
public static final int DEFAULT_DUTY_CYCLE_DURATION = 2;
public static final int DEFAULT_DUTY_CYCLE_INTERVAL = 15;
protected final List<StreamSource> listeners = Collections
.synchronizedList(new ArrayList<StreamSource>());
protected int dcDuration = DEFAULT_DUTY_CYCLE_DURATION;
protected int dcInterval = DEFAULT_DUTY_CYCLE_INTERVAL;
protected HashMap<String, String> parameters = new HashMap<>();
private WrapperConfig config = null;
private static final String LOGTAG = "AbstractWrapper";
public AbstractWrapper(WrapperConfig wc) {
config = wc;
}
public AbstractWrapper() {
}
@TargetApi(Build.VERSION_CODES.KITKAT_WATCH)
public static Properties getWrapperList(Context context) {
Properties wrapperList = new Properties();
Properties wrapperListTemp = new Properties();
try {
InputStream is = context.getAssets().open("wrapper_list.properties");
wrapperList.load(is);
int currentAPIVersion = android.os.Build.VERSION.SDK_INT;
//KITKAT corresponds to API 19
if (currentAPIVersion > Build.VERSION_CODES.KITKAT) {
SensorManager deviceSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
List<android.hardware.Sensor> sensorList = deviceSensorManager.getSensorList(Sensor.TYPE_ALL);
Iterator it = sensorList.iterator();
while (it.hasNext()) {
Sensor sensorObject = (Sensor) it.next();
String property = wrapperList.getProperty(sensorObject.getStringType());
if (property != null) {
wrapperListTemp.put(sensorObject.getStringType(), property);
}
}
PackageManager pm = context.getPackageManager();
FeatureInfo[] featureInfos = pm.getSystemAvailableFeatures();
for (FeatureInfo featureInfo : featureInfos) {
if (featureInfo.name != null) {
String property = wrapperList.getProperty(featureInfo.name);
if (property != null) {
wrapperListTemp.put(featureInfo.name, property);
}
}
}
if (isPlayServiceAvailable()) {
wrapperListTemp.put("activityrecognition", wrapperList.getProperty("android.google.activityrecognition"));
}
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter != null) {
if (!mBluetoothAdapter.isEnabled()) {
ToastUtils.showToastInUiThread(context, "To connect to external sensors, please enable Bluetooth.", Toast.LENGTH_LONG);
} else {
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
wrapperListTemp.put("serial.bluetoothle.openswiss", wrapperList.getProperty("serial.bluetoothle.openswiss"));
}else{
ToastUtils.showToastInUiThread(context, "Bluetooth Low Energy not available.", Toast.LENGTH_LONG);
}
wrapperListTemp.put("serial.bluetooth.openswiss", wrapperList.getProperty("serial.bluetooth.openswiss"));
}
}
//wrapperListTemp.put("file_reader", wrapperList.getProperty("file_reader"));
wrapperList = wrapperListTemp;
}
} catch (IOException e) {
}
return wrapperList;
}
//Check for Google play services available on device
private static boolean isPlayServiceAvailable() {
return GooglePlayServicesUtil.isGooglePlayServicesAvailable(StaticData.globalContext) == ConnectionResult.SUCCESS;
}
public WrapperConfig getConfig() {
return config;
}
public void setConfig(WrapperConfig config) {
this.config = config;
}
public abstract Class<? extends WrapperService> getSERVICE();
public int getDcDuration() {
return dcDuration;
}
public int getDcInterval() {
return dcInterval;
}
public void registerListener(StreamSource s) {
synchronized (listeners) {
Log.i(getWrapperName(), "registered");
listeners.add(s);
}
}
public void unregisterListener(StreamSource s) {
synchronized (listeners) {
Log.i(getWrapperName(), "unregistered");
listeners.remove(s);
}
}
/**
* The output structure should be specified in the XML config file. However,
* for the simplicity of this tinygsn version, we return it from wrapper.
*
* @return
*/
public abstract DataField[] getOutputStructure();
/**
* This method gets the generated stream element and notifies the input
* streams if needed. The return value specifies if the newly provided stream
* element generated at least one input stream notification or not.
*
* @param streamElement
* @return If the method returns false, it means the insertion doesn't
* effected any input stream.
*/
public Boolean postStreamElement(StreamElement streamElement) {
synchronized (listeners) {
for (StreamSource s : listeners) {
if (s.getInputStream().getVirtualSensor().getConfig().getRunning()) {
s.add(streamElement);
}
}
}
return true;
}
public void releaseResources() {
config.setRunning(false);
}
public boolean isRunning() {
return config.isRunning();
}
public abstract String[] getFieldList();
public abstract Byte[] getFieldType();
public abstract void runOnce();
public String getWrapperName() {
return this.getClass().getName();
}
public void updateWrapperInfo() {
SqliteStorageManager storage = new SqliteStorageManager();
int[] info = storage.getWrapperInfo(getWrapperName());
if (info != null) {
dcInterval = info[0];
dcDuration = info[1];
}
}
synchronized public boolean start() {
try {
Intent serviceIntent = StaticData.getRunningIntentByName(getWrapperName());
if (serviceIntent == null) {
serviceIntent = new Intent(StaticData.globalContext, getSERVICE());
config.setRunning(true);
Bundle bundle = new Bundle();
bundle.putParcelable("tinygsn.beans.config", config);
serviceIntent.putExtra("tinygsn.beans.config", bundle);
StaticData.addRunningService(getWrapperName(), serviceIntent);
StaticData.globalContext.startService(serviceIntent);
return true;
}
} catch (Exception e) {
// release anything?
}
return false;
}
synchronized public boolean stop() {
try {
Intent serviceIntent = StaticData.getRunningIntentByName(getWrapperName());
if (serviceIntent != null) {
serviceIntent.removeExtra("tinygsn.beans.config");
config.setRunning(false);
Bundle bundle = new Bundle();
bundle.putParcelable("tinygsn.beans.config", config);
serviceIntent.putExtra("tinygsn.beans.config", bundle);
StaticData.globalContext.startService(serviceIntent);
StaticData.IntentStopped(getWrapperName());
return true;
}
} catch (Exception e) {
// release anything?
}
return false;
}
public void initialize_wrapper() {
SqliteStorageManager storage = new SqliteStorageManager();
HashMap<String, String> param = storage.getSetting("wrapper:" + config.getWrapperName() + ":");
for (Entry<String, String> e : param.entrySet()) {
initParameter(e.getKey(), e.getValue());
}
initialize();
}
public void update_wrapper() {
SqliteStorageManager storage = new SqliteStorageManager();
HashMap<String, String> param = storage.getSetting("wrapper:" + config.getWrapperName() + ":");
parameters.clear();
for (Entry<String, String> e : param.entrySet()) {
parameters.put(e.getKey(), e.getValue());
}
}
protected void initParameter(String key, String value) {
parameters.put(key, value);
}
public ArrayList<Parameter> getParameters() {
return new ArrayList<>();
}
public void initialize() {
}
protected static void log(Context context, String s) {
/*if ((boolean) Utils.getBuildConfigValue(context, "LOGGING")) {
Log.d(LOGTAG, s);
Logging.createNewLoggingFolder(context, "Wrapper");
Logging.appendLog("Wrapper", LOGTAG + ".txt", s, context);
}*/
}
}