org.opendatakit.sensors.manager.ODKSensorManager.java Source code

Java tutorial

Introduction

Here is the source code for org.opendatakit.sensors.manager.ODKSensorManager.java

Source

/*
 * Copyright (C) 2013 University of Washington
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package org.opendatakit.sensors.manager;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;

import org.json.JSONArray;
import org.json.JSONObject;
import org.opendatakit.aggregate.odktables.rest.entity.Column;
import org.opendatakit.common.android.utilities.ODKDatabaseUtils;
import org.opendatakit.common.android.utilities.ODKJsonNames;
import org.opendatakit.sensors.CommunicationChannelType;
import org.opendatakit.sensors.DriverCommunicator;
import org.opendatakit.sensors.DriverType;
import org.opendatakit.sensors.GenericDriverProxy;
import org.opendatakit.sensors.ODKExternalSensor;
import org.opendatakit.sensors.ODKSensor;
import org.opendatakit.sensors.SensorDataPacket;
import org.opendatakit.sensors.SensorDriverDiscovery;
import org.opendatakit.sensors.SensorStateMachine;
import org.opendatakit.sensors.bluetooth.BluetoothManager;
import org.opendatakit.sensors.builtin.BuiltInSensorType;
import org.opendatakit.sensors.builtin.ODKBuiltInSensor;
import org.opendatakit.sensors.drivers.ManifestMetadata;
import org.opendatakit.sensors.tests.DummyManager;
import org.opendatakit.sensors.usb.USBManager;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;

/**
 * 
 * @author wbrunette@gmail.com
 * @author rohitchaudhri@gmail.com
 * 
 */
public class ODKSensorManager {

    private static final String TAG = "ODKSensorManager";
    private DatabaseManager databaseManager;

    private Thread workerThread;
    private Context svcContext;

    private Map<String, ODKSensor> sensors;
    private List<DriverType> driverTypes;
    private Map<CommunicationChannelType, ChannelManager> channelManagers;

    public ODKSensorManager(Context context, DatabaseManager dbManager, BluetoothManager btManager,
            USBManager usbManager, DummyManager dummyManager) {

        svcContext = context;
        this.databaseManager = dbManager;

        sensors = new Hashtable<String, ODKSensor>();
        channelManagers = new HashMap<CommunicationChannelType, ChannelManager>();

        channelManagers.put(btManager.getCommChannelType(), btManager);
        channelManagers.put(usbManager.getCommChannelType(), usbManager);
        channelManagers.put(dummyManager.getCommChannelType(), dummyManager);

        queryNupdateSensorDriverTypes();

        //XXX FIX THIS: This needs to move to the superclass. being done here because each f/w version has a different contenturi      
        workerThread = new WorkerThread(svcContext, this);
        workerThread.start();

    }

