Java tutorial
/* * Copyright (C) 2014 TU Darmstadt, Hessen, Germany. * Department of Computer Science Databases and Distributed Systems * * This program 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. * * This program 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. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ /** * */ package de.tudarmstadt.dvs.myhealthassistant.myhealthhub.services; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import android.app.Notification; import android.app.PendingIntent; import android.app.Service; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; import android.os.Binder; import android.os.Handler; import android.os.IBinder; import android.preference.PreferenceManager; import android.support.v4.content.LocalBroadcastManager; import android.util.Log; import de.tudarmstadt.dvs.myhealthassistant.myhealthhub.MyHealthHubWithFragments; import de.tudarmstadt.dvs.myhealthassistant.myhealthhub.Preferences; import de.tudarmstadt.dvs.myhealthassistant.myhealthhub.R; import de.tudarmstadt.dvs.myhealthassistant.myhealthhub.events.AbstractChannel; import de.tudarmstadt.dvs.myhealthassistant.myhealthhub.events.Event; import de.tudarmstadt.dvs.myhealthassistant.myhealthhub.events.management.Announcement; import de.tudarmstadt.dvs.myhealthassistant.myhealthhub.events.management.StartProducer; import de.tudarmstadt.dvs.myhealthassistant.myhealthhub.events.management.StopProducer; import de.tudarmstadt.dvs.myhealthassistant.myhealthhub.fragments.SensorConfigFragment; import de.tudarmstadt.dvs.myhealthassistant.myhealthhub.sensormodules.AbstractBluetoothSensorModule; import de.tudarmstadt.dvs.myhealthassistant.myhealthhub.sensormodules.AbstractSensorModule; import de.tudarmstadt.dvs.myhealthassistant.myhealthhub.sensormodules.cardiovascular.PolarHRModule; import de.tudarmstadt.dvs.myhealthassistant.myhealthhub.sensormodules.physical.AccSensorModule; import de.tudarmstadt.dvs.myhealthassistant.myhealthhub.sensormodules.physical.DebugSensorModule; import de.tudarmstadt.dvs.myhealthassistant.myhealthhub.sensorrepository.BodySensors; import de.tudarmstadt.dvs.myhealthassistant.myhealthhub.sensorrepository.cardiovascular.HeartRatePolarBluetoothSensor; import de.tudarmstadt.dvs.myhealthassistant.myhealthhub.sensorrepository.physical.PorcupineAccelerometer; /** * @author Christian Seeger * */ public class SensorModuleManager extends Service { /* for debugging */ private static String TAG = SensorModuleManager.class.getSimpleName(); private static boolean D = true; private DebugSensorModule mDebugAccSensor; // ECG Modules // private ZephyrHxMModule mZephyrHxmModule; private PolarHRModule mPolarHRModule; // Acc Modules private AccSensorModule mHedgeHogAccAnkleLegSensor; private AccSensorModule mPorcupineChestAccSensor; private AccSensorModule mHedgeHogWristSensor; private DebugSensorModule mHedgehogDebugSensor; // Blood Pressure private AbstractBluetoothSensorModule mCorscienceBloodPressureSensor; // Scale // Ambient Sensing // running sensor modules: eventType -> list of modules providing this event // type private HashMap<String, List<AbstractSensorModule>> availableSensorModules; // For auto-connect private SharedPreferences preferences; private static int AUTO_CONNECT_WARM_UP = 2000; // was: 3000 private static int AUTO_CONNECT_TIME_TO_NEXT_CONNECT = 3000; // was: 3000 private static int AUTO_CONNECT_TIME_UNTIL_NEXT_CONNECTION_CHECK = 3000; // was: // 60000 private static Handler autoConnectionHandler = new Handler(); private LinkedList<AbstractSensorModule> listOfActiveModules; // list of all // active // modules private int activeModulesPointer; // pointer in order to allow re-trying a // connection one after the other // Local management receiver private LocalManagementReceiver mLocalManagementReceiver; @Override public void onCreate() { if (D) Log.d(TAG, TAG + ": onCreate"); // Initialize map of running modules availableSensorModules = new HashMap<String, List<AbstractSensorModule>>(); // Initialize list of active modules that try to connect to their // sensors listOfActiveModules = new LinkedList<AbstractSensorModule>(); activeModulesPointer = 0; // Load preferences preferences preferences = PreferenceManager.getDefaultSharedPreferences(this); // TODO add further preferences such as timeouts // autoConnectionHandler.postDelayed(autoConnection, // AUTO_CONNECT_WARM_UP); // Subscribe to local management channel for receiving // StartProducer and StopProducer events mLocalManagementReceiver = new LocalManagementReceiver(); LocalBroadcastManager.getInstance(getApplicationContext()).registerReceiver(mLocalManagementReceiver, new IntentFilter(AbstractChannel.LOCAL_MANAGEMENT)); super.onCreate(); } @Override public int onStartCommand(Intent i, int flags, int startId) { // Log.e(TAG, // "call me redundant BABY! onStartCommand service"); Intent intent = new Intent(this, MyHealthHubWithFragments.class); PendingIntent pendIntent = PendingIntent.getActivity(this, 0, intent, 0); int myID = android.os.Process.myPid(); Notification notice = new Notification.Builder(getApplicationContext()).setSmallIcon(R.drawable.ic_launcher) .setWhen(System.currentTimeMillis()).setContentTitle(getPackageName()) .setContentText(TAG + " running").setContentIntent(pendIntent).getNotification(); notice.flags |= Notification.FLAG_AUTO_CANCEL; startForeground(myID, notice); // Start sensor connections startAutoConnectSensorModules(); return START_STICKY; } @Override public void onDestroy() { if (D) Log.d(TAG, "I was destroyed"); // Unregister local management receiver LocalBroadcastManager.getInstance(getApplicationContext()).unregisterReceiver(mLocalManagementReceiver); // stop auto-connection of active modules autoConnectionHandler.removeCallbacks(autoConnection); // stop all sensor modules stopSensorModules(); stopForeground(true); super.onDestroy(); } /** Management Receiver */ private class LocalManagementReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String eventType = ((Event) intent.getParcelableExtra(Event.PARCELABLE_EXTRA_EVENT)).getEventType(); if (D) Log.d(TAG, "Received local management event of type: " + eventType); if (D) { if (eventType.equals(Announcement.EVENT_TYPE)) { Announcement ann = (Announcement) intent.getParcelableExtra(Event.PARCELABLE_EXTRA_EVENT); Log.d(TAG, "Announcement: " + ann.getAnncouncementText()); } } // StartProducer event was received if (eventType.equals(StartProducer.EVENT_TYPE)) { StartProducer start = (StartProducer) intent.getParcelableExtra(Event.PARCELABLE_EXTRA_EVENT); if (D) Log.d(TAG, "searching for fitting event producer to start for event type: " + start.getStartEventType()); List<AbstractSensorModule> producers = availableSensorModules.get(start.getStartEventType()); if (producers != null) { // start each sensor modules that provides the required // event type for (AbstractSensorModule sensorModule : producers) { if (!sensorModule.isActiveModule()) { if (D) Log.i(TAG, "+ Incoming request for events of type '" + start.getShortStartEventType() + "' starting PASSIVE module: " + sensorModule.getModuleID() + "."); sensorModule.start(); } else { if (D) Log.i(TAG, "+ Incoming request for events of type '" + start.getShortStartEventType() + "' starting ACTIVE module: " + sensorModule.getModuleID() + "."); if (!sensorModule.isConnected()) sensorModule.start(); addToActiveModules(sensorModule); } } } else { if (D) Log.d(TAG, "List of producers is null"); } // StopProducer event was received } else if (eventType.equals(StopProducer.EVENT_TYPE)) { StopProducer stop = (StopProducer) intent.getParcelableExtra(Event.PARCELABLE_EXTRA_EVENT); if (D) Log.d(TAG, "searching for fitting event producer to stop for event type: " + stop.getStopEventType()); List<AbstractSensorModule> producers = availableSensorModules.get(stop.getStopEventType()); if (producers != null) { // stop each sensor modules that provides the required event // type for (AbstractSensorModule sensorModule : producers) { if (!sensorModule.isActiveModule()) { if (D) Log.i(TAG, "- Incoming stop request for events of type '" + stop.getShortStopEventType() + "' stopping PASSIVE module: " + sensorModule.getModuleID() + "."); sensorModule.stop(); } else { if (D) Log.i(TAG, "- Incoming stop request for events of type '" + stop.getShortStopEventType() + "' stopping ACTIVE module: " + sensorModule.getModuleID() + "."); sensorModule.stop(); removeFromActiveModules(sensorModule); } } } } } }; /** * Checks preferences for auto connection */ private void startAutoConnectSensorModules() { Log.e(TAG, "..."); if (preferences.getBoolean(Preferences.AUTO_CONNECT_ENABLED, false)) { if (D) Log.e(TAG, "Auto-Connect is selected. StartProducer enabling modules..."); String[] sensorTypesArray = getResources().getStringArray(R.array.sensor_type_config); for (String st : sensorTypesArray) { if (preferences.getBoolean(st, false)) { String type = preferences.getString(st + SensorConfigFragment.deviceType, ""); String deviceMac = preferences.getString(st + SensorConfigFragment.deviceMac, ""); if (!type.isEmpty() && !deviceMac.isEmpty()) { Log.i(TAG, st + "\n" + type + " --- " + deviceMac); enableSensorModule(type, true, type, deviceMac); } else Log.e(TAG, "sth might wrong here: " + st); } } } } private void stopSensorModules() { if (D) Log.e(TAG, "disabling modules..."); String[] sensorTypesArray = getResources().getStringArray(R.array.sensor_type_config); for (String st : sensorTypesArray) { AbstractSensorModule module = getModule(st); if (module != null) disable(module); } } public void enableSensorModule(String moduleKey, boolean enable, String id, String mac) { if (moduleKey.equals(getResources().getString(R.string.key_polar))) { if (enable) mPolarHRModule = (PolarHRModule) initializeSensorModule( new PolarHRModule(getApplicationContext(), new HeartRatePolarBluetoothSensor(id, mac))); else disable(mPolarHRModule); } // if (moduleKey.equals(getResources().getString(R.string.key_zephyrHxM))) { // if (enable) { // mZephyrHxmModule = (ZephyrHxMModule) initializeSensorModule(new ZephyrHxMModule( // getApplicationContext(), // new HeartRateZephyrHxM(id, mac))); // } else // disable(mZephyrHxmModule); // } if (moduleKey.equals(getResources().getString(R.string.key_debug))) { if (enable) mHedgehogDebugSensor = (DebugSensorModule) initializeSensorModule( new DebugSensorModule(getApplicationContext(), new PorcupineAccelerometer( BodySensors.ACC_HEDGEHOG_DEBUG_ID, BodySensors.ACC_HEDGEHOG_DEBUG_MAC))); else disable(mHedgehogDebugSensor); } } private Runnable autoConnection = new Runnable() { public void run() { boolean loop = true; AbstractSensorModule module; while (loop) { if (listOfActiveModules.size() == 0) { loop = false; } if (activeModulesPointer < listOfActiveModules.size()) { // TODO Check null Pointer Exception module = listOfActiveModules.get(activeModulesPointer); if (module != null && module.isConnected()) { activeModulesPointer++; } else { module.start(); activeModulesPointer++; checkNextDev(); loop = false; } } else { activeModulesPointer = 0; loop = false; waitBeforeCheckNextDev(); } } } private void checkNextDev() { if (D) Log.d(TAG, "autoConnection: checkNextDev()"); autoConnectionHandler.postDelayed(autoConnection, AUTO_CONNECT_TIME_TO_NEXT_CONNECT); } private void waitBeforeCheckNextDev() { autoConnectionHandler.postDelayed(autoConnection, AUTO_CONNECT_TIME_UNTIL_NEXT_CONNECTION_CHECK); } }; private AbstractSensorModule initializeSensorModule(AbstractSensorModule module) { // Initialize sensor module module.initializeSensorModule(); // Add module to list of available sensor modules addModuleToAvailableSensorModules(module); if (D) Log.i(TAG, "Module " + module.getModuleID() + " is initialized."); return module; } private void destroySensorModule(AbstractSensorModule module) { if (module != null) { module.destroySensorModule(); listOfActiveModules.remove(module); availableSensorModules.remove(module); module = null; } } /* * private void startInfraWoTModule() { if(mInfraWOTModule == null) * mInfraWOTModule = new InfraWotModule(this); } */ private void addModuleToAvailableSensorModules(AbstractSensorModule module) { List<AbstractSensorModule> modules = availableSensorModules.get(module.getProducingEventType()); if (D) Log.d(TAG, "Adding module for event type " + module.getProducingEventType() + " to availableSensorModules"); // Create new list if list does not exist already if (modules == null) { modules = new LinkedList<AbstractSensorModule>(); } // add module to list modules.add(module); availableSensorModules.put(module.getProducingEventType(), modules); } private void removeModuleFromAvailableSensorModules(AbstractSensorModule module) { // if module was not instantiated it can't be removed if (module == null) return; List<AbstractSensorModule> modules = availableSensorModules.get(module.getProducingEventType()); // Create new list if list does not exist already if (modules != null) { modules.remove(module); } } private void disable(AbstractSensorModule module) { removeModuleFromAvailableSensorModules(module); destroySensorModule(module); module = null; } private void addToActiveModules(AbstractSensorModule module) { listOfActiveModules.add(module); } private void removeFromActiveModules(AbstractSensorModule module) { listOfActiveModules.remove(module); } private AbstractSensorModule getModule(String moduleKey) { // switch with mapping sensor ID to its Module; if (moduleKey.equals(getResources().getString(R.string.key_polar))) { return mPolarHRModule; } // if (moduleKey.equals(getResources().getString(R.string.key_zephyrHxM))){ // return mZephyrHxmModule; // } if (moduleKey.equals(getResources().getString(R.string.key_debug))) { return mHedgehogDebugSensor; } return null; } @Override public IBinder onBind(Intent intent) { return mSensorModuleManagerBinder; } @Override public boolean onUnbind(Intent intent) { super.onUnbind(intent); return true; } private final IBinder mSensorModuleManagerBinder = new SensorModuleManagerBinder(); public class SensorModuleManagerBinder extends Binder { public boolean isActiveModule(String id) { AbstractSensorModule module = getModule(id); if (module != null) return module.isActiveModule(); return false; } public String getMacAddress(String sensorType) { String result = null; if (preferences != null) { result = preferences.getString(sensorType + SensorConfigFragment.deviceMac, ""); } return result; } // ********************* public void connectModule(String moduleKey) { AbstractSensorModule module = getModule(moduleKey); if (module != null) module.start(); } /** * Ha enableModule according to moduleKey * * @param moduleKey * @param enable * @param id * @param mac */ public void enableModule(String moduleKey, boolean enable, String id, String mac) { enableSensorModule(moduleKey, enable, id, mac); } // ********************************** } }