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:
@@ -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) + "\"}";
|
||||
|
@@ -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;
|
||||
}
|
@@ -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
|
33
code/arduino/bluetoothEsp/bluetoothEsp.ino
Normal file
33
code/arduino/bluetoothEsp/bluetoothEsp.ino
Normal 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
|
||||
}
|
17
code/src/Fitbot/.idea/deploymentTargetDropDown.xml
generated
17
code/src/Fitbot/.idea/deploymentTargetDropDown.xml
generated
@@ -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>
|
40
code/src/Fitbot/.idea/misc.xml
generated
40
code/src/Fitbot/.idea/misc.xml
generated
@@ -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>
|
||||
|
@@ -7,7 +7,7 @@ android {
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.example.fitbot"
|
||||
minSdk 29
|
||||
minSdk 23
|
||||
targetSdk 29
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
|
@@ -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"
|
||||
|
@@ -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();
|
||||
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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 {
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
@@ -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)
|
||||
}
|
||||
}
|
||||
|
@@ -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);
|
||||
|
@@ -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();
|
||||
});
|
||||
}
|
||||
}
|
@@ -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.");
|
||||
}
|
||||
}
|
@@ -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");
|
||||
}
|
||||
}
|
||||
}
|
@@ -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);
|
||||
}
|
@@ -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"
|
||||
|
@@ -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"
|
||||
|
@@ -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>
|
Reference in New Issue
Block a user