Skip to content

Commit

Permalink
added version checking setting, laser metrics, network handshake freq…
Browse files Browse the repository at this point in the history
…uency setting
  • Loading branch information
aidanahram committed May 22, 2024
1 parent 54c41f2 commit 60f8dd4
Show file tree
Hide file tree
Showing 9 changed files with 55 additions and 13 deletions.
4 changes: 2 additions & 2 deletions lib/src/data/metrics/arm.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ class ArmMetrics extends Metrics<ArmData> {

/// Returns a description of a [MotorData].
List<MetricLine> getMotorData(MotorData motor) => [
MetricLine(" Is moving? ${motor.isMoving}", severity: motor.isMoving.toBool() ? Severity.info : null),
MetricLine(" Limit? ${motor.isLimitSwitchPressed}", severity: motor.isLimitSwitchPressed.toBool() ? Severity.warning : null),
MetricLine(" Is moving? ${motor.isMoving.displayName}", severity: motor.isMoving.toBool() ? Severity.info : null),
MetricLine(" Limit? ${motor.isLimitSwitchPressed.displayName}", severity: motor.isLimitSwitchPressed.toBool() ? Severity.warning : null),
MetricLine(" Direction: ${motor.direction.humanName}"),
MetricLine(" Steps: ${motor.currentStep} --> ${motor.targetStep}"),
MetricLine(" Angle: ${motor.angle.toDegrees()} degrees"),
Expand Down
7 changes: 5 additions & 2 deletions lib/src/data/metrics/gripper.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,18 @@ class GripperMetrics extends Metrics<GripperData> {

/// Returns a description of a [MotorData].
List<MetricLine> getMotorData(MotorData motor) => [
MetricLine(" Is moving? ${motor.isMoving}", severity: motor.isMoving.toBool() ? Severity.info : null),
MetricLine(" Limit? ${motor.isLimitSwitchPressed}", severity: motor.isLimitSwitchPressed.toBool() ? Severity.warning : null),
MetricLine(" Is moving? ${motor.isMoving.displayName}", severity: motor.isMoving.toBool() ? Severity.info : null),
MetricLine(" Limit? ${motor.isLimitSwitchPressed.displayName}", severity: motor.isLimitSwitchPressed.toBool() ? Severity.warning : null),
MetricLine(" Direction: ${motor.direction.humanName}"),
MetricLine(" Steps: ${motor.currentStep} --> ${motor.targetStep}"),
MetricLine(" Angle: ${motor.angle.toDegrees() % 360} degrees"),
];

@override
List<MetricLine> get allMetrics => [
MetricLine("Camera Angle: ${data.servoAngle} degrees"),
MetricLine("Laser: ${data.laserState.displayName}", severity: data.laserState.toBool() ? Severity.critical : null),
MetricLine("------------------------------",),
MetricLine("Lift:"),
...getMotorData(data.lift,),
MetricLine("------------------------------",),
Expand Down
1 change: 1 addition & 0 deletions lib/src/data/metrics/metrics.dart
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ abstract class Metrics<T extends Message> with ChangeNotifier {

/// Checks this message's version and checks for support.
bool checkVersion(T data) {
if (!models.settings.dashboard.versionChecking) return true;
if (data is RoverPosition) return true;
final newVersion = parseVersion(data);
if (newVersion.hasMajor()) version = newVersion;
Expand Down
9 changes: 9 additions & 0 deletions lib/src/data/protobuf.dart
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,15 @@ extension BoolUtils on BoolState {
bool toBool() => switch (this) {
BoolState.NO => false,
BoolState.YES => true,
BoolState.BOOL_UNDEFINED => false,
_ => throw ArgumentError("Unrecognized bool state: $this"),
};

/// Converts this Protobuf boolean into a human readable string.
String get displayName => switch(this) {
BoolState.NO => "No",
BoolState.YES => "Yes",
BoolState.BOOL_UNDEFINED => "No Data",
_ => throw ArgumentError("Unrecognized bool state: $this"),
};
}
6 changes: 6 additions & 0 deletions lib/src/data/settings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,9 @@ class DashboardSettings {
/// Tank controls offer more custom control, but modern drive controls are more intuitive.
final bool preferTankControls;

/// Whether to have version checking on protobuf messages.
final bool versionChecking;

/// A const constructor.
const DashboardSettings({
required this.splitMode,
Expand All @@ -250,6 +253,7 @@ class DashboardSettings {
required this.themeMode,
required this.splitCameras,
required this.preferTankControls,
required this.versionChecking,
});

/// Parses Dashboard settings from JSON.
Expand All @@ -259,6 +263,7 @@ class DashboardSettings {
maxFps = (json?["maxFps"] ?? 60) as int,
splitCameras = json?["splitCameras"] ?? false,
preferTankControls = json?["preferTankControls"] ?? false,
versionChecking = json?["versionChecking"] ?? true,
themeMode = ThemeMode.values.byName(json?["theme"] ?? ThemeMode.system.name);

/// Serializes these settings to JSON.
Expand All @@ -269,6 +274,7 @@ class DashboardSettings {
"theme": themeMode.name,
"splitCameras": splitCameras,
"preferTankControls": preferTankControls,
"versionChecking": versionChecking,
};
}

Expand Down
3 changes: 2 additions & 1 deletion lib/src/models/data/messages.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ class MessagesModel {

/// Sends a command over the network or over Serial.
void sendMessage(Message message, {bool checkVersion = true}) {
if (checkVersion && !models.rover.metrics.isSupportedVersion(message)) {
final shouldCheck = checkVersion && models.settings.dashboard.versionChecking;
if (shouldCheck && !models.rover.metrics.isSupportedVersion(message)) {
if (models.rover.isConnected) {
models.home.setMessage(severity: Severity.error, text: "Rover has the wrong ${message.messageName} version!");
}
Expand Down
14 changes: 13 additions & 1 deletion lib/src/models/view/builders/settings_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class NetworkSettingsBuilder extends ValueBuilder<NetworkSettings> {
videoSocket = SocketBuilder(initial.videoSocket),
autonomySocket = SocketBuilder(initial.autonomySocket),
tankSocket = SocketBuilder(initial.tankSocket),
connectionTimeout = NumberBuilder<double>(initial.connectionTimeout);
connectionTimeout = NumberBuilder<double>(initial.connectionTimeout, min: 0);

@override
bool get isValid => dataSocket.isValid
Expand Down Expand Up @@ -195,13 +195,17 @@ class DashboardSettingsBuilder extends ValueBuilder<DashboardSettings> {
/// Whether to default to tank controls. See [DashboardSettings.preferTankControls].
bool preferTankControls;

/// Whether to use version checking. See [DashboardSettings.versionChecking].
bool versionChecking;

/// Modifies the given [DashboardSettings].
DashboardSettingsBuilder(DashboardSettings initial) :
fps = NumberBuilder(initial.maxFps),
blockSize = NumberBuilder(initial.mapBlockSize),
splitMode = initial.splitMode,
splitCameras = initial.splitCameras,
preferTankControls = initial.preferTankControls,
versionChecking = initial.versionChecking,
themeMode = initial.themeMode;

@override
Expand All @@ -215,6 +219,7 @@ class DashboardSettingsBuilder extends ValueBuilder<DashboardSettings> {
themeMode: themeMode,
splitCameras: splitCameras,
preferTankControls: preferTankControls,
versionChecking: versionChecking,
);

/// Updates the [splitMode] when a new one is selected.
Expand Down Expand Up @@ -244,6 +249,13 @@ class DashboardSettingsBuilder extends ValueBuilder<DashboardSettings> {
preferTankControls = input;
notifyListeners();
}

/// Updates [versionChecking].
void updateVersionChecking(bool? input){ // ignore: avoid_positional_boolean_parameters
if (input == null) return;
versionChecking = input;
notifyListeners();
}
}

/// A [ValueBuilder] that modifies an [EasterEggsSettings].
Expand Down
8 changes: 7 additions & 1 deletion lib/src/pages/settings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ class SettingsPage extends ReactiveWidget<SettingsBuilder> {
}
},
),
NumberEditor(name: "Connection Timeout", model: model.network.connectionTimeout),
NumberEditor(name: "Heart beats per second", model: model.network.connectionTimeout),
],
),
const Divider(),
Expand Down Expand Up @@ -136,6 +136,12 @@ class SettingsPage extends ReactiveWidget<SettingsBuilder> {
value: model.dashboard.preferTankControls,
onChanged: model.dashboard.updateTank,
),
SwitchListTile(
title: const Text("Require version checking"),
subtitle: const Text("Default to version checking on"),
value: model.dashboard.versionChecking,
onChanged: model.dashboard.updateVersionChecking,
),
Row(children: [
const SizedBox(
width: 200,
Expand Down
16 changes: 10 additions & 6 deletions lib/src/services/socket.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import "package:burt_network/burt_network.dart";
import "package:flutter/foundation.dart"; // <-- Used for ValueNotifier

import "package:rover_dashboard/data.dart";
import "package:rover_dashboard/models.dart";

/// A service to send and receive Protobuf messages over a UDP socket, using [ProtoSocket].
///
Expand All @@ -24,6 +25,9 @@ class DashboardSocket extends BurtUdpProtocol {
/// The handler to call when a [WrappedMessage] comes in. Used by [onMessage].
final WrappedMessageHandler messageHandler;

/// Number of times to check heart beat per seconds based on [settings.network.connectionTimeout].
double get frequency => models.settings.network.connectionTimeout;

/// Listens for incoming messages on a UDP socket and sends heartbeats to the [device].
DashboardSocket({
required this.onConnect,
Expand All @@ -36,7 +40,7 @@ class DashboardSocket extends BurtUdpProtocol {
);

@override
Duration get heartbeatInterval => const Duration(milliseconds: 200);
Duration get heartbeatInterval => Duration(milliseconds: 1000 ~/ frequency);

/// The connection strength, as a percentage to this [device].
final connectionStrength = ValueNotifier<double>(0);
Expand Down Expand Up @@ -78,10 +82,10 @@ class DashboardSocket extends BurtUdpProtocol {
if (wasConnected && !isConnected) onDisconnect(device);
_isChecking = false;
}
}

/// How much each successful/missed handshake is worth, as a percent.
const connectionIncrement = 0.2;
/// How much each successful/missed handshake is worth, as a percent.
double get connectionIncrement => 1 / frequency;

/// How long to wait for incoming heartbeats after sending them out.
const heartbeatWaitDelay = Duration(milliseconds: 200);
/// How long to wait for incoming heartbeats after sending them out.
Duration get heartbeatWaitDelay => Duration(milliseconds: 1000 ~/ frequency);
}

0 comments on commit 60f8dd4

Please sign in to comment.