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 @@ -11,12 +11,15 @@
import com.acmerobotics.dashboard.message.redux.ReceiveHardwareConfigList;
import com.acmerobotics.dashboard.message.redux.ReceiveImage;
import com.acmerobotics.dashboard.message.redux.ReceiveLogcatErrors;
import com.acmerobotics.dashboard.message.redux.ReceiveLogcatLines;
import com.acmerobotics.dashboard.message.redux.ReceiveOpModeList;
import com.acmerobotics.dashboard.message.redux.ReceiveRobotStatus;
import com.acmerobotics.dashboard.message.redux.ReceiveTelemetry;
import com.acmerobotics.dashboard.message.redux.SaveConfig;
import com.acmerobotics.dashboard.message.redux.SetHardwareConfig;
import com.acmerobotics.dashboard.message.redux.StartLogcatCapture;
import com.acmerobotics.dashboard.message.redux.StartOpMode;
import com.acmerobotics.dashboard.message.redux.StopLogcatCapture;
import com.acmerobotics.dashboard.message.redux.StopOpMode;
import com.acmerobotics.dashboard.message.redux.WriteHardwareConfig;

Expand Down Expand Up @@ -55,7 +58,12 @@ public enum MessageType {
DELETE_HARDWARE_CONFIG(DeleteHardwareConfig.class),

/* logcat errors */
RECEIVE_LOGCAT_ERRORS(ReceiveLogcatErrors.class);
RECEIVE_LOGCAT_ERRORS(ReceiveLogcatErrors.class),

/* full logcat capture */
START_LOGCAT_CAPTURE(StartLogcatCapture.class),
STOP_LOGCAT_CAPTURE(StopLogcatCapture.class),
RECEIVE_LOGCAT_LINES(ReceiveLogcatLines.class);

final Class<? extends Message> msgClass;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.acmerobotics.dashboard.message.redux;

import com.acmerobotics.dashboard.message.Message;
import com.acmerobotics.dashboard.message.MessageType;
import java.util.List;

public class ReceiveLogcatLines extends Message {
private List<ReceiveLogcatErrors.LogcatError> lines;

public ReceiveLogcatLines(List<ReceiveLogcatErrors.LogcatError> lines) {
super(MessageType.RECEIVE_LOGCAT_LINES);
this.lines = lines;
}

public List<ReceiveLogcatErrors.LogcatError> getLines() {
return lines;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.acmerobotics.dashboard.message.redux;

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

public class StartLogcatCapture extends Message {
public StartLogcatCapture() {
super(MessageType.START_LOGCAT_CAPTURE);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.acmerobotics.dashboard.message.redux;

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

public class StopLogcatCapture extends Message {
public StopLogcatCapture() {
super(MessageType.STOP_LOGCAT_CAPTURE);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import com.acmerobotics.dashboard.message.Message;
import com.acmerobotics.dashboard.message.redux.InitOpMode;
import com.acmerobotics.dashboard.message.redux.ReceiveHardwareConfigList;
import com.acmerobotics.dashboard.message.redux.ReceiveLogcatErrors;
import com.acmerobotics.dashboard.message.redux.ReceiveLogcatLines;
import com.acmerobotics.dashboard.message.redux.ReceiveOpModeList;
import com.acmerobotics.dashboard.message.redux.ReceiveRobotStatus;
import com.acmerobotics.dashboard.message.redux.SetHardwareConfig;
Expand All @@ -13,7 +15,11 @@
import fi.iki.elonen.NanoWSD;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Random;
import java.util.Set;
import java.util.stream.Collectors;

public class TestDashboardInstance {
Expand All @@ -25,6 +31,9 @@ public class TestDashboardInstance {

private TelemetryPacket currentPacket;

private final Set<SendFun> logcatCaptureSockets =
Collections.synchronizedSet(new LinkedHashSet<>());

DashboardCore core = new DashboardCore();

private NanoWSD server =
Expand Down Expand Up @@ -86,6 +95,8 @@ protected void onClose(
NanoWSD.WebSocketFrame.CloseCode code, String reason, boolean initiatedByRemote) {
sh.onClose();

logcatCaptureSockets.remove(this);

opModeManager.clearSendFun();
}

Expand Down Expand Up @@ -135,6 +146,12 @@ protected void onMessage(NanoWSD.WebSocketFrame message) {
case STOP_OP_MODE:
opModeManager.stopOpMode();
break;
case START_LOGCAT_CAPTURE:
logcatCaptureSockets.add(this);
break;
case STOP_LOGCAT_CAPTURE:
logcatCaptureSockets.remove(this);
break;
case SET_HARDWARE_CONFIG:
SetHardwareConfig setHardwareConfig = (SetHardwareConfig) msg;
hardwareConfigManager.setHardwareConfig(
Expand Down Expand Up @@ -272,12 +289,108 @@ public void set(Float value) {
throw new RuntimeException(e);
}

startFakeLogcatEmitter();

while (true) {
opModeManager.loop();
Thread.yield();
}
}

// Emits fake logcat traffic so the client can be exercised without a robot: OpModeManager
// entries on the always-on error stream, and full device log lines to whichever sockets asked
// for a capture.
private void startFakeLogcatEmitter() {
Thread emitter =
new Thread(
() -> {
String[] levels = {"INFO", "DEBUG", "WARN", "ERROR", "VERBOSE"};
String[] opModeMessages = {
"OpMode initialized",
"Loop time: 12ms",
"Battery voltage: 12.4V",
"IMU calibration complete",
"Encoder positions reset",
"Motor power set to 0.75",
"Vision pipeline latency: 33ms",
};
String[] deviceTags = {
"RobotCore", "LynxModule", "EventLoopManager", "ActivityManager",
};
String[] deviceMessages = {
"onDrawFrame: 16ms",
"bulk read cache invalidated",
"sending heartbeat",
"gc freed 2048K, 12% free",
"wifi direct group owner negotiation complete",
};
Random random = new Random();
int tick = 0;
while (true) {
try {
Thread.sleep(250);
} catch (InterruptedException e) {
return;
}

tick++;
if (tick % 4 == 0) {
ReceiveLogcatErrors.LogcatError error =
new ReceiveLogcatErrors.LogcatError(
System.currentTimeMillis(),
levels[random.nextInt(levels.length)],
"OpModeManager",
opModeMessages[
random.nextInt(opModeMessages.length)]);
try {
core.sendAll(
new ReceiveLogcatErrors(
Collections.singletonList(error)));
} catch (RuntimeException e) {
// a socket went away between the copy and the send
}
}

List<SendFun> targets;
synchronized (logcatCaptureSockets) {
targets = new ArrayList<>(logcatCaptureSockets);
}
if (targets.isEmpty()) {
continue;
}

ReceiveLogcatLines lines =
new ReceiveLogcatLines(
Collections.singletonList(
new ReceiveLogcatErrors.LogcatError(
System.currentTimeMillis(),
levels[
random.nextInt(
levels.length)],
deviceTags[
random.nextInt(
deviceTags.length)],
deviceMessages[
random.nextInt(
deviceMessages
.length)]
+ " #"
+ tick)));
for (SendFun target : targets) {
try {
target.send(lines);
} catch (RuntimeException e) {
// the socket went away between the copy and the send
logcatCaptureSockets.remove(target);
}
}
}
},
"fake logcat emitter");
emitter.setDaemon(true);
emitter.start();
}

public void addData(String x, Object o) {
if (currentPacket == null) {
currentPacket = new TelemetryPacket();
Expand Down
Loading
Loading