Skip to content

Commit

Permalink
feat: improve exception handling
Browse files Browse the repository at this point in the history
  • Loading branch information
doinkythederp committed Dec 6, 2024
1 parent 2fe77ab commit ece75c5
Show file tree
Hide file tree
Showing 7 changed files with 147 additions and 8 deletions.
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ jreleaser {
}

dependencies {
implementation("org.jetbrains:annotations:24.0.0")
compileOnly("org.jetbrains:annotations:24.0.0")

implementation(project(":vex-sdk"))
}
Expand Down
Binary file modified hydrozoa.bin
Binary file not shown.
5 changes: 2 additions & 3 deletions src/main/java/dev/vexide/hydrozoa/CompetitionRuntime.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public static void assertRobotEnabled() throws DeviceException {
* @param factory a function which creates a robot instance from the peripherals
* @throws IllegalStateException if the peripherals have already been taken or this method has already been called
*/
public static void start(@NotNull Function<@NotNull Peripherals, @NotNull CompetitionRobot> factory) throws IllegalStateException {
public static void start(@NotNull Function<@NotNull Peripherals, @NotNull CompetitionRobot> factory) {
try {
var robot = factory.apply(Peripherals.take().orElseThrow(() -> new IllegalStateException("Peripherals already taken")));

Expand Down Expand Up @@ -96,8 +96,7 @@ public static void start(@NotNull Function<@NotNull Peripherals, @NotNull Compet
}
}
} catch (Throwable e) {
System.err.println("Uncaught exception in competition runtime");
e.printStackTrace();
Platform.handleException(e);
}
}

Expand Down
60 changes: 60 additions & 0 deletions src/main/java/dev/vexide/hydrozoa/Platform.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
package dev.vexide.hydrozoa;

import dev.vexide.hydrozoa.sdk.Hydrozoa;
import dev.vexide.hydrozoa.sdk.VexSdk;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.time.Duration;

/**
* A utility class for platform-specific operations.
Expand All @@ -9,11 +16,64 @@ public final class Platform {
private Platform() {
}

public static final int STDOUT_BUFFER_SIZE = 2048;
public static final int STDIN_BUFFER_SIZE = 4096;
private static final int STDIO_CHANNEL = 1;

/**
* Yields the current task so that background processing may run, sensors may be updated, and the serial port may be
* flushed.
*/
public static void yield() {
VexSdk.vexTasksRun();
}
private static final Duration FLUSH_TIMEOUT = Duration.ofMillis(15);

// TODO: Does System.exit() work in Hydrozoa?
// /**
// * Exits the program, flushing the serial port before returning to the VEX V5's home screen.
// * <p>
// * This method does not return.
// */
// @SuppressWarnings("InfiniteLoopStatement")
// @Contract("-> fail")
// public static void exit() {
// var exitTime = Instant.now().plus(FLUSH_TIMEOUT);
//
// while (Instant.now().isBefore(exitTime)) {
// VexSdk.vexTasksRun();
//
// if (VexSdk.Serial.vexSerialWriteFree(STDIO_CHANNEL) == STDOUT_BUFFER_SIZE) {
// break;
// }
// }
//
// VexSdk.System.vexSystemExitRequest();
//
// while (true) {
// VexSdk.vexTasksRun();
// }
// }

private static final int SKIPPED_FRAMES = 7;
private static final String EXCEPTION_PREFIX = "Uncaught exception: ";

@Contract("_ -> fail")
public static void handleException(@NotNull Throwable error) {
System.out.println(EXCEPTION_PREFIX);
error.printStackTrace();

StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);

pw.print(EXCEPTION_PREFIX);
pw.println(error);

var stackTraceElements = error.getStackTrace();
for (int i = SKIPPED_FRAMES; i < stackTraceElements.length; i++) {
pw.println("\tat " + stackTraceElements[i]);
}

Hydrozoa.panic(sw.toString());
}
}
2 changes: 1 addition & 1 deletion vex-sdk/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ publishing {
}

dependencies {
implementation("org.jetbrains:annotations:24.0.0")
compileOnly("org.jetbrains:annotations:24.0.0")

implementation(teavm.libs.interop)
}
Expand Down
22 changes: 22 additions & 0 deletions vex-sdk/src/main/java/dev/vexide/hydrozoa/sdk/Hydrozoa.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package dev.vexide.hydrozoa.sdk;

import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.teavm.interop.Import;

