Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import com.acmerobotics.dashboard.message.MessageDeserializer;
import com.acmerobotics.dashboard.message.MessageType;
import com.acmerobotics.dashboard.message.redux.ReceiveConfig;
import com.acmerobotics.dashboard.message.redux.ReceiveConfigBaseline;
import com.acmerobotics.dashboard.message.redux.ReceiveTelemetry;
import com.acmerobotics.dashboard.message.redux.SaveConfig;
import com.acmerobotics.dashboard.telemetry.TelemetryPacket;
Expand Down Expand Up @@ -39,6 +40,7 @@ public class DashboardCore {
private volatile int telemetryTransmissionInterval = DEFAULT_TELEMETRY_TRANSMISSION_INTERVAL;

private final Mutex<CustomVariable> configRoot = new Mutex<>(new CustomVariable());
private final Mutex<CustomVariable> configBaseline = new Mutex<>(new CustomVariable());

// NOTE: Helps to have this here for testing
public static final Gson GSON = new GsonBuilder()
Expand All @@ -50,6 +52,15 @@ public class DashboardCore {
.serializeNulls()
.create();

/**
* Creates a deep copy of a CustomVariable by serializing and deserializing it.
* This ensures we capture the current state of all configuration values.
*/
private CustomVariable deepCopyConfig(CustomVariable original) {
String json = GSON.toJson(original);
return GSON.fromJson(json, CustomVariable.class);
}

private class TelemetryUpdateRunnable implements Runnable {
@Override
public void run() {
Expand Down Expand Up @@ -105,6 +116,10 @@ public void onOpen() {
configRoot.with(v -> {
sendFun.send(new ReceiveConfig(v));
});

configBaseline.with(v -> {
sendFun.send(new ReceiveConfigBaseline(v));
});

sockets.with(l -> {
l.add(sendFun);
Expand Down Expand Up @@ -132,6 +147,12 @@ public boolean onMessage(Message message) {
});
return true;
}
case GET_CONFIG_BASELINE: {
configBaseline.with(v -> {
sendFun.send(new ReceiveConfigBaseline(v));
});
return true;
}
case SAVE_CONFIG: {
withConfigRoot(new CustomVariableConsumer() {
@Override
Expand Down Expand Up @@ -246,6 +267,24 @@ public <T> void addConfigVariable(String category, String name, ValueProvider<T>
catVar.putVariable(name, new BasicVariable<>(provider));
v.putVariable(category, catVar);
}

// Update baseline with current configuration state if this is the first time we're adding this variable
configBaseline.with(baseline -> {
CustomVariable baselineCatVar = (CustomVariable) baseline.getVariable(category);
if (baselineCatVar == null || baselineCatVar.getVariable(name) == null) {
// Capture the current state as baseline
CustomVariable currentSnapshot = deepCopyConfig(v);

// Clear and copy the new baseline
List<String> keysToRemove = new ArrayList<>();
baseline.entrySet().forEach(entry -> keysToRemove.add(entry.getKey()));
keysToRemove.forEach(baseline::removeVariable);

currentSnapshot.entrySet().forEach(entry ->
baseline.putVariable(entry.getKey(), entry.getValue()));
}
});

updateConfig();
});
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package com.acmerobotics.dashboard.message;

import com.acmerobotics.dashboard.message.redux.GetConfig;
import com.acmerobotics.dashboard.message.redux.GetConfigBaseline;
import com.acmerobotics.dashboard.message.redux.GetRobotStatus;
import com.acmerobotics.dashboard.message.redux.InitOpMode;
import com.acmerobotics.dashboard.message.redux.ReceiveConfig;
import com.acmerobotics.dashboard.message.redux.ReceiveConfigBaseline;
import com.acmerobotics.dashboard.message.redux.ReceiveGamepadState;
import com.acmerobotics.dashboard.message.redux.ReceiveHardwareConfigList;
import com.acmerobotics.dashboard.message.redux.ReceiveImage;
Expand Down Expand Up @@ -31,8 +33,10 @@ public enum MessageType {

/* config */
GET_CONFIG(GetConfig.class),
GET_CONFIG_BASELINE(GetConfigBaseline.class),
SAVE_CONFIG(SaveConfig.class),
RECEIVE_CONFIG(ReceiveConfig.class),
RECEIVE_CONFIG_BASELINE(ReceiveConfigBaseline.class),

/* telemetry */
RECEIVE_TELEMETRY(ReceiveTelemetry.class),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.acmerobotics.dashboard.message.redux;

import com.acmerobotics.dashboard.message.Message;
import com.acmerobotics.dashboard.message.MessageType;

/**
* Message to request the baseline configuration values (values that were present when deployed to the bot).
*/
public class GetConfigBaseline extends Message {
public GetConfigBaseline() {
super(MessageType.GET_CONFIG_BASELINE);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.acmerobotics.dashboard.message.redux;

import com.acmerobotics.dashboard.config.variable.CustomVariable;
import com.acmerobotics.dashboard.message.Message;
import com.acmerobotics.dashboard.message.MessageType;

/**
* Message containing the baseline configuration values (values that were present when deployed to the bot).
*/
public class ReceiveConfigBaseline extends Message {
private CustomVariable configBaseline;

public ReceiveConfigBaseline(CustomVariable configBaseline) {
super(MessageType.RECEIVE_CONFIG_BASELINE);

this.configBaseline = configBaseline;
}

public CustomVariable getConfigBaseline() {
return configBaseline;
}
}
3 changes: 3 additions & 0 deletions client/src/assets/icons/filter.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading