package com.chameleonvision.web; import com.chameleonvision.NoCameraException; import com.chameleonvision.settings.SettingsManager; import com.chameleonvision.vision.GeneralSettings; import com.chameleonvision.vision.Pipeline; import com.google.gson.JsonObject; import io.javalin.Javalin; import io.javalin.websocket.WsContext; import java.lang.reflect.Field; import java.util.*; import org.json.JSONArray; import org.json.JSONObject; import org.springframework.beans.BeanUtils; public class Server { private static List users = new ArrayList(); public static void main(int port) { Javalin app = Javalin.create(); app.config.addStaticFiles("web"); app.ws("/websocket", ws -> { ws.onConnect(ctx -> { users.add(ctx); System.out.println("Socket Connected"); sendFullSettings(); }); ws.onClose(ctx -> { users.remove(ctx); System.out.println("Socket Disconnected"); SettingsManager.getInstance().SaveSettings(); }); ws.onMessage(ctx -> { // System.out.println(SettingsManager.getInstance().GetCurrentPipeline().); broadcastMessage(ctx, ctx.message()); JSONObject jsonObject = new JSONObject(ctx.message()); String key = null; var jsonKeySetArray = jsonObject.keySet().toArray(); try { key = jsonKeySetArray[0].toString(); } catch (Exception ex) { System.err.println("WebSocket JSON data was empty!"); } if (key == null) return; Object value = jsonObject.get(key); // System.out.printf("Got websocket json data: [%s, %s]\n", key, value); if (!setField(SettingsManager.getInstance().GetCurrentPipeline(), key, value)) { //If field not in pipeline switch (key) { case "change_general_settings_values": JSONObject newSettings = (JSONObject) value; setFields(SettingsManager.GeneralSettings, newSettings); break; case "curr_camera": String newCamera = (String) value; System.out.printf("Changing camera to %s\n", newCamera); SettingsManager.getInstance().SetCurrentCamera(newCamera); //broadcastMessage((Map) new HashMap(){}.put("port",SettingsManager.CameraPorts.get(SettingsManager.GeneralSettings.curr_camera))); //broadcastMessage(ctx, SettingsManager.getInstance().GetCurrentCamera()); //TODO CHECK JSON FOR CAMERA CHANGE break; case "curr_pipeline": String newPipeline = (String) value; System.out.printf("Changing pipeline to %s\n", newPipeline); SettingsManager.getInstance().SetCurrentPipeline(newPipeline); SettingsManager.CamerasCurrentPipeline.put(SettingsManager.GeneralSettings.curr_camera, newPipeline); break; case "resolution": int newResolution = (int) value; System.out.printf("Changing resolution mode to %d\n", newResolution); SettingsManager.getInstance().GetCurrentCamera().resolution = newResolution; SettingsManager.getInstance().SetCameraSettings(SettingsManager.GeneralSettings.curr_camera, "resolution", newResolution); SettingsManager.getInstance().SaveSettings(); break; case "fov": double newFov = (double) value; System.out.printf("Changing FOV to %d\n", newFov); SettingsManager.getInstance().GetCurrentCamera().FOV = newFov; SettingsManager.getInstance().SaveSettings(); break; default: System.out.printf("Unexpected value from websocket: [%s, %s]\n", key, value); break; } } else { // switch (key) { case "exposure": int newExposure = (int) value; System.out.printf("Changing exposure to %d\n", newExposure); SettingsManager.getInstance().GetCurrentPipeline().exposure = newExposure; SettingsManager.getInstance().GetCurrentUsbCamera().setExposureManual(newExposure); SettingsManager.getInstance().SaveSettings(); break; case "brightness": int newBrightness = (int) value; System.out.printf("Changing brightness to %d\n", newBrightness); SettingsManager.getInstance().GetCurrentPipeline().brightness = newBrightness; SettingsManager.getInstance().GetCurrentUsbCamera().setBrightness(newBrightness); SettingsManager.getInstance().SaveSettings(); break; } } }); }); app.start(port); } public static boolean setField(Object obj, String fieldName, Object value) { boolean successful = false; try { Field[] fields = obj.getClass().getFields(); for (Field f : fields) { if (f.getName().equals(fieldName)) { successful = true; if (BeanUtils.isSimpleValueType(value.getClass())) { f.set(obj, value); } else if (value.getClass() == JSONArray.class) { f.set(obj, ((JSONArray) value).toList()); } } } } catch (IllegalAccessException e) { return false; } return successful; } public static boolean setFields(Object obj, JSONObject data) { boolean successful = false; try { Field[] fields = obj.getClass().getFields(); for (Field f : fields) { if (data.has(f.getName())) { Object value = data.get(f.getName()); if (BeanUtils.isSimpleValueType(value.getClass())) { successful = true; f.set(obj, value); } } } } catch (IllegalAccessException e) { return false; } return successful; } public static void broadcastMessage(WsContext sendingUser, Object obj) {//TODO chekc if session id is a good way to differentiate users for (var user : users) { if (sendingUser!=null&& user.getSessionId().equals(sendingUser.getSessionId())) { continue; } if (obj.getClass() == String.class) user.send((String) obj); else if (obj.getClass() == HashMap.class) user.send(new JSONObject((HashMap) obj).toString()); else user.send(new JSONObject(obj).toString()); } } private static void addAllFieldsToMap(Map map, Object obj) { try { Field[] fields = obj.getClass().getFields(); for (Field field : fields) map.put(field.getName(), field.get(obj)); } catch (IllegalAccessException e) { System.err.println("Illegal Access error:" + e.getStackTrace().toString()); } } private static void sendFullSettings() { Map fullSettings = new HashMap<>(); //General settings addAllFieldsToMap(fullSettings, SettingsManager.GeneralSettings); fullSettings.put("cameraList", SettingsManager.Cameras.keySet()); try { addAllFieldsToMap(fullSettings, SettingsManager.getInstance().GetCurrentPipeline()); fullSettings.put("pipelineList", SettingsManager.getInstance().GetCurrentCamera().pipelines.keySet()); fullSettings.put("resolutionList", SettingsManager.getInstance().GetResolutionList()); fullSettings.put("resolution", SettingsManager.getInstance().GetCurrentCamera().resolution); fullSettings.put("FOV", SettingsManager.getInstance().GetCurrentCamera().FOV); // fullSettings.put("port", SettingsManager.CameraPorts.get(SettingsManager.GeneralSettings.curr_camera)); } catch (NoCameraException e) { System.err.println("No camera found!"); //TODO: add message to ui to inform that there are no cameras } broadcastMessage(null, fullSettings); } }