package com.chameleonvision.web; import com.chameleonvision.config.GeneralSettings; import com.chameleonvision.vision.VisionManager; import com.chameleonvision.vision.VisionProcess; import com.chameleonvision.vision.camera.CameraCapture; import com.chameleonvision.config.ConfigManager; import com.chameleonvision.vision.enums.CalibrationMode; import com.chameleonvision.vision.pipeline.CVPipeline; import com.chameleonvision.vision.pipeline.CVPipeline2dSettings; import com.chameleonvision.vision.pipeline.CVPipelineSettings; import com.chameleonvision.vision.enums.StreamDivisor; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import io.javalin.websocket.*; import org.apache.commons.lang3.ArrayUtils; import org.msgpack.jackson.dataformat.MessagePackFactory; import java.lang.reflect.Field; import java.nio.ByteBuffer; import java.util.*; public class ServerHandler { private static List users; private static ObjectMapper objectMapper; ServerHandler() { users = new ArrayList<>(); objectMapper = new ObjectMapper(new MessagePackFactory()); } void onConnect(WsConnectContext context) { users.add(context); sendFullSettings(); } void onClose(WsCloseContext context) { users.remove(context); } @SuppressWarnings("unchecked") void onBinaryMessage(WsBinaryMessageContext context) throws Exception { Map deserialized = objectMapper.readValue(ArrayUtils.toPrimitive(context.data()), new TypeReference<>() { }); for (Map.Entry entry : deserialized.entrySet()) { try { VisionProcess currentProcess = VisionManager.getCurrentUIVisionProcess(); CameraCapture currentCamera = currentProcess.getCamera(); CVPipeline currentPipeline = currentProcess.getCurrentPipeline(); switch (entry.getKey()) { case "generalSettings": { HashMap data = (HashMap) entry.getValue(); for (HashMap.Entry e : data.entrySet()) { setField(ConfigManager.settings, e.getKey(), e.getValue()); } ConfigManager.saveGeneralSettings(); sendFullSettings(); break; } case "driverMode": { HashMap data = (HashMap) entry.getValue(); currentProcess.getDriverModeSettings().exposure = (Integer) data.get("exposure"); currentProcess.getDriverModeSettings().brightness = (Integer) data.get("brightness"); currentProcess.setDriverMode((Boolean) data.get("isDriver")); VisionManager.saveCurrentCameraDriverMode(); break; } case "cameraSettings": { HashMap camSettings = (HashMap) entry.getValue(); Number newFOV = (Number) camSettings.get("fov"); StreamDivisor newStreamDivisor = StreamDivisor.values()[(Integer) camSettings.get("streamDivisor")]; // Integer newResolution = (Integer) camSettings.get("resolution"); currentCamera.getProperties().FOV = (double) newFOV; if (currentProcess.cameraStreamer.getDivisor() != newStreamDivisor) { currentProcess.cameraStreamer.setDivisor(newStreamDivisor, false); } // TODO (HIGH) get and set video modes! // var currentResolutionIndex = currentPipeline.getVideoModeIndex(); // if (currentResolutionIndex != newResolution) { // currentCamera.getProperties().setCamVideoMode(newResolution, true); // } VisionManager.saveCurrentCameraSettings(); sendFullSettings(); break; } case "changeCameraName": { currentCamera.getProperties().setNickname((String) entry.getValue()); sendFullSettings(); VisionManager.saveCurrentCameraSettings(); break; } case "changePipelineName": { currentPipeline.settings.nickname = ((String) entry.getValue()); sendFullSettings(); VisionManager.saveCurrentCameraPipelines(); break; } case "duplicatePipeline": { HashMap pipelineVals = (HashMap) entry.getValue(); int pipelineIndex = (int) pipelineVals.get("pipeline"); int cameraIndex = (int) pipelineVals.get("camera"); CVPipeline origPipeline = currentProcess.getPipelineByIndex(pipelineIndex); if (cameraIndex != -1) { VisionProcess newProcess = VisionManager.getVisionProcessByIndex(cameraIndex); if(newProcess != null) { newProcess.addPipeline(origPipeline); } } else { currentProcess.addPipeline(origPipeline); } VisionManager.saveCurrentCameraPipelines(); break; } case "command": { switch ((String) entry.getValue()) { case "addNewPipeline": currentProcess.addPipeline(); sendFullSettings(); VisionManager.saveCurrentCameraPipelines(); break; // TODO: (HIGH) this never worked before, re-visit now that VisionProcess is written sanely case "deleteCurrentPipeline": // int currentIndex = currentProcess.getCurrentPipelineIndex(); // int nextIndex; // if (currentIndex == currentProcess.getPipelines().size() - 1) { // nextIndex = currentIndex - 1; // } else { // nextIndex = currentIndex; // } // cam.deletePipeline(); // cam.setCurrentPipelineIndex(nextIndex); // sendFullSettings(); // VisionManager.saveCurrentCameraPipelines(); break; case "save": ConfigManager.saveGeneralSettings(); System.out.println("saved Settings"); break; } // used to define all incoming commands break; } case "currentCamera": { VisionManager.setCurrentProcessByIndex((Integer) entry.getValue()); sendFullSettings(); break; } case "currentPipeline": { currentProcess.setPipeline((Integer) entry.getValue(), true); sendFullSettings(); break; } default: { setField(currentPipeline.settings, entry.getKey(), entry.getValue()); switch (entry.getKey()) { case "exposure": { currentCamera.setExposure((Integer) entry.getValue()); } case "brightness": { currentCamera.setBrightness((Integer) entry.getValue()); } } break; } } } catch (Exception e) { System.err.println(e.getMessage()); } broadcastMessage(deserialized, context); } } private void setField(Object obj, String fieldName, Object value) { try { Field field = obj.getClass().getField(fieldName); if (field.getType().isEnum()) field.set(obj, field.getType().getEnumConstants()[(Integer) value]); else field.set(obj, value); } catch (NoSuchFieldException | IllegalAccessException ex) { ex.printStackTrace(); } } private static void broadcastMessage(Object obj, WsContext userToSkip) { if (users != null) for (WsContext user : users) { if (userToSkip != null && user.getSessionId().equals(userToSkip.getSessionId())) { continue; } try { ByteBuffer b = ByteBuffer.wrap(objectMapper.writeValueAsBytes(obj)); user.send(b); } catch (JsonProcessingException e) { e.printStackTrace(); } } } public static void broadcastMessage(Object obj) { broadcastMessage(obj, null);//Broadcasts the message to every user } private static HashMap getOrdinalPipeline() throws IllegalAccessException { HashMap tmp = new HashMap<>(); for (Field field : CVPipelineSettings.class.getFields()) { // iterate over every field in CVPipelineSettings try { if (!field.getType().isEnum()) { // if the field is not an enum, get it based on the current pipeline tmp.put(field.getName(), field.get(VisionManager.getCurrentUIVisionProcess().getCurrentPipeline().settings)); } else { var ordinal = (Enum) field.get(VisionManager.getCurrentUIVisionProcess().getCurrentPipeline().settings); tmp.put(field.getName(), ordinal.ordinal()); } } catch (IllegalArgumentException e) { e.printStackTrace(); } } return tmp; } private static HashMap getOrdinalSettings() { HashMap tmp = new HashMap<>(); tmp.put("teamNumber", ConfigManager.settings.teamNumber); tmp.put("connectionType", ConfigManager.settings.connectionType.ordinal()); tmp.put("ip", ConfigManager.settings.ip); tmp.put("gateway", ConfigManager.settings.gateway); tmp.put("netmask", ConfigManager.settings.netmask); tmp.put("hostname", ConfigManager.settings.hostname); return tmp; } private static HashMap getOrdinalCameraSettings() { HashMap tmp = new HashMap<>(); VisionProcess currentVisionProcess = VisionManager.getCurrentUIVisionProcess(); CameraCapture currentCamera = VisionManager.getCurrentUIVisionProcess().getCamera(); tmp.put("fov", currentCamera.getProperties().FOV); tmp.put("streamDivisor", currentVisionProcess.cameraStreamer.getDivisor().ordinal()); // TODO: (HIGH) get videomode index! // tmp.put("resolution", currentCamera.getVideoModeIndex()); return tmp; } private static HashMap getOrdinalDriver() { HashMap tmp = new HashMap<>(); VisionProcess currentProcess = VisionManager.getCurrentUIVisionProcess(); CVPipelineSettings driverModeSettings = currentProcess.getDriverModeSettings(); tmp.put("isDriver", currentProcess.getDriverMode()); tmp.put("driverBrightness", driverModeSettings.brightness); tmp.put("driverExposure", driverModeSettings.exposure); return tmp; } private static Map settingsToMap(GeneralSettings settings) { Map map = new HashMap<>(); map.put("team_number", settings.teamNumber); map.put("connection_type", settings.connectionType); map.put("ip", settings.ip); map.put("gateway", settings.gateway); map.put("netmask", settings.netmask); map.put("hostname", settings.hostname); map.put("curr_camera", settings.currentCamera); map.put("curr_pipeline", settings.currentPipeline); return map; } private static Map pipelineToMap(CVPipelineSettings s) { Map map = new HashMap<>(); map.put("exposure", s.exposure); map.put("brightness", s.brightness); if(s instanceof CVPipeline2dSettings) { var s_ = (CVPipeline2dSettings) s; map.put("orientation", s.flipMode.name()); map.put("hue", s_.hue); map.put("saturation", s_.saturation); map.put("value", s_.value); map.put("erode", s_.erode); map.put("dilate", s_.dilate); map.put("area", s_.area); map.put("ratio", s_.ratio); map.put("extent", s_.extent); map.put("is_binary", s_.isBinary); map.put("sort_mode", s_.sortMode.name()); map.put("target_group", s_.targetGroup.name()); map.put("target_intersection", s_.targetIntersection.name()); map.put("M", s_.dualTargetCalibrationM); map.put("B", s_.dualTargetCalibrationB); map.put("is_calibrated", !s_.calibrationMode.equals(CalibrationMode.None)); } return map; } public static void sendFullSettings() { //General settings Map fullSettings = new HashMap<>(); VisionProcess currentProcess = VisionManager.getCurrentUIVisionProcess(); CameraCapture currentCamera = currentProcess.getCamera(); CVPipeline currentPipeline = currentProcess.getCurrentPipeline(); try { fullSettings.putAll(settingsToMap(ConfigManager.settings)); fullSettings.putAll(pipelineToMap(currentPipeline.settings)); fullSettings.put("settings", getOrdinalSettings()); fullSettings.put("cameraSettings", getOrdinalCameraSettings()); fullSettings.put("cameraList", VisionManager.getAllCameraNicknames()); fullSettings.put("pipeline", getOrdinalPipeline()); fullSettings.put("driverMode", getOrdinalDriver()); fullSettings.put("pipelineList", VisionManager.getCurrentCameraPipelineNicknames()); fullSettings.put("resolutionList", VisionManager.getCurrentCameraResolutionList()); fullSettings.put("FOV", currentCamera.getProperties().FOV); fullSettings.put("port", currentProcess.cameraStreamer.getStreamPort()); fullSettings.put("currentPipelineIndex", VisionManager.getCurrentUIVisionProcess().getCurrentPipelineIndex()); fullSettings.put("currentCameraIndex", VisionManager.getCurrentUIVisionProcessIndex()); } catch (IllegalAccessException e) { System.err.println("No camera found!"); } broadcastMessage(fullSettings); } }