diff --git a/android/robot/src/main/java/org/openbot/autopilot/AutopilotFragment.java b/android/robot/src/main/java/org/openbot/autopilot/AutopilotFragment.java
index 2754a88d8..f88283d53 100644
--- a/android/robot/src/main/java/org/openbot/autopilot/AutopilotFragment.java
+++ b/android/robot/src/main/java/org/openbot/autopilot/AutopilotFragment.java
@@ -589,4 +589,3 @@ private void disconnectPhoneController() {
binding.controllerContainer.driveMode.setAlpha(1.0f);
}
}
-
diff --git a/android/robot/src/main/java/org/openbot/env/SharedPreferencesManager.java b/android/robot/src/main/java/org/openbot/env/SharedPreferencesManager.java
index 2d476440d..7eb5e79aa 100644
--- a/android/robot/src/main/java/org/openbot/env/SharedPreferencesManager.java
+++ b/android/robot/src/main/java/org/openbot/env/SharedPreferencesManager.java
@@ -1,5 +1,6 @@
package org.openbot.env;
+import android.app.Fragment;
import android.content.Context;
import android.content.SharedPreferences;
import com.google.common.reflect.TypeToken;
@@ -43,6 +44,9 @@ public class SharedPreferencesManager {
private static final String DELAY = "DELAY";
private static final String PROJECTS_LIST = "PROJECTS_LIST";
+ private static final String FRAGMENT_TYPE = "FRAGMENT_TYPE";
+
+
private final SharedPreferences preferences;
public SharedPreferencesManager(Context context) {
@@ -51,6 +55,11 @@ public SharedPreferencesManager(Context context) {
.getApplicationContext()
.getSharedPreferences(PREFERENCES_NAME, Context.MODE_PRIVATE);
}
+ public String getFragment(){return preferences.getString(FRAGMENT_TYPE, "" );}
+ public void setFragment(String fragment)
+ {
+ preferences.edit().putString(FRAGMENT_TYPE, fragment).apply();
+ }
public int getBaudrate() {
return preferences.getInt(BAUD_RATE, DEFAULT_BAUD_RATE);
diff --git a/android/robot/src/main/java/org/openbot/env/WebRtcServer.java b/android/robot/src/main/java/org/openbot/env/WebRtcServer.java
index e3b0a6fcc..d7339f209 100644
--- a/android/robot/src/main/java/org/openbot/env/WebRtcServer.java
+++ b/android/robot/src/main/java/org/openbot/env/WebRtcServer.java
@@ -127,6 +127,7 @@ public void startClient() {
@Override
public void sendServerUrl() {
BotToControllerEventBus.emitEvent(ConnectionUtils.createStatus("VIDEO_SERVER_URL", ""));
+ BotToControllerEventBus.emitEvent(ConnectionUtils.createFragment(""));
}
@Override
@@ -369,7 +370,6 @@ public void onTrack(RtpTransceiver transceiver) {}
return factory.createPeerConnection(rtcConfig, pcConstraints, pcObserver);
}
-
private void sendMessage(JSONObject message) {
BotToControllerEventBus.emitEvent(ConnectionUtils.createStatus("WEB_RTC_EVENT", message));
}
diff --git a/android/robot/src/main/java/org/openbot/logging/LoggerFragment.java b/android/robot/src/main/java/org/openbot/logging/LoggerFragment.java
index 1a6741c93..2d54e7627 100644
--- a/android/robot/src/main/java/org/openbot/logging/LoggerFragment.java
+++ b/android/robot/src/main/java/org/openbot/logging/LoggerFragment.java
@@ -85,6 +85,8 @@ public View onCreateView(
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
+ preferencesManager.setFragment(Enums.fragmentType.DATACOLLECTION.getFragment());
+ BotToControllerEventBus.emitEvent(ConnectionUtils.createFragment(preferencesManager.getFragment()));
binding.controllerContainer.speedInfo.setText(getString(R.string.speedInfo, "---,---"));
intentSensorService = new Intent(requireActivity(), SensorService.class);
diff --git a/android/robot/src/main/java/org/openbot/objectNav/ObjectNavFragment.java b/android/robot/src/main/java/org/openbot/objectNav/ObjectNavFragment.java
index 4729cf253..e62c32be9 100644
--- a/android/robot/src/main/java/org/openbot/objectNav/ObjectNavFragment.java
+++ b/android/robot/src/main/java/org/openbot/objectNav/ObjectNavFragment.java
@@ -33,12 +33,14 @@
import org.openbot.common.CameraFragment;
import org.openbot.databinding.FragmentObjectNavBinding;
import org.openbot.env.BorderedText;
+import org.openbot.env.BotToControllerEventBus;
import org.openbot.env.ImageUtils;
import org.openbot.tflite.Detector;
import org.openbot.tflite.Model;
import org.openbot.tflite.Network;
import org.openbot.tracking.MultiBoxTracker;
import org.openbot.utils.CameraUtils;
+import org.openbot.utils.ConnectionUtils;
import org.openbot.utils.Constants;
import org.openbot.utils.Enums;
import org.openbot.utils.MovingAverage;
@@ -97,9 +99,9 @@ public View onCreateView(
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
-
+ preferencesManager.setFragment(Enums.fragmentType.OBJECTDETECTION.getFragment());
+ BotToControllerEventBus.emitEvent(ConnectionUtils.createFragment(preferencesManager.getFragment()));
binding.confidenceValue.setText((int) (MINIMUM_CONFIDENCE_TF_OD_API * 100) + "%");
-
binding.plusConfidence.setOnClickListener(
v -> {
String trimConfValue = binding.confidenceValue.getText().toString().trim();
diff --git a/android/robot/src/main/java/org/openbot/robot/FreeRoamFragment.java b/android/robot/src/main/java/org/openbot/robot/FreeRoamFragment.java
index b41667d26..88505c72b 100644
--- a/android/robot/src/main/java/org/openbot/robot/FreeRoamFragment.java
+++ b/android/robot/src/main/java/org/openbot/robot/FreeRoamFragment.java
@@ -20,7 +20,9 @@
import org.openbot.R;
import org.openbot.common.ControlsFragment;
import org.openbot.databinding.FragmentFreeRoamBinding;
+import org.openbot.env.BotToControllerEventBus;
import org.openbot.env.PhoneController;
+import org.openbot.utils.ConnectionUtils;
import org.openbot.utils.Constants;
import org.openbot.utils.Enums;
import org.openbot.utils.PermissionUtils;
@@ -45,6 +47,10 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat
phoneController = PhoneController.getInstance(requireContext());
+ preferencesManager.setFragment(Enums.fragmentType.FREEROAM.getFragment());
+
+ BotToControllerEventBus.emitEvent(ConnectionUtils.createFragment(preferencesManager.getFragment()));
+
binding.voltageInfo.setText(getString(R.string.voltageInfo, "--.-"));
binding.controllerContainer.speedInfo.setText(getString(R.string.speedInfo, "---,---"));
binding.sonarInfo.setText(getString(R.string.distanceInfo, "---"));
diff --git a/android/robot/src/main/java/org/openbot/utils/ConnectionUtils.java b/android/robot/src/main/java/org/openbot/utils/ConnectionUtils.java
index c45d0facf..2f1f62e1d 100644
--- a/android/robot/src/main/java/org/openbot/utils/ConnectionUtils.java
+++ b/android/robot/src/main/java/org/openbot/utils/ConnectionUtils.java
@@ -24,6 +24,7 @@ public static JSONObject createStatus(String name, String value) {
return new JSONObject();
}
+
public static JSONObject createStatus(String name, JSONObject value) {
try {
return new JSONObject().put("status", new JSONObject().put(name, value.toString()));
@@ -33,6 +34,15 @@ public static JSONObject createStatus(String name, JSONObject value) {
return new JSONObject();
}
+ public static JSONObject createFragment(String value){
+ try {
+ return new JSONObject().put("FRAGMENT_TYPE", value);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return new JSONObject();
+ }
+
public static JSONObject getStatus(
boolean loggingEnabled,
boolean noiseEnabled,
diff --git a/android/robot/src/main/java/org/openbot/utils/Enums.java b/android/robot/src/main/java/org/openbot/utils/Enums.java
index fad69aec3..4de1b4528 100644
--- a/android/robot/src/main/java/org/openbot/utils/Enums.java
+++ b/android/robot/src/main/java/org/openbot/utils/Enums.java
@@ -29,6 +29,16 @@ public String getSensor() {
}
}
+ public enum fragmentType{
+ AUTOPILOT("Autopilot"),
+ OBJECTDETECTION("ObjectDetection"),
+ DATACOLLECTION("DataCollection"),
+ FREEROAM("FreeRoam");
+ private String fragmentType;
+ fragmentType(String fragmentType) {this.fragmentType=fragmentType;}
+ public String getFragment() {return fragmentType;}
+ }
+
public enum LogMode {
ALL_IMGS(0),
CROP_IMG(1),
diff --git a/controller/flutter/README.md b/controller/flutter/README.md
index 74f9c3e7c..aa801e792 100644
--- a/controller/flutter/README.md
+++ b/controller/flutter/README.md
@@ -10,7 +10,7 @@
This Controller app serves as a `remote controller` for the [OpenBot](https://www.openbot.org) vehicle similar as a BT controller (e.g. PS3/4 or Xbox). It runs on another Android/iOS device and supports live video/audio streaming in addition to control.
- ## Getting Started
+## Getting Started
Begin by installing [Flutter](https://flutter.dev/) on your system. Choose the appropriate download for your operating system, which includes options for Windows, macOS, Linux, and ChromeOS. Follow the official Flutter installation guide for detailed instructions: [Flutter Installation Guide](https://docs.flutter.dev/get-started/install)
### Using Terminal
@@ -22,16 +22,16 @@ Begin by installing [Flutter](https://flutter.dev/) on your system. Choose the a
```bash
flutter pub get
```
- Run the project:
+ Run the project:
```bash
flutter run
```
- If you encounter any issues, run the following command:
+ If you encounter any issues, run the following command:
```bash
flutter doctor
```
### Using Editor
-- Follow the official Flutter guide for setting up an editor: [Set up an editor ](https://docs.flutter.dev/tools/android-studio)
+- Follow the official Flutter guide for setting up an editor: [Set up an editor ](https://docs.flutter.dev/tools/android-studio)
- Ensure that your editor is configured for Flutter development. Install any required plugins or extensions, following the editor-specific instructions in the Flutter documentation for the best development experience.
- Once you open your project in the editor after the setup, it will appear as shown in the following image.
@@ -46,7 +46,7 @@ Begin by installing [Flutter](https://flutter.dev/) on your system. Choose the a
-## Connection
+## Connection
When the controller app is started, it immediately tries to connect to the robot and shows the following screen:
@@ -89,7 +89,7 @@ above/below the center of the slider.
- ``Switch Camera``: switch between the front and back camera modes.
- ``Mute``: enable/disable audio transmission.
-- ``Mirror view``: mirror the the video feed.
+- ``Mirror view``: mirror the the video feed.
### Tilt to drive
@@ -112,4 +112,18 @@ Use the `accelerator` and `brake` buttons to move forward/backward.
robot will come to a stop.
- The robot is steered by tilting the controller phone left or right.
+### Controller Settings UI
+
+Here is a picture of the `Controller Settings` screen:
+
+- Controller Selection: Switch between different controller types (e.g., mobile, joystick) using the provided icons.
+
+- Server: Displays the current server status with a dropdown to select or change the server.
+
+- Noise Toggle : Enable or disable noise simulation through the toggle switch.
+
+
+
+
+
Here is a [Technical Overview](../../docs/technical/OpenBotController.pdf) of the controller app.
diff --git a/controller/flutter/android/build.gradle b/controller/flutter/android/build.gradle
index 3cdaac958..6617c1e94 100644
--- a/controller/flutter/android/build.gradle
+++ b/controller/flutter/android/build.gradle
@@ -1,5 +1,5 @@
buildscript {
- ext.kotlin_version = '1.6.10'
+ ext.kotlin_version = '1.7.0'
repositories {
google()
mavenCentral()
diff --git a/controller/flutter/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/controller/flutter/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md
index e005bfba8..5ddcaf2b4 100644
--- a/controller/flutter/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md
+++ b/controller/flutter/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md
@@ -10,4 +10,4 @@
You can customize the launch screen with your own desired assets by replacing the image files in this directory.
-You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
+You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
\ No newline at end of file
diff --git a/controller/flutter/lib/screens/component/onScreenIcon.dart b/controller/flutter/lib/screens/component/onScreenIcon.dart
index d3b3cb40f..d304c4d5c 100644
--- a/controller/flutter/lib/screens/component/onScreenIcon.dart
+++ b/controller/flutter/lib/screens/component/onScreenIcon.dart
@@ -2,15 +2,17 @@ import 'package:flutter/material.dart';
import 'package:flutter_webrtc/flutter_webrtc.dart';
import 'package:openbot_controller/buttonCommands/buttonCommands.dart';
import 'package:openbot_controller/screens/component/blinkingButton.dart';
+import 'package:openbot_controller/globals.dart';
class OnScreenIcon extends StatefulWidget {
final dynamic updateMirrorView;
final bool indicatorLeft;
final bool indicatorRight;
final RTCPeerConnection? peerConnection;
+ final String fragmentType;
const OnScreenIcon(this.updateMirrorView, this.indicatorLeft,
- this.indicatorRight, this.peerConnection,
+ this.indicatorRight, this.peerConnection, this.fragmentType,
{super.key});
@override
@@ -24,6 +26,7 @@ class OnScreenIconState extends State {
bool speaker = false;
bool leftIndicator = false;
bool rightIndicator = false;
+ String typeOfFragment = "";
@override
void didUpdateWidget(covariant OnScreenIcon oldWidget) {
@@ -31,6 +34,7 @@ class OnScreenIconState extends State {
setState(() {
leftIndicator = widget.indicatorLeft;
rightIndicator = widget.indicatorRight;
+ typeOfFragment = widget.fragmentType;
});
super.didUpdateWidget(oldWidget);
}
@@ -186,6 +190,52 @@ class OnScreenIconState extends State {
width: 23,
),
)),
+ const SizedBox(
+ width: 15,
+ ),
+ GestureDetector(
+ onTap: () {
+ if (typeOfFragment == "DataCollection") {
+ clientSocket?.writeln("{command: LOGS}");
+ }
+ }, // Image tapped
+ child: Container(
+ padding: const EdgeInsets.all(15),
+ decoration: BoxDecoration(
+ borderRadius: BorderRadius.circular(45),
+ color: typeOfFragment == "DataCollection"
+ ? Colors.white.withOpacity(0.5)
+ : Colors.grey.withOpacity(0.5),
+ ),
+ child: const Icon(
+ Icons.file_present,
+ color: Colors.blue,
+ ),
+ )),
+ const SizedBox(
+ width: 15,
+ ),
+ GestureDetector(
+ onTap: () {
+ if (typeOfFragment == "Autopilot" ||
+ typeOfFragment == "ObjectDetection") {
+ clientSocket?.writeln("{command: NETWORK}");
+ }
+ }, // Image tapped
+ child: Container(
+ padding: const EdgeInsets.all(15),
+ decoration: BoxDecoration(
+ borderRadius: BorderRadius.circular(45),
+ color: typeOfFragment == "Autopilot" ||
+ typeOfFragment == "ObjectDetection"
+ ? Colors.white.withOpacity(0.5)
+ : Colors.grey.withOpacity(0.5),
+ ),
+ child: const Icon(
+ Icons.network_check,
+ color: Colors.blue,
+ ),
+ )),
],
),
);
diff --git a/controller/flutter/lib/screens/controlSelector.dart b/controller/flutter/lib/screens/controlSelector.dart
index f45e11193..e3cee1f07 100644
--- a/controller/flutter/lib/screens/controlSelector.dart
+++ b/controller/flutter/lib/screens/controlSelector.dart
@@ -1,8 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_webrtc/flutter_webrtc.dart';
-import 'package:fluttertoast/fluttertoast.dart';
import 'package:nsd/nsd.dart';
-import 'package:openbot_controller/globals.dart';
import 'package:openbot_controller/screens/tiltingPhoneMode.dart';
import 'onScreenMode.dart';
@@ -13,9 +11,19 @@ class ControlSelector extends StatefulWidget {
final bool indicatorRight;
final List networkServices;
final RTCPeerConnection? peerConnection;
-
- const ControlSelector(this.updateMirrorView, this.indicatorLeft,
- this.indicatorRight, this.networkServices, this.peerConnection,
+ final bool isTiltingPhoneMode;
+ final bool isScreenMode;
+ final String fragmentType;
+
+ const ControlSelector(
+ this.updateMirrorView,
+ this.indicatorLeft,
+ this.indicatorRight,
+ this.networkServices,
+ this.peerConnection,
+ this.isTiltingPhoneMode,
+ this.isScreenMode,
+ this.fragmentType,
{super.key});
@override
@@ -25,9 +33,6 @@ class ControlSelector extends StatefulWidget {
}
class ControlSelectorState extends State {
- bool isTiltingPhoneMode = false;
- bool isScreenMode = false;
-
// Initial Selected Value
String dropDownValue = 'No server';
late List> items = [];
@@ -38,359 +43,21 @@ class ControlSelectorState extends State {
// items.clear();
}
- // Function to generate DropdownMenuItem widgets
- List> buildDropdownMenuItems() {
- items = [
- DropdownMenuItem(
- value: 'No server',
- child: Container(
- height: 30,
- width: 85,
- decoration: const BoxDecoration(
- borderRadius: BorderRadius.all(Radius.circular(3)),
- color: Color(0xFF0071C5),
- ),
- alignment: Alignment.center,
- child: const Text(
- 'No server',
- textAlign: TextAlign.center,
- style: TextStyle(
- fontSize: 13,
- color: Color(0xFFffffff),
- ),
- ),
- ),
- ),
- ];
- items.addAll(widget.networkServices.map((discovery) {
- return DropdownMenuItem(
- value: discovery.name,
- child: Container(
- height: 30,
- width: 85,
- decoration: const BoxDecoration(
- borderRadius: BorderRadius.all(Radius.circular(3)),
- color: Color(0xFF0071C5),
- ),
- alignment: Alignment.center,
- child: Text(
- discovery.name ?? '',
- textAlign: TextAlign.center,
- style: const TextStyle(
- fontSize: 13,
- color: Color(0xFFffffff),
- ),
- ),
- ),
- );
- }));
- return items;
- }
-
@override
Widget build(BuildContext context) {
- if (isTiltingPhoneMode) {
+ if (widget.isTiltingPhoneMode) {
return GestureDetector(
- onDoubleTap: () {
- setState(() {
- isTiltingPhoneMode = false;
- });
- },
- child: const TiltingPhoneMode());
- } else if (isScreenMode) {
+ child: TiltingPhoneMode(fragmentType: widget.fragmentType));
+ } else if (widget.isScreenMode) {
return GestureDetector(
- onDoubleTap: () {
- setState(() {
- isScreenMode = false;
- });
- },
child: OnScreenMode(widget.updateMirrorView, widget.indicatorLeft,
- widget.indicatorRight, widget.peerConnection),
+ widget.indicatorRight, widget.peerConnection, widget.fragmentType),
);
} else {
- return Scaffold(
- backgroundColor: Colors.transparent,
- body: Center(
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.center,
- mainAxisAlignment: MainAxisAlignment.center,
- children: [
- Row(
- crossAxisAlignment: CrossAxisAlignment.center,
- mainAxisAlignment: MainAxisAlignment.center,
- children: [
- GestureDetector(
- onTap: () {
- Fluttertoast.showToast(
- msg: "Double tap on screen to get back",
- toastLength: Toast.LENGTH_LONG,
- gravity: ToastGravity.BOTTOM,
- backgroundColor: Colors.grey,
- textColor: Colors.white,
- fontSize: 18);
- setState(() {
- isScreenMode = true;
- });
- },
- child: Container(
- height: 180,
- width: 180,
- padding: const EdgeInsets.all(20),
- margin: const EdgeInsets.all(20),
- decoration: const BoxDecoration(
- borderRadius: BorderRadius.all(Radius.circular(10)),
- color: Color(0xFF292929),
- boxShadow: [
- BoxShadow(
- blurRadius: 0.5,
- spreadRadius: 0.1,
- color: Color(0xFFffffff),
- offset: Offset(
- -1,
- -1,
- ),
- ),
- BoxShadow(
- blurRadius: 1,
- spreadRadius: 0.1,
- color: Color(0xFF000000),
- offset: Offset(
- -1,
- -1,
- ),
- ),
- ]),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- mainAxisAlignment: MainAxisAlignment.start,
- children: [
- Image.asset(
- "images/controller_icon.png",
- height: 18,
- width: 18,
- ),
- const SizedBox(
- height: 20,
- ),
- const Text(
- "Use On-Screen Controls to Drive",
- style: TextStyle(
- fontSize: 15,
- fontWeight: FontWeight.w500,
- color: Color(0xFFffffff),
- ),
- ),
- const SizedBox(
- height: 55,
- ),
- Container(
- alignment: Alignment.bottomRight,
- child: Image.asset(
- "images/arrow_icon.png",
- width: 50,
- ),
- ),
- ]),
- ),
- ),
- GestureDetector(
- onTap: () {
- Fluttertoast.showToast(
- msg: "Double tap on screen to get back",
- toastLength: Toast.LENGTH_LONG,
- gravity: ToastGravity.BOTTOM,
- backgroundColor: Colors.grey,
- textColor: Colors.white,
- fontSize: 18);
- setState(() {
- isTiltingPhoneMode = true;
- });
- },
- child: Container(
- height: 180,
- width: 180,
- padding: const EdgeInsets.all(20),
- margin: const EdgeInsets.all(20),
- decoration: const BoxDecoration(
- borderRadius: BorderRadius.all(Radius.circular(10)),
- color: Color(0xFF292929),
- boxShadow: [
- BoxShadow(
- blurRadius: 0.5,
- spreadRadius: 0.1,
- color: Color(0xFFffffff),
- offset: Offset(
- -1,
- -1,
- ),
- ),
- BoxShadow(
- blurRadius: 1,
- spreadRadius: 0.1,
- color: Color(0xFF000000),
- offset: Offset(
- -1,
- -1,
- ),
- ),
- ]),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- mainAxisAlignment: MainAxisAlignment.start,
- children: [
- Image.asset(
- "images/tilting_phone_icon.png",
- height: 18,
- width: 18,
- ),
- const SizedBox(
- height: 20,
- ),
- const Text(
- "Drive by tilting\nthe phone",
- style: TextStyle(
- fontSize: 15,
- fontWeight: FontWeight.w500,
- color: Color(0xFFffffff),
- ),
- ),
- const SizedBox(
- height: 55,
- ),
- Container(
- alignment: Alignment.bottomRight,
- child: Image.asset(
- "images/arrow_icon.png",
- width: 50,
- ),
- ),
- ]),
- ),
- ),
- ],
- ),
- Row(
- crossAxisAlignment: CrossAxisAlignment.center,
- mainAxisAlignment: MainAxisAlignment.center,
- children: [
- DropdownButton(
- value: dropDownValue,
- borderRadius: const BorderRadius.all(Radius.circular(3)),
- underline: Container(),
- dropdownColor: const Color(0xFF0071C5),
- style: const TextStyle(
- fontSize: 13,
- color: Color(0xFFffffff),
- ),
- menuMaxHeight: 150,
- items: buildDropdownMenuItems(),
- onChanged: (String? serverName) {
- setState(() {
- dropDownValue = serverName!;
- });
- if (serverName != "No server") {
- clientSocket?.writeln("{server: $serverName}");
- } else {
- clientSocket?.writeln("{server: noServerFound}");
- }
- },
- ),
- GestureDetector(
- onTap: () {
- clientSocket?.writeln("{command: LOGS}");
- },
- child: Container(
- height: 30,
- width: 85,
- margin: const EdgeInsets.all(20),
- decoration: const BoxDecoration(
- borderRadius: BorderRadius.all(Radius.circular(3)),
- color: Color(0xFF0071C5),
- ),
- child: const Center(
- child: Text(
- "Logs",
- textAlign: TextAlign.center,
- style: TextStyle(
- fontSize: 13,
- color: Color(0xFFffffff),
- ),
- ),
- ),
- )),
- GestureDetector(
- onTap: () {
- clientSocket?.writeln("{command: NOISE}");
- },
- child: Container(
- height: 30,
- width: 85,
- margin: const EdgeInsets.all(20),
- decoration: const BoxDecoration(
- borderRadius: BorderRadius.all(Radius.circular(3)),
- color: Color(0xFF0071C5),
- ),
- child: const Center(
- child: Text(
- "Noise",
- textAlign: TextAlign.center,
- style: TextStyle(
- fontSize: 13,
- color: Color(0xFFffffff),
- ),
- ),
- ),
- )),
- GestureDetector(
- onTap: () {
- clientSocket?.writeln("{command: NETWORK}");
- },
- child: Container(
- height: 30,
- width: 85,
- margin: const EdgeInsets.all(20),
- decoration: const BoxDecoration(
- borderRadius: BorderRadius.all(Radius.circular(3)),
- color: Color(0xFF0071C5),
- ),
- child: const Center(
- child: Text(
- "Network",
- textAlign: TextAlign.center,
- style: TextStyle(
- fontSize: 13,
- color: Color(0xFFffffff),
- ),
- ),
- ),
- )),
- GestureDetector(
- onTap: () {
- clientSocket?.writeln("{command: DRIVE_MODE}");
- },
- child: Container(
- height: 30,
- width: 85,
- margin: const EdgeInsets.all(20),
- decoration: const BoxDecoration(
- borderRadius: BorderRadius.all(Radius.circular(3)),
- color: Color(0xFF0071C5),
- ),
- child: const Center(
- child: Text(
- "Game",
- textAlign: TextAlign.center,
- style: TextStyle(
- fontSize: 13,
- color: Color(0xFFffffff),
- ),
- ),
- ),
- )),
- ],
- )
- ],
- )));
+ return GestureDetector(
+ child: OnScreenMode(widget.updateMirrorView, widget.indicatorLeft,
+ widget.indicatorRight, widget.peerConnection, widget.fragmentType),
+ );
}
}
-}
+}
\ No newline at end of file
diff --git a/controller/flutter/lib/screens/controller.dart b/controller/flutter/lib/screens/controller.dart
index fc07cd040..9ad1a32df 100644
--- a/controller/flutter/lib/screens/controller.dart
+++ b/controller/flutter/lib/screens/controller.dart
@@ -1,7 +1,6 @@
import 'dart:convert';
import 'dart:developer';
import 'dart:io';
-
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_webrtc/flutter_webrtc.dart';
@@ -9,7 +8,7 @@ import 'package:fluttertoast/fluttertoast.dart';
import 'package:nsd/nsd.dart';
import 'package:openbot_controller/globals.dart';
import 'package:openbot_controller/screens/controlSelector.dart';
-
+import 'package:openbot_controller/screens/settingsDrawer.dart';
import '../utils/constants.dart';
import 'discoveringDevices.dart';
@@ -32,6 +31,10 @@ class ControllerState extends State {
bool mirroredVideo = false;
bool indicatorLeft = false;
bool indicatorRight = false;
+ bool isSettings = false;
+ bool isTiltingPhoneMode = false;
+ bool isScreenMode = false;
+ String fragmentType = "";
var _nextPort = 56360;
int get nextPort => _nextPort++;
@@ -194,6 +197,11 @@ class ControllerState extends State {
if (msgInObject["status"] != null) {
processMessageFromBot(msgInObject["status"]);
}
+ if (msgInObject["FRAGMENT_TYPE"] != null) {
+ setState(() {
+ fragmentType = msgInObject["FRAGMENT_TYPE"];
+ });
+ }
}
}
} catch (e) {
@@ -254,7 +262,50 @@ class ControllerState extends State {
mirror: mirroredVideo,
),
ControlSelector(setMirrorVideo, indicatorLeft, indicatorRight,
- services, _peerConnection)
+ services, _peerConnection, isTiltingPhoneMode, isScreenMode,fragmentType),
+ Positioned(
+ left: isTiltingPhoneMode ? 45 : 110,
+ top: 16.0, // Adjust the top margin as needed
+ child: Container(
+ // padding: EdgeInsets.only(left: ),
+ decoration: BoxDecoration(
+ borderRadius: BorderRadius.circular(45),
+ color: Colors.transparent,
+ ),
+ child: FloatingActionButton(
+ backgroundColor: Colors.white.withOpacity(0.5),
+ onPressed: () {
+ setState(() {
+ isSettings = true;
+ });
+ },
+ child: const Icon(Icons.menu)),
+ ),
+ ),
+ if (isSettings)
+ Stack(
+ children: [
+ GestureDetector(
+ onTap: () {
+ setState(() {
+ isSettings = false;
+ });
+ },
+ child: Container(
+ color: Colors.transparent,
+ ),
+ ),
+ SettingsDrawer(
+ services,
+ (bool newTiltingMode, bool newScreenMode) {
+ setState(() {
+ isTiltingPhoneMode = newTiltingMode;
+ isScreenMode = newScreenMode;
+ });
+ },
+ ),
+ ],
+ ),
],
),
debugShowCheckedModeBanner: false,
diff --git a/controller/flutter/lib/screens/onScreenMode.dart b/controller/flutter/lib/screens/onScreenMode.dart
index 88d204c6e..72a13ad59 100644
--- a/controller/flutter/lib/screens/onScreenMode.dart
+++ b/controller/flutter/lib/screens/onScreenMode.dart
@@ -10,9 +10,10 @@ class OnScreenMode extends StatefulWidget {
final bool indicatorLeft;
final bool indicatorRight;
final RTCPeerConnection? peerConnection;
+ final String fragmentType;
const OnScreenMode(this.updateMirrorView, this.indicatorLeft,
- this.indicatorRight, this.peerConnection,
+ this.indicatorRight, this.peerConnection, this.fragmentType,
{super.key});
@override
@@ -66,7 +67,7 @@ class OnScreenModeState extends State {
alignment: AlignmentDirectional.bottomEnd,
margin: const EdgeInsets.only(bottom: 20),
child: OnScreenIcon(widget.updateMirrorView, widget.indicatorLeft,
- widget.indicatorRight, widget.peerConnection),
+ widget.indicatorRight, widget.peerConnection,widget.fragmentType),
),
Container(
margin: const EdgeInsets.only(right: 50),
@@ -112,15 +113,15 @@ class SquareSliderComponentShape extends SliderComponentShape {
@override
void paint(PaintingContext context, Offset center,
{required Animation activationAnimation,
- required Animation enableAnimation,
- required bool isDiscrete,
- required TextPainter labelPainter,
- required RenderBox parentBox,
- required SliderThemeData sliderTheme,
- required TextDirection textDirection,
- required double value,
- required double textScaleFactor,
- required Size sizeWithOverflow}) {
+ required Animation enableAnimation,
+ required bool isDiscrete,
+ required TextPainter labelPainter,
+ required RenderBox parentBox,
+ required SliderThemeData sliderTheme,
+ required TextDirection textDirection,
+ required double value,
+ required double textScaleFactor,
+ required Size sizeWithOverflow}) {
final Canvas canvas = context.canvas;
canvas.drawRRect(
RRect.fromRectAndRadius(
@@ -138,18 +139,18 @@ class MyRoundedRectSliderTrackShape extends SliderTrackShape
@override
void paint(
- PaintingContext context,
- Offset offset, {
- required RenderBox parentBox,
- required SliderThemeData sliderTheme,
- required Animation enableAnimation,
- required TextDirection textDirection,
- required Offset thumbCenter,
- Offset? secondaryOffset,
- bool isDiscrete = false,
- bool isEnabled = false,
- double additionalTrackHeight = 30,
- }) {
+ PaintingContext context,
+ Offset offset, {
+ required RenderBox parentBox,
+ required SliderThemeData sliderTheme,
+ required Animation enableAnimation,
+ required TextDirection textDirection,
+ required Offset thumbCenter,
+ Offset? secondaryOffset,
+ bool isDiscrete = false,
+ bool isEnabled = false,
+ double additionalTrackHeight = 30,
+ }) {
if (sliderTheme.trackHeight == null) {
return;
}
@@ -209,4 +210,4 @@ class MyRoundedRectSliderTrackShape extends SliderTrackShape
rightTrackPaint,
);
}
-}
+}
\ No newline at end of file
diff --git a/controller/flutter/lib/screens/settingsDrawer.dart b/controller/flutter/lib/screens/settingsDrawer.dart
new file mode 100644
index 000000000..a51abc561
--- /dev/null
+++ b/controller/flutter/lib/screens/settingsDrawer.dart
@@ -0,0 +1,202 @@
+import 'package:flutter/material.dart';
+import 'package:nsd/nsd.dart';
+import 'package:openbot_controller/globals.dart';
+
+class SettingsDrawer extends StatefulWidget {
+ final List networkServices;
+ final Function(bool, bool) onSettingsChanged;
+
+ SettingsDrawer(this.networkServices, this.onSettingsChanged, {super.key});
+
+ @override
+ _SettingsDrawerState createState() => _SettingsDrawerState();
+}
+
+class _SettingsDrawerState extends State {
+ List isSelected = [false, false];
+ String dropDownValue = 'No server';
+ late List> items = [];
+ bool isNoise = false;
+ bool isNetwork = false;
+
+ // Function to generate DropdownMenuItem widgets
+ List> buildDropdownMenuItems() {
+ items = [
+ DropdownMenuItem(
+ value: 'No server',
+ child: Container(
+ height: 30,
+ width: 85,
+ decoration: const BoxDecoration(
+ borderRadius: BorderRadius.all(Radius.circular(30)),
+ color: Color(0xFF0071C5),
+ ),
+ alignment: Alignment.center,
+ child: const Text(
+ 'No server',
+ textAlign: TextAlign.center,
+ style: TextStyle(
+ fontSize: 18,
+ color: Color(0xFFffffff),
+ ),
+ ),
+ ),
+ ),
+ ];
+ items.addAll(widget.networkServices.map((discovery) {
+ return DropdownMenuItem(
+ value: discovery.name,
+ child: Container(
+ height: 30,
+ width: 85,
+ decoration: const BoxDecoration(
+ borderRadius: BorderRadius.all(Radius.circular(3)),
+ color: Color(0xFF0071C5),
+ ),
+ alignment: Alignment.center,
+ child: Text(
+ discovery.name ?? '',
+ textAlign: TextAlign.center,
+ style: const TextStyle(
+ fontSize: 18,
+ color: Color(0xFFffffff),
+ ),
+ ),
+ ),
+ );
+ }));
+ return items;
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Drawer(
+ backgroundColor: const Color(0xFF202020),
+ child: ListView(
+ padding: EdgeInsets.zero,
+ children: [
+ Padding(
+ padding: const EdgeInsets.only(left: 30, top: 35),
+ child: Row(children: [
+ const Text(
+ 'Controller',
+ style: TextStyle(
+ fontSize: 20,
+ fontWeight: FontWeight.w500,
+ color: Color(0xFF0071C5),
+ ),
+ ),
+ const SizedBox(
+ width: 30,
+ ),
+ ToggleButtons(
+ borderRadius: BorderRadius.circular(10),
+ selectedBorderColor: const Color(0xFF0071C5).withOpacity(0.4),
+ disabledBorderColor: const Color(0xFF0071C5).withOpacity(0.4),
+ onPressed: (int newIndex) {
+ setState(() {
+ for (int index = 0; index < isSelected.length; index++) {
+ if (index == newIndex) {
+ isSelected[index] = true;
+ if (index == 0) {
+ setState(() {
+ widget.onSettingsChanged(true, false);
+ });
+ } else {
+ setState(() {
+ widget.onSettingsChanged(false, true);
+ });
+ }
+ } else {
+ isSelected[index] = false;
+ }
+ }
+ });
+ },
+ isSelected: isSelected,
+ children: [
+ Image.asset(
+ "images/tilting_phone_icon.png",
+ height: 33,
+ width: 33,
+ ),
+ Image.asset(
+ "images/controller_icon.png",
+ height: 33,
+ width: 33,
+ )
+ ],
+ ),
+ ])),
+ Padding(
+ padding: const EdgeInsets.only(left: 30, top: 35),
+ child: Row(children: [
+ const Text(
+ 'Server',
+ style: TextStyle(
+ fontSize: 20,
+ fontWeight: FontWeight.w500,
+ color: Color(0xFF0071C5),
+ ),
+ ),
+ const SizedBox(
+ width: 54,
+ ),
+ DropdownButton(
+ value: dropDownValue,
+ borderRadius: const BorderRadius.all(Radius.circular(3)),
+ underline: Container(),
+ dropdownColor: const Color(0xFF0071C5),
+ style: const TextStyle(
+ fontSize: 18,
+ color: Color(0xFFffffff),
+ ),
+ menuMaxHeight: 150,
+ items: buildDropdownMenuItems(),
+ onChanged: (String? serverName) {
+ setState(() {
+ dropDownValue = serverName!;
+ });
+ if (serverName != "No server") {
+ clientSocket?.writeln("{server: $serverName}");
+ } else {
+ clientSocket?.writeln("{server: noServerFound}");
+ }
+ },
+ ),
+ ]),
+ ),
+ Padding(
+ padding: const EdgeInsets.only(left: 30, top: 35),
+ child: Row(children: [
+ const Text(
+ 'Noise',
+ style: TextStyle(
+ fontSize: 20,
+ fontWeight: FontWeight.w500,
+ color: Color(0xFF0071C5),
+ ),
+ ),
+ const SizedBox(
+ width: 54,
+ ),
+
+ Switch(
+ value: isNoise,
+ onChanged: (bool value) {
+ setState(() {
+ isNoise = value;
+ });
+ if (isNoise) {
+ clientSocket?.writeln("{command: NOISE}");
+ }
+ },
+ activeColor: const Color(0xFF0071C5),
+ )
+ ]),
+ ),
+ ],
+ ),
+ );
+ }
+}
diff --git a/controller/flutter/lib/screens/tiltingPhoneMode.dart b/controller/flutter/lib/screens/tiltingPhoneMode.dart
index 4479199da..c679436cd 100644
--- a/controller/flutter/lib/screens/tiltingPhoneMode.dart
+++ b/controller/flutter/lib/screens/tiltingPhoneMode.dart
@@ -4,11 +4,13 @@ import 'package:flutter/material.dart';
import 'package:openbot_controller/utils/forwardSpeed.dart';
import 'package:openbot_controller/utils/phoneSensorToDualDriveConverter.dart';
import 'package:sensors_plus/sensors_plus.dart';
-
+import 'package:openbot_controller/globals.dart';
import 'driveCommandReducer.dart';
class TiltingPhoneMode extends StatefulWidget {
- const TiltingPhoneMode({super.key});
+ final String fragmentType;
+
+ const TiltingPhoneMode({required this.fragmentType, super.key});
@override
State createState() {
@@ -28,6 +30,7 @@ class TiltingPhoneModeState extends State {
PhoneSensorToDualDriveConverter();
double leftSpeedValue = 0;
double rightSpeedValue = 0;
+ String typeOfFragment = "";
@override
void initState() {
@@ -43,6 +46,15 @@ class TiltingPhoneModeState extends State {
super.initState();
}
+ @override
+ void didUpdateWidget(covariant TiltingPhoneMode oldWidget) {
+ // TODO: implement didUpdateWidget
+ setState(() {
+ typeOfFragment = widget.fragmentType;
+ });
+ super.didUpdateWidget(oldWidget);
+ }
+
@override
Widget build(BuildContext context) {
return WillPopScope(
@@ -111,6 +123,54 @@ class TiltingPhoneModeState extends State {
width: 64,
),
)),
+ Container(
+ alignment: AlignmentDirectional.bottomEnd,
+ margin: const EdgeInsets.only(bottom: 20),
+ child: Row(children: [
+ GestureDetector(
+ onTap: () {
+ if (typeOfFragment == "DataCollection") {
+ clientSocket?.writeln("{command: LOGS}");
+ }
+ }, // Image tapped
+ child: Container(
+ padding: const EdgeInsets.all(15),
+ decoration: BoxDecoration(
+ borderRadius: BorderRadius.circular(45),
+ color: typeOfFragment == "DataCollection"
+ ? Colors.white.withOpacity(0.5)
+ : Colors.grey.withOpacity(0.5),
+ ),
+ child: const Icon(
+ Icons.file_present,
+ color: Colors.blue,
+ ),
+ )),
+ const SizedBox(
+ width: 15,
+ ),
+ GestureDetector(
+ onTap: () {
+ if (typeOfFragment == "Autopilot" ||
+ typeOfFragment == "ObjectDetection") {
+ clientSocket?.writeln("{command: NETWORK}");
+ }
+ }, // Image tapped
+ child: Container(
+ padding: const EdgeInsets.all(15),
+ decoration: BoxDecoration(
+ borderRadius: BorderRadius.circular(45),
+ color: typeOfFragment == "Autopilot" ||
+ typeOfFragment == "ObjectDetection"
+ ? Colors.white.withOpacity(0.5)
+ : Colors.grey.withOpacity(0.5),
+ ),
+ child: const Icon(
+ Icons.network_check,
+ color: Colors.blue,
+ ),
+ )),
+ ])),
GestureDetector(
onTapDown: (details) {
setState(() {
diff --git a/controller/flutter/pubspec.lock b/controller/flutter/pubspec.lock
index eabcf9292..e8c03be3d 100644
--- a/controller/flutter/pubspec.lock
+++ b/controller/flutter/pubspec.lock
@@ -13,10 +13,10 @@ packages:
dependency: "direct main"
description:
name: blinking_text
- sha256: "3f0c300f9f67ff3455e303a7dea7825bd96965d17295e4e831f29040c0379e69"
+ sha256: b5af1883380ab88ee6a9337a1b44fbba7d0670ba889b810c57c9aa58eb33ad92
url: "https://pub.dev"
source: hosted
- version: "1.0.2"
+ version: "1.0.4"
boolean_selector:
dependency: transitive
description:
@@ -45,42 +45,42 @@ packages:
dependency: transitive
description:
name: collection
- sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c"
+ sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
url: "https://pub.dev"
source: hosted
- version: "1.17.1"
+ version: "1.18.0"
crypto:
dependency: transitive
description:
name: crypto
- sha256: aa274aa7774f8964e4f4f38cc994db7b6158dd36e9187aaceaddc994b35c6c67
+ sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855"
url: "https://pub.dev"
source: hosted
- version: "3.0.2"
+ version: "3.0.6"
csslib:
dependency: transitive
description:
name: csslib
- sha256: b36c7f7e24c0bdf1bf9a3da461c837d1de64b9f8beb190c9011d8c72a3dfd745
+ sha256: "09bad715f418841f976c77db72d5398dc1253c21fb9c0c7f0b0b985860b2d58e"
url: "https://pub.dev"
source: hosted
- version: "0.17.2"
+ version: "1.0.2"
cupertino_icons:
dependency: "direct main"
description:
name: cupertino_icons
- sha256: e35129dc44c9118cee2a5603506d823bab99c68393879edb440e0090d07586be
+ sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6
url: "https://pub.dev"
source: hosted
- version: "1.0.5"
+ version: "1.0.8"
dart_webrtc:
dependency: transitive
description:
name: dart_webrtc
- sha256: "8949301071ac7c3fb8f78ef7dffc48652db16f2ec63d84078b608f2ca27cca38"
+ sha256: c664ad88d5646735753add421ee2118486c100febef5e92b7f59cdbabf6a51f6
url: "https://pub.dev"
source: hosted
- version: "1.0.17"
+ version: "1.4.9"
fake_async:
dependency: transitive
description:
@@ -93,18 +93,18 @@ packages:
dependency: transitive
description:
name: ffi
- sha256: a38574032c5f1dd06c4aee541789906c12ccaab8ba01446e800d9c5b79c4a978
+ sha256: "16ed7b077ef01ad6170a3d0c57caa4a112a38d7a2ed5602e0aca9ca6f3d98da6"
url: "https://pub.dev"
source: hosted
- version: "2.0.1"
- file:
+ version: "2.1.3"
+ fixnum:
dependency: transitive
description:
- name: file
- sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d"
+ name: fixnum
+ sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be
url: "https://pub.dev"
source: hosted
- version: "6.1.4"
+ version: "1.1.1"
flutter:
dependency: "direct main"
description: flutter
@@ -114,18 +114,18 @@ packages:
dependency: "direct dev"
description:
name: flutter_lints
- sha256: aeb0b80a8b3709709c9cc496cdc027c5b3216796bc0af0ce1007eaf24464fd4c
+ sha256: "5398f14efa795ffb7a33e9b6a08798b26a180edac4ad7db3f231e40f82ce11e1"
url: "https://pub.dev"
source: hosted
- version: "2.0.1"
+ version: "5.0.0"
flutter_speed_dial:
dependency: "direct main"
description:
name: flutter_speed_dial
- sha256: aba767df2df60ccb10ff9fecadd197c83e49ef4c3bc80bc55865eb4d023781d6
+ sha256: "698a037274a66dbae8697c265440e6acb6ab6cae9ac5f95c749e7944d8f28d41"
url: "https://pub.dev"
source: hosted
- version: "5.1.0"
+ version: "7.0.0"
flutter_test:
dependency: "direct dev"
description: flutter
@@ -140,26 +140,26 @@ packages:
dependency: "direct main"
description:
name: flutter_webrtc
- sha256: "4a3194900981ac7a2aa1e68a37903d8910cc3459c7a1ab68ad0407310cea1642"
+ sha256: "0b69ecab98211504c10d40c1c4cb48eb387e03ea8e732079bd0d2665d8c20d3f"
url: "https://pub.dev"
source: hosted
- version: "0.9.34"
+ version: "0.12.1+hotfix.1"
fluttertoast:
dependency: "direct main"
description:
name: fluttertoast
- sha256: "7cc92eabe01e3f1babe1571c5560b135dfc762a34e41e9056881e2196b178ec1"
+ sha256: "95f349437aeebe524ef7d6c9bde3e6b4772717cf46a0eb6a3ceaddc740b297cc"
url: "https://pub.dev"
source: hosted
- version: "8.1.2"
+ version: "8.2.8"
html:
dependency: transitive
description:
name: html
- sha256: d9793e10dbe0e6c364f4c59bf3e01fb33a9b2a674bc7a1081693dba0614b6269
+ sha256: "1fc58edeaec4307368c60d59b7e15b9d658b57d7f3125098b6294153c75337ec"
url: "https://pub.dev"
source: hosted
- version: "0.15.1"
+ version: "0.15.5"
http_parser:
dependency: transitive
description:
@@ -172,42 +172,74 @@ packages:
dependency: transitive
description:
name: js
- sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
+ sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.7.1"
+ leak_tracker:
+ dependency: transitive
+ description:
+ name: leak_tracker
+ sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05"
+ url: "https://pub.dev"
+ source: hosted
+ version: "10.0.5"
+ leak_tracker_flutter_testing:
+ dependency: transitive
+ description:
+ name: leak_tracker_flutter_testing
+ sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.0.5"
+ leak_tracker_testing:
+ dependency: transitive
+ description:
+ name: leak_tracker_testing
+ sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
url: "https://pub.dev"
source: hosted
- version: "0.6.7"
+ version: "3.0.1"
lints:
dependency: transitive
description:
name: lints
- sha256: "5e4a9cd06d447758280a8ac2405101e0e2094d2a1dbdd3756aec3fe7775ba593"
+ sha256: "3315600f3fb3b135be672bf4a178c55f274bebe368325ae18462c89ac1e3b413"
url: "https://pub.dev"
source: hosted
- version: "2.0.1"
+ version: "5.0.0"
+ logging:
+ dependency: transitive
+ description:
+ name: logging
+ sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.3.0"
matcher:
dependency: transitive
description:
name: matcher
- sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb"
+ sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb
url: "https://pub.dev"
source: hosted
- version: "0.12.15"
+ version: "0.12.16+1"
material_color_utilities:
dependency: transitive
description:
name: material_color_utilities
- sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724
+ sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
url: "https://pub.dev"
source: hosted
- version: "0.2.0"
+ version: "0.11.1"
meta:
dependency: transitive
description:
name: meta
- sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3"
+ sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7
url: "https://pub.dev"
source: hosted
- version: "1.9.1"
+ version: "1.15.0"
nested:
dependency: transitive
description:
@@ -220,194 +252,170 @@ packages:
dependency: "direct main"
description:
name: nsd
- sha256: "55b1f27a75e427ef3ba20d445b341a1c3666209f8a71559b43233877b8d3af08"
+ sha256: cae71ee9c23ea7f75d4610efe7ff335b1f575fb93ef7b7f9a5c6183a091cbb74
url: "https://pub.dev"
source: hosted
- version: "2.3.0"
+ version: "4.0.3"
nsd_android:
dependency: transitive
description:
name: nsd_android
- sha256: "7a38d0b2d21f1e578cd3020940b95b22d5260413dc0c8cf30a987a4e410b166d"
+ sha256: "1309cd47d02c99bd305219f0a226644f9f4a964d341c3d6730cebb906bb1ec78"
url: "https://pub.dev"
source: hosted
- version: "1.2.2"
+ version: "2.1.2"
nsd_ios:
dependency: transitive
description:
name: nsd_ios
- sha256: "7034134dd89595362d5e464030081b0d542120a558ab7fe6227df44365df3e8a"
+ sha256: "562fffe753543a65190344d3acd0ed80d96c571ac1a05bf10780c5584b5055ac"
url: "https://pub.dev"
source: hosted
- version: "1.0.3"
+ version: "2.0.1"
nsd_macos:
dependency: transitive
description:
name: nsd_macos
- sha256: "2403b8d599f50fc9179db1420a0ffc25bfa8bbeb814aa31ca0a71f804fc938da"
+ sha256: "47cd355d84009befe02710c72bf1c1999b24d5f3fb3a3d914f8b77bcaca42542"
url: "https://pub.dev"
source: hosted
- version: "1.0.3"
+ version: "2.0.1"
nsd_platform_interface:
dependency: transitive
description:
name: nsd_platform_interface
- sha256: "2f4033fa13cc45375253bf348abdb9712004e656462205543ec9506b43c67bb2"
+ sha256: "7220c8e0beeacd06c180fefcd6bb708415ed889c76f656e75ac633d09ceaa761"
url: "https://pub.dev"
source: hosted
- version: "1.6.0"
+ version: "2.1.1"
nsd_windows:
dependency: transitive
description:
name: nsd_windows
- sha256: "06601efdd3268cbce4b90f8e23ae1dab445c97c661fba417821ce118add722e7"
+ sha256: "68b4a256b0be258dbbad0ae789f2e8838d0935a353dac86b17c14c1a05df4ecd"
url: "https://pub.dev"
source: hosted
- version: "2.0.1"
+ version: "3.0.1"
path:
dependency: transitive
description:
name: path
- sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917"
+ sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
url: "https://pub.dev"
source: hosted
- version: "1.8.3"
+ version: "1.9.0"
path_provider:
dependency: transitive
description:
name: path_provider
- sha256: "050e8e85e4b7fecdf2bb3682c1c64c4887a183720c802d323de8a5fd76d372dd"
+ sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd"
url: "https://pub.dev"
source: hosted
- version: "2.0.11"
+ version: "2.1.5"
path_provider_android:
dependency: transitive
description:
name: path_provider_android
- sha256: a776c088d671b27f6e3aa8881d64b87b3e80201c64e8869b811325de7a76c15e
+ sha256: c464428172cb986b758c6d1724c603097febb8fb855aa265aeecc9280c294d4a
url: "https://pub.dev"
source: hosted
- version: "2.0.22"
- path_provider_ios:
+ version: "2.2.12"
+ path_provider_foundation:
dependency: transitive
description:
- name: path_provider_ios
- sha256: "03d639406f5343478352433f00d3c4394d52dac8df3d847869c5e2333e0bbce8"
+ name: path_provider_foundation
+ sha256: f234384a3fdd67f989b4d54a5d73ca2a6c422fa55ae694381ae0f4375cd1ea16
url: "https://pub.dev"
source: hosted
- version: "2.0.11"
+ version: "2.4.0"
path_provider_linux:
dependency: transitive
description:
name: path_provider_linux
- sha256: ab0987bf95bc591da42dffb38c77398fc43309f0b9b894dcc5d6f40c4b26c379
- url: "https://pub.dev"
- source: hosted
- version: "2.1.7"
- path_provider_macos:
- dependency: transitive
- description:
- name: path_provider_macos
- sha256: "2a97e7fbb7ae9dcd0dfc1220a78e9ec3e71da691912e617e8715ff2a13086ae8"
+ sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279
url: "https://pub.dev"
source: hosted
- version: "2.0.6"
+ version: "2.2.1"
path_provider_platform_interface:
dependency: transitive
description:
name: path_provider_platform_interface
- sha256: f0abc8ebd7253741f05488b4813d936b4d07c6bae3e86148a09e342ee4b08e76
+ sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334"
url: "https://pub.dev"
source: hosted
- version: "2.0.5"
+ version: "2.1.2"
path_provider_windows:
dependency: transitive
description:
name: path_provider_windows
- sha256: bcabbe399d4042b8ee687e17548d5d3f527255253b4a639f5f8d2094a9c2b45c
+ sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7
url: "https://pub.dev"
source: hosted
- version: "2.1.3"
+ version: "2.3.0"
platform:
dependency: transitive
description:
name: platform
- sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76"
+ sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984"
url: "https://pub.dev"
source: hosted
- version: "3.1.0"
+ version: "3.1.6"
platform_detect:
dependency: transitive
description:
name: platform_detect
- sha256: "14afcb6ffcd93745e39a288db53d1d6522ea25d71f7993c13a367a86c437b54d"
+ sha256: a62f99417fc4fa2d099ce0ccdbb1bd3977920f2a64292c326271f049d4bc3a4f
url: "https://pub.dev"
source: hosted
- version: "2.0.7"
+ version: "2.1.0"
plugin_platform_interface:
dependency: transitive
description:
name: plugin_platform_interface
- sha256: dbf0f707c78beedc9200146ad3cb0ab4d5da13c246336987be6940f026500d3a
+ sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02"
url: "https://pub.dev"
source: hosted
- version: "2.1.3"
- process:
- dependency: transitive
- description:
- name: process
- sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09"
- url: "https://pub.dev"
- source: hosted
- version: "4.2.4"
+ version: "2.1.8"
provider:
dependency: "direct main"
description:
name: provider
- sha256: cdbe7530b12ecd9eb455bdaa2fcb8d4dad22e80b8afb4798b41479d5ce26847f
+ sha256: c8a055ee5ce3fd98d6fc872478b03823ffdb448699c6ebdbbc71d59b596fd48c
url: "https://pub.dev"
source: hosted
- version: "6.0.5"
+ version: "6.1.2"
pub_semver:
dependency: transitive
description:
name: pub_semver
- sha256: "307de764d305289ff24ad257ad5c5793ce56d04947599ad68b3baa124105fc17"
+ sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c"
url: "https://pub.dev"
source: hosted
- version: "2.1.3"
+ version: "2.1.4"
sensors_plus:
dependency: "direct main"
description:
name: sensors_plus
- sha256: "362c8f4f001838b90dd5206b898bbad941bc0142479eab9a3415f0f79e622908"
+ sha256: "44b2297fbbcaa92273c356f7f4f72ad668ba5c0ddd79f890cb1152eaeea40a8b"
url: "https://pub.dev"
source: hosted
- version: "1.4.1"
+ version: "6.1.0"
sensors_plus_platform_interface:
dependency: transitive
description:
name: sensors_plus_platform_interface
- sha256: "95f0cc08791b8bf0c41c5fa99c84be2a7d5bf60a811ddc17e1438b1e68caf0d3"
+ sha256: b6cacfe243cbeb16403ba688cb0d7054ad4dccb946dcd1254bebdf345fe4b187
url: "https://pub.dev"
source: hosted
- version: "1.1.3"
- sensors_plus_web:
- dependency: transitive
- description:
- name: sensors_plus_web
- sha256: fca8d7d9ab6233b2a059952666415508e252420be1ef54f092d07884da53ec5e
- url: "https://pub.dev"
- source: hosted
- version: "1.1.2"
+ version: "2.0.0"
shelf:
dependency: "direct main"
description:
name: shelf
- sha256: c24a96135a2ccd62c64b69315a14adc5c3419df63b4d7c05832a346fdb73682c
+ sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4
url: "https://pub.dev"
source: hosted
- version: "1.4.0"
+ version: "1.4.1"
sky_engine:
dependency: transitive
description: flutter
@@ -417,26 +425,34 @@ packages:
dependency: transitive
description:
name: source_span
- sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250
+ sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.10.0"
+ sprintf:
+ dependency: transitive
+ description:
+ name: sprintf
+ sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23"
url: "https://pub.dev"
source: hosted
- version: "1.9.1"
+ version: "7.0.0"
stack_trace:
dependency: transitive
description:
name: stack_trace
- sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5
+ sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b"
url: "https://pub.dev"
source: hosted
- version: "1.11.0"
+ version: "1.11.1"
stream_channel:
dependency: transitive
description:
name: stream_channel
- sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8"
+ sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
url: "https://pub.dev"
source: hosted
- version: "2.1.1"
+ version: "2.1.2"
string_scanner:
dependency: transitive
description:
@@ -445,6 +461,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.2.0"
+ synchronized:
+ dependency: transitive
+ description:
+ name: synchronized
+ sha256: "69fe30f3a8b04a0be0c15ae6490fc859a78ef4c43ae2dd5e8a623d45bfcf9225"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.3.0+3"
term_glyph:
dependency: transitive
description:
@@ -457,26 +481,26 @@ packages:
dependency: transitive
description:
name: test_api
- sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb
+ sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb"
url: "https://pub.dev"
source: hosted
- version: "0.5.1"
+ version: "0.7.2"
typed_data:
dependency: transitive
description:
name: typed_data
- sha256: "26f87ade979c47a150c9eaab93ccd2bebe70a27dc0b4b29517f2904f04eb11a5"
+ sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006
url: "https://pub.dev"
source: hosted
- version: "1.3.1"
+ version: "1.4.0"
uuid:
dependency: "direct main"
description:
name: uuid
- sha256: "648e103079f7c64a36dc7d39369cabb358d377078a051d6ae2ad3aa539519313"
+ sha256: a5be9ef6618a7ac1e964353ef476418026db906c4facdedaa299b7a2e71690ff
url: "https://pub.dev"
source: hosted
- version: "3.0.7"
+ version: "4.5.1"
vector_math:
dependency: transitive
description:
@@ -489,66 +513,74 @@ packages:
dependency: "direct main"
description:
name: video_player
- sha256: "86b4fb9e30613ef4ff7e47367bfec4b080ab17205b7d969cd12bbebde49476b1"
+ sha256: "4a8c3492d734f7c39c2588a3206707a05ee80cef52e8c7f3b2078d430c84bc17"
url: "https://pub.dev"
source: hosted
- version: "2.4.10"
+ version: "2.9.2"
video_player_android:
dependency: transitive
description:
name: video_player_android
- sha256: "984388511230bac63feb53b2911a70e829fe0976b6b2213f5c579c4e0a882db3"
+ sha256: "391e092ba4abe2f93b3e625bd6b6a6ec7d7414279462c1c0ee42b5ab8d0a0898"
url: "https://pub.dev"
source: hosted
- version: "2.3.10"
+ version: "2.7.16"
video_player_avfoundation:
dependency: transitive
description:
name: video_player_avfoundation
- sha256: d9f7a46d6a77680adb03ec05a381025d6e890ebe636637c6c3014cc3926b97e9
+ sha256: "0b146e5d82e886ff43e5a46c6bcbe390761b802864a6e2503eb612d69a405dfa"
url: "https://pub.dev"
source: hosted
- version: "2.3.8"
+ version: "2.6.3"
video_player_platform_interface:
dependency: transitive
description:
name: video_player_platform_interface
- sha256: "42bb75de5e9b79e1f20f1d95f688fac0f95beac4d89c6eb2cd421724d4432dae"
+ sha256: "229d7642ccd9f3dc4aba169609dd6b5f3f443bb4cc15b82f7785fcada5af9bbb"
url: "https://pub.dev"
source: hosted
- version: "6.0.1"
+ version: "6.2.3"
video_player_web:
dependency: transitive
description:
name: video_player_web
- sha256: b649b07b8f8f553bee4a97a0a53d0fe78a70b115eafaf0105b612b32b05ddb99
+ sha256: "881b375a934d8ebf868c7fb1423b2bfaa393a0a265fa3f733079a86536064a10"
url: "https://pub.dev"
source: hosted
- version: "2.0.13"
- webrtc_interface:
+ version: "2.3.3"
+ vm_service:
dependency: transitive
description:
- name: webrtc_interface
- sha256: "0ac4693f921c81005edefd2f43b9fe84b0ed54481474fe1ee16b789b0c84a77c"
+ name: vm_service
+ sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d"
+ url: "https://pub.dev"
+ source: hosted
+ version: "14.2.5"
+ web:
+ dependency: transitive
+ description:
+ name: web
+ sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb
url: "https://pub.dev"
source: hosted
- version: "1.0.13"
- win32:
+ version: "1.1.0"
+ webrtc_interface:
dependency: transitive
description:
- name: win32
- sha256: c9ebe7ee4ab0c2194e65d3a07d8c54c5d00bb001b76081c4a04cdb8448b59e46
+ name: webrtc_interface
+ sha256: abec3ab7956bd5ac539cf34a42fa0c82ea26675847c0966bb85160400eea9388
url: "https://pub.dev"
source: hosted
- version: "3.1.3"
+ version: "1.2.0"
xdg_directories:
dependency: transitive
description:
name: xdg_directories
- sha256: bd512f03919aac5f1313eb8249f223bacf4927031bf60b02601f81f687689e86
+ sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15"
url: "https://pub.dev"
source: hosted
- version: "0.2.0+3"
+ version: "1.1.0"
sdks:
- dart: ">=3.0.0-0 <4.0.0"
- flutter: ">=3.0.0"
+ dart: ">=3.5.0 <4.0.0"
+ flutter: ">=3.24.0"
diff --git a/controller/flutter/pubspec.yaml b/controller/flutter/pubspec.yaml
index c61a16442..9a0b6d0af 100644
--- a/controller/flutter/pubspec.yaml
+++ b/controller/flutter/pubspec.yaml
@@ -31,19 +31,19 @@ environment:
dependencies:
flutter:
sdk: flutter
- sensors_plus: ^1.2.2
+ sensors_plus: ^6.1.0
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.2
- nsd: ^2.3.0
+ nsd: ^4.0.3
provider: ^6.0.2
- flutter_speed_dial: ^5.1.0
- uuid: ^3.0.6
+ flutter_speed_dial: ^7.0.0
+ uuid: ^4.5.1
shelf: ^1.3.0
blinking_text: ^1.0.2
video_player: ^2.4.10
- flutter_webrtc: ^0.9.34
+ flutter_webrtc: ^0.12.1+hotfix.1
fluttertoast: ^8.1.2
dev_dependencies:
flutter_test:
@@ -54,7 +54,7 @@ dev_dependencies:
# activated in the `analysis_options.yaml` file located at the root of your
# package. See that file for information about deactivating specific lint
# rules and activating additional ones.
- flutter_lints: ^2.0.0
+ flutter_lints: ^5.0.0
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
diff --git a/docs/images/app_controller_settings_1.jpg b/docs/images/app_controller_settings_1.jpg
new file mode 100644
index 000000000..ce3ecd3bf
Binary files /dev/null and b/docs/images/app_controller_settings_1.jpg differ
diff --git a/docs/images/app_controller_settings_2.jpg b/docs/images/app_controller_settings_2.jpg
new file mode 100644
index 000000000..d78201d5f
Binary files /dev/null and b/docs/images/app_controller_settings_2.jpg differ
diff --git a/docs/images/flutter_controller_connected.jpg b/docs/images/flutter_controller_connected.jpg
index 98426c429..6fa866ff5 100644
Binary files a/docs/images/flutter_controller_connected.jpg and b/docs/images/flutter_controller_connected.jpg differ
diff --git a/docs/images/flutter_controller_dual_drive_mode.jpg b/docs/images/flutter_controller_dual_drive_mode.jpg
index fd13ad9ee..a18652b42 100644
Binary files a/docs/images/flutter_controller_dual_drive_mode.jpg and b/docs/images/flutter_controller_dual_drive_mode.jpg differ
diff --git a/docs/images/flutter_controller_setting.jpg b/docs/images/flutter_controller_setting.jpg
new file mode 100644
index 000000000..509a71dde
Binary files /dev/null and b/docs/images/flutter_controller_setting.jpg differ
diff --git a/docs/images/flutter_controller_tilt_mode.jpg b/docs/images/flutter_controller_tilt_mode.jpg
index 8c660848e..3f1545a23 100644
Binary files a/docs/images/flutter_controller_tilt_mode.jpg and b/docs/images/flutter_controller_tilt_mode.jpg differ