From 70a1da8c8c5dc8f43658afc85f652cfa7136a6fb Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Fri, 31 May 2024 12:31:16 +0200 Subject: [PATCH] thunderstorm a blowing update whatever that means --- pom.xml | 5 ++ .../m724/wtapi/thunder/ThunderProvider.java | 36 ++++++++ .../impl/lightningmaps/LMWebsocketClient.java | 71 ++++++++++++++++ .../lightningmaps/LightningMapsProvider.java | 85 +++++++++++++++++++ .../impl/lightningmaps/TimedStrike.java | 13 +++ src/test/java/eu/m724/wtapi/TestLM.java | 34 ++++++++ 6 files changed, 244 insertions(+) create mode 100644 src/main/java/eu/m724/wtapi/thunder/ThunderProvider.java create mode 100644 src/main/java/eu/m724/wtapi/thunder/impl/lightningmaps/LMWebsocketClient.java create mode 100644 src/main/java/eu/m724/wtapi/thunder/impl/lightningmaps/LightningMapsProvider.java create mode 100644 src/main/java/eu/m724/wtapi/thunder/impl/lightningmaps/TimedStrike.java create mode 100644 src/test/java/eu/m724/wtapi/TestLM.java diff --git a/pom.xml b/pom.xml index 86c8139..07889be 100644 --- a/pom.xml +++ b/pom.xml @@ -30,6 +30,11 @@ 4.13.2 test + + org.java-websocket + Java-WebSocket + 1.5.6 + diff --git a/src/main/java/eu/m724/wtapi/thunder/ThunderProvider.java b/src/main/java/eu/m724/wtapi/thunder/ThunderProvider.java new file mode 100644 index 0000000..cdf50be --- /dev/null +++ b/src/main/java/eu/m724/wtapi/thunder/ThunderProvider.java @@ -0,0 +1,36 @@ +package eu.m724.wtapi.thunder; + +import java.util.concurrent.Callable; +import java.util.function.Consumer; + +import eu.m724.wtapi.object.Coordinates; +import eu.m724.wtapi.provider.exception.ProviderException; + +public abstract class ThunderProvider { + + public abstract void init() throws ProviderException; + + /** + * connects to remote server and starts processing data + * @throws ProviderException + */ + public abstract void start() throws ProviderException; + + /** + * disconnects from remote server + */ + public abstract void stop(); + + /** + * check for new data and call callback and stuff + */ + public abstract void tick(); + + public abstract void registerStrikeHandler(Consumer runnable); + + /** + * delay between irl strike and receiving of data + * @return delay in ms + */ + public abstract int getDelay(); +} diff --git a/src/main/java/eu/m724/wtapi/thunder/impl/lightningmaps/LMWebsocketClient.java b/src/main/java/eu/m724/wtapi/thunder/impl/lightningmaps/LMWebsocketClient.java new file mode 100644 index 0000000..702afd9 --- /dev/null +++ b/src/main/java/eu/m724/wtapi/thunder/impl/lightningmaps/LMWebsocketClient.java @@ -0,0 +1,71 @@ +package eu.m724.wtapi.thunder.impl.lightningmaps; + +import java.net.URI; + +import org.java_websocket.client.WebSocketClient; +import org.java_websocket.handshake.ServerHandshake; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.google.gson.JsonSyntaxException; + +import eu.m724.wtapi.object.Coordinates; + +class LMWebsocketClient extends WebSocketClient { + LightningMapsProvider lightningMapsProvider; + + private static URI[] uris = new URI[] { + URI.create("wss://live.lightningmaps.org/"), + URI.create("wss://live2.lightningmaps.org/") + }; + private int currentUri = 0; + + public LMWebsocketClient(LightningMapsProvider lightningMapsProvider) { + super(uris[0]); + this.lightningMapsProvider = lightningMapsProvider; + } + + @Override + public void onOpen(ServerHandshake handshakedata) { + this.send("{\"v\":24,\"i\":{},\"s\":false,\"x\":0,\"w\":4,\"tx\":0,\"tw\":3,\"a\":4,\"z\":2,\"b\":true,\"h\":\"#m=oss;t=3;s=0;o=0;b=;ts=0;z=2;y=45.4601;x=17.5814;d=2;dl=2;dc=0;\",\"l\":5,\"t\":5,\"from_lightningmaps_org\":true,\"p\":[87,309,-72.5,-273.9],\"r\":\"re\"}"); + } + + @Override + public void onMessage(String message) { + try { + JsonObject json = + JsonParser.parseString(message) + .getAsJsonObject(); + + if (!json.has("strokes")) return; + + json.getAsJsonArray("strokes").forEach(ele -> { + long time = ele.getAsJsonObject().getAsJsonPrimitive("time").getAsLong(); + double lat = ele.getAsJsonObject().getAsJsonPrimitive("lat").getAsDouble(); + double lon = ele.getAsJsonObject().getAsJsonPrimitive("lon").getAsDouble(); + + Coordinates coordinates = new Coordinates(lat, lon); + lightningMapsProvider.submitStrike(coordinates, time); + }); + } catch (JsonSyntaxException e) { + // ignore invalid json + } + + } + + @Override + public void onClose(int code, String reason, boolean remote) { + System.out.printf("%s Closed: %d %s\n", this.uri, code, reason); + this.uri = uris[++currentUri % 2]; + lightningMapsProvider.reconnect(); + + } + + @Override + public void onError(Exception ex) { + this.uri = uris[++currentUri % 2]; + lightningMapsProvider.reconnect(); + } + +} diff --git a/src/main/java/eu/m724/wtapi/thunder/impl/lightningmaps/LightningMapsProvider.java b/src/main/java/eu/m724/wtapi/thunder/impl/lightningmaps/LightningMapsProvider.java new file mode 100644 index 0000000..d4d57fc --- /dev/null +++ b/src/main/java/eu/m724/wtapi/thunder/impl/lightningmaps/LightningMapsProvider.java @@ -0,0 +1,85 @@ +package eu.m724.wtapi.thunder.impl.lightningmaps; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Queue; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.DelayQueue; +import java.util.function.Consumer; + +import eu.m724.wtapi.object.Coordinates; +import eu.m724.wtapi.object.Weather; +import eu.m724.wtapi.provider.exception.ProviderException; +import eu.m724.wtapi.thunder.ThunderProvider; + +public class LightningMapsProvider extends ThunderProvider { + LMWebsocketClient websocketClient = new LMWebsocketClient(this); + ArrayList> strikeHandlers = new ArrayList<>(); + CopyOnWriteArrayList strikes = new CopyOnWriteArrayList<>(); // TODO optimize? + + private long reconnectPending; + private final int delay = 10000; + + @Override + public void init() throws ProviderException { + // TODO Auto-generated method stub + + } + + @Override + public void start() throws ProviderException { + try { + websocketClient.connectBlocking(); + } catch (InterruptedException e) { + throw new ProviderException("unexpected interruptedexception"); + } + } + + @Override + public void stop() { + try { + websocketClient.closeBlocking(); + } catch (InterruptedException e) { + websocketClient.close(); + } + } + + @Override + public void registerStrikeHandler(Consumer runnable) { + strikeHandlers.add(runnable); + } + + @Override + public int getDelay() { + return this.delay; + } + + @Override + public void tick() { + long now = System.currentTimeMillis(); + + if (reconnectPending > 0) { + if (now > reconnectPending) { + websocketClient.reconnect(); + reconnectPending = 0; + } + } + + for (TimedStrike strike : strikes) { + if (strike.timestamp > now) + break; + strikeHandlers.forEach(con -> con.accept(strike.coordinates)); + strikes.remove(0); + } + } + + void reconnect() { + System.out.println("reconnecting in 5 seconds"); + reconnectPending = System.currentTimeMillis() + 3000; + } + + void submitStrike(Coordinates coordinates, long timestamp) { + strikes.add(new TimedStrike(timestamp, coordinates)); + } + +} diff --git a/src/main/java/eu/m724/wtapi/thunder/impl/lightningmaps/TimedStrike.java b/src/main/java/eu/m724/wtapi/thunder/impl/lightningmaps/TimedStrike.java new file mode 100644 index 0000000..240d092 --- /dev/null +++ b/src/main/java/eu/m724/wtapi/thunder/impl/lightningmaps/TimedStrike.java @@ -0,0 +1,13 @@ +package eu.m724.wtapi.thunder.impl.lightningmaps; + +import eu.m724.wtapi.object.Coordinates; + +public class TimedStrike { + public long timestamp; + public Coordinates coordinates; + + public TimedStrike(long timestamp, Coordinates coordinates) { + this.timestamp = timestamp; + this.coordinates = coordinates; + } +} diff --git a/src/test/java/eu/m724/wtapi/TestLM.java b/src/test/java/eu/m724/wtapi/TestLM.java new file mode 100644 index 0000000..050f23c --- /dev/null +++ b/src/test/java/eu/m724/wtapi/TestLM.java @@ -0,0 +1,34 @@ +package eu.m724.wtapi; + +import java.util.ArrayList; + +import org.junit.Test; + +import eu.m724.wtapi.object.Coordinates; +import eu.m724.wtapi.thunder.ThunderProvider; +import eu.m724.wtapi.thunder.impl.lightningmaps.LightningMapsProvider; + +public class TestLM { + @Test + public void lightningMapsTest() throws InterruptedException { + ArrayList coordinatesList = new ArrayList<>(); + + ThunderProvider provider = new LightningMapsProvider(); + + provider.registerStrikeHandler(coordinates -> + coordinatesList.add(coordinates)); + + provider.init(); + + provider.start(); + + for (int i=0; i < 100; i++) { + provider.tick(); + Thread.sleep(100); + } + + System.out.printf("Strikes in the last 10s: %d\n", coordinatesList.size()); + System.out.printf("%f %f", coordinatesList.get(0).latitude, coordinatesList.get(0).longitude); + + } +}