Page MenuHomec4science

MetaMotionManager.java
No OneTemporary

File Metadata

Created
Tue, Sep 17, 10:39

MetaMotionManager.java

package ch.epfl.esl.elevatedmonitor.Devices.MetaMotionR;
import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.os.Build;
import android.support.v4.util.Pair;
import android.util.Log;
import com.mbientlab.metawear.MetaWearBoard;
import com.mbientlab.metawear.Route;
import com.mbientlab.metawear.Subscriber;
import com.mbientlab.metawear.data.Quaternion;
import com.mbientlab.metawear.module.Settings;
import com.mbientlab.metawear.module.Timer;
import java.util.ArrayList;
import java.util.Arrays;
import bolts.Continuation;
import bolts.Task;
import ch.epfl.esl.elevatedmonitor.Devices.MetaMotionR.Sensors.SensorFusion;
import ch.epfl.esl.elevatedmonitor.Devices.MetaMotionR.Sensors.Temperature;
import ch.epfl.esl.elevatedmonitor.Interfaces.InterfaceManager;
import ch.epfl.esl.elevatedmonitor.ServiceManager;
import ch.epfl.esl.elevatedmonitor.SuperClasses.Device;
import ch.epfl.esl.elevatedmonitor.SuperClasses.Manager;
public class MetaMotionManager extends Manager implements InterfaceManager{
private static final String TAG = "MetaWear Man SQUINCI";
//--------- Flags
private Boolean scanAllowed = true;
private ArrayList<ConnBool> connectings = new ArrayList<>();
private ArrayList<DisconBool> disconnectings = new ArrayList<>();
private ArrayList<MetaWearBoard> boards = new ArrayList<>();
private ArrayList<MetaWear> metaWears = new ArrayList<>();
private ArrayList<Pair<String, Timer.ScheduledTask>> scheduledTasks = new ArrayList<>();
public MetaMotionManager(Context context) {
super(context, TAG);
}
//--- Interface Manager
@Override
public void scan() {
if (scanAllowed) {
ServiceManager.scanBluetooth();
}
}
private class ConnBool {
private String id;
private Boolean bool;
ConnBool(String id, Boolean bool){
this.id = id;
this.bool = bool;
}
Boolean getBool(){
return bool;
}
void setBool(Boolean bool){
this.bool = bool;
}
public String getId(){
return id;
}
}
private class DisconBool {
private String id;
private Boolean bool;
DisconBool(String id, Boolean bool){
this.id = id;
this.bool = bool;
}
Boolean getBool(){
return bool;
}
void setBool(Boolean bool){
this.bool = bool;
}
public String getId(){
return id;
}
}
@Override
public void isDevice(String name, String address) {
boolean alreadyThere = false;
ArrayList<String> deviceNames = new ArrayList<>(Arrays.asList("MetaWear 0",
"MetaWear 1",
"MetaWear 2"));
for (Device device : getScannedDevices()) {
if (device.getId().equals(address)) {
alreadyThere = true;
}
deviceNames.remove(device.getName());
}
if(!deviceNames.isEmpty() && !alreadyThere) {
if (name != null && name.equals(MetaWear.NAME)) {
Log.d(TAG, "found device: " + name + " " + address);
MetaWear metaWear = new MetaWear(managerContext, deviceNames.get(0), address);
Log.d(TAG, "Found this one: " + deviceNames.get(0) + ": " + address);
addScannedDevice(metaWear);
ServiceManager.startActionScanned(managerContext);
connectings.add(new ConnBool(address, false));
disconnectings.add(new DisconBool(address, false));
}
}
}
@Override
public void stopScan() {
scanAllowed = false;
ServiceManager.stopScanBluetooth();
//Stop the process
Log.d(TAG, "Scan stopped");
}
private void connected(String deviceID) {
for (ConnBool conn : connectings){
if (conn.getId().equals(deviceID)){
conn.setBool(false);
}
}
boolean alreadyThere = false;
for (Device cd : getConnectedDevice()) {
if (cd.getId().equals(deviceID)) {
alreadyThere = true;
}
}
if(!alreadyThere) {
for (Device device : getScannedDevices()) {
if (deviceID.equals(device.getId())) {
for (MetaWearBoard board : boards) {
if (board.getMacAddress().equals(deviceID)) {
stopScan();
device.setConnected(true);
MetaWear metaWear = new MetaWear(managerContext, device.getName(), device.getId(), board);
metaWear.setConnected(true);
metaWears.add(metaWear);
addConnectedDevice(metaWear);
//Insert into file memory connected device
// saveConnectedFile();
Log.d(TAG, "Device Connected");
// Notify the Service Manager that there is a new connection
ServiceManager.startActionConnected(managerContext);
startStreaming(deviceID);
configureBatteryRoute(deviceID);
break;
}
}
}
}
}
}
private void configureBatteryRoute(String id){
for (MetaWear metaWear : metaWears) {
if (metaWear.getId().equals(id)) {
Settings settings = metaWear.getSettings();
settings.battery().addRouteAsync(source -> source.limit(1).stream((Subscriber) (data, env) -> {
for (Device cd : getConnectedDevice()) {
if (cd.getId().equals(id)) {
cd.setBatteryLevel((int) data.value(Settings.BatteryState.class).charge);
break;
}
}
ServiceManager.startActionBatteryRead(managerContext);
Log.d(TAG, "battery state = " + data.value(Settings.BatteryState.class));
})).continueWith((Continuation<Route, Void>) task -> {
settings.battery().read();
return null;
});
break;
}
}
}
@Override
public void readBatteryLevel(String id) {
for (MetaWear metaWear : metaWears) {
if (metaWear.getId().equals(id)) {
Settings settings = metaWear.getSettings();
settings.battery().read();
break;
}
}
}
private void startStreaming(String id){
for (MetaWear metaWear : metaWears) {
if (metaWear.getId().equals(id)) {
com.mbientlab.metawear.module.SensorFusionBosch sensorFusionBosch = metaWear.getSensorFusion();
sensorFusionBosch.quaternion().addRouteAsync(source -> source.limit(33).stream((Subscriber) (data, env) -> {
for (Device device : getConnectedDevice()) {
if (id.equals(device.getId())) {
device.getSensor(MetaWear.SENSOR_FUSION)
.getData(SensorFusion.W)
.set(data.value(Quaternion.class).w());
device.getSensor(MetaWear.SENSOR_FUSION)
.getData(SensorFusion.X)
.set(data.value(Quaternion.class).x());
device.getSensor(MetaWear.SENSOR_FUSION)
.getData(SensorFusion.Y)
.set(data.value(Quaternion.class).y());
device.getSensor(MetaWear.SENSOR_FUSION)
.getData(SensorFusion.Z)
.set(data.value(Quaternion.class).z());
device.getSensor(MetaWear.SENSOR_FUSION)
.getTimeStamp()
.set(data.timestamp());
ServiceManager.save(device.getId());
// Log.d("TIME", data.formattedTimestamp());
}
}
})).continueWith((Continuation<Route, Void>) ignored -> {
sensorFusionBosch.quaternion().start();
sensorFusionBosch.start();
return null;
});
}
}
}
private void scheduleTask(String id){
for (MetaWear metaWear : metaWears) {
if (metaWear.getId().equals(id)) {
metaWear.getTimer().scheduleAsync(60000, false, () ->
metaWear.getTemperatureSensor().read()).continueWith(task -> {
Timer.ScheduledTask scheduledTask;
scheduledTask = task.getResult();
scheduledTask.start();
scheduledTasks.add(new Pair<>(id,scheduledTask));
return null;
});
}
}
}
private void setTimer(String id){
for (MetaWear metaWear : metaWears) {
if (metaWear.getId().equals(id)) {
metaWear.getTemperatureSensor().addRouteAsync(source -> source.limit(1).stream((Subscriber) (data, env) -> {
Log.i(TAG, metaWear.getName() + " Temperature (C) = " + data.value(Float.class));
for (Device device : getConnectedDevice()) {
if (id.equals(device.getId())) {
device.getSensor(MetaWear.TEMPERATURE)
.getData(Temperature.TEMP)
.set(data.value(Float.class));
device.getSensor(MetaWear.TEMPERATURE)
.getTimeStamp()
.set(data.timestamp());
ServiceManager.save(device.getId());
break;
}
}
})).continueWith(task -> {
scheduleTask(id);
return null;
});
}
}
}
@Override
public void connect(String id) {
// Look if we are already connected to it
boolean connecting = false;
boolean alreadyThere = false;
for (Device cd : getConnectedDevice()) {
if (cd.getId().equals(id)) {
alreadyThere = true;
}
}
for (ConnBool conn : connectings){
if (conn.getId().equals(id)){
connecting = conn.getBool();
}
}
if(!alreadyThere && !connecting) {
// Inform that we have to connect.
for (ConnBool conn : connectings){
if (conn.getId().equals(id)){
conn.setBool(true);
}
}
for (Device device : getScannedDevices()) {
if (device.getId().equals(id)) {
// get BLE device
BluetoothDevice _device = ServiceManager.getBLEDevice(id);
if (ServiceManager.getMetawearBinder() != null) {
// Create a MetaWear board object for the Bluetooth Device
MetaWearBoard board;
board = ServiceManager.getMetawearBinder().getMetaWearBoard(_device);
boards.add(board);
board.onUnexpectedDisconnect(status -> {
Log.d(TAG, "Unexpected disconnection");
for (MetaWear metaWear : metaWears) {
if (metaWear.getId().equals(id)) {
if (board != null) {
for (Device cd : getConnectedDevice()) {
if (cd.getId().equals(metaWear.getId())) {
cd.setConnected(false);
cd.setScanned(false);
break;
}
}
for (Device sc : getScannedDevices()) {
if (sc.getId().equals(metaWear.getId())) {
sc.setConnected(false);
sc.setScanned(false);
break;
}
}
deleteDisconnectedDevice();
board.tearDown();
ServiceManager.startActionDisconnect(managerContext, metaWear.getName());
// If a saving has already been started, stop that saving
if (ServiceManager.saving()) {
ServiceManager.startActionStopOneSave(managerContext, metaWear.getId(), metaWear.getName());
}
board.connectAsync().continueWithTask(task -> {
if (task.isCancelled()) {
return task;
}
return task.isFaulted() ? reconnect(board) : task;
}).continueWith(task -> {
if (!task.isCancelled()) {
addScannedDevice(metaWear);
connected(id);
} else {
board.tearDown();
disconnected(id);
Log.d(TAG, "MetaWear Disconnected");
}
return null;
});
}
}
}
});
board.connectAsync().continueWithTask(task -> {
if (task.isCancelled()) {
return task;
}
return task.isFaulted() ? reconnect(board) : task;
}).continueWith(task -> {
if (!task.isCancelled()) {
board.getModule(Settings.class).editBleConnParams()
.maxConnectionInterval(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? 11.25f : 7.5f)
.commit();
connected(id);
setTimer(id);
}
return null;
});
} else {
ServiceManager.startActionScanned(managerContext);
Log.d(TAG, "I have to notify another action scan because I was not ready to connect yet, the service has not given me the reference to the board");
for (ConnBool conn : connectings){
if (conn.getId().equals(id)){
conn.setBool(false);
}
}
}
break;
}
}
}
}
private void disconnected(String id){
for (MetaWear metaWear : metaWears) {
if (metaWear.getId().equals(id)) {
for (Device device : getConnectedDevice()) {
if (device.getId().equals(id)) {
device.setConnected(false);
device.setScanned(false);
break;
}
}
for (Device device : getScannedDevices()) {
if (device.getId().equals(id)) {
device.setConnected(false);
device.setScanned(false);
break;
}
}
ServiceManager.stopScanBluetooth();
for (DisconBool discon : disconnectings){
if (discon.getId().equals(id)){
discon.setBool(false);
}
}
deleteDisconnectedDevice();
// If a saving has already been started, stop that saving
if (ServiceManager.saving()) {
ServiceManager.startActionStopOneSave(managerContext, metaWear.getId(), metaWear.getName());
}
ServiceManager.startActionDisconnect(managerContext, metaWear.getName());
scanAllowed = true;
}
}
}
@Override
public void disconnect(String id) {
boolean disconnecting = false;
for (DisconBool discon : disconnectings){
if (discon.getId().equals(id)){
disconnecting = discon.getBool();
}
}
for (MetaWear metaWear : metaWears) {
if (metaWear.getId().equals(id)) {
for (MetaWearBoard board : boards) {
if (board.getMacAddress().equals(id)) {
if (metaWear.isConnected() && !disconnecting) {
for (DisconBool discon : disconnectings){
if (discon.getId().equals(id)){
discon.setBool(true);
}
}
metaWear.getSensorFusion().stop();
metaWear.getSensorFusion().quaternion().stop();
ArrayList<Pair<String, Timer.ScheduledTask>> iterScheduledTasks = new ArrayList<>(scheduledTasks);
for (Pair<String, Timer.ScheduledTask> pair : iterScheduledTasks){
if (pair.first != null && pair.first.equals(id)){
if (pair.second != null){
pair.second.stop();
pair.second.remove();
}
}
}
board.tearDown();
// When you are done using your board, call tearDown to remove resources allocated by the firmware and API such as routes,
// loggers, and data processors. this method does not reset the board so any configuration changes are preserved.
board.disconnectAsync().continueWithTask(task -> task.isCancelled() || !task.isFaulted() ? task : disconnect(board))
.continueWith((Continuation<Void, Void>) task -> {
if (!task.isCancelled()) {
disconnected(id);
removeResources(id);
Log.d(TAG, "MetaWear Disconnected");
}
return null;
});
break;
}
}
}
}
}
}
private void removeResources(String id) {
ArrayList<ConnBool> iterConnectings = new ArrayList<>(connectings);
ArrayList<DisconBool> iterDisconnectings = new ArrayList<>(disconnectings);
ArrayList<MetaWearBoard> iterBoards = new ArrayList<>(boards);
ArrayList<MetaWear> iterMetaWears = new ArrayList<>(metaWears);
ArrayList<Pair<String, Timer.ScheduledTask>> iterscheduledTasks = new ArrayList<>(scheduledTasks);
for (MetaWearBoard board : iterBoards) {
if (board.getMacAddress().equals(id)){
boards.remove(board);
}
}
for (MetaWear metaWear : iterMetaWears) {
if (metaWear.getId().equals(id)){
metaWears.remove(metaWear);
}
}
for (Pair<String, Timer.ScheduledTask> pair : iterscheduledTasks) {
if (pair.first != null && pair.first.equals(id)){
scheduledTasks.remove(pair);
}
}
for (ConnBool connBool : iterConnectings){
if (connBool.getId().equals(id)){
connectings.remove(connBool);
}
}
for (DisconBool disconBool : iterDisconnectings){
if (disconBool.getId().equals(id)){
disconnectings.remove(disconBool);
}
}
}
@Override
public void onActivityResult(String requestCode, int resultCode) {
}
private static Task<Void> disconnect(final MetaWearBoard board) {
Log.d(TAG, "I'm trying to disconnect");
return board.disconnectAsync().continueWithTask(task -> task.isFaulted() ? disconnect(board) : task);
}
private static Task<Void> reconnect(final MetaWearBoard board) {
return board.connectAsync()
.continueWithTask(task -> {
if (task.isFaulted()) {
Log.d(TAG, "I'm trying to reconnect, task faulted");
return reconnect(board);
} else if (task.isCancelled()) {
Log.d(TAG, "Task cancelled.");
return task;
}
return Task.forResult(null);
});
}
}

Event Timeline