Files
allwpilib/cameraserver/multiCameraServer/src/main/java/edu/wpi/Main.java

197 lines
5.4 KiB
Java
Raw Normal View History

// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
package edu.wpi;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
2025-11-07 19:55:43 -05:00
import org.wpilib.vision.stream.CameraServer;
import org.wpilib.vision.camera.VideoSource;
import org.wpilib.networktables.NetworkTableInstance;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
/*
JSON format:
{
"team": <team number>,
"ntmode": <"client" or "server", "client" if unspecified>
"cameras": [
{
"name": <camera name>
"path": <path, e.g. "/dev/video0">
"pixel format": <"MJPEG", "YUYV", etc> // optional
"width": <video mode width> // optional
"height": <video mode height> // optional
"fps": <video mode fps> // optional
"brightness": <percentage brightness> // optional
"white balance": <"auto", "hold", value> // optional
"exposure": <"auto", "hold", value> // optional
"properties": [ // optional
{
"name": <property name>
"value": <property value>
}
]
}
]
}
*/
public final class Main {
private static String configFile = "/boot/frc.json";
@SuppressWarnings("MemberName")
public static class CameraConfig {
public String name;
public String path;
public JsonObject config;
}
private static int team;
private static boolean server;
private static List<CameraConfig> cameras = new ArrayList<>();
private Main() {}
/** Report parse error. */
public static void parseError(String str) {
System.err.println("config error in '" + configFile + "': " + str);
}
/** Read single camera configuration. */
public static boolean readCameraConfig(JsonObject config) {
CameraConfig cam = new CameraConfig();
// name
JsonElement nameElement = config.get("name");
if (nameElement == null) {
parseError("could not read camera name");
return false;
}
cam.name = nameElement.getAsString();
// path
JsonElement pathElement = config.get("path");
if (pathElement == null) {
parseError("camera '" + cam.name + "': could not read path");
return false;
}
cam.path = pathElement.getAsString();
cam.config = config;
cameras.add(cam);
return true;
}
/** Read configuration file. */
public static boolean readConfig() {
// parse file
JsonElement top;
try {
top = JsonParser.parseReader(Files.newBufferedReader(Paths.get(configFile)));
} catch (IOException ex) {
System.err.println("could not open '" + configFile + "': " + ex);
return false;
}
// top level must be an object
if (!top.isJsonObject()) {
parseError("must be JSON object");
return false;
}
JsonObject obj = top.getAsJsonObject();
// team number
JsonElement teamElement = obj.get("team");
if (teamElement == null) {
parseError("could not read team number");
return false;
}
team = teamElement.getAsInt();
// ntmode (optional)
if (obj.has("ntmode")) {
String str = obj.get("ntmode").getAsString();
if ("client".equalsIgnoreCase(str)) {
server = false;
} else if ("server".equalsIgnoreCase(str)) {
server = true;
} else {
parseError("could not understand ntmode value '" + str + "'");
}
}
// cameras
JsonElement camerasElement = obj.get("cameras");
if (camerasElement == null) {
parseError("could not read cameras");
return false;
}
JsonArray cameras = camerasElement.getAsJsonArray();
for (JsonElement camera : cameras) {
if (!readCameraConfig(camera.getAsJsonObject())) {
return false;
}
}
return true;
}
/** Start running the camera. */
public static void startCamera(CameraConfig config) {
System.out.println("Starting camera '" + config.name + "' on " + config.path);
VideoSource camera = CameraServer.startAutomaticCapture(config.name, config.path);
Gson gson = new GsonBuilder().create();
camera.setConfigJson(gson.toJson(config.config));
}
/** Main. */
public static void main(String... args) {
if (args.length > 0) {
configFile = args[0];
}
// read configuration
if (!readConfig()) {
return;
}
// start NetworkTables
NetworkTableInstance ntinst = NetworkTableInstance.getDefault();
if (server) {
System.out.println("Setting up NetworkTables server");
ntinst.startServer();
} else {
System.out.println("Setting up NetworkTables client for team " + team);
2022-10-08 10:01:31 -07:00
ntinst.setServerTeam(team);
ntinst.startClient("multicameraserver");
}
// start cameras
for (CameraConfig camera : cameras) {
startCamera(camera);
}
// loop forever
for (; ; ) {
try {
Thread.sleep(10000);
} catch (InterruptedException ex) {
return;
}
}
}
}