/**
* A utility class for operations specific to the Hydrozoa runtime.
*/
public final class Hydrozoa {
private Hydrozoa() {
}

/**
* Causes the program to abnormally terminate with the given message.
*
* @param message a message describing the cause of the panic
*/
@Import(module = "hydrozoa", name = "panic")
@Contract("_ -> fail")
public static native void panic(@NotNull String message);
}
64 changes: 61 additions & 3 deletions vex-sdk/src/main/java/dev/vexide/hydrozoa/sdk/VexSdk.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
@SuppressWarnings("MissingJavadoc")
@StaticInit
public final class VexSdk {
private VexSdk() {
}

@Import(module = "vex", name = "vexTasksRun")
public static native void vexTasksRun();

Expand All @@ -16,6 +19,9 @@ public final class VexSdk {

@StaticInit
public static final class Display {
private Display() {
}

@Import(module = "vex", name = "vexDisplayRender")
public static native void vexDisplayRender(boolean bVsyncWait, boolean bRunScheduler);

Expand Down Expand Up @@ -81,6 +87,9 @@ public static final class Display {

@StaticInit
public static final class Controller {
private Controller() {
}

/**
* Get the value of a controller's data channel.
*/
Expand All @@ -102,9 +111,11 @@ public static int vexControllerGet(@NotNull V5_ControllerId id, @NotNull V5_Cont
private static native byte vexControllerConnectionStatusGetRaw(byte id);
}


@StaticInit
public static final class Device {
private Device() {
}

public static final int V5_MAX_DEVICE_PORTS = 32;

@Import(module = "vex", name = "vexControllerConnectionStatusGet")
Expand All @@ -131,6 +142,9 @@ public static int vexDevicesGetNumberByType(@NotNull V5_DeviceType deviceType) {

@StaticInit
public static final class Motor {
private Motor() {
}

// TODO:
// vexDeviceMotorZeroPositionFlagGet(device: V5_DeviceT) -> bool,
// vexDeviceMotorReverseFlagGet(device: V5_DeviceT) -> bool,
Expand Down Expand Up @@ -310,7 +324,7 @@ public static boolean vexDeviceMotorZeroPositionFlagGet(@NotNull V5_Device devic
@Import(module = "vex", name = "vexDeviceMotorZeroPositionFlagGet")
private static native boolean vexDeviceMotorZeroPositionFlagGetRaw(int device);

public static void vexDeviceMotorGearingSet(@NotNull V5_Device device, V5MotorGearset gearset) {
public static void vexDeviceMotorGearingSet(@NotNull V5_Device device, @NotNull V5MotorGearset gearset) {
vexDeviceMotorGearingSetRaw(device.raw(), gearset.value());
}

Expand All @@ -330,7 +344,7 @@ public static void vexDeviceMotorReverseFlagSet(@NotNull V5_Device device, boole
@Import(module = "vex", name = "vexDeviceMotorReverseFlagSet")
private static native void vexDeviceMotorReverseFlagSetRaw(int device, boolean flag);

public static void vexDeviceMotorEncoderUnitsSet(@NotNull V5_Device device, V5MotorEncoderUnits units) {
public static void vexDeviceMotorEncoderUnitsSet(@NotNull V5_Device device, @NotNull V5MotorEncoderUnits units) {
vexDeviceMotorEncoderUnitsSetRaw(device.raw(), units.value());
}
@Import(module = "vex", name = "vexDeviceMotorEncoderUnitsSet")
Expand All @@ -351,4 +365,48 @@ public static void vexDeviceMotorVoltageGet(@NotNull V5_Device device, int volta
private static native void vexDeviceMotorVoltageGetRaw(int device, int voltage);
}

@StaticInit
public static final class Serial {
private Serial() {
}

@Import(module = "vex", name = "vexSerialWriteChar")
public static native int vexSerialWriteChar(int channel, byte c);

@Import(module = "vex", name = "vexSerialReadChar")
public static native int vexSerialReadChar(int channel);

@Import(module = "vex", name = "vexSerialPeekChar")
public static native int vexSerialPeekChar(int channel);

@Import(module = "vex", name = "vexSerialWriteFree")
public static native int vexSerialWriteFree(int channel);
}

@StaticInit
public static final class System {
private System() {
}

@Import(module = "vex", name = "vexSystemTimeGet")
public static native int vexSystemTimeGet();

@Import(module = "vex", name = "vexSystemExitRequest")
public static native void vexSystemExitRequest();

@Import(module = "vex", name = "vexSystemHighResTimeGet")
public static native long vexSystemHighResTimeGet();

@Import(module = "vex", name = "vexSystemPowerupTimeGet")
public static native long vexSystemPowerupTimeGet();

@Import(module = "vex", name = "vexSystemLinkAddrGet")
public static native int vexSystemLinkAddrGet();

@Import(module = "vex", name = "vexSystemVersion")
public static native int vexSystemVersion();

@Import(module = "vex", name = "vexStdlibVersion")
public static native int vexStdlibVersion();
}
}

0 comments on commit ece75c5

Please sign in to comment.