diff --git a/photon-core/src/main/java/org/photonvision/common/configuration/NetworkConfig.java b/photon-core/src/main/java/org/photonvision/common/configuration/NetworkConfig.java index b38cbdb497..fd4890a31b 100644 --- a/photon-core/src/main/java/org/photonvision/common/configuration/NetworkConfig.java +++ b/photon-core/src/main/java/org/photonvision/common/configuration/NetworkConfig.java @@ -89,6 +89,21 @@ public NetworkConfig( setShouldManage(shouldManage); } + public NetworkConfig(NetworkConfig config) { + this( + config.ntServerAddress, + config.connectionType, + config.staticIp, + config.hostname, + config.runNTServer, + config.shouldManage, + config.shouldPublishProto, + config.networkManagerIface, + config.setStaticCommand, + config.setDHCPcommand, + config.matchCamerasOnlyByPath); + } + public Map toHashMap() { try { var ret = new ObjectMapper().convertValue(this, JacksonUtils.UIMap.class); diff --git a/photon-core/src/main/java/org/photonvision/common/configuration/PhotonConfiguration.java b/photon-core/src/main/java/org/photonvision/common/configuration/PhotonConfiguration.java index 74d67ec73e..66018ec6ca 100644 --- a/photon-core/src/main/java/org/photonvision/common/configuration/PhotonConfiguration.java +++ b/photon-core/src/main/java/org/photonvision/common/configuration/PhotonConfiguration.java @@ -21,19 +21,6 @@ import java.util.Collection; import java.util.HashMap; import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import org.photonvision.PhotonVersion; -import org.photonvision.common.hardware.Platform; -import org.photonvision.common.networking.NetworkManager; -import org.photonvision.common.networking.NetworkUtils; -import org.photonvision.common.util.SerializationUtils; -import org.photonvision.mrcal.MrCalJNILoader; -import org.photonvision.raspi.LibCameraJNILoader; -import org.photonvision.vision.calibration.UICameraCalibrationCoefficients; -import org.photonvision.vision.camera.QuirkyCamera; -import org.photonvision.vision.processes.VisionModule; -import org.photonvision.vision.processes.VisionModuleManager; import org.photonvision.vision.processes.VisionSource; public class PhotonConfiguration { @@ -124,81 +111,6 @@ public boolean removeCameraConfig(String name) { return cameraConfigurations.remove(name) != null; } - public Map toHashMap() { - Map map = new HashMap<>(); - var settingsSubmap = new HashMap(); - - // Hack active interfaces into networkSettings - var netConfigMap = networkConfig.toHashMap(); - netConfigMap.put("networkInterfaceNames", NetworkUtils.getAllActiveWiredInterfaces()); - netConfigMap.put("networkingDisabled", NetworkManager.getInstance().networkingIsDisabled); - - settingsSubmap.put("networkSettings", netConfigMap); - - var lightingConfig = new UILightingConfig(); - lightingConfig.brightness = hardwareSettings.ledBrightnessPercentage; - lightingConfig.supported = !hardwareConfig.ledPins.isEmpty(); - settingsSubmap.put("lighting", SerializationUtils.objectToHashMap(lightingConfig)); - // General Settings - var generalSubmap = new HashMap(); - generalSubmap.put("version", PhotonVersion.versionString); - generalSubmap.put( - "gpuAcceleration", - LibCameraJNILoader.isSupported() - ? "Zerocopy Libcamera Working" - : ""); // TODO add support for other types of GPU accel - generalSubmap.put("mrCalWorking", MrCalJNILoader.getInstance().isLoaded()); - generalSubmap.put("availableModels", NeuralNetworkModelManager.getInstance().getModels()); - generalSubmap.put( - "supportedBackends", NeuralNetworkModelManager.getInstance().getSupportedBackends()); - generalSubmap.put( - "hardwareModel", - hardwareConfig.deviceName.isEmpty() - ? Platform.getHardwareModel() - : hardwareConfig.deviceName); - generalSubmap.put("hardwarePlatform", Platform.getPlatformName()); - settingsSubmap.put("general", generalSubmap); - // AprilTagFieldLayout - settingsSubmap.put("atfl", this.atfl); - - map.put( - "cameraSettings", - VisionModuleManager.getInstance().getModules().stream() - .map(VisionModule::toUICameraConfig) - .map(SerializationUtils::objectToHashMap) - .collect(Collectors.toList())); - map.put("settings", settingsSubmap); - - return map; - } - - public static class UILightingConfig { - public int brightness = 0; - public boolean supported = true; - } - - public static class UICameraConfiguration { - @SuppressWarnings("unused") - public double fov; - - public String nickname; - public String uniqueName; - public HashMap currentPipelineSettings; - public int currentPipelineIndex; - public List pipelineNicknames; - public HashMap> videoFormatList; - public int outputStreamPort; - public int inputStreamPort; - public List calibrations; - public boolean isFovConfigurable = true; - public QuirkyCamera cameraQuirks; - public boolean isCSICamera; - public double minExposureRaw; - public double maxExposureRaw; - public double minWhiteBalanceTemp; - public double maxWhiteBalanceTemp; - } - @Override public String toString() { return "PhotonConfiguration [\n hardwareConfig=" diff --git a/photon-core/src/main/java/org/photonvision/common/dataflow/networktables/NetworkTablesManager.java b/photon-core/src/main/java/org/photonvision/common/dataflow/networktables/NetworkTablesManager.java index 21c22ad22f..5765972f91 100644 --- a/photon-core/src/main/java/org/photonvision/common/dataflow/networktables/NetworkTablesManager.java +++ b/photon-core/src/main/java/org/photonvision/common/dataflow/networktables/NetworkTablesManager.java @@ -32,6 +32,7 @@ import org.photonvision.common.configuration.NetworkConfig; import org.photonvision.common.dataflow.DataChangeService; import org.photonvision.common.dataflow.events.OutgoingUIEvent; +import org.photonvision.common.dataflow.websocket.UIPhotonConfiguration; import org.photonvision.common.hardware.HardwareManager; import org.photonvision.common.logging.LogGroup; import org.photonvision.common.logging.LogLevel; @@ -165,7 +166,8 @@ private void onFieldLayoutChanged(NetworkTableEvent event) { DataChangeService.getInstance() .publishEvent( new OutgoingUIEvent<>( - "fullsettings", ConfigManager.getInstance().getConfig().toHashMap())); + "fullsettings", + UIPhotonConfiguration.programStateToUi(ConfigManager.getInstance().getConfig()))); } catch (IOException e) { logger.error("Error deserializing atfl!"); logger.error(atfl_json); diff --git a/photon-core/src/main/java/org/photonvision/common/dataflow/websocket/UICameraConfiguration.java b/photon-core/src/main/java/org/photonvision/common/dataflow/websocket/UICameraConfiguration.java new file mode 100644 index 0000000000..f8e5a114ae --- /dev/null +++ b/photon-core/src/main/java/org/photonvision/common/dataflow/websocket/UICameraConfiguration.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) Photon Vision. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.photonvision.common.dataflow.websocket; + +import java.util.HashMap; +import java.util.List; +import org.photonvision.vision.calibration.UICameraCalibrationCoefficients; +import org.photonvision.vision.camera.QuirkyCamera; + +public class UICameraConfiguration { + @SuppressWarnings("unused") + public double fov; + + public String nickname; + public String uniqueName; + public HashMap currentPipelineSettings; + public int currentPipelineIndex; + public List pipelineNicknames; + public HashMap> videoFormatList; + public int outputStreamPort; + public int inputStreamPort; + public List calibrations; + public boolean isFovConfigurable = true; + public QuirkyCamera cameraQuirks; + public boolean isCSICamera; + public double minExposureRaw; + public double maxExposureRaw; + public double minWhiteBalanceTemp; + public double maxWhiteBalanceTemp; +} diff --git a/photon-core/src/main/java/org/photonvision/common/dataflow/websocket/UIGeneralSettings.java b/photon-core/src/main/java/org/photonvision/common/dataflow/websocket/UIGeneralSettings.java new file mode 100644 index 0000000000..00ece4d1c1 --- /dev/null +++ b/photon-core/src/main/java/org/photonvision/common/dataflow/websocket/UIGeneralSettings.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) Photon Vision. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.photonvision.common.dataflow.websocket; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class UIGeneralSettings { + public UIGeneralSettings( + String version, + String gpuAcceleration, + boolean mrCalWorking, + Map> availableModels, + List supportedBackends, + String hardwareModel, + String hardwarePlatform) { + this.version = version; + this.gpuAcceleration = gpuAcceleration; + this.mrCalWorking = mrCalWorking; + this.availableModels = availableModels; + this.supportedBackends = supportedBackends; + this.hardwareModel = hardwareModel; + this.hardwarePlatform = hardwarePlatform; + } + + public String version; + public String gpuAcceleration; + public boolean mrCalWorking; + public Map> availableModels; + public List supportedBackends; + public String hardwareModel; + public String hardwarePlatform; +} diff --git a/photon-core/src/main/java/org/photonvision/common/dataflow/websocket/UILightingConfig.java b/photon-core/src/main/java/org/photonvision/common/dataflow/websocket/UILightingConfig.java new file mode 100644 index 0000000000..57d5579f54 --- /dev/null +++ b/photon-core/src/main/java/org/photonvision/common/dataflow/websocket/UILightingConfig.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) Photon Vision. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.photonvision.common.dataflow.websocket; + +public class UILightingConfig { + public UILightingConfig(int brightness, boolean supported) { + this.brightness = brightness; + this.supported = supported; + } + + public int brightness = 0; + public boolean supported = true; +} diff --git a/photon-core/src/main/java/org/photonvision/common/dataflow/websocket/UINetConfig.java b/photon-core/src/main/java/org/photonvision/common/dataflow/websocket/UINetConfig.java new file mode 100644 index 0000000000..b9cc906c69 --- /dev/null +++ b/photon-core/src/main/java/org/photonvision/common/dataflow/websocket/UINetConfig.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) Photon Vision. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.photonvision.common.dataflow.websocket; + +import java.util.List; +import org.photonvision.common.configuration.NetworkConfig; +import org.photonvision.common.networking.NetworkUtils.NMDeviceInfo; + +public class UINetConfig extends NetworkConfig { + public UINetConfig( + NetworkConfig config, List networkInterfaceNames, boolean networkingDisabled) { + super(config); + this.networkInterfaceNames = networkInterfaceNames; + this.networkingDisabled = networkingDisabled; + } + + public List networkInterfaceNames; + public boolean networkingDisabled; +} diff --git a/photon-core/src/main/java/org/photonvision/common/dataflow/websocket/UIPhotonConfiguration.java b/photon-core/src/main/java/org/photonvision/common/dataflow/websocket/UIPhotonConfiguration.java new file mode 100644 index 0000000000..0ed805e04e --- /dev/null +++ b/photon-core/src/main/java/org/photonvision/common/dataflow/websocket/UIPhotonConfiguration.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) Photon Vision. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.photonvision.common.dataflow.websocket; + +import java.util.List; +import java.util.stream.Collectors; +import org.photonvision.PhotonVersion; +import org.photonvision.common.configuration.NeuralNetworkModelManager; +import org.photonvision.common.configuration.PhotonConfiguration; +import org.photonvision.common.hardware.Platform; +import org.photonvision.common.networking.NetworkManager; +import org.photonvision.common.networking.NetworkUtils; +import org.photonvision.mrcal.MrCalJNILoader; +import org.photonvision.raspi.LibCameraJNILoader; +import org.photonvision.vision.processes.VisionModule; +import org.photonvision.vision.processes.VisionModuleManager; + +public class UIPhotonConfiguration { + public List cameraSettings; + public UIProgramSettings settings; + + public UIPhotonConfiguration( + UIProgramSettings settings, List cameraSettings) { + this.cameraSettings = cameraSettings; + this.settings = settings; + } + + public static UIPhotonConfiguration programStateToUi(PhotonConfiguration c) { + return new UIPhotonConfiguration( + new UIProgramSettings( + new UINetConfig( + c.getNetworkConfig(), + NetworkUtils.getAllActiveWiredInterfaces(), + NetworkManager.getInstance().networkingIsDisabled), + new UILightingConfig( + c.getHardwareSettings().ledBrightnessPercentage, + !c.getHardwareConfig().ledPins.isEmpty()), + new UIGeneralSettings( + PhotonVersion.versionString, + // TODO add support for other types of GPU accel + LibCameraJNILoader.isSupported() ? "Zerocopy Libcamera Working" : "", + MrCalJNILoader.getInstance().isLoaded(), + NeuralNetworkModelManager.getInstance().getModels(), + NeuralNetworkModelManager.getInstance().getSupportedBackends(), + c.getHardwareConfig().deviceName.isEmpty() + ? Platform.getHardwareModel() + : c.getHardwareConfig().deviceName, + Platform.getPlatformName()), + c.getApriltagFieldLayout()), + VisionModuleManager.getInstance().getModules().stream() + .map(VisionModule::toUICameraConfig) + .collect(Collectors.toList())); + } +} diff --git a/photon-core/src/main/java/org/photonvision/common/dataflow/websocket/UIProgramSettings.java b/photon-core/src/main/java/org/photonvision/common/dataflow/websocket/UIProgramSettings.java new file mode 100644 index 0000000000..16710a1b7b --- /dev/null +++ b/photon-core/src/main/java/org/photonvision/common/dataflow/websocket/UIProgramSettings.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) Photon Vision. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.photonvision.common.dataflow.websocket; + +import edu.wpi.first.apriltag.AprilTagFieldLayout; + +public class UIProgramSettings { + public UIProgramSettings( + UINetConfig networkSettings, + UILightingConfig lighting, + UIGeneralSettings general, + AprilTagFieldLayout atfl) { + this.networkSettings = networkSettings; + this.lighting = lighting; + this.general = general; + this.atfl = atfl; + } + + public UINetConfig networkSettings; + public UILightingConfig lighting; + public UIGeneralSettings general; + public AprilTagFieldLayout atfl; +} diff --git a/photon-core/src/main/java/org/photonvision/vision/processes/PipelineManager.java b/photon-core/src/main/java/org/photonvision/vision/processes/PipelineManager.java index 6745a3ab0b..8da870dd72 100644 --- a/photon-core/src/main/java/org/photonvision/vision/processes/PipelineManager.java +++ b/photon-core/src/main/java/org/photonvision/vision/processes/PipelineManager.java @@ -26,6 +26,7 @@ import org.photonvision.common.configuration.ConfigManager; import org.photonvision.common.dataflow.DataChangeService; import org.photonvision.common.dataflow.events.OutgoingUIEvent; +import org.photonvision.common.dataflow.websocket.UIPhotonConfiguration; import org.photonvision.common.logging.LogGroup; import org.photonvision.common.logging.Logger; import org.photonvision.vision.pipeline.*; @@ -231,7 +232,8 @@ private void updatePipelineFromRequested() { DataChangeService.getInstance() .publishEvent( new OutgoingUIEvent<>( - "fullsettings", ConfigManager.getInstance().getConfig().toHashMap())); + "fullsettings", + UIPhotonConfiguration.programStateToUi(ConfigManager.getInstance().getConfig()))); } /** diff --git a/photon-core/src/main/java/org/photonvision/vision/processes/VisionModule.java b/photon-core/src/main/java/org/photonvision/vision/processes/VisionModule.java index 5aeda5ed78..cdb4943004 100644 --- a/photon-core/src/main/java/org/photonvision/vision/processes/VisionModule.java +++ b/photon-core/src/main/java/org/photonvision/vision/processes/VisionModule.java @@ -30,13 +30,14 @@ import org.opencv.core.Size; import org.photonvision.common.configuration.CameraConfiguration; import org.photonvision.common.configuration.ConfigManager; -import org.photonvision.common.configuration.PhotonConfiguration; import org.photonvision.common.dataflow.CVPipelineResultConsumer; import org.photonvision.common.dataflow.DataChangeService; import org.photonvision.common.dataflow.events.OutgoingUIEvent; import org.photonvision.common.dataflow.networktables.NTDataPublisher; import org.photonvision.common.dataflow.statusLEDs.StatusLEDConsumer; +import org.photonvision.common.dataflow.websocket.UICameraConfiguration; import org.photonvision.common.dataflow.websocket.UIDataPublisher; +import org.photonvision.common.dataflow.websocket.UIPhotonConfiguration; import org.photonvision.common.hardware.HardwareManager; import org.photonvision.common.logging.LogGroup; import org.photonvision.common.logging.Logger; @@ -489,7 +490,8 @@ void saveAndBroadcastAll() { DataChangeService.getInstance() .publishEvent( new OutgoingUIEvent<>( - "fullsettings", ConfigManager.getInstance().getConfig().toHashMap())); + "fullsettings", + UIPhotonConfiguration.programStateToUi(ConfigManager.getInstance().getConfig()))); } void saveAndBroadcastSelective(WsContext originContext, String propertyName, Object value) { @@ -516,8 +518,8 @@ public void setCameraNickname(String newName) { saveAndBroadcastAll(); } - public PhotonConfiguration.UICameraConfiguration toUICameraConfig() { - var ret = new PhotonConfiguration.UICameraConfiguration(); + public UICameraConfiguration toUICameraConfig() { + var ret = new UICameraConfiguration(); ret.fov = visionSource.getSettables().getFOV(); ret.isCSICamera = visionSource.getCameraConfiguration().cameraType == CameraType.ZeroCopyPicam; diff --git a/photon-core/src/main/java/org/photonvision/vision/processes/VisionSourceManager.java b/photon-core/src/main/java/org/photonvision/vision/processes/VisionSourceManager.java index f71bd9d926..1e40248a2e 100644 --- a/photon-core/src/main/java/org/photonvision/vision/processes/VisionSourceManager.java +++ b/photon-core/src/main/java/org/photonvision/vision/processes/VisionSourceManager.java @@ -29,6 +29,7 @@ import org.photonvision.common.configuration.ConfigManager; import org.photonvision.common.dataflow.DataChangeService; import org.photonvision.common.dataflow.events.OutgoingUIEvent; +import org.photonvision.common.dataflow.websocket.UIPhotonConfiguration; import org.photonvision.common.hardware.Platform; import org.photonvision.common.hardware.Platform.OSType; import org.photonvision.common.logging.LogGroup; @@ -122,7 +123,8 @@ protected void tryMatchCams() { DataChangeService.getInstance() .publishEvent( new OutgoingUIEvent<>( - "fullsettings", ConfigManager.getInstance().getConfig().toHashMap())); + "fullsettings", + UIPhotonConfiguration.programStateToUi(ConfigManager.getInstance().getConfig()))); } protected List tryMatchCamImpl() { diff --git a/photon-server/src/main/java/org/photonvision/server/UIInboundSubscriber.java b/photon-server/src/main/java/org/photonvision/server/UIInboundSubscriber.java index 5f1e125a4b..e7f101d15a 100644 --- a/photon-server/src/main/java/org/photonvision/server/UIInboundSubscriber.java +++ b/photon-server/src/main/java/org/photonvision/server/UIInboundSubscriber.java @@ -27,6 +27,7 @@ import org.photonvision.common.dataflow.events.IncomingWebSocketEvent; import org.photonvision.common.dataflow.events.OutgoingUIEvent; import org.photonvision.common.dataflow.networktables.NetworkTablesManager; +import org.photonvision.common.dataflow.websocket.UIPhotonConfiguration; import org.photonvision.common.logging.Logger; public class UIInboundSubscriber extends DataChangeSubscriber { @@ -43,7 +44,8 @@ public void onDataChangeEvent(DataChangeEvent event) { if (incomingWSEvent.propertyName.equals("userConnected") || incomingWSEvent.propertyName.equals("sendFullSettings")) { // Send full settings - var settings = ConfigManager.getInstance().getConfig().toHashMap(); + var settings = + UIPhotonConfiguration.programStateToUi(ConfigManager.getInstance().getConfig()); var message = new OutgoingUIEvent<>("fullsettings", settings, incomingWSEvent.originContext); DataChangeService.getInstance().publishEvent(message);