From 8ecc20801ac5a909c011f7d24757fcdc83f05ce4 Mon Sep 17 00:00:00 2001 From: Topvennie Date: Tue, 1 Apr 2025 22:23:54 +0200 Subject: [PATCH 1/2] support multiple positioners --- src/main/java/telraam/App.java | 1 + .../telraam/api/PositionSourceResource.java | 20 ++++++++++++++ .../database/daos/PositionSourceDAO.java | 27 +++++++++++++++++++ .../database/models/PositionSource.java | 17 ++++++++++++ .../logic/positioner/PositionSender.java | 4 +-- .../positioner/nostradamus/Nostradamus.java | 15 +++++++---- .../db/migration/V17__Add_position_source.sql | 6 +++++ 7 files changed, 83 insertions(+), 7 deletions(-) create mode 100644 src/main/java/telraam/api/PositionSourceResource.java create mode 100644 src/main/java/telraam/database/daos/PositionSourceDAO.java create mode 100644 src/main/java/telraam/database/models/PositionSource.java create mode 100644 src/main/resources/db/migration/V17__Add_position_source.sql diff --git a/src/main/java/telraam/App.java b/src/main/java/telraam/App.java index 4f4348c..859270c 100644 --- a/src/main/java/telraam/App.java +++ b/src/main/java/telraam/App.java @@ -105,6 +105,7 @@ public void run(AppConfiguration configuration, Environment environment) { jersey.register(new LapResource(database.onDemand(LapDAO.class))); jersey.register(new TeamResource(database.onDemand(TeamDAO.class), database.onDemand(BatonSwitchoverDAO.class))); jersey.register(new LapSourceResource(database.onDemand(LapSourceDAO.class))); + jersey.register(new PositionSourceResource(database.onDemand(PositionSourceDAO.class))); jersey.register(new BatonSwitchoverResource(database.onDemand(BatonSwitchoverDAO.class))); jersey.register(new LapSourceSwitchoverResource(database.onDemand(LapSourceSwitchoverDAO.class))); jersey.register(new AcceptedLapsResource()); diff --git a/src/main/java/telraam/api/PositionSourceResource.java b/src/main/java/telraam/api/PositionSourceResource.java new file mode 100644 index 0000000..f59c7bb --- /dev/null +++ b/src/main/java/telraam/api/PositionSourceResource.java @@ -0,0 +1,20 @@ +package telraam.api; + +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.core.MediaType; +import telraam.database.daos.DAO; +import telraam.database.models.PositionSource; + + +import java.awt.*; + +@Path("/position-source") +@Tag(name = "Position Source") +@Produces(MediaType.APPLICATION_JSON) +public class PositionSourceResource extends AbstractListableResource { + public PositionSourceResource(DAO dao) { + super(dao); + } +} diff --git a/src/main/java/telraam/database/daos/PositionSourceDAO.java b/src/main/java/telraam/database/daos/PositionSourceDAO.java new file mode 100644 index 0000000..36f172f --- /dev/null +++ b/src/main/java/telraam/database/daos/PositionSourceDAO.java @@ -0,0 +1,27 @@ +package telraam.database.daos; + +import org.jdbi.v3.sqlobject.config.RegisterBeanMapper; +import org.jdbi.v3.sqlobject.customizer.Bind; +import org.jdbi.v3.sqlobject.customizer.BindBean; +import org.jdbi.v3.sqlobject.statement.GetGeneratedKeys; +import org.jdbi.v3.sqlobject.statement.SqlQuery; +import org.jdbi.v3.sqlobject.statement.SqlUpdate; +import telraam.database.models.PositionSource; + +import java.util.List; +import java.util.Optional; + +public interface PositionSourceDAO extends DAO { + @Override + @SqlQuery("SELECT * FROM position_source") + @RegisterBeanMapper(PositionSource.class) + List getAll(); + + @SqlUpdate("INSERT INTO position_source (name) VALUES (:name)") + @GetGeneratedKeys({"id"}) + int insert(@BindBean PositionSource positionSource); + + @SqlQuery("SELECT * FROM position_source WHERE name = :name") + @RegisterBeanMapper(PositionSource.class) + Optional getByName(@Bind("name") String name); +} diff --git a/src/main/java/telraam/database/models/PositionSource.java b/src/main/java/telraam/database/models/PositionSource.java new file mode 100644 index 0000000..19d2fd1 --- /dev/null +++ b/src/main/java/telraam/database/models/PositionSource.java @@ -0,0 +1,17 @@ +package telraam.database.models; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@NoArgsConstructor +public class PositionSource { + private Integer id; + private String name; + + public PositionSource(String name) { + this.name = name; + } +} diff --git a/src/main/java/telraam/logic/positioner/PositionSender.java b/src/main/java/telraam/logic/positioner/PositionSender.java index 5e779dc..e909d5e 100644 --- a/src/main/java/telraam/logic/positioner/PositionSender.java +++ b/src/main/java/telraam/logic/positioner/PositionSender.java @@ -8,8 +8,8 @@ public class PositionSender { private final WebSocketMessage> message = new WebSocketMessage<>(); - public PositionSender() { - this.message.setTopic("position"); + public PositionSender(String name) { + this.message.setTopic("position_" + name); } public void send(List positions) { diff --git a/src/main/java/telraam/logic/positioner/nostradamus/Nostradamus.java b/src/main/java/telraam/logic/positioner/nostradamus/Nostradamus.java index 825d250..2fa7a85 100644 --- a/src/main/java/telraam/logic/positioner/nostradamus/Nostradamus.java +++ b/src/main/java/telraam/logic/positioner/nostradamus/Nostradamus.java @@ -2,12 +2,10 @@ import org.jdbi.v3.core.Jdbi; import telraam.database.daos.BatonSwitchoverDAO; +import telraam.database.daos.PositionSourceDAO; import telraam.database.daos.StationDAO; import telraam.database.daos.TeamDAO; -import telraam.database.models.BatonSwitchover; -import telraam.database.models.Detection; -import telraam.database.models.Station; -import telraam.database.models.Team; +import telraam.database.models.*; import telraam.logic.positioner.Position; import telraam.logic.positioner.PositionSender; import telraam.logic.positioner.Positioner; @@ -20,6 +18,7 @@ public class Nostradamus implements Positioner { private static final Logger logger = Logger.getLogger(Nostradamus.class.getName()); + private final String SOURCE_NAME = "nostradamus"; private final int INTERVAL_CALCULATE_MS = 500; // How often to handle new detections (in milliseconds) private final int INTERVAL_FETCH_MS = 10000; // Interval between fetching baton switchovers (in milliseconds) private final int INTERVAL_DETECTIONS_MS = 3000; // Amount of milliseconds to group detections by @@ -38,6 +37,12 @@ public class Nostradamus implements Positioner { public Nostradamus(Jdbi jdbi) { this.jdbi = jdbi; + + PositionSourceDAO positionSourceDAO = jdbi.onDemand(PositionSourceDAO.class); + if (positionSourceDAO.getByName(SOURCE_NAME).isEmpty()) { + positionSourceDAO.insert(new PositionSource(SOURCE_NAME)); + } + this.newDetections = new ArrayList<>(); this.detectionLock = new ReentrantLock(); this.dataLock = new ReentrantLock(); @@ -46,7 +51,7 @@ public Nostradamus(Jdbi jdbi) { this.batonToTeam = new HashMap<>(); this.teamData = getTeamData(); - this.positionSender = new PositionSender(); + this.positionSender = new PositionSender(SOURCE_NAME); new Thread(this::fetch).start(); new Thread(this::calculatePosition).start(); diff --git a/src/main/resources/db/migration/V17__Add_position_source.sql b/src/main/resources/db/migration/V17__Add_position_source.sql new file mode 100644 index 0000000..fa8c759 --- /dev/null +++ b/src/main/resources/db/migration/V17__Add_position_source.sql @@ -0,0 +1,6 @@ +create table position_source +( + id serial not null + constraint position_source_pk primary key, + name varchar(255) not null unique +); \ No newline at end of file From f22a61fe320077aeb342b852222baf4b92e7ab4d Mon Sep 17 00:00:00 2001 From: Topvennie Date: Tue, 1 Apr 2025 22:31:47 +0200 Subject: [PATCH 2/2] adjust position message --- .../java/telraam/logic/positioner/PositionSender.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/main/java/telraam/logic/positioner/PositionSender.java b/src/main/java/telraam/logic/positioner/PositionSender.java index e909d5e..54166d0 100644 --- a/src/main/java/telraam/logic/positioner/PositionSender.java +++ b/src/main/java/telraam/logic/positioner/PositionSender.java @@ -4,16 +4,22 @@ import telraam.websocket.WebSocketMessageSingleton; import java.util.List; +import java.util.Map; public class PositionSender { private final WebSocketMessage> message = new WebSocketMessage<>(); + private final String name; public PositionSender(String name) { - this.message.setTopic("position_" + name); + this.message.setTopic("position"); + this.name = name; } public void send(List positions) { - this.message.setData(positions); + Map data = Map.of( + "positioner", this.name, + "positions", positions + ); WebSocketMessageSingleton.getInstance().sendToAll(this.message); }