- FRC Game Manual
- FRC Game Q&A

# Creating a Plugin

## Overview

Plugins provide the ability to create custom widgets, layouts, data sources/types, and custom themes. Shuffleboard provides the following built-in plugins.

- NetworkTables Plugin: To connect to data published over NetworkTables

- Base Plugin: To display custom FRC® data types in custom widgets

- CameraServer Plugin: To view streams from the CameraServer

Tip

An example custom Shuffleboard plugin which creates a custom data type and a simple widget for displaying it can be found here.

## Create a Custom Plugin

In order to define a plugin, the plugin class must be a subclass of edu.wpi.first.shuffleboard.api.Plugin or one of its subclasses. An example of a plugin class would be as following.

JAVA

    import edu.wpi.first.shuffleboard.api.plugin.Description;
    import edu.wpi.first.shuffleboard.api.plugin.Plugin;
    @Description(group = "com.example", name = "MyPlugin", version = "1.2.3", summary = "An example plugin")
    public class MyPlugin extends Plugin {
    }

Additional explanations on how these attributes are used, including version numbers can be found here.

Note the `@Description` annotation is needed to tell the plugin loader the properties of the custom plugin class. Plugin classes are permitted to have a default constructor but it cannot take any arguments.

## Building plugin

The easiest way to build plugins is to utilize the example-plugins folder in the shufflebloard source tree. Clone Shuffleboard with `git clone https://github.com/wpilibsuite/shuffleboard.git`, and checkout the version that corresponds to the WPILib version you have installed (e.g. 2023.2.1). `git checkout v2023.2.1`

Put your plugin in the `example-plugins\PLUGIN-NAME` directory. Copy the `custom-data-and-widget.gradle` from `example-plugins\custom-data-and-widget` and rename to match your plugin name. Edit `settings.gradle` in the shuffleboard root directory to add `include "example-plugins:PLUGIN-NAME"`

Plugins are allowed to have dependencies on other plugins and libraries, however, they must be included correctly in the maven or gradle build file. When a plugin depends on other plugins, it is good practice to define those dependencies so the plugin does not load when the dependencies do not load as well. This can be done using the `@Requires` annotation as shown below:

    @Requires(group = "com.example", name = "Good Plugin", minVersion = "1.2.3")
    @Requires(group = "edu.wpi.first.shuffleboard", name = "Base", minVersion = "1.0.0")
    @Description(group = "com.example", name = "MyPlugin", version = "1.2.3", summary = "An example plugin")
    public class MyPlugin extends Plugin {
    }

The `minVersion` specifies the minimum allowable version of the plugin that can be loaded. For example, if the `minVersion` is 1.4.5, and the plugin with the version 1.4.7 is loaded, it will be allowed to do so. However, if the plugin with the version 1.2.4 is loaded, it will not be allowed to since it is less than the `minVersion`.

## Deploying Plugin To Shuffleboard

In order to load a plugin in Shuffleboard, you will need to generate a jar file of the plugin and put it in the `~/Shuffleboard/plugins` folder. This can be done automatically by running from the shuffleboard root `gradlew :example-plugins:PLUGIN-NAME:installPlugin`

After deploying, Shuffleboard will cache the path of the plugin so it can be automatically loaded the next time Shuffleboard loads. It may be necessary to click on `Clear Cache` under the plugins menu to remove a plugin or reload a plugin into Shuffleboard.

## Manually Adding Plugin

The other way to add a plugin to Shuffleboard is to compile it to a jar file and add it from Shuffleboard. The jar file is located in `example-plugins\PLUGIN-NAME\build\libs` after running `gradlew build` in the shuffleboard root Open Shuffleboard, click on the file tab in the top left, and choose Plugins from the drop down menu.

From the plugins window, choose the “Load plugin” button in the bottom right, and select your jar file.