diff --git a/pom.xml b/pom.xml
index cdb6427d33..249fed1eee 100644
--- a/pom.xml
+++ b/pom.xml
@@ -48,8 +48,8 @@
-SNAPSHOT
UTF-8
- 9.4.41.v20210516
- 2.29.1
+ 12.0.3
+ 3.1.5
2.5.0
2.5.0
3.7.4
diff --git a/ugs-pendant/pom.xml b/ugs-pendant/pom.xml
index afdd52e000..a24b0ecd58 100644
--- a/ugs-pendant/pom.xml
+++ b/ugs-pendant/pom.xml
@@ -27,22 +27,24 @@
${commons-lang3.version}
+
- org.eclipse.jetty
- jetty-server
- ${jetty.version}
+ jakarta.servlet
+ jakarta.servlet-api
+ 6.0.0
- org.eclipse.jetty
- jetty-servlet
- ${jetty.version}
+ jakarta.ws.rs
+ jakarta.ws.rs-api
+ 3.1.0
- org.eclipse.jetty
- jetty-util
- ${jetty.version}
+ jakarta.websocket
+ jakarta.websocket-api
+ 2.0.0
+
org.glassfish.jersey.core
jersey-server
@@ -73,6 +75,23 @@
jersey-media-multipart
${jersey.version}
+
+ org.glassfish.jersey.core
+ jersey-client
+ ${jersey.version}
+
+
+
+
+ org.eclipse.jetty.ee10.websocket
+ jetty-ee10-websocket-jakarta-server
+ ${jetty.version}
+
+
+ org.eclipse.jetty.ee10
+ jetty-ee10-servlet
+ ${jetty.version}
+
diff --git a/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/BackendAPIFactory.java b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/BackendProvider.java
similarity index 62%
rename from ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/BackendAPIFactory.java
rename to ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/BackendProvider.java
index 76d2c31fbc..bda3c63127 100644
--- a/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/BackendAPIFactory.java
+++ b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/BackendProvider.java
@@ -1,5 +1,5 @@
/*
- Copyright 2016-2019 Will Winder
+ Copyright 2016-2023 Will Winder
This file is part of Universal Gcode Sender (UGS).
@@ -21,24 +21,16 @@ This file is part of Universal Gcode Sender (UGS).
import com.willwinder.universalgcodesender.model.BackendAPI;
/**
- * A factory for accessing the backend in injected resources
+ * A provider for accessing the backend in injected resources
*/
-public class BackendAPIFactory {
- private static BackendAPIFactory instance;
- private BackendAPI backendAPI;
-
- public static BackendAPIFactory getInstance() {
- if (instance == null) {
- instance = new BackendAPIFactory();
- }
- return instance;
- }
+public class BackendProvider {
+ private static BackendAPI backendAPI;
- public void register(BackendAPI backendAPI) {
- this.backendAPI = backendAPI;
+ public static void register(BackendAPI backendAPI) {
+ BackendProvider.backendAPI = backendAPI;
}
- public BackendAPI getBackendAPI() {
+ public static BackendAPI getBackendAPI() {
return backendAPI;
}
}
diff --git a/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/ExceptionMapper.java b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/ExceptionMapper.java
index 6fbd1d4784..c5eb4ed044 100644
--- a/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/ExceptionMapper.java
+++ b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/ExceptionMapper.java
@@ -1,5 +1,5 @@
/*
- Copyright 2016-2019 Will Winder
+ Copyright 2016-2023 Will Winder
This file is part of Universal Gcode Sender (UGS).
@@ -20,11 +20,11 @@ This file is part of Universal Gcode Sender (UGS).
import com.willwinder.universalgcodesender.pendantui.v1.model.PendantError;
-import javax.ws.rs.WebApplicationException;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
+import jakarta.ws.rs.WebApplicationException;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
-public class ExceptionMapper implements javax.ws.rs.ext.ExceptionMapper {
+public class ExceptionMapper implements jakarta.ws.rs.ext.ExceptionMapper {
@Override
public Response toResponse(Exception e) {
diff --git a/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/PendantUI.java b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/PendantUI.java
index 66bbd8963d..ebb6f12680 100644
--- a/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/PendantUI.java
+++ b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/PendantUI.java
@@ -1,5 +1,5 @@
/*
- Copyright 2016-2019 Will Winder
+ Copyright 2016-2023 Will Winder
This file is part of Universal Gcode Sender (UGS).
@@ -22,24 +22,27 @@ This file is part of Universal Gcode Sender (UGS).
import com.willwinder.universalgcodesender.model.BackendAPI;
import com.willwinder.universalgcodesender.model.UGSEvent;
import com.willwinder.universalgcodesender.model.events.SettingChangedEvent;
+import com.willwinder.universalgcodesender.pendantui.html.StaticConfig;
+import com.willwinder.universalgcodesender.pendantui.v1.AppV1Config;
+import com.willwinder.universalgcodesender.pendantui.v1.ws.EventsSocket;
+import com.willwinder.universalgcodesender.services.JogService;
+import jakarta.ws.rs.core.UriBuilder;
import net.glxn.qrgen.QRCode;
import net.glxn.qrgen.image.ImageType;
-import org.eclipse.jetty.server.Handler;
+import org.eclipse.jetty.ee10.servlet.ServletContextHandler;
+import org.eclipse.jetty.ee10.servlet.ServletHolder;
+import org.eclipse.jetty.ee10.websocket.jakarta.server.config.JakartaWebSocketServletContainerInitializer;
import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.handler.ContextHandler;
-import org.eclipse.jetty.server.handler.DefaultHandler;
-import org.eclipse.jetty.server.handler.HandlerList;
-import org.eclipse.jetty.server.handler.ResourceHandler;
-import org.eclipse.jetty.servlet.ServletContextHandler;
-import org.eclipse.jetty.servlet.ServletHolder;
-import org.eclipse.jetty.util.resource.Resource;
+import org.eclipse.jetty.server.handler.ContextHandlerCollection;
+import org.glassfish.jersey.jetty.JettyHttpContainerFactory;
+import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.servlet.ServletContainer;
import java.io.ByteArrayOutputStream;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
-import java.net.URL;
+import java.net.URI;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
@@ -51,55 +54,37 @@ This file is part of Universal Gcode Sender (UGS).
* @author bobj
*/
public class PendantUI implements UGSEventListener {
- private BackendAPI backendAPI;
- private Server server = null;
- private int port = 8080;
+ public static final String WEBSOCKET_CONTEXT_PATH = "/ws/v1";
+ public static final String API_CONTEXT_PATH = "/api/v1";
private static final Logger LOG = Logger.getLogger(PendantUI.class.getSimpleName());
+ private final JogService jogService;
+ private final BackendAPI backendAPI;
+ private int port = 8080;
+ private Server server;
public PendantUI(BackendAPI backendAPI) {
this.backendAPI = backendAPI;
backendAPI.addUGSEventListener(this);
- BackendAPIFactory.getInstance().register(backendAPI);
+ jogService = new JogService(backendAPI);
+ BackendProvider.register(backendAPI);
}
- public Resource getBaseResource(String directory) {
- try {
- URL res = getClass().getResource(directory);
- return Resource.newResource(res);
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
-
-
/**
* Launches the local web server.
*
* @return the url for the pendant interface
*/
public List start() {
- int port = backendAPI.getSettings().getPendantPort();
- server = new Server(port);
+ port = backendAPI.getSettings().getPendantPort();
+ URI baseUri = UriBuilder.fromUri("http://localhost/").port(port).build();
- ResourceHandler staticResourceHandler = new ResourceHandler();
- staticResourceHandler.setDirectoriesListed(true);
- staticResourceHandler.setWelcomeFiles(new String[]{"index.html"});
- staticResourceHandler.setBaseResource(getBaseResource("/resources/ugs-pendant"));
+ server = JettyHttpContainerFactory.createServer(baseUri, false);
+ ContextHandlerCollection contextHandlerCollection = new ContextHandlerCollection();
+ server.setHandler(contextHandlerCollection);
- ContextHandler staticResourceHandlerContext = new ContextHandler();
- staticResourceHandlerContext.setContextPath("/");
- staticResourceHandlerContext.setHandler(staticResourceHandler);
-
- // Create a servlet servletContextHandler
- ServletContextHandler servletContextHandler = new ServletContextHandler(ServletContextHandler.NO_SESSIONS);
- servletContextHandler.setContextPath("/api");
- ServletHolder servletHolder = servletContextHandler.addServlet(ServletContainer.class, "/*");
- servletHolder.setInitOrder(1);
- servletHolder.setInitParameter("javax.ws.rs.Application", AppConfig.class.getCanonicalName());
-
- HandlerList handlers = new HandlerList();
- handlers.setHandlers(new Handler[]{servletContextHandler, staticResourceHandlerContext, new DefaultHandler()});
- server.setHandler(handlers);
+ contextHandlerCollection.addHandler(createResourceConfigHandler(new StaticConfig(), ""));
+ contextHandlerCollection.addHandler(createResourceConfigHandler(new AppV1Config(backendAPI, jogService), API_CONTEXT_PATH));
+ contextHandlerCollection.addHandler(createWebSocketHandler(WEBSOCKET_CONTEXT_PATH));
try {
server.start();
@@ -110,6 +95,25 @@ public List start() {
return getUrlList();
}
+ private ServletContextHandler createResourceConfigHandler(ResourceConfig config, String path) {
+ ServletContainer servletContainer = new ServletContainer(config);
+ ServletHolder servletHolder = new ServletHolder(servletContainer);
+ ServletContextHandler servletContextHandler = new ServletContextHandler();
+ servletContextHandler.setContextPath(path);
+ servletContextHandler.addServlet(servletHolder, "/*");
+ return servletContextHandler;
+ }
+
+ private ServletContextHandler createWebSocketHandler(String contextPath) {
+ ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
+ context.setContextPath(contextPath);
+ JakartaWebSocketServletContainerInitializer.configure(context, (servletContext, wsContainer) -> {
+ wsContainer.setDefaultMaxTextMessageBufferSize(65535);
+ wsContainer.addEndpoint(EventsSocket.class);
+ });
+ return context;
+ }
+
/**
* Unfortunately, this is not as simple as it seems... since you can have multiple addresses and some of those may not be available via wireless
*
@@ -131,8 +135,7 @@ public List getUrlList() {
while (addressEnum.hasMoreElements()) {
InetAddress addr = addressEnum.nextElement();
String hostAddress = addr.getHostAddress();
- if (!hostAddress.contains(":") &&
- !hostAddress.equals("127.0.0.1")) {
+ if (!hostAddress.contains(":") && !hostAddress.equals("127.0.0.1")) {
String url = "http://" + hostAddress + ":" + port;
ByteArrayOutputStream bout = QRCode.from(url).to(ImageType.PNG).stream();
out.add(new PendantURLBean(url, bout.toByteArray()));
@@ -162,10 +165,6 @@ public BackendAPI getBackendAPI() {
return backendAPI;
}
- public void setBackendAPI(BackendAPI backendAPI) {
- this.backendAPI = backendAPI;
- }
-
@Override
public void UGSEvent(UGSEvent evt) {
if (evt instanceof SettingChangedEvent) {
diff --git a/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/html/StaticConfig.java b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/html/StaticConfig.java
new file mode 100644
index 0000000000..6cab16bd70
--- /dev/null
+++ b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/html/StaticConfig.java
@@ -0,0 +1,27 @@
+/*
+ Copyright 2023 Will Winder
+
+ This file is part of Universal Gcode Sender (UGS).
+
+ UGS 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.
+
+ UGS 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 UGS. If not, see .
+ */
+package com.willwinder.universalgcodesender.pendantui.html;
+
+import org.glassfish.jersey.server.ResourceConfig;
+
+public class StaticConfig extends ResourceConfig {
+ public StaticConfig() {
+ register(StaticResource.class);
+ }
+}
diff --git a/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/html/StaticResource.java b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/html/StaticResource.java
new file mode 100644
index 0000000000..a633016cc6
--- /dev/null
+++ b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/html/StaticResource.java
@@ -0,0 +1,65 @@
+/*
+ Copyright 2023 Will Winder
+
+ This file is part of Universal Gcode Sender (UGS).
+
+ UGS 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.
+
+ UGS 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 UGS. If not, see .
+ */
+package com.willwinder.universalgcodesender.pendantui.html;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.PathParam;
+import jakarta.ws.rs.core.HttpHeaders;
+import jakarta.ws.rs.core.Response;
+import static jakarta.ws.rs.core.Response.Status.NOT_FOUND;
+
+import java.io.InputStream;
+import java.util.Objects;
+
+@Path("/")
+public class StaticResource {
+
+ public static final String RESOURCES_PATH = "/resources/ugs-pendant/%s";
+
+ private static String getMimeType(String path) {
+ String mimeType = "application/octet-stream";
+ if (path.endsWith(".js")) {
+ mimeType = "text/javascript";
+ } else if (path.endsWith(".html")) {
+ mimeType = "text/html";
+ } else if (path.endsWith(".css")) {
+ mimeType = "text/css";
+ }
+ return mimeType;
+ }
+
+ @GET
+ public Response getIndex() throws Exception {
+ return getStaticResource("");
+ }
+
+ @GET
+ @Path("{path:.*\\.(jpg|gif|html|js|css|ico)$}")
+ public Response getStaticResource(@PathParam("path") String path) throws Exception {
+ if (path.equalsIgnoreCase("")) {
+ path = "index.html";
+ }
+
+ InputStream resource = StaticResource.class.getResourceAsStream(String.format(RESOURCES_PATH, path));
+ String mimeType = getMimeType(path);
+ return Objects.isNull(resource) ? Response.status(NOT_FOUND).build() :
+ Response.ok().entity(resource).header(HttpHeaders.CONTENT_TYPE, mimeType).build();
+ }
+}
diff --git a/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/AppConfig.java b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/AppV1Config.java
similarity index 51%
rename from ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/AppConfig.java
rename to ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/AppV1Config.java
index 97478d7f56..b7d8dd26c5 100644
--- a/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/AppConfig.java
+++ b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/AppV1Config.java
@@ -1,6 +1,26 @@
-package com.willwinder.universalgcodesender.pendantui;
+/*
+ Copyright 2023 Will Winder
+
+ This file is part of Universal Gcode Sender (UGS).
+
+ UGS 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.
+
+ UGS 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 UGS. If not, see .
+ */
+package com.willwinder.universalgcodesender.pendantui.v1;
import com.willwinder.universalgcodesender.model.BackendAPI;
+import com.willwinder.universalgcodesender.pendantui.ExceptionMapper;
+import com.willwinder.universalgcodesender.pendantui.html.StaticResource;
import com.willwinder.universalgcodesender.pendantui.v1.resources.FilesResource;
import com.willwinder.universalgcodesender.pendantui.v1.resources.MachineResource;
import com.willwinder.universalgcodesender.pendantui.v1.resources.MacrosResource;
@@ -8,16 +28,13 @@
import com.willwinder.universalgcodesender.pendantui.v1.resources.StatusResource;
import com.willwinder.universalgcodesender.pendantui.v1.resources.TextResource;
import com.willwinder.universalgcodesender.services.JogService;
-import org.glassfish.hk2.utilities.binding.AbstractBinder;
+import org.glassfish.jersey.internal.inject.AbstractBinder;
import org.glassfish.jersey.media.multipart.MultiPartFeature;
import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.wadl.WadlFeature;
-import javax.ws.rs.ApplicationPath;
-
-@ApplicationPath("/api")
-public class AppConfig extends ResourceConfig {
- public AppConfig() {
- register(ExceptionMapper.class);
+public class AppV1Config extends ResourceConfig {
+ public AppV1Config(BackendAPI backendAPI, JogService jogService) {
register(StatusResource.class);
register(MachineResource.class);
@@ -26,9 +43,9 @@ public AppConfig() {
register(SettingsResource.class);
register(FilesResource.class);
register(MultiPartFeature.class);
-
- BackendAPI backendAPI = BackendAPIFactory.getInstance().getBackendAPI();
- JogService jogService = new JogService(backendAPI);
+ register(WadlFeature.class);
+ register(StaticResource.class);
+ register(ExceptionMapper.class);
register(new AbstractBinder() {
@Override
diff --git a/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/model/Event.java b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/model/Event.java
new file mode 100644
index 0000000000..b30e199f04
--- /dev/null
+++ b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/model/Event.java
@@ -0,0 +1,42 @@
+/*
+ Copyright 2023 Will Winder
+
+ This file is part of Universal Gcode Sender (UGS).
+
+ UGS 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.
+
+ UGS 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 UGS. If not, see .
+ */
+package com.willwinder.universalgcodesender.pendantui.v1.model;
+
+import com.willwinder.universalgcodesender.model.UGSEvent;
+
+import java.io.Serializable;
+
+public class Event implements Serializable {
+ private final String eventType;
+
+ private final UGSEvent event;
+
+ public Event(UGSEvent event) {
+ this.eventType = event.getClass().getSimpleName();
+ this.event = event;
+ }
+
+ public String getEventType() {
+ return eventType;
+ }
+
+ public UGSEvent getEvent() {
+ return event;
+ }
+}
diff --git a/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/resources/FilesResource.java b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/resources/FilesResource.java
index 650c0b380a..2ebfe45775 100644
--- a/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/resources/FilesResource.java
+++ b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/resources/FilesResource.java
@@ -1,26 +1,44 @@
+/*
+ Copyright 2023 Will Winder
+
+ This file is part of Universal Gcode Sender (UGS).
+
+ UGS 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.
+
+ UGS 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 UGS. If not, see .
+ */
package com.willwinder.universalgcodesender.pendantui.v1.resources;
import com.willwinder.universalgcodesender.model.BackendAPI;
import com.willwinder.universalgcodesender.pendantui.v1.model.WorkspaceFileList;
+import jakarta.inject.Inject;
import org.apache.commons.io.IOUtils;
import org.glassfish.jersey.media.multipart.FormDataBodyPart;
import org.glassfish.jersey.media.multipart.FormDataParam;
-import javax.inject.Inject;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.QueryParam;
-import javax.ws.rs.core.MediaType;
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.QueryParam;
+import jakarta.ws.rs.core.MediaType;
import java.io.File;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.List;
-@Path("/v1/files")
+@Path("/files")
public class FilesResource {
@Inject
diff --git a/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/resources/MachineResource.java b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/resources/MachineResource.java
index a2ba647299..0288fd47f8 100644
--- a/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/resources/MachineResource.java
+++ b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/resources/MachineResource.java
@@ -1,3 +1,21 @@
+/*
+ Copyright 2023 Will Winder
+
+ This file is part of Universal Gcode Sender (UGS).
+
+ UGS 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.
+
+ UGS 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 UGS. If not, see .
+ */
package com.willwinder.universalgcodesender.pendantui.v1.resources;
import com.google.gson.JsonObject;
@@ -13,17 +31,17 @@
import com.willwinder.universalgcodesender.utils.FirmwareUtils;
import com.willwinder.universalgcodesender.utils.Settings;
import com.willwinder.universalgcodesender.utils.SettingsFactory;
+import jakarta.inject.Inject;
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.NotAcceptableException;
+import jakarta.ws.rs.NotFoundException;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.QueryParam;
+import jakarta.ws.rs.core.MediaType;
-import javax.inject.Inject;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.GET;
-import javax.ws.rs.NotAcceptableException;
-import javax.ws.rs.NotFoundException;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.QueryParam;
-import javax.ws.rs.core.MediaType;
import java.io.BufferedReader;
import java.io.StringReader;
import java.util.Arrays;
@@ -31,7 +49,7 @@
import java.util.Optional;
import java.util.stream.Collectors;
-@Path("/v1/machine")
+@Path("/machine")
public class MachineResource {
@Inject
@@ -92,7 +110,7 @@ public List getBaudRateList() {
@GET
@Path("getSelectedBaudRate")
@Produces(MediaType.APPLICATION_JSON)
- public String getSelectedFBaudRate() {
+ public String getSelectedBaudRate() {
JsonObject jsonObject = new JsonObject();
jsonObject.add("selectedBaudRate", new JsonPrimitive(SettingsFactory.loadSettings().getPortRate()));
return jsonObject.toString();
diff --git a/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/resources/MacrosResource.java b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/resources/MacrosResource.java
index f6ad34b6b3..2afd82dab2 100644
--- a/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/resources/MacrosResource.java
+++ b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/resources/MacrosResource.java
@@ -1,30 +1,44 @@
+/*
+ Copyright 2023 Will Winder
+
+ This file is part of Universal Gcode Sender (UGS).
+
+ UGS 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.
+
+ UGS 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 UGS. If not, see .
+ */
package com.willwinder.universalgcodesender.pendantui.v1.resources;
import com.willwinder.universalgcodesender.MacroHelper;
import com.willwinder.universalgcodesender.model.BackendAPI;
import com.willwinder.universalgcodesender.pendantui.v1.model.Macro;
-import com.willwinder.universalgcodesender.services.JogService;
import com.willwinder.universalgcodesender.utils.SettingsFactory;
+import jakarta.inject.Inject;
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.core.MediaType;
-import javax.inject.Inject;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
import java.util.List;
import java.util.stream.Collectors;
-@Path("/v1/macros")
+@Path("/macros")
public class MacrosResource {
@Inject
private BackendAPI backendAPI;
- @Inject
- private JogService jogService;
-
@GET
@Path("getMacroList")
@Produces(MediaType.APPLICATION_JSON)
diff --git a/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/resources/SettingsResource.java b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/resources/SettingsResource.java
index d2648adc65..ef75fe226c 100644
--- a/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/resources/SettingsResource.java
+++ b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/resources/SettingsResource.java
@@ -1,18 +1,34 @@
+/*
+ Copyright 2023 Will Winder
+
+ This file is part of Universal Gcode Sender (UGS).
+
+ UGS 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.
+
+ UGS 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 UGS. If not, see .
+ */
package com.willwinder.universalgcodesender.pendantui.v1.resources;
import com.willwinder.universalgcodesender.model.BackendAPI;
import com.willwinder.universalgcodesender.pendantui.v1.model.Settings;
+import jakarta.inject.Inject;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.core.MediaType;
-import javax.inject.Inject;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
-
-@Path("/v1/settings")
+@Path("/settings")
public class SettingsResource {
-
@Inject
private BackendAPI backendAPI;
diff --git a/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/resources/StatusResource.java b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/resources/StatusResource.java
index 3a1d61c78c..f643719584 100644
--- a/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/resources/StatusResource.java
+++ b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/resources/StatusResource.java
@@ -1,3 +1,21 @@
+/*
+ Copyright 2023 Will Winder
+
+ This file is part of Universal Gcode Sender (UGS).
+
+ UGS 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.
+
+ UGS 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 UGS. If not, see .
+ */
package com.willwinder.universalgcodesender.pendantui.v1.resources;
import com.willwinder.universalgcodesender.IController;
@@ -6,14 +24,13 @@
import com.willwinder.universalgcodesender.model.BackendAPI;
import com.willwinder.universalgcodesender.model.UnitUtils;
import com.willwinder.universalgcodesender.pendantui.v1.model.Status;
+import jakarta.inject.Inject;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.core.MediaType;
-import javax.inject.Inject;
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
-
-@Path("/v1/status")
+@Path("/status")
public class StatusResource {
@Inject
diff --git a/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/resources/TextResource.java b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/resources/TextResource.java
index d84735aebc..72c94ce63d 100644
--- a/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/resources/TextResource.java
+++ b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/resources/TextResource.java
@@ -1,14 +1,32 @@
+/*
+ Copyright 2023 Will Winder
+
+ This file is part of Universal Gcode Sender (UGS).
+
+ UGS 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.
+
+ UGS 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 UGS. If not, see .
+ */
package com.willwinder.universalgcodesender.pendantui.v1.resources;
import com.willwinder.universalgcodesender.i18n.Localization;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.core.MediaType;
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
import java.util.Map;
-@Path("/v1/text")
+@Path("/text")
public class TextResource {
@GET
@Path("getTexts")
diff --git a/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/ws/EventsSocket.java b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/ws/EventsSocket.java
new file mode 100644
index 0000000000..ff007597d3
--- /dev/null
+++ b/ugs-pendant/src/main/java/com/willwinder/universalgcodesender/pendantui/v1/ws/EventsSocket.java
@@ -0,0 +1,89 @@
+/*
+ Copyright 2023 Will Winder
+
+ This file is part of Universal Gcode Sender (UGS).
+
+ UGS 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.
+
+ UGS 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 UGS. If not, see .
+ */
+
+package com.willwinder.universalgcodesender.pendantui.v1.ws;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.willwinder.universalgcodesender.listeners.UGSEventListener;
+import com.willwinder.universalgcodesender.model.UGSEvent;
+import com.willwinder.universalgcodesender.pendantui.BackendProvider;
+import com.willwinder.universalgcodesender.pendantui.v1.model.Event;
+import jakarta.websocket.ClientEndpoint;
+import jakarta.websocket.OnClose;
+import jakarta.websocket.OnError;
+import jakarta.websocket.OnOpen;
+import jakarta.websocket.Session;
+import jakarta.websocket.server.ServerEndpoint;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+@ClientEndpoint
+@ServerEndpoint(value = "/events")
+public class EventsSocket implements UGSEventListener {
+
+ private static final Logger LOGGER = Logger.getLogger(EventsSocket.class.getSimpleName());
+ private final Map sessions = new ConcurrentHashMap<>();
+ private final Gson gson;
+
+ public EventsSocket() {
+ gson = new GsonBuilder().serializeSpecialFloatingPointValues().create();
+ if (BackendProvider.getBackendAPI() != null) {
+ BackendProvider.getBackendAPI().addUGSEventListener(this);
+ }
+ }
+
+ @OnOpen
+ public void onWebSocketConnect(Session session) {
+ sessions.put(session.getId(), session);
+ LOGGER.info("WebSocket Connected: " + session.getId());
+ }
+
+ @OnClose
+ public void onWebSocketClose(Session session) {
+ sessions.remove(session.getId());
+ LOGGER.info("WebSocket Closed: " + session.getId());
+ }
+
+ @OnError
+ public void onWebSocketError(Session session, Throwable cause) {
+ sessions.remove(session.getId());
+ LOGGER.log(Level.WARNING, "WebSocket Closed: " + session.getId(), cause);
+ }
+
+ @Override
+ public void UGSEvent(UGSEvent evt) {
+ try {
+ String data = gson.toJson(new Event(evt)).replaceAll(":NaN", ":null");
+ sessions.values().forEach(session -> {
+ try {
+ session.getBasicRemote().sendText(data);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ });
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
\ No newline at end of file
diff --git a/ugs-platform/ugs-platform-ugslib/pom.xml b/ugs-platform/ugs-platform-ugslib/pom.xml
index 3608c454e5..f8fc43f001 100644
--- a/ugs-platform/ugs-platform-ugslib/pom.xml
+++ b/ugs-platform/ugs-platform-ugslib/pom.xml
@@ -133,10 +133,14 @@
org.apache.commons.codec.binary
org.apache.commons.io
org.apache.commons.lang3
- javax.xml.bind
- javax.xml.bind.annotation
- javax.xml.bind.annotation.adapters
+ jakarta.activation
+ jakarta.xml.bind
+ jakarta.xml.bind.annotation
+ jakarta.xml.bind.annotation.adapters
org.openjdk.nashorn.*
+ org.slf4j
+ org.slf4j.helpers
+ org.slf4j.spi