Merge remote-tracking branch 'origin/main'

# Conflicts:
#	code/src/Fitbot/app/src/main/java/com/example/fitbot/EndScreenActivity.java
#	code/src/Fitbot/app/src/main/java/com/example/fitbot/ui/activities/FitnessActivity.java
#	code/src/Fitbot/app/src/main/res/layout/activity_fitness.xml
This commit is contained in:
Luca Warmenhoven
2024-05-22 11:03:11 +03:00
44 changed files with 1900 additions and 414 deletions

View File

@@ -1,6 +1,6 @@
#include "headerFile.h"
SensorManager::Rotation offset;
// SensorManager::Rotation offset;
void setup() {
Serial.begin(9600);
@@ -10,51 +10,49 @@ void setup() {
sensorManager.sensorSetup();
//ws server address, port and URL
webSocket.begin("145.3.245.22", 8001, "");
webSocket.begin("145.28.160.108", 8001, "");
// try every 500 again if connection has failed
webSocket.setReconnectInterval(500);
}
void loop() {
SensorManager::Rotation rotation = sensorManager.readLoop();
SensorManager::eulerAngles eulerRotation = sensorManager.getEulerAngles();
// Subtract offset
rotation.i -= offset.i;
rotation.j -= offset.j;
rotation.k -= offset.k;
rotation.w -= offset.w;
// rotation.i -= offset.i;
// rotation.j -= offset.j;
// rotation.k -= offset.k;
// rotation.w -= offset.w;
// Convert quaternion to Euler angles in radians
float roll = atan2(2.0f * (rotation.w * rotation.i + rotation.j * rotation.k), 1.0f - 2.0f * (rotation.i * rotation.i + rotation.j * rotation.j));
float pitch = asin(2.0f * (rotation.w * rotation.j - rotation.k * rotation.i));
float yaw = atan2(2.0f * (rotation.w * rotation.k + rotation.i * rotation.j), 1.0f - 2.0f * (rotation.j * rotation.j + rotation.k * rotation.k));
// Convert to degrees
float rollDegrees = roll * 180.0f / PI;
float pitchDegrees = pitch * 180.0f / PI;
float yawDegrees = yaw * 180.0f / PI;
// float rollDegrees = roll * 180.0f / PI;
// float pitchDegrees = pitch * 180.0f / PI;
// float yawDegrees = yaw * 180.0f / PI;
Serial.print(roll);
Serial.print(eulerRotation.roll);
Serial.print(" ");
Serial.print(pitch);
Serial.print(eulerRotation.pitch);
Serial.print(" ");
Serial.print(yaw);
sendData(roll, pitch, yaw);
Serial.print(eulerRotation.yaw);
sendData(eulerRotation.roll, eulerRotation.pitch, eulerRotation.yaw);
Serial.println();
webSocket.loop();
if (Serial.available()) {
String command = Serial.readStringUntil('\n');
command.trim(); // remove any trailing whitespace
if (command == "setZeroPoint") {
setZeroPoint();
}
}
}
void setZeroPoint() {
offset = sensorManager.readLoop();
}
// if (Serial.available()) {
// String command = Serial.readStringUntil('\n');
// command.trim(); // remove any trailing whitespace
// if (command == "setZeroPoint") {
// setZeroPoint();
// }
// }
// }
// void setZeroPoint() {
// offset = sensorManager.readLoop();
// }
void sendData(float roll, float pitch, float yaw){
String message = "{\"Sensor\": 1, \"roll\":\"" + String(roll) + "\",\"pitch\":\"" + String(pitch) + "\",\"yaw\":\"" + String(yaw) + "\"}";

View File

@@ -15,12 +15,12 @@ void SensorManager::sensorSetup() {
//start sensorfunction and start autocalibration
//once calibration is enabled it attempts to every 5 min
Wire.setClock(400000); //Increase I2C data rate to 400kHz
myIMU.calibrateAll(); //Turn on cal for Accel, Gyro, and Mag
myIMU.enableGyroIntegratedRotationVector(100); //send data every 100ms
myIMU.enableMagnetometer(100); //Send data update every 100ms
myIMU.saveCalibration(); //Saves the current dynamic calibration data (DCD) to memory
myIMU.requestCalibrationStatus(); //Sends command to get the latest calibration status
Wire.setClock(400000); //Increase I2C data rate to 400kHz
myIMU.calibrateAll(); //Turn on cal for Accel, Gyro, and Mag
myIMU.enableGyroIntegratedRotationVector(100); //send data every 100ms
myIMU.enableMagnetometer(100); //Send data update every 100ms
myIMU.saveCalibration(); //Saves the current dynamic calibration data (DCD) to memory
myIMU.requestCalibrationStatus(); //Sends command to get the latest calibration status
if (myIMU.calibrationComplete() == true) {
Serial.println("Calibration data successfully stored");
@@ -29,23 +29,31 @@ void SensorManager::sensorSetup() {
Serial.println(F("magnetometer rotation enabled"));
}
SensorManager::Rotation SensorManager::readLoop() {
SensorManager::RotationQuintillions SensorManager::getQuintillions() {
if (myIMU.dataAvailable() == true) {
float i = myIMU.getQuatI();
float j = myIMU.getQuatJ();
float k = myIMU.getQuatK();
float w = myIMU.getQuatReal();
Rotation rotation = { i, j, k, w };
RotationQuintillions rotation = { i, j, k, w };
return rotation;
}
else {
} else {
float i = myIMU.getQuatI();
float j = myIMU.getQuatJ();
float k = myIMU.getQuatK();
float w = myIMU.getQuatReal();
Rotation rotation = { i, j, k, w };
RotationQuintillions rotation = { i, j, k, w };
return rotation;
}
}
SensorManager::eulerAngles SensorManager::getEulerAngles() {
SensorManager::RotationQuintillions rotation = getQuintillions();
float roll = atan2(2.0f * (rotation.w * rotation.i + rotation.j * rotation.k), 1.0f - 2.0f * (rotation.i * rotation.i + rotation.j * rotation.j));
float pitch = asin(2.0f * (rotation.w * rotation.j - rotation.k * rotation.i));
float yaw = atan2(2.0f * (rotation.w * rotation.k + rotation.i * rotation.j), 1.0f - 2.0f * (rotation.j * rotation.j + rotation.k * rotation.k));
eulerAngles EulerAngles = { roll, pitch, yaw };
return EulerAngles;
}

View File

@@ -5,18 +5,26 @@
#include "SparkFun_BNO080_Arduino_Library.h"
class SensorManager {
public:
SensorManager();
void sensorSetup();
struct Rotation {
float i;
float j;
float k;
float w;
};
Rotation readLoop();
private:
BNO080 myIMU;
public:
SensorManager();
void sensorSetup();
struct eulerAngles {
float roll;
float pitch;
float yaw;
};
eulerAngles getEulerAngles();
private:
struct RotationQuintillions {
float i;
float j;
float k;
float w;
};
RotationQuintillions getQuintillions();
BNO080 myIMU;
};
#endif

View File

@@ -0,0 +1,33 @@
#include <BLEDevice.h>
#include <BLEServer.h>
// Define the service UUID
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
// Define the characteristic UUID
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
void setup() {
// Create a BLE server
BLEServer *pServer = BLEDevice::createServer();
// Create a BLE service
BLEService *pService = pServer->createService(SERVICE_UUID);
// Create a BLE characteristic
BLECharacteristic *pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_READ);
// Set the characteristic value
pCharacteristic->setValue("Hello, Bluetooth!");
// Start the service
pService->start();
// Start advertising the service
pServer->getAdvertising()->start();
}
void loop() {
// Nothing to do here
}

View File

@@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="deploymentTargetDropDown">
<targetSelectedWithDropDown>
<Target>
<type value="QUICK_BOOT_TARGET" />
<deviceKey>
<Key>
<type value="VIRTUAL_DEVICE_PATH" />
<value value="C:\Users\sebas\.android\avd\Pepper_1.9_API_29.avd" />
</Key>
</deviceKey>
</Target>
</targetSelectedWithDropDown>
<timeTargetWasSelectedWithDropDown value="2024-04-26T10:10:48.222593700Z" />
</component>
</project>

View File

@@ -13,6 +13,7 @@
<entry key="..\:/Users/Niels/muupooviixee66-3/code/src/Fitbot/app/src/main/res/drawable/rectangle.xml" value="0.1665" />
<entry key="..\:/Users/Niels/muupooviixee66-3/code/src/Fitbot/app/src/main/res/layout/activity_end_screen.xml" value="0.165" />
<entry key="..\:/Users/Niels/muupooviixee66-3/code/src/Fitbot/app/src/main/res/layout/activity_endscreen.xml" value="0.1" />
<entry key="..\:/Users/Niels/muupooviixee66-3/code/src/Fitbot/app/src/main/res/layout/activity_fitness.xml" value="0.1234375" />
<entry key="..\:/Users/Niels/muupooviixee66-3/code/src/Fitbot/app/src/main/res/layout/activity_main.xml" value="0.1" />
<entry key="..\:/Users/Niels/muupooviixee66-3/code/src/Fitbot/app/src/main/res/layout/header.xml" value="0.1234375" />
<entry key="..\:/Users/sebas/Documents/HvA/Reposetories/muupooviixee66/code/src/Fitbot/app/src/main/res/drawable-v24/ic_launcher_foreground.xml" value="0.25" />
@@ -40,6 +41,45 @@
</map>
</option>
</component>
<component name="NullableNotNullManager">
<option name="myDefaultNullable" value="androidx.annotation.Nullable" />
<option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
<option name="myNullables">
<value>
<list size="12">
<item index="0" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableDecl" />
<item index="1" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
<item index="2" class="java.lang.String" itemvalue="androidx.annotation.Nullable" />
<item index="3" class="java.lang.String" itemvalue="org.eclipse.jdt.annotation.Nullable" />
<item index="4" class="java.lang.String" itemvalue="com.android.annotations.Nullable" />
<item index="5" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
<item index="6" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNullable" />
<item index="7" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
<item index="8" class="java.lang.String" itemvalue="javax.annotation.CheckForNull" />
<item index="9" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
<item index="10" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.Nullable" />
<item index="11" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableType" />
</list>
</value>
</option>
<option name="myNotNulls">
<value>
<list size="11">
<item index="0" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNonNull" />
<item index="1" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.NonNull" />
<item index="2" class="java.lang.String" itemvalue="com.android.annotations.NonNull" />
<item index="3" class="java.lang.String" itemvalue="androidx.annotation.NonNull" />
<item index="4" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullType" />
<item index="5" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
<item index="6" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullDecl" />
<item index="7" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
<item index="8" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
<item index="9" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
<item index="10" class="java.lang.String" itemvalue="org.eclipse.jdt.annotation.NonNull" />
</list>
</value>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="11" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>

View File

@@ -7,7 +7,7 @@ android {
defaultConfig {
applicationId "com.example.fitbot"
minSdk 29
minSdk 23
targetSdk 29
versionCode 1
versionName "1.0"

View File

@@ -7,6 +7,12 @@
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.BLUETOOTH_SCAN"/>
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-feature android:name="android.hardware.bluetooth" android:required="true" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<application
android:allowBackup="true"
@@ -16,7 +22,7 @@
android:supportsRtl="true"
android:theme="@style/Theme.Fitbot" >
<activity
android:name=".EndScreenActivity"
android:name=".ui.activities.EndScreenActivity"
android:exported="false" />
<activity
android:name=".ui.activities.FitnessActivity"

View File

@@ -0,0 +1,34 @@
/*
Copyright 2008 Nedim Jackman
This file is part of Wiiboard Simple
Wiiboard Simple 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, either version 3 of the License, or
(at your option) any later version.
Wiiboard Simple 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 Wiiboard Simple. If not, see <http://www.gnu.org/licenses/>.
*/
package com.example.fitbot.bluetooth;
/**
* In very basic structure, all bluetooth devices have an address that the connection
* is associated with.
*/
public interface BluetoothDevice {
/**
* The fixed address of the device.
* Constant throughout the connection of the device.
*/
public String getBluetoothAddress();
}

View File

@@ -0,0 +1,133 @@
package com.example.fitbot.bluetooth;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.Context;
import android.util.Log;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.UUID;
public class BluetoothManager {
private BluetoothAdapter bluetoothAdapter;
private Context context;
public BluetoothManager(Context context) {
this.context = context;
this.bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
}
public boolean isBluetoothSupported() {
return bluetoothAdapter != null;
}
public boolean isBluetoothEnabled() {
return bluetoothAdapter.isEnabled();
}
public void startDiscovery() {
if (!isBluetoothEnabled()) {
Log.e("BluetoothManager", "Bluetooth is not enabled");
return;
}
if (bluetoothAdapter.isDiscovering()) {
bluetoothAdapter.cancelDiscovery();
Log.d("BluetoothManager", "Cancelling current discovery process...");
}
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
context.registerReceiver(receiver, filter);
bluetoothAdapter.startDiscovery();
Log.d("BluetoothManager", "Starting discovery process...");
}
public final BroadcastReceiver receiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (device.getName() != null && device.getName().contains("Nintendo RVL-WBC-01")) {
Log.d("BluetoothManager", "Wii Balance Board found: " + device.getName() + " [" + device.getAddress() + "]");
connectToDevice(device);
}
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
context.unregisterReceiver(this);
Log.d("BluetoothManager", "Discovery finished.");
}
}
};
public void connectToDevice(BluetoothDevice device) {
new Thread(() -> {
BluetoothSocket socket = null;
final int MAX_RETRIES = 3;
final long RETRY_DELAY_MS = 1000;
boolean isConnected = false;
for (int attempt = 1; attempt <= MAX_RETRIES; attempt++) {
try {
UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
socket = device.createRfcommSocketToServiceRecord(SPP_UUID);
bluetoothAdapter.cancelDiscovery();
byte[] pinBytes = getPinBytes(device.getAddress());
try {
Method setPinMethod = device.getClass().getDeclaredMethod("setPin", byte[].class);
setPinMethod.invoke(device, pinBytes);
Log.d("BluetoothManager", "PIN set successfully");
} catch (Exception e) {
Log.e("BluetoothManager", "Failed to set PIN", e);
}
socket.connect();
Log.d("BluetoothManager", "Connected to Wii Balance Board");
isConnected = true;
break;
} catch (IOException e) {
Log.e("BluetoothManager", "Connection attempt " + attempt + " failed", e);
if (attempt < MAX_RETRIES) {
try {
Thread.sleep(RETRY_DELAY_MS);
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
break;
}
}
} finally {
if (!isConnected && socket != null) {
try {
socket.close();
} catch (IOException ex) {
Log.e("BluetoothManager", "Could not close the client socket", ex);
}
}
}
}
if (!isConnected) {
Log.e("BluetoothManager", "All connection attempts failed.");
}
}).start();
}
private byte[] getPinBytes(String address) {
String[] addrParts = address.split(":");
byte[] pin = new byte[addrParts.length];
for (int i = 0; i < addrParts.length; i++) {
pin[i] = (byte) Integer.parseInt(addrParts[addrParts.length - 1 - i], 16);
}
Log.i("BluetoothManager", "PIN: " + pin);
return pin;
}
}

View File

@@ -1,4 +1,4 @@
package com.example.fitbot;
package com.example.fitbot.sports;
import android.support.v7.app.AppCompatActivity;
@@ -7,6 +7,7 @@ import com.aldebaran.qi.sdk.builder.AnimateBuilder;
import com.aldebaran.qi.sdk.builder.AnimationBuilder;
import com.aldebaran.qi.sdk.object.actuation.Animate;
import com.aldebaran.qi.sdk.object.actuation.Animation;
import com.example.fitbot.ui.activities.MainActivity;
public class Animations extends AppCompatActivity {

View File

@@ -1,10 +1,10 @@
package com.example.fitbot;
package com.example.fitbot.ui.activities;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.Button;
import com.example.fitbot.R;
import com.example.fitbot.ui.activities.FitnessActivity;
import com.example.fitbot.ui.activities.MainActivity;
public class EndScreenActivity extends AppCompatActivity {
@@ -13,12 +13,8 @@ public class EndScreenActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_end_screen);
Button homeButton = findViewById(R.id.homeButton);
homeButton.setOnClickListener(v -> {
Intent intent = new Intent(EndScreenActivity.this, MainActivity.class);
startActivity(intent);
finish();
});
com.example.fitbot.util.ButtonNavigation.setupButtonNavigation(this, R.id.homeButton, MainActivity.class);
com.example.fitbot.util.ButtonNavigation.setupButtonNavigation(this, R.id.continueButton, FitnessActivity.class);
}
}

View File

@@ -4,8 +4,12 @@ import android.os.Bundle;
import android.util.Log;
import com.aldebaran.qi.sdk.QiContext;
import com.aldebaran.qi.sdk.QiSDK;
import com.aldebaran.qi.sdk.RobotLifecycleCallbacks;
import com.aldebaran.qi.sdk.design.activity.RobotActivity;
import com.example.fitbot.ui.activities.EndScreenActivity;
import com.example.fitbot.R;
import com.example.fitbot.sports.Animations;
import com.example.fitbot.R;
import com.example.fitbot.exercise.Exercise;
import com.example.fitbot.exercise.EMuscleGroup;
@@ -52,6 +56,8 @@ public class FitnessActivity extends RobotActivity implements RobotLifecycleCall
@Override
public void onRobotFocusGained(QiContext qiContext) {
// Implement your logic when the robot focus is gained
Animate("bicepcurl", qiContext);
}
@Override
@@ -63,4 +69,17 @@ public class FitnessActivity extends RobotActivity implements RobotLifecycleCall
public void onRobotFocusRefused(String reason) {
// Implement your logic when the robot focus is refused
}
}
@Override
protected void onDestroy() {
QiSDK.unregister(this, this);
super.onDestroy();
}
public static class PersonalMotionPreviewElement extends View {
public PersonalMotionPreviewElement(Context context, AttributeSet attrs) {
super(context, attrs);
// Initialize your custom view here (optional)
}
}

View File

@@ -1,9 +1,16 @@
package com.example.fitbot.ui.activities;
import android.Manifest;
import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.NavigationView;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
@@ -13,9 +20,13 @@ import android.util.Log;
import android.widget.Button;
import com.example.fitbot.R;
import com.example.fitbot.wiiboard.WiiBoardDiscoverer;
public class MainActivity extends AppCompatActivity {
private static final int REQUEST_LOCATION_PERMISSION = 1;
private WiiBoardDiscoverer wiiBoardDiscoverer;
//Variables
DrawerLayout drawerLayout;
NavigationView navigationView;
@@ -23,11 +34,67 @@ public class MainActivity extends AppCompatActivity {
Button startButton;
@SuppressLint("WrongViewCast")
@Override
protected void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main );
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button startButton = findViewById(R.id.startButton);
startButton.setOnClickListener(v -> {
Uri videoUri = Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.bicepvideo);
Intent intent = new Intent(MainActivity.this, FitnessActivity.class);
intent.putExtra("videoUri", videoUri);
startActivity(intent);
});
// Check if the device supports Bluetooth
if (BluetoothAdapter.getDefaultAdapter() == null) {
Log.i("WiiBoardDiscoverer", "Device doesn't support Bluetooth. Exiting.");
return;
}
// Request location permissions for Bluetooth discovery on Android 6.0 and above
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_LOCATION_PERMISSION);
} else {
// Initialize WiiBoardDiscoverer
wiiBoardDiscoverer = new WiiBoardDiscoverer(this);
}
setUpUi();
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_LOCATION_PERMISSION && grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Permission granted, initialize WiiBoardDiscoverer
wiiBoardDiscoverer = new WiiBoardDiscoverer(this);
} else {
// Handle the case where the user denies the location permission
Log.i("WiiBoardDiscoverer", "Location permission is required for Bluetooth discovery.");
}
}
@Override
protected void onResume() {
super.onResume();
if (wiiBoardDiscoverer != null) {
wiiBoardDiscoverer.startWiiBoardSearch();
}
}
@Override
protected void onPause() {
super.onPause();
if (wiiBoardDiscoverer != null) {
wiiBoardDiscoverer.stopWiiBoardSearch();
}
}
private void setUpUi() {
/*---Hooks---*/
drawerLayout = findViewById(R.id.drawer_layout);
navigationView = findViewById(R.id.nav_view);

View File

@@ -0,0 +1,19 @@
package com.example.fitbot.util;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.view.View;
import android.widget.Button;
public class ButtonNavigation {
public static void setupButtonNavigation(Activity currentActivity, int buttonId, Class<? extends Activity> targetActivity) {
Button button = currentActivity.findViewById(buttonId);
button.setOnClickListener(v -> {
Intent intent = new Intent(currentActivity, targetActivity);
currentActivity.startActivity(intent);
currentActivity.finish();
});
}
}

View File

@@ -0,0 +1,48 @@
package com.example.fitbot.wiiboard;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.util.Log;
import java.io.IOException;
import java.lang.reflect.Method;
public class WiiBoard {
private static final String TAG = "WiiBoard";
public static void connectToExtension(String address) {
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
BluetoothDevice device = bluetoothAdapter.getRemoteDevice(address);
BluetoothSocket socket = null;
final int maxTries = 3;
int currentTry = 0;
while (currentTry < maxTries) {
try {
// Use reflection to create a BluetoothSocket without UUID
Method m = device.getClass().getMethod("createRfcommSocket", new Class[]{int.class});
socket = (BluetoothSocket) m.invoke(device, 1);
bluetoothAdapter.cancelDiscovery();
socket.connect();
Log.i(TAG, "Connected to WiiBoard");
// Handle your communication here
return; // Exit the method upon successful connection
} catch (Exception e) { // Catching Exception to handle reflection exceptions too
Log.e(TAG, "Attempt " + (currentTry + 1) + " failed to connect", e);
currentTry++;
try {
// Wait a bit before retrying
Thread.sleep(1000);
} catch (InterruptedException ie) {
Log.e(TAG, "Interrupted while waiting to retry connection", ie);
}
}
}
Log.e(TAG, "Could not connect to WiiBoard after " + maxTries + " attempts.");
}
}

View File

@@ -0,0 +1,66 @@
package com.example.fitbot.wiiboard;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.util.Log;
public class WiiBoardDiscoverer {
private BluetoothAdapter bluetoothAdapter;
private Context context;
private String discoveredAddress;
private boolean isSearching;
private final BroadcastReceiver receiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
String name = device.getName();
if ("Nintendo RVL-WBC-01".equals(name)) {
discoveredAddress = device.getAddress();
Log.i("WiiBoardDiscoverer", "Discovered " + name + " " + discoveredAddress + ".");
isSearching = false;
bluetoothAdapter.cancelDiscovery();
context.unregisterReceiver(this); // Important to unregister
WiiBoard.connectToExtension(discoveredAddress);
}
}
}
};
public WiiBoardDiscoverer(Context context) {
this.context = context;
this.bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (bluetoothAdapter == null) {
Log.i("WiiBoardDiscoverer", "Device doesn't support Bluetooth. Exiting.");
System.exit(0);
}
}
public void startWiiBoardSearch() {
if (!isSearching && !bluetoothAdapter.isDiscovering()) {
isSearching = true;
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
context.registerReceiver(receiver, filter);
bluetoothAdapter.startDiscovery();
Log.i("WiiBoardDiscoverer", "WiiBoard Discovery Started");
}
}
public void stopWiiBoardSearch() {
if (bluetoothAdapter.isDiscovering()) {
bluetoothAdapter.cancelDiscovery();
}
isSearching = false;
try {
context.unregisterReceiver(receiver);
} catch (IllegalArgumentException e) {
// This can happen if the receiver was not registered or already unregistered
Log.i("WiiBoardDiscoverer", "Receiver was not registered or already unregistered");
}
}
}

View File

@@ -0,0 +1,13 @@
package com.example.fitbot.wiiboard;
/**
* Implement this interface to be notified of WiiBoards that are connected to. Register your
* listener with an instance of WiiBoardDiscoverer.
*/
public interface WiiBoardDiscoveryListener {
/**
* Is called by a WiiBoardDiscoverer when a WiiBoard has been found and successfully connected to.
*/
public void wiiBoardDiscovered(WiiBoard wiiboard);
}

View File

@@ -5,7 +5,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".EndScreenActivity">
tools:context=".ui.activities.EndScreenActivity">
<View
android:id="@+id/myRectangleView"

View File

@@ -1,6 +1,6 @@
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"

View File

@@ -8,4 +8,7 @@
<item name="colorAccent">@color/teal_200</item>
<!-- Customize your theme here. -->
</style>
<!-- Style for general buttons -->
<!-- Add button styles here, if needed -->
</resources>