    public void initializeRegisteredSensors() {

        // discover built in sensors
        android.hardware.SensorManager builtInSensorManager = (android.hardware.SensorManager) svcContext
                .getSystemService(Context.SENSOR_SERVICE);
        if (builtInSensorManager != null) {
            List<android.hardware.Sensor> deviceSensors = builtInSensorManager
                    .getSensorList(android.hardware.Sensor.TYPE_ALL);
            for (android.hardware.Sensor hwSensor : deviceSensors) {
                BuiltInSensorType sensorType = BuiltInSensorType.convertToBuiltInSensor(hwSensor.getType());
                if (sensorType != null) {
                    try {
                        String id = sensorType.name();
                        //Log.d(TAG,"Found sensor "+ id);
                        ODKSensor sensor = new ODKBuiltInSensor(sensorType, builtInSensorManager, id);
                        sensors.put(id, sensor);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }

        // load sensors from the database      
        for (ChannelManager channelManager : channelManagers.values()) {
            CommunicationChannelType type = channelManager.getCommChannelType();
            Log.d(TAG, "Load from DB:" + type.name());

            List<SensorData> savedSensorList = databaseManager.sensorList(type);

            for (SensorData sensorData : savedSensorList) {
                Log.d(TAG, "Sensor in DB:" + sensorData.id + " Type:" + sensorData.type);
                DriverType driverType = getDriverType(sensorData.type);

                if (driverType != null) {
                    Log.d(TAG, "initing sensor from DB: id: " + sensorData.id + " driverType: " + sensorData.type
                            + " state " + sensorData.state);

                    if (connectToDriver(sensorData.id, driverType)) {
                        Log.d(TAG, sensorData.id + " connected to driver " + sensorData.type);

                        if (sensorData.state == DetailedSensorState.CONNECTED) {
                            try {
                                channelManager.sensorConnect(sensorData.id);
                                //                        updateSensorState(sensorData.id, DetailedSensorState.CONNECTED);
                                Log.d(TAG, "connected to sensor " + sensorData.id + " over "
                                        + channelManager.getCommChannelType());
                            } catch (SensorNotFoundException snfe) {
                                updateSensorState(sensorData.id, DetailedSensorState.DISCONNECTED);
                                Log.d(TAG, "SensorNotFoundException. unable to connect to sensor " + sensorData.id
                                        + " over " + channelManager.getCommChannelType());
                            }
                        }
                    }
                } else {
                    Log.e(TAG, "driver NOT FOUND for type : " + sensorData.type);
                }
            }
        }
    }

    private boolean connectToDriver(String id, DriverType driver) {
        // create the sensor      
        ODKExternalSensor sensorFacade = null;
        try {
            DriverCommunicator sensorDriver = new GenericDriverProxy(driver.getSensorPackageName(),
                    driver.getSensorDriverAddress(), this.svcContext);
            sensorFacade = new ODKExternalSensor(id, sensorDriver,
                    channelManagers.get(driver.getCommunicationChannelType()), driver.getReadingUiIntentStr(),
                    driver.getConfigUiIntentStr());
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        //put facade instead of driver
        sensors.put(id, sensorFacade);
        return true;
    }

    private void shutdownAllSensors() {
        for (ODKSensor sensor : sensors.values()) {
            try {
                sensor.shutdown();
            } catch (SensorNotFoundException snfe) {
                snfe.printStackTrace();
            }
        }
    }

    public void queryNupdateSensorDriverTypes() {
        List<DriverType> allDrivers = new ArrayList<DriverType>();
        List<DriverType> btDrivers = SensorDriverDiscovery.getAllDriversForChannel(svcContext,
                CommunicationChannelType.BLUETOOTH, ManifestMetadata.FRAMEWORK_VERSION_2);
        List<DriverType> usbDrivers = SensorDriverDiscovery.getAllDriversForChannel(svcContext,
                CommunicationChannelType.USB, ManifestMetadata.FRAMEWORK_VERSION_2);
        List<DriverType> dummyDrivers = SensorDriverDiscovery.getAllDriversForChannel(svcContext,
                CommunicationChannelType.DUMMY, ManifestMetadata.FRAMEWORK_VERSION_2);
        allDrivers.addAll(btDrivers);
        allDrivers.addAll(usbDrivers);
        allDrivers.addAll(dummyDrivers);
        driverTypes = allDrivers;
    }

    public void parseDriverTableDefintionAndCreateTable(String sensorId, String appName, SQLiteDatabase db) {
        String strTableDef = null;
        // Get the sensor information from the database
        SensorData sensorDataFromDb;
        if (databaseManager.sensorIsInDatabase(sensorId)) {
            sensorDataFromDb = databaseManager.getSensorDataForId(sensorId);
            DriverType driver = getDriverType(sensorDataFromDb.type);
            if (driver != null) {
                strTableDef = driver.getTableDefinitionStr();
            }
        }

        if (strTableDef == null) {
            return;
        }

        JSONObject jsonTableDef = null;

        try {

            jsonTableDef = new JSONObject(strTableDef);

            JSONObject theTableDef = jsonTableDef.getJSONObject(ODKJsonNames.jsonTableStr);

            String tableId = theTableDef.getString(ODKJsonNames.jsonTableIdStr);

            List<Column> columns = new ArrayList<Column>();

            // Create the columns for the driver table
            JSONArray colJsonArray = theTableDef.getJSONArray(ODKJsonNames.jsonColumnsStr);

            for (int i = 0; i < colJsonArray.length(); i++) {
                JSONObject colJson = colJsonArray.getJSONObject(i);
                String elementKey = colJson.getString(ODKJsonNames.jsonElementKeyStr);
                String elementName = colJson.getString(ODKJsonNames.jsonElementNameStr);
                String elementType = colJson.getString(ODKJsonNames.jsonElementTypeStr);
                String listChildElementKeys = colJson.getString(ODKJsonNames.jsonListChildElementKeysStr);
                columns.add(new Column(elementKey, elementName, elementType, listChildElementKeys));
            }

            // Create the table for driver
            ODKDatabaseUtils.get().createOrOpenDBTableWithColumns(db, appName, tableId, columns);

        } catch (Exception e) {
            e.printStackTrace();
        }

        db.close();
    }

    public DriverType getDriverType(String type) {
        DriverType foundDriverType = null;
        for (DriverType driverType : driverTypes) {
            if (driverType.getSensorType().equals(type)) {
                foundDriverType = driverType;
                break;
            }
        }
        return foundDriverType;
    }

    public ODKSensor getSensor(String id) {
        return sensors.get(id);
    }

    /**
     * Get the sensor status
     * @param id Sensor id.
     * @return SensorState as determined by communication manager.
     */

    public SensorStateMachine getSensorState(String id) {
        Log.d(TAG, "getting sensor state");
        ODKSensor sensor = sensors.get(id);
        if (sensor == null) {
            Log.e(TAG, "Can't find sensor type");
            return null;
        }

        ChannelManager cm = channelManagers.get(sensor.getCommunicationChannelType());
        if (cm == null) {
            Log.e(TAG, "unkown channel type: " + sensor.getCommunicationChannelType());
            return null;
        }

        return cm.getSensorStatus(id);
    }

    public void addSensorDataPacket(String id, SensorDataPacket sdp) {
        ODKSensor sensor = sensors.get(id);
        if (sensor != null) {
            sensor.addSensorDataPacket(sdp);
        } else {
            Log.e(TAG, "can't route data for sensor ID: " + id);
        }
    }

    public void shutdown() {
        shutdownAllSensors();
        ((WorkerThread) workerThread).stopthread();
    }

    public boolean addSensor(String id, DriverType driver) {

        if (driver == null) {
            return false;
        }

        Log.d(TAG, "sensor type: " + driver);
        connectToDriver(id, driver);

        databaseManager.sensorInsert(id, driver.getSensorType(), driver.getSensorType(),
                DetailedSensorState.DISCONNECTED, driver.getCommunicationChannelType());

        return true;
    }

    public List<ODKSensor> getSensorsUsingAppForDatabase() {
        List<ODKSensor> sensorList = new ArrayList<ODKSensor>();

        for (ODKSensor sensor : sensors.values()) {
            if (sensor.hasAppNameForDatabase()) {
                sensorList.add(sensor);
            }
        }
        return sensorList;
    }

    public void removeAllSensors() {
        shutdownAllSensors();
        sensors = new Hashtable<String, ODKSensor>();

        // TODO: after mobisys consider what is the right thing
        databaseManager.deleteAllSensors();
    }

    public List<DriverType> getDriverTypes() {
        return driverTypes;
    }

    public List<ODKSensor> getRegisteredSensors(CommunicationChannelType channelType) {
        List<ODKSensor> sensorList = new ArrayList<ODKSensor>();

        for (ODKSensor sensor : sensors.values()) {
            if (sensor.getCommunicationChannelType() == channelType) {
                sensorList.add(sensor);
            }
        }
        return sensorList;
    }

    public void updateSensorState(String id, DetailedSensorState state) {
        databaseManager.sensorUpdateState(id, state);
    }

    public DetailedSensorState querySensorState(String id) {
        return databaseManager.sensorQuerySensorState(id);
    }

    public String getSensorReadingUiIntentStr(String id) {
        ODKSensor sensor = sensors.get(id);
        if (sensor != null) {
            return sensor.getReadingUiIntentStr();
        }
        return null;
    }

    public String getSensorConfigUiIntentStr(String id) {
        ODKSensor sensor = sensors.get(id);
        if (sensor != null) {
            return sensor.getConfigUiIntentStr();
        }
        return null;
    }

    public boolean hasSensorReadingUi(String id) {
        ODKSensor sensor = sensors.get(id);
        if (sensor != null) {
            return sensor.hasReadingUi();
        }
        return false;
    }

    public boolean hasSensorConfigUi(String id) {
        ODKSensor sensor = sensors.get(id);
        if (sensor != null) {
            return sensor.hasConfigUi();
        }
        return false;
    }

    public DriverType getSensorDriverType(String sensorId) {
        DriverType sensorDriverType = getDriverType(databaseManager.sensorQueryType(sensorId));
        return sensorDriverType;

    }
}