├── .gitignore ├── openNTRIP.iml ├── src ├── test │ ├── resources │ │ ├── 2233 │ │ ├── RTCM_30 │ │ ├── RTCM_31 │ │ ├── RTCM_32 │ │ ├── RTCM_33 │ │ ├── 1004.rtcm3 │ │ ├── 1019.rtcm3 │ │ ├── 1021.rtcm3 │ │ ├── 1023.rtcm3 │ │ ├── 1025.rtcm3 │ │ ├── RTCM3EPH(3.3) │ │ ├── geoids │ │ │ ├── spb.GGF │ │ │ ├── bering.GGF │ │ │ ├── england.GGF │ │ │ ├── florida.GGF │ │ │ └── australia.GGF │ │ └── testRtcm.rtcm3 │ └── java │ │ ├── org │ │ └── dav95s │ │ │ └── openNTRIP │ │ │ ├── crs │ │ │ └── gridShift │ │ │ │ └── GridShiftTest.java │ │ │ ├── utils │ │ │ ├── BasicAuthParserTest.java │ │ │ ├── binaryParse │ │ │ │ └── BitUtilsTest.java │ │ │ └── Geoids │ │ │ │ └── GGFTest.java │ │ │ ├── protocols │ │ │ └── rtcm │ │ │ │ ├── MSG1026Test.java │ │ │ │ ├── MSG1027Test.java │ │ │ │ ├── MSG1023Test.java │ │ │ │ ├── MSG1006Test.java │ │ │ │ ├── MSG1025Test.java │ │ │ │ └── MSG1021Test.java │ │ │ └── users │ │ │ └── passwords │ │ │ └── BCryptTest.java │ │ └── SandBox.java └── main │ ├── java │ └── org │ │ └── dav95s │ │ └── openNTRIP │ │ ├── protocols │ │ ├── ntrip │ │ │ ├── NetworkType.java │ │ │ ├── NtripResponse.java │ │ │ └── SourceLoginMessage.java │ │ ├── rtcm │ │ │ ├── assets │ │ │ │ ├── CRS2.java │ │ │ │ ├── CRS3.java │ │ │ │ ├── CRS1.java │ │ │ │ ├── ProjectionType.java │ │ │ │ ├── TransformationType.java │ │ │ │ └── Plates.java │ │ │ ├── messages │ │ │ │ ├── MSG1014.java │ │ │ │ ├── MSG1007.java │ │ │ │ ├── MSG1008.java │ │ │ │ ├── MSG1013.java │ │ │ │ ├── MSG1017.java │ │ │ │ ├── MSG1001.java │ │ │ │ ├── MSG1025.java │ │ │ │ ├── MSG1002.java │ │ │ │ ├── MSG1022.java │ │ │ │ ├── MSG1026.java │ │ │ │ ├── MSG1003.java │ │ │ │ ├── MSG1020.java │ │ │ │ └── MSG1027.java │ │ │ └── Rtcm3Separator.java │ │ └── nmea │ │ │ └── NMEA.java │ │ ├── crs │ │ ├── geoids │ │ │ ├── IGeoid.java │ │ │ └── GGF.java │ │ └── gridShift │ │ │ ├── GridNode.java │ │ │ ├── GeodeticPoint.java │ │ │ └── ResidualsGrid.java │ │ ├── database │ │ ├── models │ │ │ ├── assets │ │ │ │ └── Authenticator.java │ │ │ ├── ServerModel.java │ │ │ ├── GridModel.java │ │ │ ├── UserGroupModel.java │ │ │ ├── SourceTableModel.java │ │ │ ├── CrsModel.java │ │ │ ├── UserModel.java │ │ │ └── MountPointModel.java │ │ ├── modelsV2 │ │ │ ├── UserModel.java │ │ │ ├── ReferenceStationModel.java │ │ │ ├── NetworkModel.java │ │ │ └── MountpointModel.java │ │ ├── DataSource.java │ │ └── repository │ │ │ ├── UserRepository.java │ │ │ ├── MountpointRepository.java │ │ │ ├── NetworkRepository.java │ │ │ └── ReferenceStationRepository.java │ │ ├── users │ │ ├── User.java │ │ └── passwords │ │ │ └── BCrypt.java │ │ ├── exception │ │ ├── MountpointNotFound.java │ │ ├── ReferenceStationNotFoundException.java │ │ ├── UserAuthorizationException.java │ │ └── ReferenceStationAuthorizationException.java │ │ ├── commons │ │ ├── GlobalStats.java │ │ ├── Message.java │ │ └── Registry.java │ │ ├── utils │ │ ├── geometry │ │ │ ├── Point.java │ │ │ ├── AngleTools.java │ │ │ └── Polygon.java │ │ ├── binaryParse │ │ │ ├── Normalize.java │ │ │ ├── Crc24q.java │ │ │ └── BitUtils.java │ │ ├── Config.java │ │ ├── ParseUtil.java │ │ ├── BasicAuthParser.java │ │ └── ServerProperties.java │ │ ├── core │ │ ├── stationsServer │ │ │ ├── ReferenceStationChannelMatcher.java │ │ │ ├── ReferenceStationServer.java │ │ │ └── handlers │ │ │ │ ├── Rtcm3InboundHandler.java │ │ │ │ └── ReferenceStationAuthHandler.java │ │ ├── ChannelState.java │ │ ├── userServer │ │ │ ├── handlers │ │ │ │ ├── NmeaPositionHander.java │ │ │ │ ├── authentication │ │ │ │ │ ├── NtripNoneAuthHandler.java │ │ │ │ │ └── NtripBasicAuthHandler.java │ │ │ │ └── UserAuthHandler.java │ │ │ └── NtripServer.java │ │ └── BaseServer.java │ │ ├── TransportTypeHolder.java │ │ └── ServerLauncher.java │ └── resources │ ├── db.properties │ ├── database.properties │ ├── logback.xml │ └── app.properties ├── .idea ├── vcs.xml ├── misc.xml └── compiler.xml ├── README.md └── pom.xml /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | .idea -------------------------------------------------------------------------------- /openNTRIP.iml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/test/resources/2233: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DAV95s/openNTRIP/HEAD/src/test/resources/2233 -------------------------------------------------------------------------------- /src/test/resources/RTCM_30: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DAV95s/openNTRIP/HEAD/src/test/resources/RTCM_30 -------------------------------------------------------------------------------- /src/test/resources/RTCM_31: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DAV95s/openNTRIP/HEAD/src/test/resources/RTCM_31 -------------------------------------------------------------------------------- /src/test/resources/RTCM_32: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DAV95s/openNTRIP/HEAD/src/test/resources/RTCM_32 -------------------------------------------------------------------------------- /src/test/resources/RTCM_33: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DAV95s/openNTRIP/HEAD/src/test/resources/RTCM_33 -------------------------------------------------------------------------------- /src/test/resources/1004.rtcm3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DAV95s/openNTRIP/HEAD/src/test/resources/1004.rtcm3 -------------------------------------------------------------------------------- /src/test/resources/1019.rtcm3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DAV95s/openNTRIP/HEAD/src/test/resources/1019.rtcm3 -------------------------------------------------------------------------------- /src/test/resources/1021.rtcm3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DAV95s/openNTRIP/HEAD/src/test/resources/1021.rtcm3 -------------------------------------------------------------------------------- /src/test/resources/1023.rtcm3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DAV95s/openNTRIP/HEAD/src/test/resources/1023.rtcm3 -------------------------------------------------------------------------------- /src/test/resources/1025.rtcm3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DAV95s/openNTRIP/HEAD/src/test/resources/1025.rtcm3 -------------------------------------------------------------------------------- /src/test/resources/RTCM3EPH(3.3): -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DAV95s/openNTRIP/HEAD/src/test/resources/RTCM3EPH(3.3) -------------------------------------------------------------------------------- /src/test/resources/geoids/spb.GGF: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DAV95s/openNTRIP/HEAD/src/test/resources/geoids/spb.GGF -------------------------------------------------------------------------------- /src/test/resources/testRtcm.rtcm3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DAV95s/openNTRIP/HEAD/src/test/resources/testRtcm.rtcm3 -------------------------------------------------------------------------------- /src/test/resources/geoids/bering.GGF: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DAV95s/openNTRIP/HEAD/src/test/resources/geoids/bering.GGF -------------------------------------------------------------------------------- /src/test/resources/geoids/england.GGF: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DAV95s/openNTRIP/HEAD/src/test/resources/geoids/england.GGF -------------------------------------------------------------------------------- /src/test/resources/geoids/florida.GGF: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DAV95s/openNTRIP/HEAD/src/test/resources/geoids/florida.GGF -------------------------------------------------------------------------------- /src/test/resources/geoids/australia.GGF: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DAV95s/openNTRIP/HEAD/src/test/resources/geoids/australia.GGF -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/protocols/ntrip/NetworkType.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.protocols.ntrip; 2 | 3 | public enum NetworkType { 4 | CAS, NET, STR 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/crs/geoids/IGeoid.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.crs.geoids; 2 | 3 | public interface IGeoid { 4 | double getValueByPoint(double lat, double lon); 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/database/models/assets/Authenticator.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.database.models.assets; 2 | 3 | public enum Authenticator { 4 | None, Basic, Digest; 5 | } 6 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/users/User.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.users; 2 | 3 | public class User { 4 | int id; 5 | String username; 6 | String password; 7 | 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/exception/MountpointNotFound.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.exception; 2 | 3 | public class MountpointNotFound extends Exception { 4 | public MountpointNotFound(String message) { 5 | super(message); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/commons/GlobalStats.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.commons; 2 | 3 | import org.dav95s.openNTRIP.utils.ServerProperties; 4 | 5 | public class GlobalStats { 6 | public GlobalStats(ServerProperties serverProperties) { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/main/resources/db.properties: -------------------------------------------------------------------------------- 1 | jdbcUrl=jdbc:mysql://localhost:3306/ntrip?useSSL=false&serverTimezone=UTC 2 | dataSource.user=root 3 | dataSource.password=123 4 | dataSource.cachePrepStmts=true 5 | dataSource.prepStmtCacheSize=250 6 | dataSource.prepStmtCacheSqlLimit=2048 7 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/protocols/rtcm/assets/CRS2.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.protocols.rtcm.assets; 2 | 3 | /** 4 | * Upcast residuals grid message 5 | */ 6 | public interface CRS2 { 7 | int getMessageNumber(); 8 | byte[] getBytes(); 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/protocols/rtcm/assets/CRS3.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.protocols.rtcm.assets; 2 | 3 | /** 4 | * Upcast projection message 5 | */ 6 | public interface CRS3 { 7 | int getMessageNumber(); 8 | byte[] getBytes(); 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/exception/ReferenceStationNotFoundException.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.exception; 2 | 3 | public class ReferenceStationNotFoundException extends Exception{ 4 | public ReferenceStationNotFoundException() { 5 | super(); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/exception/UserAuthorizationException.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.exception; 2 | 3 | public class UserAuthorizationException extends Exception { 4 | public UserAuthorizationException(String message) { 5 | super(message); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/protocols/rtcm/assets/CRS1.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.protocols.rtcm.assets; 2 | 3 | /** 4 | * Upcast transformation parameters message 5 | */ 6 | public interface CRS1 { 7 | int getMessageNumber(); 8 | byte[] getBytes(); 9 | } 10 | -------------------------------------------------------------------------------- /src/test/java/org/dav95s/openNTRIP/crs/gridShift/GridShiftTest.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.crs.gridShift; 2 | 3 | import org.junit.Test; 4 | 5 | public class GridShiftTest { 6 | @Test 7 | public void GridShift(){ 8 | 9 | System.out.println(123); 10 | } 11 | } -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/exception/ReferenceStationAuthorizationException.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.exception; 2 | 3 | public class ReferenceStationAuthorizationException extends Exception{ 4 | public ReferenceStationAuthorizationException(String message) { 5 | super(message); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/utils/geometry/Point.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.utils.geometry; 2 | 3 | public final class Point { 4 | public final double x; 5 | public final double y; 6 | 7 | public Point(double x, double y) { 8 | this.x = x; 9 | this.y = y; 10 | } 11 | } -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/protocols/ntrip/NtripResponse.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.protocols.ntrip; 2 | 3 | public class NtripResponse { 4 | public static final byte[] OK_MESSAGE = "ICY 200 OK\r\n".getBytes(); 5 | public static final byte[] BAD_PASSWORD = "ERROR - Bad Password\r\n".getBytes(); 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/crs/gridShift/GridNode.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.crs.gridShift; 2 | 3 | public class GridNode { 4 | public long id; 5 | public double north; 6 | public double east; 7 | public double height; 8 | 9 | public double dNorth; 10 | public double dEast; 11 | public double dH; 12 | 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/protocols/ntrip/SourceLoginMessage.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.protocols.ntrip; 2 | 3 | public class SourceLoginMessage { 4 | public final String login; 5 | public final String password; 6 | 7 | public SourceLoginMessage(String login, String password) { 8 | this.login = login; 9 | this.password = password; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/resources/database.properties: -------------------------------------------------------------------------------- 1 | development.driver=com.mysql.cj.jdbc.Driver 2 | development.username=root 3 | development.password=123 4 | development.url=jdbc:mysql://localhost:3306/ntrip?useSSL=false&serverTimezone=UTC 5 | 6 | test.driver=com.mysql.cj.jdbc.Driver 7 | test.username=user2 8 | test.password=pwd 9 | test.url=jdbc:mysql://localhost/acme_test 10 | 11 | production.jndi=java:comp/env/jdbc/acme -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/utils/binaryParse/Normalize.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.utils.binaryParse; 2 | 3 | public class Normalize { 4 | private static final int[] pow10 = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000}; 5 | 6 | public static double normalize(double nmb, int scale) { 7 | return (double) Math.round(nmb * pow10[scale]) / pow10[scale]; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/protocols/rtcm/assets/ProjectionType.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.protocols.rtcm.assets; 2 | 3 | public enum ProjectionType { 4 | NONE(0), TM(1), TMS(2), LCC1SP(3), LCC2SP(4), 5 | LCCW(5), CS(6), OM(7), OS(8), MC(9), PS(10), DS(11); 6 | 7 | public int getNmb() { 8 | return nmb; 9 | } 10 | 11 | int nmb; 12 | 13 | ProjectionType(int i) { 14 | nmb = i; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/utils/Config.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.utils; 2 | 3 | import java.nio.charset.Charset; 4 | import java.nio.charset.StandardCharsets; 5 | 6 | public class Config { 7 | public static final Charset DEFAULT_CHARSET = StandardCharsets.ISO_8859_1; 8 | 9 | public static final String SERVER_PROPERTIES_FILENAME = "app.properties"; 10 | public static final String MAIL_PROPERTIES_FILENAME = "mail.properties"; 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/commons/Message.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.commons; 2 | 3 | public class Message { 4 | public final String name; 5 | public final byte[] bytes; 6 | 7 | 8 | public Message(String name, byte[] bytes) { 9 | this.name = name; 10 | this.bytes = bytes; 11 | } 12 | 13 | public Message(short name, byte[] bytes) { 14 | this.name = String.valueOf(name); 15 | this.bytes = bytes; 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/protocols/rtcm/assets/TransformationType.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.protocols.rtcm.assets; 2 | 3 | public enum TransformationType { 4 | HelmertLinearExpression(0), 5 | HelmertStrict(1), 6 | MolodenskiAbridged(2), 7 | MolodenskiBadekas(3); 8 | 9 | private int index; 10 | 11 | TransformationType(int i) { 12 | this.index = i; 13 | } 14 | 15 | public int getIndex() { 16 | return index; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/protocols/rtcm/assets/Plates.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.protocols.rtcm.assets; 2 | 3 | public enum Plates { 4 | NONE(0), AFRC(1), ANTA(2), ARAB(3), AUST(4), CARB(5), COCO(6), EURA(7), INDI(8), 5 | NOAM(9), NAZC(10), PCFC(11), SOAM(12), JUFU(13), PHIL(14), RIVR(15), SCOT(16); 6 | 7 | int plateNmb; 8 | 9 | public int getPlateNmb() { 10 | return plateNmb; 11 | } 12 | 13 | Plates(int i) { 14 | plateNmb = i; 15 | } 16 | } -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/database/modelsV2/UserModel.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.database.modelsV2; 2 | 3 | public class UserModel { 4 | public final int id; 5 | public final String username; 6 | public final String password; 7 | public final String email; 8 | 9 | public UserModel(int id, String username, String password, String email) { 10 | this.id = id; 11 | this.username = username; 12 | this.password = password; 13 | this.email = email; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/crs/gridShift/GeodeticPoint.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.crs.gridShift; 2 | 3 | public class GeodeticPoint { 4 | public long id; 5 | public double north; 6 | public double east; 7 | public double dNorth; 8 | public double dEast; 9 | 10 | public double distance; 11 | 12 | public double distance(double pNorth, double pEast) { 13 | distance = Math.sqrt(Math.pow(north + pNorth, 2) + Math.pow(east + pEast, 2)); 14 | return distance; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # openNTRIP 2 | openNTRIP is multi-caster server for streaming RTCM data to internet. 3 | 4 | ## Installation 5 | 1. Install mysql 6 | 2. Insert table "ntrip" in the database (openNTRIP/src/main/resources/ntrip.sql) 7 | 3. Edit config file (openNTRIP/src/main/resources/ntrip.sql/db.properties) 8 | 4. Try to run 9 | 10 | ## Usage 11 | For reference station 12 | SOURCE: AL1 or AL2 13 | PASSWORD: 44444 14 | 15 | For user (if mountpoint authentication set 1) 16 | Account: Administrator 17 | Password: password 18 | 19 | You can use RtkLib for retranslating gnns data to openNTRIP. 20 | 21 | ## Roadmap 22 | 1. Add support RTCM 1021-1027 message. 23 | 2. Add support FKP. 24 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/utils/ParseUtil.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.utils; 2 | 3 | public class ParseUtil { 4 | public static int parseInt(String intProperty) { 5 | try { 6 | return Integer.parseInt(intProperty); 7 | } catch (NumberFormatException nfe) { 8 | throw new RuntimeException(intProperty + " not a number. " + nfe.getMessage()); 9 | } 10 | } 11 | 12 | public static long parseLong(String longProperty) { 13 | try { 14 | return Long.parseLong(longProperty); 15 | } catch (NumberFormatException nfe) { 16 | throw new RuntimeException(longProperty + " not a number. " + nfe.getMessage()); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/core/stationsServer/ReferenceStationChannelMatcher.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.core.stationsServer; 2 | 3 | import io.netty.channel.Channel; 4 | import io.netty.channel.group.ChannelMatcher; 5 | import io.netty.util.AttributeKey; 6 | import org.dav95s.openNTRIP.core.ChannelState; 7 | 8 | public class ReferenceStationChannelMatcher implements ChannelMatcher { 9 | final AttributeKey key = ChannelState.REFERENCE_STATION; 10 | final String name; 11 | 12 | public ReferenceStationChannelMatcher(String name) { 13 | this.name = name; 14 | } 15 | 16 | @Override 17 | public boolean matches(Channel channel) { 18 | return channel.attr(key).get().equals(name) || (channel.attr(key).get() == null); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/utils/geometry/AngleTools.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.utils.geometry; 2 | 3 | public class AngleTools { 4 | static public double dmsToDecimal(int degrees, int minutes, float seconds){ 5 | if (minutes > 59 || seconds > 59.9999){ 6 | throw new IllegalArgumentException("minutes or seconds more than 59"); 7 | } 8 | 9 | return Math.signum(degrees) * (Math.abs(degrees) + (minutes / 60.0) + (seconds / 3600.0)); 10 | } 11 | static public double dmsToDecimal(int degrees, int minutes){ 12 | if (minutes > 59){ 13 | throw new IllegalArgumentException("minutes or seconds more than 59"); 14 | } 15 | 16 | return Math.signum(degrees) * (Math.abs(degrees) + (minutes / 60.0)); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/database/DataSource.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.database; 2 | 3 | import com.zaxxer.hikari.HikariConfig; 4 | import com.zaxxer.hikari.HikariDataSource; 5 | 6 | import java.sql.Connection; 7 | import java.sql.SQLException; 8 | 9 | public class DataSource { 10 | 11 | private static final HikariConfig configHikari = new HikariConfig(); 12 | private static final HikariDataSource ds; 13 | 14 | static { 15 | String configFile = "src/main/resources/db.properties"; 16 | HikariConfig cfg = new HikariConfig(configFile); 17 | 18 | ds = new HikariDataSource(cfg); 19 | } 20 | 21 | private DataSource() {} 22 | 23 | public static Connection getConnection() throws SQLException { 24 | return ds.getConnection(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/core/ChannelState.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.core; 2 | 3 | import io.netty.util.AttributeKey; 4 | import org.dav95s.openNTRIP.database.modelsV2.MountpointModel; 5 | import org.dav95s.openNTRIP.database.modelsV2.ReferenceStationModel; 6 | 7 | public class ChannelState { 8 | public static final AttributeKey MOUNTPOINT = AttributeKey.valueOf("MOUNT_POINT"); 9 | public static final AttributeKey REFERENCE_STATION_MODEL = AttributeKey.valueOf("REFERENCE_STATION_MODEL"); 10 | public static final AttributeKey REFERENCE_STATION = AttributeKey.valueOf("REFERENCE_STATION"); 11 | public static final AttributeKey NETWORK = AttributeKey.valueOf("NETWORK"); 12 | public static final AttributeKey AUTHENTICATION = AttributeKey.valueOf("AUTHENTICATION"); 13 | } 14 | -------------------------------------------------------------------------------- /src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/database/modelsV2/ReferenceStationModel.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.database.modelsV2; 2 | 3 | public class ReferenceStationModel { 4 | public final int id; 5 | public final String name; 6 | public final String format; 7 | public final double lat; 8 | public final double lon; 9 | public final double alt; 10 | public final String password; 11 | public final int hz; 12 | public final String[] networks; 13 | 14 | 15 | public ReferenceStationModel(int id, String name, String format, double lat, double lon, double alt, String password, int hz, String[] networks) { 16 | this.id = id; 17 | this.name = name; 18 | this.format = format; 19 | this.lat = lat; 20 | this.lon = lon; 21 | this.alt = alt; 22 | this.password = password; 23 | this.hz = hz; 24 | this.networks = networks; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/core/userServer/handlers/NmeaPositionHander.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.core.userServer.handlers; 2 | 3 | import io.netty.channel.ChannelHandlerContext; 4 | import io.netty.channel.SimpleChannelInboundHandler; 5 | import org.dav95s.openNTRIP.commons.Registry; 6 | import org.dav95s.openNTRIP.protocols.nmea.NMEA; 7 | 8 | public class NmeaPositionHander extends SimpleChannelInboundHandler { 9 | Registry registry; 10 | 11 | public NmeaPositionHander(Registry registry) { 12 | this.registry = registry; 13 | } 14 | 15 | @Override 16 | protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception { 17 | NMEA nmea = new NMEA(); 18 | NMEA.GPSPosition gpsPosition = nmea.parse(msg); 19 | if (gpsPosition.isSet()) { 20 | System.out.println("No implement!"); 21 | 22 | } else { 23 | System.out.println("No nmea coordinate!"); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/utils/BasicAuthParser.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.utils; 2 | 3 | import java.util.Base64; 4 | 5 | public class BasicAuthParser { 6 | public final String account; 7 | public final String password; 8 | 9 | public BasicAuthParser(String authorization) { 10 | String[] split = authorization.split(" ", 2); 11 | if (split.length != 2 || !split[0].equals("Basic")) { 12 | throw new IllegalArgumentException(); 13 | } 14 | 15 | byte[] accPassBytes = Base64.getDecoder().decode(split[1]); 16 | String accPass = new String(accPassBytes); 17 | split = accPass.split(":"); 18 | 19 | if (split.length == 1) { 20 | this.account = split[0]; 21 | this.password = ""; 22 | } else if (split.length == 2) { 23 | this.account = split[0]; 24 | this.password = split[1]; 25 | } else { 26 | throw new IllegalArgumentException(); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/test/java/org/dav95s/openNTRIP/utils/BasicAuthParserTest.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.utils; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | 6 | public class BasicAuthParserTest { 7 | @Test(expected = IllegalArgumentException.class) 8 | public void test1() { 9 | String tested = "Basic"; 10 | BasicAuthParser basicAuthParser = new BasicAuthParser(tested); 11 | } 12 | 13 | @Test 14 | public void test2() { 15 | String tested = "Basic QUNDOlBBU1M="; 16 | BasicAuthParser basicAuthParser = new BasicAuthParser(tested); 17 | 18 | Assert.assertEquals("ACC", basicAuthParser.account); 19 | Assert.assertEquals("PASS", basicAuthParser.password); 20 | 21 | } 22 | 23 | @Test 24 | public void test3() { 25 | String tested = "Basic QUNDOg=="; 26 | BasicAuthParser basicAuthParser = new BasicAuthParser(tested); 27 | 28 | Assert.assertEquals("ACC", basicAuthParser.account); 29 | Assert.assertEquals("", basicAuthParser.password); 30 | 31 | } 32 | 33 | } -------------------------------------------------------------------------------- /src/test/java/org/dav95s/openNTRIP/utils/binaryParse/BitUtilsTest.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.utils.binaryParse; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | 6 | public class BitUtilsTest { 7 | @Test 8 | public void IntUnsignedTest() { 9 | BitUtils bitUtils = new BitUtils(); 10 | bitUtils.setInt(2147483647, 31); 11 | bitUtils.setInt(16777215, 24); 12 | bitUtils.setPointer(0); 13 | Assert.assertEquals(2147483647, bitUtils.getUnsignedInt(31)); 14 | Assert.assertEquals(16777215, bitUtils.getUnsignedInt(24)); 15 | } 16 | 17 | @Test 18 | public void IntSignedTest() { 19 | BitUtils bitUtils = new BitUtils(); 20 | bitUtils.setInt(0b10000000, 8); 21 | bitUtils.setInt(0b1111111110000000, 16); 22 | bitUtils.setInt(0b1101111110000000, 16); 23 | bitUtils.setPointer(0); 24 | Assert.assertEquals(-128, bitUtils.getSignedInt(8)); 25 | Assert.assertEquals(-128, bitUtils.getSignedInt(16)); 26 | Assert.assertEquals(-8320, bitUtils.getSignedInt(16)); 27 | } 28 | 29 | } -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/utils/geometry/Polygon.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.utils.geometry; 2 | 3 | public class Polygon { 4 | private Point[] points; // Points making up the boundary 5 | 6 | public Polygon(Point[] points) { 7 | this.points = points; 8 | } 9 | 10 | 11 | /** 12 | * Return true if the given point is contained inside the boundary. 13 | * See: http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html 14 | * 15 | * @param test The point to check 16 | * @return true if the point is inside the boundary, false otherwise 17 | */ 18 | public boolean contains(Point test) { 19 | int i; 20 | int j; 21 | boolean result = false; 22 | for (i = 0, j = points.length - 1; i < points.length; j = i++) { 23 | if ((points[i].y > test.y) != (points[j].y > test.y) && 24 | (test.x < (points[j].x - points[i].x) * (test.y - points[i].y) / (points[j].y - points[i].y) + points[i].x)) { 25 | result = !result; 26 | } 27 | } 28 | return result; 29 | } 30 | 31 | } -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/users/passwords/BCrypt.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.users.passwords; 2 | 3 | import static at.favre.lib.crypto.bcrypt.BCrypt.verifyer; 4 | 5 | public class BCrypt { 6 | 7 | 8 | public boolean compare(String DBPassword, String UserPassword) { 9 | if (DBPassword == null || UserPassword == null) { 10 | return false; 11 | } 12 | DBPassword = DBPassword.trim(); 13 | UserPassword = UserPassword.trim(); 14 | // if (DBPassword.isEmpty() && UserPassword.isEmpty()) { 15 | // return true; 16 | // } 17 | 18 | return verifyer().verify(UserPassword.getBytes(), DBPassword.getBytes()).verified; 19 | } 20 | 21 | public String hash(String rawPassword, int BCryptRounds) { 22 | if (rawPassword == null) { 23 | throw new NullPointerException("Input string is null"); 24 | } 25 | 26 | byte[] rawResult = at.favre.lib.crypto.bcrypt.BCrypt.withDefaults().hash(BCryptRounds, rawPassword.getBytes()); 27 | return new String(rawResult); 28 | } 29 | 30 | 31 | public String hash(String rawPassword) { 32 | return hash(rawPassword, 12); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/protocols/rtcm/messages/MSG1014.java: -------------------------------------------------------------------------------- 1 | //package org.dav95s.openNTRIP.Tools.RTCM; 2 | // 3 | //public class MSG1014 extends RTCM { 4 | // private int messageNumber; 5 | // private int NetworkID; 6 | // private int SubnetworkID; 7 | // private int NumberAuxiliaryStationsTransmitted; 8 | // private int MasterStation; 9 | // private int AuxiliaryReferenceStationID; 10 | // private int AuxMasterDeltaLatitude; 11 | // private int AuxMasterDeltaLongitude; 12 | // private int AuxMasterDeltaHeight; 13 | // 14 | // public MSG1014(byte[] msg) { 15 | // super.rawMsg = msg; 16 | // super.setToBinaryBuffer(msg); 17 | // 18 | // messageNumber = toUnsignedInt(getBits(16, 12)); 19 | // NetworkID = toUnsignedInt(getBits(28, 8)); 20 | // SubnetworkID = toUnsignedInt(getBits(36, 4)); 21 | // NumberAuxiliaryStationsTransmitted = toUnsignedInt(getBits(40,5)); 22 | // MasterStation = toUnsignedInt(getBits(45, 12)); 23 | // AuxiliaryReferenceStationID = toUnsignedInt(getBits(57, 12)); 24 | // AuxMasterDeltaLatitude = toSignedInt(getBits(69, 20)); 25 | // AuxMasterDeltaLongitude = toSignedInt(getBits(89, 21)); 26 | // AuxMasterDeltaHeight = toSignedInt(getBits(110, 23)); 27 | // } 28 | //} 29 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/core/userServer/handlers/authentication/NtripNoneAuthHandler.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.core.userServer.handlers.authentication; 2 | 3 | import io.netty.channel.ChannelHandlerContext; 4 | import io.netty.channel.SimpleChannelInboundHandler; 5 | import io.netty.handler.codec.http.FullHttpRequest; 6 | import org.dav95s.openNTRIP.commons.Registry; 7 | import org.dav95s.openNTRIP.core.ChannelState; 8 | import org.dav95s.openNTRIP.database.modelsV2.NetworkModel; 9 | import org.dav95s.openNTRIP.protocols.ntrip.NtripResponse; 10 | 11 | public class NtripNoneAuthHandler extends SimpleChannelInboundHandler { 12 | 13 | private final Registry registry; 14 | 15 | public NtripNoneAuthHandler(Registry registry) { 16 | this.registry = registry; 17 | } 18 | 19 | @Override 20 | protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest msg) throws Exception { 21 | ctx.writeAndFlush(NtripResponse.OK_MESSAGE); 22 | 23 | String networkName = ctx.channel().attr(ChannelState.NETWORK).get(); 24 | NetworkModel networkModel = registry.networks.get(networkName); 25 | networkModel.channelGroup.add(ctx.channel()); 26 | 27 | ctx.channel().attr(ChannelState.AUTHENTICATION).set(true); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/database/modelsV2/NetworkModel.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.database.modelsV2; 2 | 3 | import io.netty.channel.group.ChannelGroup; 4 | import io.netty.channel.group.ChannelMatcher; 5 | import io.netty.channel.group.DefaultChannelGroup; 6 | import io.netty.util.concurrent.GlobalEventExecutor; 7 | import org.dav95s.openNTRIP.commons.Message; 8 | import org.dav95s.openNTRIP.protocols.ntrip.NetworkType; 9 | 10 | import java.util.ArrayList; 11 | 12 | public class NetworkModel { 13 | public final ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); 14 | public final String identifier; 15 | public final NetworkType type; 16 | 17 | public NetworkModel(String identifier, String type) { 18 | this.identifier = identifier; 19 | this.type = NetworkType.valueOf(type); 20 | } 21 | public NetworkModel(String identifier, NetworkType type) { 22 | this.identifier = identifier; 23 | this.type = type; 24 | } 25 | 26 | //todo need remove cycle and unwrap array in outbound handler 27 | public synchronized void write(ArrayList messages, ChannelMatcher matcher) { 28 | for (Message message : messages) { 29 | channelGroup.write(message, matcher); 30 | } 31 | channelGroup.flush(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/test/java/org/dav95s/openNTRIP/protocols/rtcm/MSG1026Test.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.protocols.rtcm; 2 | 3 | import org.dav95s.openNTRIP.utils.binaryParse.BitUtils; 4 | import org.dav95s.openNTRIP.protocols.rtcm.messages.MSG1026; 5 | import org.junit.Assert; 6 | import org.junit.Test; 7 | 8 | import java.util.Arrays; 9 | 10 | public class MSG1026Test { 11 | @Test 12 | public void maxValues() { 13 | 14 | MSG1026 msg1026 = new MSG1026(); 15 | msg1026.setSystemIdentificationNumber(255); 16 | msg1026.setProjectionType(11); 17 | msg1026.setLaFO(90); 18 | msg1026.setLoFO(180); 19 | msg1026.setLaSP1(90); 20 | msg1026.setLaSP2(90); 21 | msg1026.setEFO(68719476.735); 22 | msg1026.setNFO(17179869.182); 23 | byte[] result1 = msg1026.getBytes(); 24 | MSG1026 msg10261 = new MSG1026(result1); 25 | byte[] result2 = msg10261.getBytes(); 26 | System.out.println(Arrays.toString(result1)); 27 | System.out.println(Arrays.toString(result2)); 28 | System.out.println(msg1026.toString()); 29 | System.out.println(msg10261.toString()); 30 | System.out.println(new BitUtils(result1).toString(' ')); 31 | System.out.println(new BitUtils(result2).toString(' ')); 32 | Assert.assertArrayEquals(result1, result2); 33 | } 34 | 35 | } -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/commons/Registry.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.commons; 2 | 3 | import org.dav95s.openNTRIP.database.modelsV2.NetworkModel; 4 | import org.dav95s.openNTRIP.database.repository.NetworkRepository; 5 | import org.dav95s.openNTRIP.utils.ServerProperties; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | import java.util.ArrayList; 10 | import java.util.Map; 11 | import java.util.concurrent.ConcurrentHashMap; 12 | 13 | public class Registry { 14 | private final static Logger logger = LoggerFactory.getLogger(Registry.class.getName()); 15 | 16 | private final NetworkRepository networkRepository; 17 | 18 | public final Map networks = new ConcurrentHashMap<>(); 19 | 20 | 21 | public Registry(ServerProperties serverProperties, NetworkRepository networkRepository) { 22 | this.networkRepository = networkRepository; 23 | updateNetworks(); 24 | } 25 | 26 | public void updateNetworks() { 27 | ArrayList allReferenceStation = this.networkRepository.getAllReferenceStations(); 28 | ArrayList allNetworks = this.networkRepository.getAllNetworks(); 29 | allReferenceStation.forEach(network -> networks.putIfAbsent(network.identifier, network)); 30 | allNetworks.forEach(network -> networks.putIfAbsent(network.identifier, network)); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/test/java/org/dav95s/openNTRIP/protocols/rtcm/MSG1027Test.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.protocols.rtcm; 2 | 3 | import org.dav95s.openNTRIP.utils.binaryParse.BitUtils; 4 | import org.dav95s.openNTRIP.protocols.rtcm.messages.MSG1027; 5 | import org.junit.Assert; 6 | import org.junit.Test; 7 | 8 | import java.util.Arrays; 9 | 10 | public class MSG1027Test { 11 | @Test 12 | public void maxValues() { 13 | 14 | MSG1027 msg1027 = new MSG1027(); 15 | msg1027.setSystemIdentificationNumber(255); 16 | msg1027.setProjectionType(11); 17 | msg1027.setLaPC(90); 18 | msg1027.setLoPC(180); 19 | msg1027.setAzIL(360); 20 | msg1027.setRectifiedToSkew(360.369098741); 21 | msg1027.setSILppm(1.003737418); 22 | msg1027.setEPC(68719476.735); 23 | msg1027.setNPC(17179869.183); 24 | 25 | byte[] result1 = msg1027.getBytes(); 26 | MSG1027 msg10271 = new MSG1027(result1); 27 | byte[] result2 = msg10271.getBytes(); 28 | 29 | System.out.println(Arrays.toString(result1)); 30 | System.out.println(Arrays.toString(result2)); 31 | System.out.println(msg1027.toString()); 32 | System.out.println(msg10271.toString()); 33 | System.out.println(new BitUtils(result1).toString(' ')); 34 | System.out.println(new BitUtils(result2).toString(' ')); 35 | Assert.assertArrayEquals(result1, result2); 36 | } 37 | } -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/database/modelsV2/MountpointModel.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.database.modelsV2; 2 | 3 | import org.dav95s.openNTRIP.database.models.assets.Authenticator; 4 | 5 | public class MountpointModel { 6 | public final int id; 7 | public final String name; 8 | public final String format; 9 | public final String network; 10 | public final boolean nmea; 11 | public final boolean solution; 12 | public final String compression; 13 | public final Authenticator authenticator; 14 | public final boolean fee; 15 | 16 | public MountpointModel(int id, String name, String format, String network, boolean nmea, boolean solution, String compression, String authenticator, boolean fee) { 17 | this.id = id; 18 | this.name = name; 19 | this.format = format; 20 | this.network = network; 21 | this.nmea = nmea; 22 | this.solution = solution; 23 | this.compression = compression; 24 | this.fee = fee; 25 | 26 | 27 | switch (authenticator) { 28 | case "B": 29 | case "Basic": 30 | this.authenticator = Authenticator.Basic; 31 | break; 32 | case "D": 33 | case "Digest": 34 | this.authenticator = Authenticator.Digest; 35 | break; 36 | default: 37 | this.authenticator = Authenticator.None; 38 | break; 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/protocols/rtcm/messages/MSG1007.java: -------------------------------------------------------------------------------- 1 | //package org.dav95s.openNTRIP.Tools.RTCM; 2 | // 3 | //public class MSG1007 extends RTCM { 4 | // 5 | // private int antennaID; 6 | // private int messageNumber; 7 | // private int stationID; 8 | // private int descriptorCounter; 9 | // private String antennaDescriptor; 10 | // 11 | // public MSG1007(byte[] msg) { 12 | // super.rawMsg = msg; 13 | // 14 | // super.setToBinaryBuffer(msg); 15 | // 16 | // messageNumber = toUnsignedInt(getBits(16, 12)); 17 | // stationID = toUnsignedInt(getBits(28, 12)); 18 | // descriptorCounter = toUnsignedInt(getBits(40, 8)); 19 | // antennaDescriptor = ""; 20 | // for (int i = 0; i < descriptorCounter; i++) { 21 | // antennaDescriptor += (char) toUnsignedInt(getBits(48 + (i * 8), 8)); 22 | // } 23 | // int pointer = 48 + (descriptorCounter * 8); 24 | // antennaID = toUnsignedInt(getBits(pointer, 8)); 25 | // 26 | // } 27 | // 28 | // public int getAntennaID() { 29 | // return antennaID; 30 | // } 31 | // 32 | // public int getMessageNumber() { 33 | // return messageNumber; 34 | // } 35 | // 36 | // public int getStationID() { 37 | // return stationID; 38 | // } 39 | // 40 | // public int getDescriptorCounter() { 41 | // return descriptorCounter; 42 | // } 43 | // 44 | // public String getAntennaDescriptor() { 45 | // return antennaDescriptor; 46 | // } 47 | //} 48 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/TransportTypeHolder.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP; 2 | 3 | import io.netty.channel.EventLoopGroup; 4 | import io.netty.channel.ServerChannel; 5 | import io.netty.channel.epoll.EpollEventLoopGroup; 6 | import io.netty.channel.epoll.EpollServerSocketChannel; 7 | import io.netty.channel.nio.NioEventLoopGroup; 8 | import io.netty.channel.socket.nio.NioServerSocketChannel; 9 | import org.dav95s.openNTRIP.utils.ServerProperties; 10 | 11 | public class TransportTypeHolder { 12 | public final EventLoopGroup bossGroup; 13 | public final EventLoopGroup workerGroup; 14 | public final Class channelClass; 15 | public final boolean epollEnabled; 16 | 17 | public TransportTypeHolder(ServerProperties serverProperties) { 18 | this(serverProperties.getBoolProperty("enable.native.epoll.transport"), 19 | serverProperties.getIntProperty("server.worker.threads", Runtime.getRuntime().availableProcessors() * 2)); 20 | } 21 | 22 | private TransportTypeHolder(boolean enableNativeEpoll, int workerThreads) { 23 | epollEnabled = enableNativeEpoll; 24 | if (enableNativeEpoll) { 25 | bossGroup = new EpollEventLoopGroup(1); 26 | workerGroup = new EpollEventLoopGroup(workerThreads); 27 | channelClass = EpollServerSocketChannel.class; 28 | } else { 29 | bossGroup = new NioEventLoopGroup(1); 30 | workerGroup = new NioEventLoopGroup(workerThreads); 31 | channelClass = NioServerSocketChannel.class; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/test/java/org/dav95s/openNTRIP/protocols/rtcm/MSG1023Test.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.protocols.rtcm; 2 | 3 | import org.dav95s.openNTRIP.commons.Message; 4 | import org.dav95s.openNTRIP.protocols.rtcm.messages.MSG1023; 5 | import org.junit.Assert; 6 | import org.junit.Test; 7 | 8 | import java.io.FileInputStream; 9 | import java.io.IOException; 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | import java.util.stream.Collectors; 13 | 14 | public class MSG1023Test { 15 | @Test 16 | public void decodeEncode() { 17 | 18 | String file = "src/test/resources/1023.rtcm3"; 19 | try (FileInputStream input = new FileInputStream(file)) { 20 | byte[] bytes = input.readAllBytes(); 21 | Rtcm3Separator separator = new Rtcm3Separator(); 22 | ArrayList separate = separator.separate(bytes); 23 | 24 | List collect1023 = separate.stream().filter(msg -> msg.name.equals("1023")).collect(Collectors.toList()); 25 | Assert.assertTrue(collect1023.size() > 0); 26 | 27 | for (Message msg1023 : collect1023){ 28 | MSG1023 msg1 = new MSG1023(msg1023.bytes); 29 | byte[] bytes1 = msg1.getBytes(); 30 | MSG1023 msg2 = new MSG1023(bytes1); 31 | byte[] bytes2 = msg2.getBytes(); 32 | Assert.assertArrayEquals(msg1023.bytes, bytes1); 33 | Assert.assertArrayEquals(msg1023.bytes, bytes2); 34 | } 35 | } catch (IOException e) { 36 | e.printStackTrace(); 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /src/test/java/org/dav95s/openNTRIP/protocols/rtcm/MSG1006Test.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.protocols.rtcm; 2 | 3 | import org.dav95s.openNTRIP.commons.Message; 4 | import org.dav95s.openNTRIP.protocols.rtcm.messages.MSG1006; 5 | import org.junit.Assert; 6 | import org.junit.Test; 7 | 8 | import java.io.File; 9 | import java.io.FileInputStream; 10 | import java.io.IOException; 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | import java.util.stream.Collectors; 14 | 15 | public class MSG1006Test { 16 | String path = "src/test/resources/RTCM_32"; 17 | 18 | @Test 19 | public void start() { 20 | 21 | File file = new File(path); 22 | 23 | try (FileInputStream input = new FileInputStream(file)) { 24 | byte[] bytes = input.readAllBytes(); 25 | Rtcm3Separator separator = new Rtcm3Separator(); 26 | ArrayList separate = separator.separate(bytes); 27 | 28 | List collect1006 = separate.stream().filter(msg -> msg.name.equals("1006")).collect(Collectors.toList()); 29 | Assert.assertTrue(collect1006.size() > 0); 30 | 31 | for (Message msg1006 : collect1006){ 32 | MSG1006 msg = new MSG1006(bytes); 33 | byte[] bytes2 = msg.getBytes(); 34 | MSG1006 msg2 = new MSG1006(bytes2); 35 | byte[] bytes3 = msg2.getBytes(); 36 | Assert.assertArrayEquals(bytes2, bytes3); 37 | } 38 | 39 | } catch (IOException e) { 40 | e.printStackTrace(); 41 | } 42 | 43 | } 44 | 45 | 46 | } -------------------------------------------------------------------------------- /src/test/java/org/dav95s/openNTRIP/protocols/rtcm/MSG1025Test.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.protocols.rtcm; 2 | 3 | import org.dav95s.openNTRIP.commons.Message; 4 | import org.dav95s.openNTRIP.protocols.rtcm.messages.MSG1025; 5 | import org.junit.Assert; 6 | import org.junit.Test; 7 | 8 | import java.io.FileInputStream; 9 | import java.io.IOException; 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | import java.util.stream.Collectors; 13 | 14 | public class MSG1025Test { 15 | 16 | @Test 17 | public void decodeEncode() { 18 | String file = "src/test/resources/1025.rtcm3"; 19 | try (FileInputStream input = new FileInputStream(file)) { 20 | byte[] bytes = input.readAllBytes(); 21 | Rtcm3Separator separator = new Rtcm3Separator(); 22 | ArrayList separate = separator.separate(bytes); 23 | 24 | List collect1025 = separate.stream().filter(msg -> msg.name.equals("1025")).collect(Collectors.toList()); 25 | Assert.assertTrue(collect1025.size() > 0); 26 | 27 | for (Message msg1025 : collect1025){ 28 | MSG1025 msg1 = new MSG1025(msg1025.bytes); 29 | byte[] bytes1 = msg1.getBytes(); 30 | MSG1025 msg2 = new MSG1025(bytes1); 31 | byte[] bytes2 = msg2.getBytes(); 32 | Assert.assertArrayEquals(msg1025.bytes, bytes1); 33 | Assert.assertArrayEquals(msg1025.bytes, bytes2); 34 | } 35 | } catch (IOException e) { 36 | e.printStackTrace(); 37 | } 38 | } 39 | 40 | } -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/database/repository/UserRepository.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.database.repository; 2 | 3 | import org.dav95s.openNTRIP.database.DataSource; 4 | import org.dav95s.openNTRIP.database.modelsV2.UserModel; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | import java.sql.Connection; 9 | import java.sql.PreparedStatement; 10 | import java.sql.ResultSet; 11 | import java.sql.SQLException; 12 | 13 | public class UserRepository { 14 | final static private Logger logger = LoggerFactory.getLogger(UserRepository.class.getName()); 15 | 16 | public UserModel getUserByUsername(String username) { 17 | String sql = "SELECT `id`,`username`, `password`, `email` FROM users WHERE `username` = ?"; 18 | 19 | try (Connection con = DataSource.getConnection(); 20 | PreparedStatement statement = con.prepareStatement(sql)) { 21 | 22 | statement.setString(1, username); 23 | 24 | try (ResultSet rs = statement.executeQuery()) { 25 | if (rs.next()) { 26 | return new UserModel( 27 | rs.getInt("id"), 28 | rs.getString("username"), 29 | rs.getString("password"), 30 | rs.getString("email") 31 | ); 32 | } else { 33 | return null; 34 | } 35 | } 36 | 37 | } catch (SQLException e) { 38 | logger.error("SQL Error", e); 39 | return null; 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/ServerLauncher.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP; 2 | 3 | import org.dav95s.openNTRIP.commons.GlobalStats; 4 | import org.dav95s.openNTRIP.commons.Registry; 5 | import org.dav95s.openNTRIP.core.userServer.NtripServer; 6 | import org.dav95s.openNTRIP.core.stationsServer.ReferenceStationServer; 7 | import org.dav95s.openNTRIP.database.repository.NetworkRepository; 8 | import org.dav95s.openNTRIP.database.repository.ReferenceStationRepository; 9 | import org.dav95s.openNTRIP.utils.ServerProperties; 10 | 11 | public class ServerLauncher { 12 | private final ServerProperties serverProperties; 13 | private final Registry registry; 14 | private final GlobalStats stats; 15 | private final ReferenceStationServer referenceStationServer; 16 | private final NtripServer ntripServer; 17 | 18 | private ServerLauncher(ServerProperties serverProperties) { 19 | this.serverProperties = serverProperties; 20 | this.registry = new Registry(serverProperties, new NetworkRepository()); 21 | this.stats = new GlobalStats(serverProperties); 22 | 23 | TransportTypeHolder transportType = new TransportTypeHolder(serverProperties); 24 | 25 | this.referenceStationServer = new ReferenceStationServer(serverProperties, registry, transportType, new ReferenceStationRepository()); 26 | this.ntripServer = new NtripServer(serverProperties, registry, transportType); 27 | } 28 | 29 | private void start() { 30 | //start servers 31 | new Thread(referenceStationServer).start(); 32 | new Thread(ntripServer).start(); 33 | } 34 | 35 | public static void main(String[] args) { 36 | ServerProperties serverProperties = new ServerProperties(); 37 | new ServerLauncher(serverProperties).start(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/database/models/ServerModel.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.database.models; 2 | 3 | public class ServerModel { 4 | int id; 5 | int port; 6 | 7 | public void read() { 8 | String sql = "SELECT * FROM `reference_stations` WHERE `id` = ?"; 9 | 10 | // try (Connection con = DataSource.getConnection(); 11 | // PreparedStatement statement = con.prepareStatement(sql)) { 12 | // 13 | // statement.setInt(1, id); 14 | // 15 | // try (ResultSet rs = statement.executeQuery()) { 16 | // if (rs.next()) { 17 | // this.name = rs.getString("name"); 18 | // this.identifier = rs.getString("identifier"); 19 | // this.format = rs.getString("format"); 20 | // this.format_details = rs.getString("format_details"); 21 | // this.carrier = rs.getInt("carrier"); 22 | // this.nav_system = rs.getString("nav_system"); 23 | // this.country = rs.getString("country"); 24 | // this.position.lat = (float) rs.getDouble("lat"); 25 | // this.position.lon = (float) rs.getDouble("lon"); 26 | // this.position.altitude = (float) rs.getDouble("alt"); 27 | // this.bitrate = rs.getInt("bitrate"); 28 | // this.misc = rs.getString("misc"); 29 | // this.password = rs.getString("password"); 30 | // this.hz = rs.getInt("hz"); 31 | // return true; 32 | // } else { 33 | // return false; 34 | // } 35 | // } 36 | // } catch (SQLException e) { 37 | // logger.error("SQL Error", e); 38 | // return false; 39 | // } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/test/java/org/dav95s/openNTRIP/users/passwords/BCryptTest.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.users.passwords; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertFalse; 6 | import static org.junit.Assert.assertTrue; 7 | 8 | public class BCryptTest { 9 | 10 | @Test 11 | public void testCompare() { 12 | BCrypt bCrypt = new BCrypt(); 13 | 14 | assertTrue(bCrypt.compare("$2y$12$P07ACb3XmtIvHJXrzhTULeOUAF1Q0zh3STfPpjZTu9z8JVD4580Uu", "password")); 15 | assertTrue(bCrypt.compare("$2a$10$eGYNvSMbYMw2ks818r6HdOlqiPRR1ETqTATsdxWzoO8aug7sxx.mC", "ffaqq")); 16 | assertTrue(bCrypt.compare("$2a$04$YFzshOrWKAZ8iu4gW0/NhOo9B.A1Lnn8k6uzXivraiAKv66ByW1q6", "rqrqrqr1144")); 17 | assertTrue(bCrypt.compare("$2b$10$uayG5HrmJSRK7.gDW9QX7.e9RYM0lwlUbzieDbVCcVrKJ14XFHwx6", "ttt4444ccz")); 18 | assertTrue(bCrypt.compare("$2a$04$AQgn0ch7ZWrrfP8Opq/k8.xazPZcqyvbz/8xf52W69utG9onGhi16", "yyytttqqee4444")); 19 | assertTrue(bCrypt.compare("$2y$12$8TkvffyD05BaK7KGKNDTD.AdvYKs0W6dfoWGvQUmbZy.9kNf0jze6", "")); 20 | 21 | 22 | assertFalse(bCrypt.compare("2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824", "hallo")); 23 | assertFalse(bCrypt.compare("$2y$12$8TkvffyD05BaK7KGKNDTD.AdvYKs0W6dfoWGvQUmbZy.9kNf0jze6", "!2@@#31")); 24 | assertFalse(bCrypt.compare(null, "11313")); 25 | assertFalse(bCrypt.compare(null, null)); 26 | assertFalse(bCrypt.compare("2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824", null)); 27 | 28 | } 29 | 30 | @Test 31 | public void testHash() { 32 | BCrypt bCrypt = new BCrypt(); 33 | 34 | String example = "12asdfasfqwrqwrqwr"; 35 | String hash = bCrypt.hash("12asdfasfqwrqwrqwr"); 36 | assertTrue(bCrypt.compare(hash, example)); 37 | assertFalse(bCrypt.compare(hash, "123123123123")); 38 | } 39 | 40 | } -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/protocols/rtcm/messages/MSG1008.java: -------------------------------------------------------------------------------- 1 | //package org.dav95s.openNTRIP.Tools.RTCM; 2 | // 3 | //public class MSG1008 extends RTCM { 4 | // 5 | // private int antennaID; 6 | // private int messageNumber; 7 | // private int stationID; 8 | // private String antennaDescriptor; 9 | // private String serialNumber; 10 | // 11 | // public MSG1008(byte[] msg) { 12 | // super.rawMsg = msg; 13 | // 14 | // super.setToBinaryBuffer(msg); 15 | // 16 | // messageNumber = toUnsignedInt(getBits(16, 12)); 17 | // stationID = toUnsignedInt(getBits(28, 12)); 18 | // int descriptorCounter = toUnsignedInt(getBits(40, 8)); 19 | // 20 | // /* antennaDescriptor */ 21 | // antennaDescriptor = ""; 22 | // for (int i = 0; i < descriptorCounter; i++) { 23 | // antennaDescriptor += (char) toUnsignedInt(getBits(48 + (i * 8), 8)); 24 | // } 25 | // /* antennaDescriptor */ 26 | // 27 | // int pointer = 48 + (descriptorCounter * 8); //pointer to next 28 | // antennaID = toUnsignedInt(getBits(pointer, 8)); 29 | // 30 | // /* serialNumber */ 31 | // int serialNumberCounter = toUnsignedInt(getBits(pointer + 8, 8)); 32 | // serialNumber = ""; 33 | // for (int i = 0; i < serialNumberCounter; i++) { 34 | // serialNumber += (char) toUnsignedInt(getBits((pointer + 16) + (i * 8), 8)); 35 | // } 36 | // /* serialNumber */ 37 | // 38 | // } 39 | // 40 | // public int getAntennaID() { 41 | // return antennaID; 42 | // } 43 | // 44 | // public int getMessageNumber() { 45 | // return messageNumber; 46 | // } 47 | // 48 | // public int getStationID() { 49 | // return stationID; 50 | // } 51 | // 52 | // public String getAntennaDescriptor() { 53 | // return antennaDescriptor; 54 | // } 55 | // 56 | // public String getSerialNumber() { 57 | // return serialNumber; 58 | // } 59 | //} 60 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/database/models/GridModel.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.database.models; 2 | 3 | import org.dav95s.openNTRIP.crs.gridShift.GeodeticPoint; 4 | import org.dav95s.openNTRIP.database.DataSource; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | import java.sql.Connection; 9 | import java.sql.PreparedStatement; 10 | import java.sql.ResultSet; 11 | import java.sql.SQLException; 12 | import java.util.ArrayList; 13 | 14 | public class GridModel { 15 | static final private Logger logger = LoggerFactory.getLogger(GridModel.class.getName()); 16 | 17 | public ArrayList getAddGeodeticPointByCrsId(int crsId) { 18 | String sql = "SELECT id, ROUND(X(geodetic_point_measured), 9) AS north, ROUND(Y(geodetic_point_measured), 9) AS east, ROUND(X(geodetic_point_from_catalog)-X(geodetic_point_measured), 9) AS dnorth, ROUND(Y(geodetic_point_from_catalog)-Y(geodetic_point_measured), 9) AS deast FROM `crs_grids` WHERE `crs_id` = ?;"; 19 | 20 | try (Connection con = DataSource.getConnection(); 21 | PreparedStatement statement = con.prepareStatement(sql)) { 22 | statement.setInt(1, crsId); 23 | 24 | try (ResultSet rs = statement.executeQuery()) { 25 | ArrayList gridNodes = new ArrayList<>(); 26 | 27 | while (rs.next()) { 28 | GeodeticPoint point = new GeodeticPoint(); 29 | point.id = rs.getLong("id"); 30 | point.north = rs.getDouble("north"); 31 | point.east = rs.getDouble("east"); 32 | point.dNorth = rs.getDouble("dnorth"); 33 | point.dEast = rs.getDouble("deast"); 34 | gridNodes.add(point); 35 | } 36 | return gridNodes; 37 | } 38 | 39 | } catch (SQLException e) { 40 | logger.error("SQL Error", e); 41 | return new ArrayList<>(); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/database/repository/MountpointRepository.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.database.repository; 2 | 3 | import org.dav95s.openNTRIP.database.DataSource; 4 | import org.dav95s.openNTRIP.database.modelsV2.MountpointModel; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | import java.sql.Connection; 9 | import java.sql.PreparedStatement; 10 | import java.sql.ResultSet; 11 | import java.sql.SQLException; 12 | 13 | public class MountpointRepository { 14 | final static private Logger logger = LoggerFactory.getLogger(MountpointRepository.class.getName()); 15 | 16 | public MountpointModel getMountpoint(String name) { 17 | if (name == null || name.isEmpty()) { 18 | return null; 19 | } 20 | 21 | String sql = "SELECT `id`, `name`, `format`, network, nmea, solution, compression, authenticator, fee FROM mountpoints WHERE `name` = ?;"; 22 | 23 | try (Connection con = DataSource.getConnection(); 24 | PreparedStatement statement = con.prepareStatement(sql)) { 25 | 26 | statement.setString(1, name); 27 | 28 | try (ResultSet rs = statement.executeQuery()) { 29 | MountpointModel response; 30 | if (rs.next()) { 31 | response = new MountpointModel( 32 | rs.getInt("id"), 33 | rs.getString("name"), 34 | rs.getString("format"), 35 | rs.getString("network"), 36 | rs.getBoolean("nmea"), 37 | rs.getBoolean("solution"), 38 | rs.getString("compression"), 39 | rs.getString("authenticator"), 40 | rs.getBoolean("fee") 41 | ); 42 | return response; 43 | } else { 44 | return null; 45 | } 46 | } 47 | 48 | } catch (SQLException e) { 49 | logger.error("SQL Error", e); 50 | return null; 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/database/models/UserGroupModel.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.database.models; 2 | 3 | import org.dav95s.openNTRIP.database.DataSource; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | 7 | import java.sql.Connection; 8 | import java.sql.PreparedStatement; 9 | import java.sql.ResultSet; 10 | import java.sql.SQLException; 11 | import java.util.HashSet; 12 | import java.util.Set; 13 | 14 | public class UserGroupModel { 15 | final static private Logger logger = LoggerFactory.getLogger(UserGroupModel.class.getName()); 16 | 17 | private int group_id; 18 | private String name; 19 | private String description; 20 | 21 | public Set readAllGroups() { 22 | String sql = "SELECT * FROM `groups`"; 23 | Set groups = new HashSet<>(); 24 | 25 | try (Connection con = DataSource.getConnection(); 26 | PreparedStatement statement = con.prepareStatement(sql)) { 27 | 28 | try (ResultSet rs = statement.executeQuery()) { 29 | 30 | while (rs.next()) { 31 | UserGroupModel group = new UserGroupModel(); 32 | group.setGroup_id(rs.getInt("id")); 33 | group.setName(rs.getString("name")); 34 | group.setDescription(rs.getString("description")); 35 | groups.add(group); 36 | } 37 | return groups; 38 | } 39 | } catch (SQLException e) { 40 | logger.error("SQL Error", e); 41 | return new HashSet<>(); 42 | } 43 | } 44 | 45 | public int getGroup_id() { 46 | return this.group_id; 47 | } 48 | 49 | public String getName() { 50 | return this.name; 51 | } 52 | 53 | public String getDescription() { 54 | return this.description; 55 | } 56 | 57 | public void setGroup_id(int group_id) { 58 | this.group_id = group_id; 59 | } 60 | 61 | public void setName(String name) { 62 | this.name = name; 63 | } 64 | 65 | public void setDescription(String description) { 66 | this.description = description; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/test/java/SandBox.java: -------------------------------------------------------------------------------- 1 | import org.dav95s.openNTRIP.database.modelsV2.ReferenceStationModel; 2 | import org.dav95s.openNTRIP.database.repository.ReferenceStationRepository; 3 | import org.json.JSONArray; 4 | import org.json.JSONObject; 5 | import org.junit.Test; 6 | 7 | public class SandBox { 8 | 9 | @Test 10 | public void start() { 11 | String json = "{\"type\":\"FeatureCollection\",\"totalFeatures\":1,\"features\":[{\"type\":\"Feature\",\"id\":\"ZKP_LAND_06.239216801\",\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[108820.5,84474.09],[108707.71,84426.3],[108734.23,84359.9],[108763.53,84346.78],[108775.15,84343.76],[108847.13,84381.85],[108843.98,84386.98],[108835.68,84400.32],[108836.44,84401.7],[108856.74,84413.87],[108820.5,84474.09]],[[108803.27,84378.69],[108772.61,84382.61],[108774.15,84394.79],[108805.11,84390.61],[108803.27,84378.69]]]},\"geometry_name\":\"GEOLOC\",\"properties\":{\"KN\":\"78:15:0843201:1008\",\"STATUS\":\"Неизвестно\",\"ADDRESS\":\"г.Санкт-Петербург, проспект Стачек, участок 238, (г.Санкт-Петербург, проспект Стачек, участок 238, (у дома 208))\",\"PERMITTED_USE\":\" Для размещения религиозных объектов\",\"FACT_AREA\":null,\"UPDATED_AREA\":null,\"DECLARED_AREA\":11480,\"RIGHT_KIND\":null,\"P_DATE\":\"22.10.2002\",\"CAD_COST\":12819205.14,\"PREV_KNS\":\"78:8432А:1008\",\"BEFORE_KN\":null,\"HAS_CAD_SURVEY\":\"Да\",\"WAS_RENTED\":\"В аренде\"}}],\"crs\":{\"type\":\"name\",\"properties\":{\"name\":\"urn:ogc:def:crs:EPSG::99781\"}}}"; 12 | JSONObject jsonObject = new JSONObject(json); 13 | 14 | JSONArray jsonArray = jsonObject.getJSONArray("features").getJSONObject(0).getJSONObject("geometry").getJSONArray("coordinates").getJSONArray(0); 15 | for (int i = 0; i < jsonArray.length(); i++) { 16 | JSONArray polygon = jsonArray.getJSONArray(i); 17 | System.out.println(polygon.getDouble(0) + " " + polygon.getDouble(1)); 18 | } 19 | } 20 | 21 | @Test 22 | public void start2(){ 23 | ReferenceStationRepository referenceStationRepository = new ReferenceStationRepository(); 24 | ReferenceStationModel al1 = referenceStationRepository.GetReferenceStationByName("AL2"); 25 | System.out.println(123); 26 | } 27 | } 28 | 29 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/database/repository/NetworkRepository.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.database.repository; 2 | 3 | import org.dav95s.openNTRIP.database.DataSource; 4 | import org.dav95s.openNTRIP.database.modelsV2.NetworkModel; 5 | import org.dav95s.openNTRIP.protocols.ntrip.NetworkType; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | import java.sql.Connection; 10 | import java.sql.PreparedStatement; 11 | import java.sql.ResultSet; 12 | import java.sql.SQLException; 13 | import java.util.ArrayList; 14 | 15 | public class NetworkRepository { 16 | final static private Logger logger = LoggerFactory.getLogger(ReferenceStationRepository.class.getName()); 17 | 18 | public ArrayList getAllNetworks() { 19 | 20 | String sql = "SELECT `type`, `identifier` FROM `networks`"; 21 | 22 | ArrayList networks = new ArrayList<>(); 23 | 24 | try (Connection con = DataSource.getConnection(); 25 | PreparedStatement statement = con.prepareStatement(sql)) { 26 | try (ResultSet rs = statement.executeQuery()) { 27 | while (rs.next()) { 28 | networks.add(new NetworkModel(rs.getString("identifier"), rs.getString("type"))); 29 | } 30 | } 31 | } catch (SQLException e) { 32 | logger.error("SQL Error", e); 33 | return null; 34 | } 35 | return networks; 36 | } 37 | 38 | public ArrayList getAllReferenceStations() { 39 | String sql = "SELECT `name` FROM `reference_stations`"; 40 | 41 | ArrayList networks = new ArrayList<>(); 42 | 43 | try (Connection con = DataSource.getConnection(); 44 | PreparedStatement statement = con.prepareStatement(sql)) { 45 | try (ResultSet rs = statement.executeQuery()) { 46 | while (rs.next()) { 47 | networks.add(new NetworkModel(rs.getString("name"), NetworkType.STR)); 48 | } 49 | } 50 | return networks; 51 | } catch (SQLException e) { 52 | logger.error("SQL Error", e); 53 | return null; 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/core/BaseServer.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.core; 2 | 3 | import io.netty.bootstrap.ServerBootstrap; 4 | import io.netty.channel.*; 5 | import io.netty.channel.socket.SocketChannel; 6 | import org.dav95s.openNTRIP.TransportTypeHolder; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | 10 | public abstract class BaseServer implements Runnable { 11 | 12 | private final static Logger logger = LoggerFactory.getLogger(BaseServer.class.getName()); 13 | protected final int port; 14 | private final TransportTypeHolder transportTypeHolder; 15 | 16 | private Channel channel; 17 | 18 | protected BaseServer(int port, TransportTypeHolder transportTypeHolder) { 19 | this.port = port; 20 | this.transportTypeHolder = transportTypeHolder; 21 | } 22 | 23 | @Override 24 | public void run() { 25 | if (transportTypeHolder.epollEnabled) { 26 | logger.warn("Native epoll transport enabled."); 27 | } 28 | buildServerAndRun( 29 | transportTypeHolder.bossGroup, 30 | transportTypeHolder.workerGroup, 31 | transportTypeHolder.channelClass 32 | ); 33 | } 34 | 35 | private void buildServerAndRun(EventLoopGroup bossGroup, EventLoopGroup workerGroup, 36 | Class channelClass) { 37 | 38 | ServerBootstrap b = new ServerBootstrap(); 39 | try { 40 | b.group(bossGroup, workerGroup) 41 | .channel(channelClass) 42 | .childOption(ChannelOption.SO_KEEPALIVE, true) 43 | .childHandler(getChannelInitializer()); 44 | 45 | ChannelFuture channelFuture = b.bind(port).sync(); 46 | 47 | this.channel = channelFuture.channel(); 48 | this.channel.closeFuture().sync(); 49 | } catch (Exception e) { 50 | logger.error("", e); 51 | } finally { 52 | bossGroup.shutdownGracefully(); 53 | workerGroup.shutdownGracefully(); 54 | } 55 | } 56 | 57 | protected abstract ChannelInitializer getChannelInitializer(); 58 | 59 | public void stop() { 60 | if (channel != null) { 61 | channel.close().awaitUninterruptibly(); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/database/models/SourceTableModel.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.database.models; 2 | 3 | import org.dav95s.openNTRIP.database.DataSource; 4 | 5 | import java.nio.charset.StandardCharsets; 6 | import java.sql.Connection; 7 | import java.sql.PreparedStatement; 8 | import java.sql.ResultSet; 9 | import java.sql.SQLException; 10 | import java.util.ArrayList; 11 | 12 | public class SourceTableModel { 13 | //"SELECT CONCAT('STR', ';', name, ';', identifier, ';', format, ';', format_details, ';', carrier, ';', nav_system, ';', network, ';', country, ';', ROUND(latitude,2), ';', ROUND(longitude,2), ';', nmea, ';', solution, ';', generator, ';', compression, ';', authenticator, ';', fee, ';', bitrate, ';', misc) as `sourcetable` FROM mountpoints WHERE caster_id = ? AND available = ?" 14 | private ArrayList getTable() { 15 | String sql = "SELECT CONCAT_WS(';','STR', name, identifier, format, format_details, carrier, nav_system, network, country, ROUND(latitude,2), ROUND(longitude,2), nmea, solution, generator, compression, authenticator, fee, bitrate, misc) as `sourcetable` FROM mountpoints WHERE available = ?"; 16 | 17 | ArrayList response = new ArrayList<>(); 18 | 19 | try (Connection con = DataSource.getConnection(); 20 | PreparedStatement statement = con.prepareStatement(sql)) { 21 | 22 | statement.setInt(1, 1); 23 | 24 | try (ResultSet rs = statement.executeQuery()) { 25 | while (rs.next()) { 26 | response.add(rs.getString("sourcetable")); 27 | } 28 | } 29 | } catch (SQLException e) { 30 | e.printStackTrace(); 31 | } 32 | return response; 33 | } 34 | 35 | public String getSourcetable() { 36 | ArrayList table = this.getTable(); 37 | String header = "SOURCETABLE 200 OK\r\n" + 38 | "Content-Type: text/html\r\n" + 39 | "Connection: close\r\n"; 40 | 41 | StringBuilder body = new StringBuilder(); 42 | table.forEach((mp) -> { 43 | body.append(mp); 44 | body.append("\r\n"); 45 | }); 46 | body.append("ENDSOURCETABLE\r\n"); 47 | 48 | String bodyString = body.toString(); 49 | header += "Content-Length: " + bodyString.getBytes(StandardCharsets.ISO_8859_1).length + "\r\n\n"; 50 | 51 | return header + bodyString; 52 | } 53 | 54 | public byte[] getBytesSourcetable() { 55 | return getSourcetable().getBytes(StandardCharsets.US_ASCII); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/core/userServer/NtripServer.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.core.userServer; 2 | 3 | import io.netty.channel.ChannelInitializer; 4 | import io.netty.channel.ChannelPipeline; 5 | import io.netty.channel.socket.SocketChannel; 6 | import io.netty.handler.codec.bytes.ByteArrayEncoder; 7 | import io.netty.handler.codec.http.HttpObjectAggregator; 8 | import io.netty.handler.codec.http.HttpRequestDecoder; 9 | import org.dav95s.openNTRIP.TransportTypeHolder; 10 | import org.dav95s.openNTRIP.commons.Registry; 11 | import org.dav95s.openNTRIP.core.BaseServer; 12 | import org.dav95s.openNTRIP.core.userServer.handlers.UserAuthHandler; 13 | import org.dav95s.openNTRIP.database.repository.MountpointRepository; 14 | import org.dav95s.openNTRIP.database.repository.UserRepository; 15 | import org.dav95s.openNTRIP.utils.ServerProperties; 16 | import org.slf4j.Logger; 17 | import org.slf4j.LoggerFactory; 18 | 19 | public class NtripServer extends BaseServer { 20 | private final static Logger logger = LoggerFactory.getLogger(NtripServer.class.getName()); 21 | 22 | MountpointRepository mountpointRepository = new MountpointRepository(); 23 | UserRepository userRepository = new UserRepository(); 24 | 25 | private final ChannelInitializer channelInitializer; 26 | 27 | public NtripServer(ServerProperties serverProperties, Registry registry, TransportTypeHolder transportType) { 28 | super(serverProperties.getIntProperty("ntrip.default.port"), transportType); 29 | 30 | int stationTimeoutSecs = serverProperties.getIntProperty("station.socket.idle.timeout", 0); 31 | 32 | channelInitializer = new ChannelInitializer() { 33 | @Override 34 | protected void initChannel(SocketChannel ch) throws Exception { 35 | ChannelPipeline pipeline = ch.pipeline(); 36 | pipeline.addLast("ByteArrayEncoder", new ByteArrayEncoder()); 37 | pipeline.addLast("HttpInboundHandler", new HttpRequestDecoder()); 38 | pipeline.addLast("HttpObjectAggregator ", new HttpObjectAggregator(2048,true)); 39 | pipeline.addLast("Authentication", new UserAuthHandler(registry, mountpointRepository, userRepository)); 40 | } 41 | }; 42 | 43 | logger.debug("hard.socket.idle.timeout = {}", stationTimeoutSecs); 44 | 45 | logger.info("Plain tcp/ip reference station server port {}.", port); 46 | } 47 | 48 | @Override 49 | protected ChannelInitializer getChannelInitializer() { 50 | return channelInitializer; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/database/models/CrsModel.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.database.models; 2 | 3 | import org.dav95s.openNTRIP.database.DataSource; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | 7 | import java.sql.Connection; 8 | import java.sql.PreparedStatement; 9 | import java.sql.ResultSet; 10 | import java.sql.SQLException; 11 | 12 | public class CrsModel { 13 | static final private Logger logger = LoggerFactory.getLogger(CrsModel.class.getName()); 14 | 15 | int id; 16 | int mountpointId; 17 | String crs; 18 | String geoidPath; 19 | 20 | 21 | String residualGrid; 22 | 23 | public CrsModel(int mountpointId) { 24 | this.mountpointId = mountpointId; 25 | } 26 | 27 | public boolean read() { 28 | String sql = "SELECT * FROM `crs` WHERE `id` = ?"; 29 | 30 | try (Connection con = DataSource.getConnection(); 31 | PreparedStatement statement = con.prepareStatement(sql)) { 32 | 33 | statement.setInt(1, mountpointId); 34 | 35 | try (ResultSet rs = statement.executeQuery()) { 36 | if (rs.next()) { 37 | id = rs.getInt("id"); 38 | crs = rs.getString("crs"); 39 | geoidPath = rs.getString("geoid_path"); 40 | residualGrid = rs.getString("residual_grid"); 41 | return true; 42 | } else { 43 | return false; 44 | } 45 | } 46 | 47 | } catch (SQLException e) { 48 | logger.error("SQL error", e); 49 | return false; 50 | } 51 | } 52 | 53 | public boolean update() { 54 | String sql = "UPDATE `crs` SET `residual_grid`= ? WHERE `id` = ?"; 55 | 56 | try (Connection con = DataSource.getConnection(); 57 | PreparedStatement statement = con.prepareStatement(sql)) { 58 | 59 | statement.setString(1, residualGrid); 60 | statement.setInt(2, id); 61 | 62 | return statement.executeUpdate() > 0; 63 | } catch (SQLException e) { 64 | logger.error("SQL Error", e); 65 | return false; 66 | } 67 | } 68 | 69 | public int getId() { 70 | return id; 71 | } 72 | 73 | public int getMountpointId() { 74 | return mountpointId; 75 | } 76 | 77 | public String getCrs() { 78 | return crs; 79 | } 80 | 81 | public String getGeoidPath() { 82 | return geoidPath; 83 | } 84 | 85 | public String getResidualGrid() { 86 | return residualGrid; 87 | } 88 | 89 | public void setResidualGrid(String residualGrid) { 90 | this.residualGrid = residualGrid; 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/core/stationsServer/ReferenceStationServer.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.core.stationsServer; 2 | 3 | import io.netty.channel.ChannelInitializer; 4 | import io.netty.channel.ChannelPipeline; 5 | import io.netty.channel.socket.SocketChannel; 6 | import io.netty.handler.codec.bytes.ByteArrayDecoder; 7 | import io.netty.handler.codec.bytes.ByteArrayEncoder; 8 | import io.netty.handler.timeout.ReadTimeoutHandler; 9 | import org.dav95s.openNTRIP.TransportTypeHolder; 10 | import org.dav95s.openNTRIP.commons.Registry; 11 | import org.dav95s.openNTRIP.core.BaseServer; 12 | import org.dav95s.openNTRIP.core.stationsServer.handlers.ReferenceStationAuthHandler; 13 | import org.dav95s.openNTRIP.database.repository.ReferenceStationRepository; 14 | import org.dav95s.openNTRIP.utils.ServerProperties; 15 | import org.slf4j.Logger; 16 | import org.slf4j.LoggerFactory; 17 | 18 | public class ReferenceStationServer extends BaseServer { 19 | private final static Logger logger = LoggerFactory.getLogger(ReferenceStationServer.class.getName()); 20 | 21 | private final ChannelInitializer channelInitializer; 22 | 23 | public ReferenceStationServer(ServerProperties serverProperties, Registry registry, 24 | TransportTypeHolder transportType, ReferenceStationRepository referenceStationRepository) { 25 | 26 | super(serverProperties.getIntProperty("station.default.port"), transportType); 27 | 28 | int stationTimeoutSecs = serverProperties.getIntProperty("station.socket.idle.timeout", 0); 29 | 30 | channelInitializer = new ChannelInitializer() { 31 | @Override 32 | protected void initChannel(SocketChannel ch) throws Exception { 33 | ChannelPipeline pipeline = ch.pipeline(); 34 | 35 | //non-sharable handlers 36 | if (stationTimeoutSecs > 0) { 37 | pipeline.addLast(new ReadTimeoutHandler(stationTimeoutSecs)); 38 | } 39 | 40 | pipeline.addLast("ByteArrayEncoder", new ByteArrayEncoder()); 41 | pipeline.addLast("ByteArrayDecoder", new ByteArrayDecoder()); 42 | pipeline.addLast("StationAuthHandler", new ReferenceStationAuthHandler(registry, referenceStationRepository)); 43 | } 44 | }; 45 | 46 | logger.debug("hard.socket.idle.timeout = {}", stationTimeoutSecs); 47 | 48 | logger.info("Plain tcp/ip reference station server port {}.", port); 49 | } 50 | 51 | @Override 52 | public ChannelInitializer getChannelInitializer() { 53 | return channelInitializer; 54 | } 55 | 56 | @Override 57 | public void stop() { 58 | logger.info("Shutting down default server..."); 59 | super.stop(); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/protocols/rtcm/messages/MSG1013.java: -------------------------------------------------------------------------------- 1 | //package org.dav95s.openNTRIP.Tools.RTCM; 2 | // 3 | //public class MSG1013 extends RTCM { 4 | // private int messageNumber; 5 | // private int stationID; 6 | // private int MJD; //Modified Julian Day Number 7 | // private int UTC; //Seconds of Day UTC 8 | // private int LeapSeconds; // Leap Seconds, GPS-UTC 9 | // private Message[] list; 10 | // 11 | // 12 | // public MSG1013(byte[] msg) { 13 | // super.rawMsg = msg; 14 | // super.setToBinaryBuffer(msg); 15 | // 16 | // messageNumber = toUnsignedInt(getBits(16, 12)); 17 | // stationID = toUnsignedInt(getBits(28, 12)); 18 | // MJD = toUnsignedInt(getBits(40, 16)); 19 | // UTC = toUnsignedInt(getBits(56, 17)); 20 | // int messageCounter = toUnsignedInt(getBits(73, 5)); 21 | // list = new Message[messageCounter]; 22 | // LeapSeconds = toUnsignedInt(getBits(78, 8));//86 23 | // 24 | // for (int i = 0; i < messageCounter; i++) { 25 | // int shift = i * 29; 26 | // Message m = new Message(); 27 | // 28 | // m.setMessageID(toUnsignedInt(getBits(89 + shift, 12))); 29 | // m.setSyncFlag(toUnsignedInt(getBits(101 + shift, 1))); 30 | // m.setTransmissionInterval(toUnsignedInt(getBits(102 + shift, 16))); 31 | // 32 | // list[i] = m; 33 | // } 34 | // 35 | // } 36 | // 37 | // public int getMessageNumber() { 38 | // return messageNumber; 39 | // } 40 | // 41 | // public int getStationID() { 42 | // return stationID; 43 | // } 44 | // 45 | // public int getMJD() { 46 | // return MJD; 47 | // } 48 | // 49 | // public int getUTC() { 50 | // return UTC; 51 | // } 52 | // 53 | // public int getLeapSeconds() { 54 | // return LeapSeconds; 55 | // } 56 | // 57 | // public Message[] getList() { 58 | // return list; 59 | // } 60 | // 61 | // public class Message { 62 | // private int MessageID; 63 | // private int SyncFlag; 64 | // private int TransmissionInterval; 65 | // 66 | // public int getMessageID() { 67 | // return MessageID; 68 | // } 69 | // 70 | // public void setMessageID(int messageID) { 71 | // MessageID = messageID; 72 | // } 73 | // 74 | // public int getSyncFlag() { 75 | // return SyncFlag; 76 | // } 77 | // 78 | // public void setSyncFlag(int syncFlag) { 79 | // SyncFlag = syncFlag; 80 | // } 81 | // 82 | // public int getTransmissionInterval() { 83 | // return TransmissionInterval; 84 | // } 85 | // 86 | // public void setTransmissionInterval(int transmissionInterval) { 87 | // TransmissionInterval = transmissionInterval; 88 | // } 89 | // 90 | // } 91 | //} 92 | // 93 | // 94 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/core/stationsServer/handlers/Rtcm3InboundHandler.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.core.stationsServer.handlers; 2 | 3 | import io.netty.channel.ChannelHandlerContext; 4 | import io.netty.channel.SimpleChannelInboundHandler; 5 | import org.dav95s.openNTRIP.commons.Message; 6 | import org.dav95s.openNTRIP.commons.Registry; 7 | import org.dav95s.openNTRIP.core.ChannelState; 8 | import org.dav95s.openNTRIP.core.stationsServer.ReferenceStationChannelMatcher; 9 | import org.dav95s.openNTRIP.database.modelsV2.NetworkModel; 10 | import org.dav95s.openNTRIP.database.modelsV2.ReferenceStationModel; 11 | import org.dav95s.openNTRIP.protocols.rtcm.Rtcm3Separator; 12 | import org.slf4j.Logger; 13 | import org.slf4j.LoggerFactory; 14 | 15 | import java.util.ArrayList; 16 | 17 | public class Rtcm3InboundHandler extends SimpleChannelInboundHandler { 18 | private final static Logger logger = LoggerFactory.getLogger(Rtcm3InboundHandler.class.getName()); 19 | 20 | private final Registry registry; 21 | private final ReferenceStationModel model; 22 | private final ReferenceStationChannelMatcher channelMatcher; 23 | private final Rtcm3Separator separator = new Rtcm3Separator(); 24 | 25 | public Rtcm3InboundHandler(Registry registry, ReferenceStationModel model) { 26 | this.model = model; 27 | this.registry = registry; 28 | this.channelMatcher = new ReferenceStationChannelMatcher(model.name); 29 | } 30 | 31 | int totalLengthBytes = 0; 32 | int totalLengthMessages = 0; 33 | 34 | @Override 35 | protected void channelRead0(ChannelHandlerContext ctx, byte[] bytes) throws Exception { 36 | ReferenceStationModel referenceStationModel = ctx.channel().attr(ChannelState.REFERENCE_STATION_MODEL).get(); 37 | 38 | ArrayList messages = separator.separate(bytes); 39 | 40 | totalLengthBytes += bytes.length; 41 | for (Message msg : messages) { 42 | totalLengthMessages += msg.bytes.length; 43 | } 44 | 45 | logger.debug("Station: " + model.name + " accept " + bytes.length + " bytes, " + " messages " + messages.size()); 46 | logger.debug("Station: " + model.name + " total bytes accepted " + totalLengthBytes + " total parser to " + totalLengthMessages); 47 | 48 | for (String network : referenceStationModel.networks) { 49 | NetworkModel networkModel = registry.networks.get(network); 50 | if (networkModel == null) { 51 | logger.warn("Reference station " + model.name + " has undefined network"); 52 | continue; 53 | } 54 | networkModel.write(messages, channelMatcher); 55 | } 56 | registry.networks.get(referenceStationModel.name).write(messages, channelMatcher); 57 | } 58 | 59 | @Override 60 | public void channelInactive(ChannelHandlerContext ctx) throws Exception { 61 | //registry.removeReferenceStation(ctx.channel().attr(ChannelState.REFERENCE_STATION).get()); 62 | super.channelInactive(ctx); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/core/userServer/handlers/authentication/NtripBasicAuthHandler.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.core.userServer.handlers.authentication; 2 | 3 | import io.netty.channel.ChannelHandlerContext; 4 | import io.netty.channel.SimpleChannelInboundHandler; 5 | import io.netty.handler.codec.http.FullHttpRequest; 6 | import org.dav95s.openNTRIP.commons.Registry; 7 | import org.dav95s.openNTRIP.core.ChannelState; 8 | import org.dav95s.openNTRIP.database.modelsV2.NetworkModel; 9 | import org.dav95s.openNTRIP.database.modelsV2.UserModel; 10 | import org.dav95s.openNTRIP.database.repository.UserRepository; 11 | import org.dav95s.openNTRIP.exception.UserAuthorizationException; 12 | import org.dav95s.openNTRIP.protocols.ntrip.NtripResponse; 13 | import org.dav95s.openNTRIP.users.passwords.BCrypt; 14 | import org.dav95s.openNTRIP.utils.BasicAuthParser; 15 | import org.slf4j.Logger; 16 | import org.slf4j.LoggerFactory; 17 | 18 | public class NtripBasicAuthHandler extends SimpleChannelInboundHandler { 19 | private final static Logger logger = LoggerFactory.getLogger(NtripBasicAuthHandler.class.getName()); 20 | 21 | private final Registry registry; 22 | private final UserRepository userRepository; 23 | 24 | public NtripBasicAuthHandler(Registry registry, UserRepository userRepository) { 25 | this.registry = registry; 26 | this.userRepository = userRepository; 27 | } 28 | 29 | @Override 30 | protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest msg) throws Exception { 31 | 32 | String authorizationString = msg.headers().get("Authorization"); 33 | 34 | BasicAuthParser parser = new BasicAuthParser(authorizationString); 35 | 36 | UserModel userModel = userRepository.getUserByUsername(parser.account); 37 | 38 | if (userModel == null) { 39 | throw new UserAuthorizationException("Bad password!"); 40 | } 41 | 42 | BCrypt bCrypt = new BCrypt(); 43 | 44 | if (bCrypt.compare(userModel.password, parser.password)) { 45 | ctx.writeAndFlush(NtripResponse.OK_MESSAGE); 46 | 47 | String networkName = ctx.channel().attr(ChannelState.NETWORK).get(); 48 | NetworkModel networkModel = registry.networks.get(networkName); 49 | networkModel.channelGroup.add(ctx.channel()); 50 | 51 | ctx.channel().attr(ChannelState.AUTHENTICATION).set(true); 52 | }else { 53 | ctx.channel().attr(ChannelState.AUTHENTICATION).set(false); 54 | } 55 | 56 | } 57 | 58 | @Override 59 | public void channelReadComplete(ChannelHandlerContext ctx) { 60 | ctx.flush(); 61 | } 62 | 63 | @Override 64 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { 65 | if (cause instanceof UserAuthorizationException) { 66 | logger.info("Channel ID:" + ctx.channel().id() + " " + cause.getMessage(), cause); 67 | ctx.writeAndFlush(NtripResponse.BAD_PASSWORD); 68 | ctx.close(); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/test/java/org/dav95s/openNTRIP/protocols/rtcm/MSG1021Test.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.protocols.rtcm; 2 | 3 | import org.dav95s.openNTRIP.commons.Message; 4 | import org.dav95s.openNTRIP.protocols.rtcm.messages.MSG1021; 5 | import org.junit.Assert; 6 | import org.junit.Test; 7 | 8 | import java.io.FileInputStream; 9 | import java.io.IOException; 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | import java.util.stream.Collectors; 13 | 14 | 15 | public class MSG1021Test { 16 | @Test 17 | public void msg1021MaxValues() { 18 | MSG1021 msg1021Max = new MSG1021(); 19 | msg1021Max.setMessageNumber(1021); 20 | msg1021Max.setSourceName("0123456789012345678901234567891"); 21 | msg1021Max.setTargetName("0123456789012345678901234567891"); 22 | msg1021Max.setSystemIdentificationNumber(255); 23 | msg1021Max.setUtilizedTransformationMessageIndicator(10); 24 | msg1021Max.setPlateNumber(31); 25 | msg1021Max.setComputationIndicator(15); 26 | msg1021Max.setHeightIndicator(3); 27 | msg1021Max.setLatValid(90); 28 | msg1021Max.setLonValid(180); 29 | msg1021Max.setdLatValid(9.1); 30 | msg1021Max.setdLonValid(9.1); 31 | msg1021Max.setdX(4194.303); 32 | msg1021Max.setdY(4194.303); 33 | msg1021Max.setdZ(4194.303); 34 | msg1021Max.setRx(42949.67291); 35 | msg1021Max.setRy(42949.67291); 36 | msg1021Max.setRz(42949.67291); 37 | msg1021Max.setdS(167.77215); 38 | msg1021Max.setAs(6386777.215); 39 | msg1021Max.setBs(6383554.431); 40 | msg1021Max.setAt(6386777.215); 41 | msg1021Max.setBt(6383554.431); 42 | msg1021Max.setHorizontalQuality(7); 43 | msg1021Max.setVerticalQuality(7); 44 | 45 | byte[] check1 = msg1021Max.getBytes(); 46 | MSG1021 msg10212 = new MSG1021(check1); 47 | byte[] check2 = msg10212.getBytes(); 48 | 49 | Assert.assertArrayEquals(check1, check2); 50 | } 51 | 52 | @Test 53 | public void decoderEncode() { 54 | String file = "src/test/resources/1021.rtcm3"; 55 | try (FileInputStream input = new FileInputStream(file)) { 56 | byte[] bytes = input.readAllBytes(); 57 | Rtcm3Separator separator = new Rtcm3Separator(); 58 | ArrayList separate = separator.separate(bytes); 59 | 60 | List collect1021 = separate.stream().filter(msg -> msg.name.equals("1021")).collect(Collectors.toList()); 61 | Assert.assertTrue(collect1021.size() > 0); 62 | 63 | for (Message msg1021 : collect1021){ 64 | MSG1021 msg1 = new MSG1021(msg1021.bytes); 65 | byte[] bytes1 = msg1.getBytes(); 66 | MSG1021 msg2 = new MSG1021(bytes1); 67 | byte[] bytes2 = msg2.getBytes(); 68 | Assert.assertArrayEquals(msg1021.bytes, bytes1); 69 | Assert.assertArrayEquals(msg1021.bytes, bytes2); 70 | } 71 | } catch (IOException e) { 72 | e.printStackTrace(); 73 | } 74 | } 75 | 76 | } -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/protocols/rtcm/Rtcm3Separator.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.protocols.rtcm; 2 | 3 | import org.dav95s.openNTRIP.commons.Message; 4 | import org.dav95s.openNTRIP.utils.binaryParse.Crc24q; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | import java.util.ArrayList; 9 | import java.util.Arrays; 10 | import java.util.HashSet; 11 | 12 | public class Rtcm3Separator { 13 | static final private Logger logger = LoggerFactory.getLogger(Rtcm3Separator.class.getName()); 14 | 15 | private static final HashSet rtcm3messages = null; 16 | private final byte PREAMBLE = -45; 17 | 18 | private byte[] tail = null; //residual of the previous message 19 | 20 | public ArrayList separate(byte[] bytes) { 21 | ArrayList messages = new ArrayList<>(); 22 | 23 | if (bytes == null || bytes.length == 0) { 24 | return messages; 25 | } 26 | 27 | if (tail == null) { 28 | if (bytes[0] == PREAMBLE) 29 | return parse(bytes, messages); 30 | } else { 31 | //Concatenation new message with residual of the previous message 32 | byte[] newBytes = new byte[tail.length + bytes.length]; 33 | System.arraycopy(tail, 0, newBytes, 0, tail.length); 34 | System.arraycopy(bytes, 0, newBytes, tail.length, bytes.length); 35 | tail = null; 36 | return parse(newBytes, messages); 37 | } 38 | 39 | return messages; 40 | } 41 | 42 | private ArrayList parse(byte[] bytes, ArrayList messages) { 43 | for (int i = 0; i < bytes.length; i++) { 44 | if (bytes[i] != PREAMBLE) { 45 | continue; 46 | } 47 | 48 | try { 49 | short length = (short) (((bytes[i + 1] & 0xFF) << 8) | (bytes[i + 2] & 0xFF)); 50 | short msgNumb = (short) (((bytes[i + 3] & 0xFF) << 8) | (bytes[i + 4] & 0xFF)); 51 | length = (short) (length & 0x3FF); //cut off reserved bits 52 | msgNumb = (short) (msgNumb >> 4); 53 | 54 | 55 | 56 | if (checkExistsMessageNumber(msgNumb)) { 57 | byte[] msg = new byte[length + 6]; 58 | System.arraycopy(bytes, i, msg, 0, length + 6); 59 | messages.add(new Message(msgNumb, msg)); 60 | i = i + length + 5; //in the next cycle i will be incremented 61 | } 62 | 63 | } catch (IndexOutOfBoundsException e) { 64 | this.tail = Arrays.copyOfRange(bytes, i, bytes.length); 65 | break; 66 | } 67 | } 68 | return messages; 69 | } 70 | 71 | 72 | protected boolean checkCrs(byte[] bytes) { 73 | byte[] crs = Crc24q.crc24q(bytes, bytes.length - 3, 0); 74 | return Arrays.equals(bytes, bytes.length - 3, bytes.length - 1, crs, 0, 2); 75 | } 76 | 77 | protected boolean checkExistsMessageNumber(int nmb) { 78 | return (1001 <= nmb && nmb <= 1039) || (1057 <= nmb && nmb <= 1068) 79 | || (1070 <= nmb && nmb <= 1230) || (4001 <= nmb && nmb <= 4095); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/utils/ServerProperties.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.utils; 2 | 3 | import java.io.InputStream; 4 | import java.nio.file.Files; 5 | import java.nio.file.Path; 6 | import java.nio.file.Paths; 7 | import java.util.Properties; 8 | 9 | public class ServerProperties extends Properties { 10 | public ServerProperties() { 11 | initProperties(Config.SERVER_PROPERTIES_FILENAME); 12 | } 13 | 14 | public ServerProperties(String propertiesFileName) { 15 | initProperties(propertiesFileName); 16 | } 17 | 18 | public ServerProperties(Path propertiesFileNamePath) { 19 | initProperties(propertiesFileNamePath); 20 | } 21 | 22 | private static Path getFileInCurrentDir(String filename) { 23 | return Paths.get(System.getProperty("user.dir"), filename); 24 | } 25 | 26 | public static Path getCurrentDir() { 27 | return Paths.get(System.getProperty("user.dir")); 28 | } 29 | 30 | /** 31 | * First loads properties file from class path after that from current folder. 32 | * So properties file in current folder is always overrides properties in classpath. 33 | * 34 | * @param filePropertiesName - name of properties file, for example "twitter4j.properties" 35 | */ 36 | private void initProperties(String filePropertiesName) { 37 | if (!filePropertiesName.startsWith("/")) { 38 | filePropertiesName = "/" + filePropertiesName; 39 | } 40 | 41 | try (InputStream classPath = ServerProperties.class.getResourceAsStream(filePropertiesName)) { 42 | if (classPath != null) { 43 | load(classPath); 44 | } 45 | } catch (Exception e) { 46 | throw new RuntimeException("Error getting properties file : " + filePropertiesName, e); 47 | } 48 | 49 | Path curDirPath = getFileInCurrentDir(filePropertiesName); 50 | if (Files.exists(curDirPath)) { 51 | try (InputStream curFolder = Files.newInputStream(curDirPath)) { 52 | load(curFolder); 53 | } catch (Exception e) { 54 | throw new RuntimeException("Error getting properties file : " + filePropertiesName, e); 55 | } 56 | } 57 | 58 | } 59 | 60 | private void initProperties(Path path) { 61 | if (Files.exists(path)) { 62 | try (InputStream curFolder = Files.newInputStream(path)) { 63 | load(curFolder); 64 | } catch (Exception e) { 65 | throw new RuntimeException("Error getting properties file : " + path, e); 66 | } 67 | } 68 | } 69 | 70 | public int getIntProperty(String propertyName) { 71 | return ParseUtil.parseInt(getProperty(propertyName)); 72 | } 73 | 74 | public int getIntProperty(String propertyName, int defaultValue) { 75 | if (getProperty(propertyName) == null || "".equals(getProperty(propertyName))) { 76 | return defaultValue; 77 | } 78 | return ParseUtil.parseInt(getProperty(propertyName)); 79 | } 80 | 81 | public boolean getBoolProperty(String propertyName) { 82 | return Boolean.parseBoolean(getProperty(propertyName)); 83 | } 84 | 85 | public long getLongProperty(String propertyName) { 86 | return ParseUtil.parseLong(getProperty(propertyName)); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/database/repository/ReferenceStationRepository.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.database.repository; 2 | 3 | import org.dav95s.openNTRIP.database.DataSource; 4 | import org.dav95s.openNTRIP.database.modelsV2.ReferenceStationModel; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | import java.sql.Connection; 9 | import java.sql.PreparedStatement; 10 | import java.sql.ResultSet; 11 | import java.sql.SQLException; 12 | import java.util.ArrayList; 13 | 14 | public class ReferenceStationRepository { 15 | final static private Logger logger = LoggerFactory.getLogger(ReferenceStationRepository.class.getName()); 16 | 17 | public ReferenceStationModel GetReferenceStationByName(String name) { 18 | String sql = "SELECT `id`, `name`, `format`, `country`, `lat`, `lon`, `alt`, `password`, `hz`, " + 19 | "(SELECT GROUP_CONCAT(network_name) FROM network_stations_mapping WHERE station_name = NAME) AS networks " + 20 | "FROM `reference_stations` " + 21 | "WHERE `name` = ?"; 22 | 23 | try (Connection con = DataSource.getConnection(); 24 | PreparedStatement statement = con.prepareStatement(sql)) { 25 | 26 | statement.setString(1, name); 27 | 28 | try (ResultSet rs = statement.executeQuery()) { 29 | if (rs.next()) { 30 | return new ReferenceStationModel( 31 | rs.getInt("id"), 32 | rs.getString("name"), 33 | rs.getString("format"), 34 | rs.getDouble("lat"), 35 | rs.getDouble("lon"), 36 | rs.getDouble("alt"), 37 | rs.getString("password"), 38 | rs.getInt("hz"), 39 | rs.getString("networks").split(",") 40 | ); 41 | } else { 42 | return null; 43 | } 44 | } 45 | } catch (SQLException e) { 46 | logger.error("SQL Error", e); 47 | return null; 48 | } 49 | } 50 | 51 | public ArrayList GetNetworksByReferenceStation(String name) { 52 | String sql = "SELECT `network_name` FROM `network_stations_mapping` WHERE station_name = ?"; 53 | 54 | ArrayList networks = new ArrayList<>(); 55 | 56 | try (Connection con = DataSource.getConnection(); 57 | PreparedStatement statement = con.prepareStatement(sql)) { 58 | 59 | statement.setString(1, name); 60 | 61 | try (ResultSet rs = statement.executeQuery()) { 62 | while (rs.next()) { 63 | networks.add(rs.getString("network_name")); 64 | } 65 | } 66 | } catch (SQLException e) { 67 | logger.error("SQL Error", e); 68 | return null; 69 | } 70 | return networks; 71 | } 72 | 73 | public boolean updateOnlineStatus(String name, boolean status) { 74 | String sql = "UPDATE `reference_stations` SET `is_online` = ? WHERE `name` = ?"; 75 | 76 | 77 | try (Connection con = DataSource.getConnection(); 78 | PreparedStatement statement = con.prepareStatement(sql)) { 79 | 80 | statement.setBoolean(1, status); 81 | statement.setString(2, name); 82 | 83 | return statement.executeUpdate() > 0; 84 | 85 | } catch (SQLException e) { 86 | logger.error("SQL Error", e); 87 | return false; 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/utils/binaryParse/Crc24q.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.utils.binaryParse; 2 | 3 | public class Crc24q { 4 | private static final int[] crc24 = new int[]{ 5 | 0x000000, 0x864CFB, 0x8AD50D, 0x0C99F6, 0x93E6E1, 0x15AA1A, 0x1933EC, 0x9F7F17, 6 | 0xA18139, 0x27CDC2, 0x2B5434, 0xAD18CF, 0x3267D8, 0xB42B23, 0xB8B2D5, 0x3EFE2E, 7 | 0xC54E89, 0x430272, 0x4F9B84, 0xC9D77F, 0x56A868, 0xD0E493, 0xDC7D65, 0x5A319E, 8 | 0x64CFB0, 0xE2834B, 0xEE1ABD, 0x685646, 0xF72951, 0x7165AA, 0x7DFC5C, 0xFBB0A7, 9 | 0x0CD1E9, 0x8A9D12, 0x8604E4, 0x00481F, 0x9F3708, 0x197BF3, 0x15E205, 0x93AEFE, 10 | 0xAD50D0, 0x2B1C2B, 0x2785DD, 0xA1C926, 0x3EB631, 0xB8FACA, 0xB4633C, 0x322FC7, 11 | 0xC99F60, 0x4FD39B, 0x434A6D, 0xC50696, 0x5A7981, 0xDC357A, 0xD0AC8C, 0x56E077, 12 | 0x681E59, 0xEE52A2, 0xE2CB54, 0x6487AF, 0xFBF8B8, 0x7DB443, 0x712DB5, 0xF7614E, 13 | 0x19A3D2, 0x9FEF29, 0x9376DF, 0x153A24, 0x8A4533, 0x0C09C8, 0x00903E, 0x86DCC5, 14 | 0xB822EB, 0x3E6E10, 0x32F7E6, 0xB4BB1D, 0x2BC40A, 0xAD88F1, 0xA11107, 0x275DFC, 15 | 0xDCED5B, 0x5AA1A0, 0x563856, 0xD074AD, 0x4F0BBA, 0xC94741, 0xC5DEB7, 0x43924C, 16 | 0x7D6C62, 0xFB2099, 0xF7B96F, 0x71F594, 0xEE8A83, 0x68C678, 0x645F8E, 0xE21375, 17 | 0x15723B, 0x933EC0, 0x9FA736, 0x19EBCD, 0x8694DA, 0x00D821, 0x0C41D7, 0x8A0D2C, 18 | 0xB4F302, 0x32BFF9, 0x3E260F, 0xB86AF4, 0x2715E3, 0xA15918, 0xADC0EE, 0x2B8C15, 19 | 0xD03CB2, 0x567049, 0x5AE9BF, 0xDCA544, 0x43DA53, 0xC596A8, 0xC90F5E, 0x4F43A5, 20 | 0x71BD8B, 0xF7F170, 0xFB6886, 0x7D247D, 0xE25B6A, 0x641791, 0x688E67, 0xEEC29C, 21 | 0x3347A4, 0xB50B5F, 0xB992A9, 0x3FDE52, 0xA0A145, 0x26EDBE, 0x2A7448, 0xAC38B3, 22 | 0x92C69D, 0x148A66, 0x181390, 0x9E5F6B, 0x01207C, 0x876C87, 0x8BF571, 0x0DB98A, 23 | 0xF6092D, 0x7045D6, 0x7CDC20, 0xFA90DB, 0x65EFCC, 0xE3A337, 0xEF3AC1, 0x69763A, 24 | 0x578814, 0xD1C4EF, 0xDD5D19, 0x5B11E2, 0xC46EF5, 0x42220E, 0x4EBBF8, 0xC8F703, 25 | 0x3F964D, 0xB9DAB6, 0xB54340, 0x330FBB, 0xAC70AC, 0x2A3C57, 0x26A5A1, 0xA0E95A, 26 | 0x9E1774, 0x185B8F, 0x14C279, 0x928E82, 0x0DF195, 0x8BBD6E, 0x872498, 0x016863, 27 | 0xFAD8C4, 0x7C943F, 0x700DC9, 0xF64132, 0x693E25, 0xEF72DE, 0xE3EB28, 0x65A7D3, 28 | 0x5B59FD, 0xDD1506, 0xD18CF0, 0x57C00B, 0xC8BF1C, 0x4EF3E7, 0x426A11, 0xC426EA, 29 | 0x2AE476, 0xACA88D, 0xA0317B, 0x267D80, 0xB90297, 0x3F4E6C, 0x33D79A, 0xB59B61, 30 | 0x8B654F, 0x0D29B4, 0x01B042, 0x87FCB9, 0x1883AE, 0x9ECF55, 0x9256A3, 0x141A58, 31 | 0xEFAAFF, 0x69E604, 0x657FF2, 0xE33309, 0x7C4C1E, 0xFA00E5, 0xF69913, 0x70D5E8, 32 | 0x4E2BC6, 0xC8673D, 0xC4FECB, 0x42B230, 0xDDCD27, 0x5B81DC, 0x57182A, 0xD154D1, 33 | 0x26359F, 0xA07964, 0xACE092, 0x2AAC69, 0xB5D37E, 0x339F85, 0x3F0673, 0xB94A88, 34 | 0x87B4A6, 0x01F85D, 0x0D61AB, 0x8B2D50, 0x145247, 0x921EBC, 0x9E874A, 0x18CBB1, 35 | 0xE37B16, 0x6537ED, 0x69AE1B, 0xEFE2E0, 0x709DF7, 0xF6D10C, 0xFA48FA, 0x7C0401, 36 | 0x42FA2F, 0xC4B6D4, 0xC82F22, 0x4E63D9, 0xD11CCE, 0x575035, 0x5BC9C3, 0xDD8538}; 37 | 38 | public static byte[] crc24q(byte[] buf, int len, int crc) { 39 | for (int i = 0; i < len; i++) { 40 | crc = ((crc << 8) & 0xFFFFFF) ^ crc24[(crc >> 16) ^ (buf[i] & 0xFF)]; 41 | } 42 | byte[] result = new byte[3]; 43 | 44 | result[0] = (byte) (crc >> 16); 45 | result[1] = (byte) (crc >> 8); 46 | result[2] = (byte) (crc); 47 | 48 | return result; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/protocols/rtcm/messages/MSG1017.java: -------------------------------------------------------------------------------- 1 | //package org.dav95s.openNTRIP.Tools.RTCM; 2 | // 3 | //public class MSG1017 extends RTCM { 4 | // private int messageNumber; 5 | // private int NetworkID; 6 | // private int SubnetworkID; 7 | // private int TOW; //GPS Epoch Time (GPS TOW) 8 | // private boolean MultipleMessageIndicator; 9 | // private int MasterStationID; 10 | // private int AuxiliaryStationID; 11 | // 12 | // private GPS[] list; 13 | // 14 | // 15 | // public MSG1017(byte[] msg) { 16 | // super.rawMsg = msg; 17 | // super.setToBinaryBuffer(msg); 18 | // 19 | // messageNumber = toUnsignedInt(getBits(16, 12)); 20 | // NetworkID = toUnsignedInt(getBits(28, 8)); 21 | // SubnetworkID = toUnsignedInt(getBits(36, 4)); 22 | // TOW = toUnsignedInt(getBits(40, 23)); 23 | // MultipleMessageIndicator = binaryBuffer.charAt(63) == BIT1; 24 | // MasterStationID = toUnsignedInt(getBits(64, 12)); 25 | // AuxiliaryStationID = toUnsignedInt(getBits(76, 12)); 26 | // int gpsCounter = toUnsignedInt(getBits(88, 4)); 27 | // for (int i = 0; i < gpsCounter; i++) { 28 | // int shift = i * 53; 29 | // GPS g = new GPS(); 30 | // 31 | // g.setID(toUnsignedInt(getBits(92, 6))); 32 | // g.setAmbiguityStatusFlag(toUnsignedInt(getBits(98, 2))); 33 | // g.setNonSyncCount(toUnsignedInt(getBits(100, 3))); 34 | // g.setGeometricCarrierPhaseCorrectionDifference(toUnsignedInt(getBits(103, 17))); 35 | // g.setIODE(toUnsignedInt(getBits(120, 8))); 36 | // g.setIonosphericCarrierPhaseCorrectionDifference(toSignedInt(getBits(128, 17))); 37 | // 38 | // } 39 | // } 40 | // 41 | // public class GPS { 42 | // private int ID; 43 | // private int AmbiguityStatusFlag; 44 | // private int NonSyncCount; 45 | // private int GeometricCarrierPhaseCorrectionDifference; 46 | // private int IODE; 47 | // private int IonosphericCarrierPhaseCorrectionDifference; 48 | // 49 | // public int getID() { 50 | // return ID; 51 | // } 52 | // 53 | // public void setID(int ID) { 54 | // this.ID = ID; 55 | // } 56 | // 57 | // public int getAmbiguityStatusFlag() { 58 | // return AmbiguityStatusFlag; 59 | // } 60 | // 61 | // public void setAmbiguityStatusFlag(int ambiguityStatusFlag) { 62 | // AmbiguityStatusFlag = ambiguityStatusFlag; 63 | // } 64 | // 65 | // public int getNonSyncCount() { 66 | // return NonSyncCount; 67 | // } 68 | // 69 | // public void setNonSyncCount(int nonSyncCount) { 70 | // NonSyncCount = nonSyncCount; 71 | // } 72 | // 73 | // public int getGeometricCarrierPhaseCorrectionDifference() { 74 | // return GeometricCarrierPhaseCorrectionDifference; 75 | // } 76 | // 77 | // public void setGeometricCarrierPhaseCorrectionDifference(int geometricCarrierPhaseCorrectionDifference) { 78 | // GeometricCarrierPhaseCorrectionDifference = geometricCarrierPhaseCorrectionDifference; 79 | // } 80 | // 81 | // public int getIODE() { 82 | // return IODE; 83 | // } 84 | // 85 | // public void setIODE(int IODE) { 86 | // this.IODE = IODE; 87 | // } 88 | // 89 | // public int getIonosphericCarrierPhaseCorrectionDifference() { 90 | // return IonosphericCarrierPhaseCorrectionDifference; 91 | // } 92 | // 93 | // public void setIonosphericCarrierPhaseCorrectionDifference(int ionosphericCarrierPhaseCorrectionDifference) { 94 | // IonosphericCarrierPhaseCorrectionDifference = ionosphericCarrierPhaseCorrectionDifference; 95 | // } 96 | // } 97 | //} 98 | -------------------------------------------------------------------------------- /src/main/resources/app.properties: -------------------------------------------------------------------------------- 1 | #station plain tcp/ip port 2 | station.default.port=8442 3 | 4 | #ntrip plain tcp/ip port 5 | ntrip.default.port=8443 6 | 7 | #by default server uses embedded in jar cert to simplify local server installation. 8 | #WARNNING DO NOT USE THIS CERTIFICATES ON PRODUCTION OR IN WHERE ENVIRNOMENTS REAL SECURITY REQUIRED. 9 | #provide either full path to files either use '.' for specifying current directory. For instance "./myfile.crt" 10 | server.ssl.cert= 11 | server.ssl.key= 12 | server.ssl.key.pass= 13 | client.ssl.cert= 14 | client.ssl.key= 15 | 16 | #by default System.getProperty("java.io.tmpdir")/blynk used 17 | data.folder= 18 | 19 | #folder for logs. 20 | logs.folder=./logs 21 | 22 | #log debug level. trace|debug|info|error. Defines how precise logging will be. 23 | log.level=trace 24 | 25 | #defines maximum allowed number of user dashboards. Needed to limit possible number of tokens. 26 | user.dashboard.max.limit=10 27 | 28 | #user is limited with 100 messages per second. 29 | user.message.quota.limit=100 30 | #in case of consistent quota limit exceed during long term, sending warning response back to exceeding channel 31 | #for performance reason sending only 1 message within interval. In millis 32 | user.message.quota.limit.exceeded.warning.period=60000 33 | 34 | #maximum allowed number of notification queue. Queue responsible for processing email, pushes, twits sending. 35 | #Because of performance issue - those queue is processed in separate thread, this is required due 36 | #to blocking nature of all above operations. Usually limit shouldn't be reached. 37 | notifications.queue.limit=10000 38 | 39 | #todo finish 40 | #this setting defines how often we can send mail/tweet/push or any other notification. Specified in seconds 41 | notifications.frequency.user.quota.limit=60 42 | 43 | #maximum size of user profile in kb's 44 | user.profile.max.size=128 45 | 46 | #in memory storage limit for storing *read* values from hardware 47 | user.in.memory.storage.limit=1000 48 | 49 | #period in millis for saving all user DB to disk. 50 | profile.save.worker.period=60000 51 | 52 | #period in millis for saving stats to disk. 53 | stats.print.worker.period=60000 54 | 55 | #@ 56 | #specifies maximum period of time when application socket could be idle. After which 57 | #socket will be closed due to non activity. In seconds. Default value 600 if not provided. 58 | #leave it empty for infinity timeout 59 | app.socket.idle.timeout=600 60 | #specifies maximum period of time when hardware socket could be idle. After which 61 | #socket will be closed due to non activity. In seconds. Default value 15 if not provided. 62 | #leave it empty for infinity timeout 63 | station.socket.idle.timeout=15 64 | 65 | #Enables native socket transport for Linux using JNI. Should be turned on only if you 100% sure. 66 | #may not work on some environments. Used to increase server performance. Performance boost is ~20-40%. 67 | enable.native.epoll.transport=false 68 | 69 | #Enabled native openSSL support for SSL handlers. Should be turned on only if you 100% sure. 70 | #may not work on some environments. Used to increase server performance. Performance boost is ~16%. 71 | #For more details see - http://netty.io/wiki/forked-tomcat-native.html 72 | enable.native.openssl=false 73 | 74 | #mostly required for local servers setup in case user want to log raw data in CSV format 75 | #from his hardware 76 | enable.raw.data.store=true 77 | 78 | #size of async logger ring buffer. should be increased for loads >2-3k req/sec 79 | async.logger.ring.buffer.size=8192 80 | 81 | 82 | #ADMINISTRATION SECTION 83 | 84 | #admin monitoring port. 85 | server.admin.port=8777 86 | 87 | #comma separated list of users allowed to create accounts. leave it empty if no restriction required. 88 | allowed.users.list= 89 | # 90 | passwordHashAlgorithm=BCrypt 91 | # Default email domain for new users 92 | 93 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/core/userServer/handlers/UserAuthHandler.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.core.userServer.handlers; 2 | 3 | import io.netty.channel.ChannelHandlerContext; 4 | import io.netty.channel.ChannelInboundHandlerAdapter; 5 | import io.netty.channel.SimpleChannelInboundHandler; 6 | import io.netty.handler.codec.http.FullHttpRequest; 7 | import io.netty.handler.codec.http.HttpMethod; 8 | import org.dav95s.openNTRIP.commons.Registry; 9 | import org.dav95s.openNTRIP.core.ChannelState; 10 | import org.dav95s.openNTRIP.core.userServer.handlers.authentication.NtripBasicAuthHandler; 11 | import org.dav95s.openNTRIP.core.userServer.handlers.authentication.NtripNoneAuthHandler; 12 | import org.dav95s.openNTRIP.database.models.SourceTableModel; 13 | import org.dav95s.openNTRIP.database.modelsV2.MountpointModel; 14 | import org.dav95s.openNTRIP.database.repository.MountpointRepository; 15 | import org.dav95s.openNTRIP.database.repository.UserRepository; 16 | import org.dav95s.openNTRIP.exception.MountpointNotFound; 17 | import org.slf4j.Logger; 18 | import org.slf4j.LoggerFactory; 19 | 20 | import java.nio.charset.StandardCharsets; 21 | 22 | public class UserAuthHandler extends ChannelInboundHandlerAdapter { 23 | private final static Logger logger = LoggerFactory.getLogger(UserAuthHandler.class.getName()); 24 | 25 | private final MountpointRepository mountpointRepository; 26 | private final UserRepository userRepository; 27 | private final Registry registry; 28 | 29 | public UserAuthHandler(Registry registry, MountpointRepository mountpointRepository, UserRepository userRepository) { 30 | this.mountpointRepository = mountpointRepository; 31 | this.userRepository = userRepository; 32 | this.registry = registry; 33 | } 34 | 35 | @Override 36 | public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { 37 | assert msg instanceof FullHttpRequest; 38 | 39 | FullHttpRequest message = (FullHttpRequest) msg; 40 | 41 | if (message.method() != HttpMethod.GET) { 42 | throw new IllegalArgumentException("Only GET messages"); 43 | } 44 | 45 | String request = message.uri().substring(1); 46 | 47 | MountpointModel mountpoint = mountpointRepository.getMountpoint(request); 48 | 49 | if (mountpoint == null) { 50 | throw new MountpointNotFound(request + " Requested reference station not exists!"); 51 | } 52 | 53 | ctx.channel().attr(ChannelState.MOUNTPOINT).set(mountpoint); 54 | ctx.channel().attr(ChannelState.NETWORK).set(mountpoint.network); 55 | 56 | ctx.channel().pipeline().remove(this); 57 | 58 | switch (mountpoint.authenticator) { 59 | case Digest: 60 | logger.warn("Digest authentication not supported!"); 61 | ctx.close(); 62 | break; 63 | 64 | case Basic: 65 | SimpleChannelInboundHandler authHandler = new NtripBasicAuthHandler(registry, userRepository); 66 | authHandler.channelRead(ctx, msg); 67 | break; 68 | 69 | case None: 70 | ctx.pipeline().addLast(new NtripNoneAuthHandler(registry)); 71 | break; 72 | } 73 | } 74 | 75 | 76 | @Override 77 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { 78 | if (cause instanceof IllegalArgumentException) { 79 | logger.info("Channel ID:" + ctx.channel().id() + " " + cause.getMessage(), cause); 80 | ctx.close(); 81 | } else if (cause instanceof MountpointNotFound) { 82 | logger.info("Channel ID:" + ctx.channel().id() + " " + cause.getMessage(), cause); 83 | sendSourceTable(ctx); 84 | } 85 | 86 | } 87 | 88 | private void sendSourceTable(ChannelHandlerContext ctx) { 89 | SourceTableModel sourceTableModel = new SourceTableModel(); 90 | ctx.writeAndFlush(sourceTableModel.getSourcetable().getBytes(StandardCharsets.US_ASCII)); 91 | ctx.close(); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | org.dav95s 8 | openNTRIP 9 | 1.0-SNAPSHOT 10 | 11 | jar 12 | 13 | 14 | 15 | 16 | org.apache.maven.plugins 17 | maven-compiler-plugin 18 | 3.5.1 19 | 20 | 11 21 | 11 22 | 23 | 24 | 25 | 26 | 27 | 28 | UTF-8 29 | 11 30 | 11 31 | 32 | 33 | 34 | 35 | 36 | org.slf4j 37 | slf4j-api 38 | 1.7.30 39 | 40 | 41 | 42 | ch.qos.logback 43 | logback-core 44 | 1.2.3 45 | 46 | 47 | 48 | ch.qos.logback 49 | logback-classic 50 | 1.2.3 51 | 52 | 53 | 54 | 55 | mysql 56 | mysql-connector-java 57 | 8.0.19 58 | 59 | 60 | 61 | 62 | com.zaxxer 63 | HikariCP 64 | 3.4.3 65 | 66 | 67 | 68 | 69 | at.favre.lib 70 | bcrypt 71 | 0.9.0 72 | 73 | 74 | 75 | 76 | com.google.guava 77 | guava 78 | 30.1-jre 79 | 80 | 81 | 82 | 83 | org.json 84 | json 85 | 20210307 86 | 87 | 88 | 89 | 90 | io.netty 91 | netty-all 92 | 4.1.69.Final 93 | 94 | 95 | 96 | junit 97 | junit 98 | 4.13.2 99 | test 100 | 101 | 102 | 103 | 104 | com.harium 105 | kdtree 106 | 1.0.0 107 | 108 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/core/stationsServer/handlers/ReferenceStationAuthHandler.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.core.stationsServer.handlers; 2 | 3 | import io.netty.channel.ChannelHandlerContext; 4 | import io.netty.channel.SimpleChannelInboundHandler; 5 | import org.dav95s.openNTRIP.commons.Registry; 6 | import org.dav95s.openNTRIP.core.ChannelState; 7 | import org.dav95s.openNTRIP.database.modelsV2.NetworkModel; 8 | import org.dav95s.openNTRIP.database.modelsV2.ReferenceStationModel; 9 | import org.dav95s.openNTRIP.database.repository.ReferenceStationRepository; 10 | import org.dav95s.openNTRIP.exception.ReferenceStationAuthorizationException; 11 | import org.dav95s.openNTRIP.protocols.ntrip.NtripResponse; 12 | import org.slf4j.Logger; 13 | import org.slf4j.LoggerFactory; 14 | 15 | public class ReferenceStationAuthHandler extends SimpleChannelInboundHandler { 16 | private final static Logger logger = LoggerFactory.getLogger(ReferenceStationAuthHandler.class.getName()); 17 | 18 | private final Registry registry; 19 | private final ReferenceStationRepository referenceStationRepository; 20 | 21 | public ReferenceStationAuthHandler(Registry registry, ReferenceStationRepository referenceStationRepository) { 22 | this.registry = registry; 23 | this.referenceStationRepository = referenceStationRepository; 24 | } 25 | 26 | @Override 27 | public void channelActive(ChannelHandlerContext ctx) throws Exception { 28 | logger.info("New inbound connect " + ctx.channel().remoteAddress() + " channelID:" + ctx.channel().id()); 29 | super.channelActive(ctx); 30 | } 31 | 32 | @Override 33 | protected void channelRead0(ChannelHandlerContext ctx, byte[] msg) throws Exception { 34 | String message = new String(msg); 35 | String[] params = message.split("\r\n"); 36 | 37 | if (params.length < 1) 38 | throw new IllegalArgumentException("Not valid request" + ctx.channel().remoteAddress()); 39 | 40 | String[] authData = params[0].split(" ", 3); 41 | 42 | if (authData.length != 3 || !authData[0].equals("SOURCE")) { 43 | throw new IllegalArgumentException("Not valid request" + ctx.channel().remoteAddress()); 44 | } 45 | 46 | String pass = authData[1]; 47 | String name = authData[2]; 48 | 49 | ReferenceStationModel model = referenceStationRepository.GetReferenceStationByName(name); 50 | 51 | if (model == null || !model.password.equals(pass)) { 52 | throw new ReferenceStationAuthorizationException("Reference station " + name + " is not exists or bad password " + ctx.channel().remoteAddress()); 53 | } 54 | 55 | ctx.channel().attr(ChannelState.REFERENCE_STATION_MODEL).set(model); 56 | 57 | logger.info(model.name + ": Successful authorization " + ctx.channel().remoteAddress()); 58 | ctx.writeAndFlush(NtripResponse.OK_MESSAGE); 59 | ctx.pipeline().remove("StationAuthHandler"); 60 | ctx.pipeline().addLast("RtcmStreamHandler", new Rtcm3InboundHandler(registry, model)); 61 | 62 | for (String network : model.networks) { 63 | NetworkModel networkModel = registry.networks.get(network); 64 | if (networkModel == null){ 65 | logger.warn("Reference station " + model.name + " has undefined network"); 66 | continue; 67 | } 68 | networkModel.channelGroup.add(ctx.channel()); 69 | } 70 | 71 | registry.networks.get(model.name).channelGroup.add(ctx.channel()); 72 | } 73 | 74 | @Override 75 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { 76 | if (cause instanceof IllegalArgumentException) { 77 | logger.info("Channel ID:" + ctx.channel().id() + " " + cause.getMessage(), cause); 78 | ctx.writeAndFlush(NtripResponse.BAD_PASSWORD); 79 | } else if (cause instanceof ReferenceStationAuthorizationException) { 80 | logger.info("Reference station is not exists or bad password "); 81 | ctx.writeAndFlush(NtripResponse.BAD_PASSWORD); 82 | } 83 | 84 | ctx.close(); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/protocols/rtcm/messages/MSG1001.java: -------------------------------------------------------------------------------- 1 | //package org.dav95s.openNTRIP.Tools.RTCM; 2 | // 3 | //import java.math.BigDecimal; 4 | //import java.math.RoundingMode; 5 | // 6 | //public class MSG1001 extends RTCM { 7 | // 8 | // private int messageNumber; 9 | // private int stationID; 10 | // private double TOW; 11 | // private boolean synchronous; 12 | // private int signalsProcessed; //No. of GPS Satellite Signals Processed 13 | // private boolean smoothingIndicator; 14 | // private int smoothingInterval; 15 | // private final double LightMilliSecond = 299792.458; 16 | // String[] smoothing = new String[]{ 17 | // "No smoothing", 18 | // "< 30 s", 19 | // "30-60 s", 20 | // "1-2 min", 21 | // "2-4 min", 22 | // "4-8 min", 23 | // ">8 min", 24 | // "Unlimited smoothing interval" 25 | // }; 26 | // 27 | // Sat1001[] listSatellites; 28 | // 29 | // public Sat1001[] getListSatellites() { 30 | // return listSatellites; 31 | // } 32 | // 33 | // public MSG1001(byte[] msg) { 34 | // 35 | // super.rawMsg = msg; 36 | // 37 | // super.setToBinaryBuffer(msg); 38 | // 39 | // messageNumber = Integer.parseUnsignedInt(binaryBuffer.substring(16, 28), 2);//1005 1006 40 | // stationID = Integer.parseUnsignedInt(binaryBuffer.substring(28, 40), 2); 41 | // TOW = toUnsignedInt(binaryBuffer.substring(40, 70)) / 1000.0d; 42 | // synchronous = binaryBuffer.charAt(70) == RTCM.BIT1; 43 | // signalsProcessed = toUnsignedInt(binaryBuffer.substring(71, 76)); 44 | // smoothingIndicator = binaryBuffer.charAt(76) == RTCM.BIT1; 45 | // smoothingInterval = toUnsignedInt(binaryBuffer.substring(77, 80)); 46 | // 47 | // listSatellites = new Sat1001[signalsProcessed]; 48 | // 49 | // for (int i = 0; i < signalsProcessed; i++) { 50 | // int shift = i * 58; 51 | // 52 | // Sat1001 s = new Sat1001(); 53 | // 54 | // s.setID(toUnsignedInt(getBits(80 + shift, 6))); 55 | // s.setCodeL1(toUnsignedInt(getBits(86 + shift, 1))); 56 | // s.setL1Psr(toUnsignedInt(getBits(87 + shift, 24))); 57 | // s.setL1Phr_L1Psr(toSignedInt(getBits(111 + shift, 20))); 58 | // s.setLockL1(toUnsignedInt(getBits(131 + shift, 7))); 59 | // 60 | // listSatellites[i] = s; 61 | // } 62 | // } 63 | // 64 | // public class Sat1001 { 65 | // //Psr - PseudoRange 66 | // //Phr - PhaseRange 67 | // 68 | // String[] L1Indicator = new String[]{ 69 | // "C/A Code", 70 | // "P(Y) Code Direct" 71 | // }; 72 | // 73 | // String[] L2Indicator = new String[]{ 74 | // "C/A or L2C code", 75 | // "P(Y) code direct", 76 | // "P(Y) code cross-correlated", 77 | // "Correlated P/Y" 78 | // }; 79 | // 80 | // private int ID; 81 | // private int CodeL1; 82 | // private int L1Psr; 83 | // private int L1Phr_L1Psr; 84 | // private int L1Phr; 85 | // private int LockL1; 86 | // 87 | // 88 | // @Override 89 | // public String toString() { 90 | // 91 | // String response = ""; 92 | // response += customFormat("##", ID) + "\t|\t"; 93 | // response += L1Indicator[CodeL1] + "\t|\t"; 94 | // //response += L1Psr + "\t|\t"; 95 | // response += new BigDecimal(L1Phr_L1Psr / 2000d).setScale(2, RoundingMode.HALF_EVEN) + "\t|\t"; 96 | // response += LockL1 + "\t|\t"; 97 | // 98 | // return response; 99 | // } 100 | // 101 | // public int getID() { 102 | // return ID; 103 | // } 104 | // 105 | // public void setID(int ID) { 106 | // this.ID = ID; 107 | // } 108 | // 109 | // public int getCodeL1() { 110 | // return CodeL1; 111 | // } 112 | // 113 | // public void setCodeL1(int codeL1) { 114 | // CodeL1 = codeL1; 115 | // } 116 | // 117 | // public int getL1Psr() { 118 | // return L1Psr; 119 | // } 120 | // 121 | // public void setL1Psr(int l1Psr) { 122 | // L1Psr = l1Psr; 123 | // } 124 | // 125 | // public int getL1Phr_L1Psr() { 126 | // return L1Phr_L1Psr; 127 | // } 128 | // 129 | // public void setL1Phr_L1Psr(int l1Phr_L1Psr) { 130 | // this.L1Phr_L1Psr = l1Phr_L1Psr; 131 | // } 132 | // 133 | // public int getLockL1() { 134 | // return LockL1; 135 | // } 136 | // 137 | // public void setLockL1(int lockL1) { 138 | // LockL1 = lockL1; 139 | // } 140 | // } 141 | //} 142 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/protocols/nmea/NMEA.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.protocols.nmea; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | /* 6 | from = https://gist.github.com/javisantana/1326141 7 | */ 8 | 9 | public class NMEA { 10 | 11 | interface SentenceParser { 12 | public boolean parse(String[] tokens, GPSPosition position); 13 | } 14 | 15 | // utils 16 | static float Latitude2Decimal(String lat, String NS) { 17 | float med = Float.parseFloat(lat.substring(2)) / 60.0f; 18 | med += Float.parseFloat(lat.substring(0, 2)); 19 | if (NS.startsWith("S")) { 20 | med = -med; 21 | } 22 | return med; 23 | } 24 | 25 | static float Longitude2Decimal(String lon, String WE) { 26 | float med = Float.parseFloat(lon.substring(3)) / 60.0f; 27 | med += Float.parseFloat(lon.substring(0, 3)); 28 | if (WE.startsWith("W")) { 29 | med = -med; 30 | } 31 | return med; 32 | } 33 | 34 | // parsers 35 | class GPGGA implements SentenceParser { 36 | public boolean parse(String[] tokens, GPSPosition position) { 37 | position.time = Float.parseFloat(tokens[1]); 38 | position.lat = Latitude2Decimal(tokens[2], tokens[3]); 39 | position.lon = Longitude2Decimal(tokens[4], tokens[5]); 40 | position.quality = Integer.parseInt(tokens[6]); 41 | position.altitude = Float.parseFloat(tokens[9]); 42 | return true; 43 | } 44 | } 45 | 46 | class GPGGL implements SentenceParser { 47 | public boolean parse(String[] tokens, GPSPosition position) { 48 | position.lat = Latitude2Decimal(tokens[1], tokens[2]); 49 | position.lon = Longitude2Decimal(tokens[3], tokens[4]); 50 | position.time = Float.parseFloat(tokens[5]); 51 | return true; 52 | } 53 | } 54 | 55 | class GPRMC implements SentenceParser { 56 | public boolean parse(String[] tokens, GPSPosition position) { 57 | position.time = Float.parseFloat(tokens[1]); 58 | position.lat = Latitude2Decimal(tokens[3], tokens[4]); 59 | position.lon = Longitude2Decimal(tokens[5], tokens[6]); 60 | position.velocity = Float.parseFloat(tokens[7]); 61 | position.dir = Float.parseFloat(tokens[8]); 62 | return true; 63 | } 64 | } 65 | 66 | class GPVTG implements SentenceParser { 67 | public boolean parse(String[] tokens, GPSPosition position) { 68 | position.dir = Float.parseFloat(tokens[3]); 69 | return true; 70 | } 71 | } 72 | 73 | class GPRMZ implements SentenceParser { 74 | public boolean parse(String[] tokens, GPSPosition position) { 75 | position.altitude = Float.parseFloat(tokens[1]); 76 | return true; 77 | } 78 | } 79 | 80 | 81 | public class GPSPosition { 82 | public float time = 0.0f; 83 | public float lat = 0.0f; 84 | public float lon = 0.0f; 85 | public boolean fixed = false; 86 | public int quality = 0; 87 | public float dir = 0.0f; 88 | public float altitude = 0.0f; 89 | public float velocity = 0.0f; 90 | 91 | public void updatefix() { 92 | fixed = quality > 0; 93 | } 94 | 95 | public String toString() { 96 | return String.format("POSITION: lat: %f, lon: %f, time: %f, Q: %d, dir: %f, alt: %f, vel: %f", lat, lon, time, quality, dir, altitude, velocity); 97 | } 98 | 99 | public boolean isSet() { 100 | System.out.println(position.lat != 0.0f && position.lon != 0.0f); 101 | return position.lat != 0.0f && position.lon != 0.0f; 102 | } 103 | } 104 | 105 | GPSPosition position = new GPSPosition(); 106 | 107 | private static final Map sentenceParsers = new HashMap(); 108 | 109 | public NMEA() { 110 | //Add new message 111 | sentenceParsers.put("GNGGA", new GPGGA()); 112 | 113 | sentenceParsers.put("GPGGA", new GPGGA()); 114 | sentenceParsers.put("GPGGL", new GPGGL()); 115 | sentenceParsers.put("GPRMC", new GPRMC()); 116 | sentenceParsers.put("GPRMZ", new GPRMZ()); 117 | //only really good GPS devices have this sentence but ... 118 | sentenceParsers.put("GPVTG", new GPVTG()); 119 | } 120 | 121 | public GPSPosition parse(String line) { 122 | 123 | if (line.startsWith("$")) { 124 | String nmea = line.substring(1); 125 | String[] tokens = nmea.split(","); 126 | String type = tokens[0]; 127 | //TODO check crc 128 | if (sentenceParsers.containsKey(type)) { 129 | sentenceParsers.get(type).parse(tokens, position); 130 | } 131 | position.updatefix(); 132 | } 133 | 134 | return position; 135 | } 136 | } -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/protocols/rtcm/messages/MSG1025.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.protocols.rtcm.messages; 2 | 3 | import com.google.common.primitives.Bytes; 4 | import org.dav95s.openNTRIP.protocols.rtcm.assets.CRS3; 5 | import org.dav95s.openNTRIP.utils.binaryParse.BitUtils; 6 | import org.dav95s.openNTRIP.utils.binaryParse.Crc24q; 7 | import org.dav95s.openNTRIP.utils.binaryParse.Normalize; 8 | 9 | import static com.google.common.base.Preconditions.checkArgument; 10 | 11 | public class MSG1025 implements CRS3 { 12 | 13 | private int messageNumber; 14 | private int SystemIdentificationNumber; 15 | private int ProjectionType; 16 | private double LaNO; 17 | private double LoNO; 18 | private double S; 19 | private double FalseEasting; 20 | private double FalseNorthing; 21 | 22 | public MSG1025() { 23 | messageNumber = 1025; 24 | } 25 | 26 | public MSG1025(byte[] msg) { 27 | BitUtils bitUtils = new BitUtils(msg); 28 | bitUtils.setPointer(24); 29 | messageNumber = bitUtils.getUnsignedInt(12); 30 | setSystemIdentificationNumber(bitUtils.getUnsignedInt(8)); 31 | setProjectionType(bitUtils.getUnsignedInt(6)); 32 | setLaNO(bitUtils.getSignedLong(34) * 0.000000011d); 33 | setLoNO(bitUtils.getSignedLong(35) * 0.000000011d); 34 | setS((bitUtils.getUnsignedLong(30) * 0.00001d + 993000) / 1000000); 35 | setFalseEasting(bitUtils.getUnsignedLong(36) * 0.001d); 36 | setFalseNorthing(bitUtils.getSignedLong(35) * 0.001d); 37 | } 38 | 39 | public byte[] getBytes() { 40 | BitUtils bitUtils = new BitUtils(); 41 | bitUtils.setBitString("11010011000000"); //preamble + 6 reserved bit 42 | bitUtils.setInt(25, 10); 43 | bitUtils.setInt(messageNumber, 12); 44 | bitUtils.setInt(SystemIdentificationNumber, 8); 45 | bitUtils.setInt(ProjectionType, 6); 46 | bitUtils.setLong(Math.round(LaNO / 0.000000011d), 34); 47 | bitUtils.setLong(Math.round(LoNO / 0.000000011d), 35); 48 | bitUtils.setLong(Math.round((S * 1000000 - 993000) / 0.00001d), 30); 49 | bitUtils.setLong(Math.round(FalseEasting / 0.001d), 36); 50 | bitUtils.setLong(Math.round(FalseNorthing / 0.001d), 35); 51 | byte[] bytes = bitUtils.getByteArray(); 52 | return Bytes.concat(bytes, Crc24q.crc24q(bytes, bytes.length, 0)); 53 | } 54 | 55 | @Override 56 | public String toString() { 57 | return "MSG1025{" + 58 | "messageNumber=" + messageNumber + 59 | ", SystemIdentificationNumber=" + SystemIdentificationNumber + 60 | ", ProjectionType=" + ProjectionType + 61 | ", LaNO=" + LaNO + 62 | ", LoNO=" + LoNO + 63 | ", S=" + S + 64 | ", FalseEasting=" + FalseEasting + 65 | ", FalseNorthing=" + FalseNorthing + 66 | '}'; 67 | } 68 | 69 | public int getMessageNumber() { 70 | return messageNumber; 71 | } 72 | 73 | public int getSystemIdentificationNumber() { 74 | return SystemIdentificationNumber; 75 | } 76 | 77 | public void setSystemIdentificationNumber(int systemIdentificationNumber) { 78 | checkArgument(0 <= systemIdentificationNumber && systemIdentificationNumber <= 255); 79 | SystemIdentificationNumber = systemIdentificationNumber; 80 | } 81 | 82 | public int getProjectionType() { 83 | return ProjectionType; 84 | } 85 | 86 | public void setProjectionType(int projectionType) { 87 | checkArgument(0 <= projectionType && projectionType <= 11); 88 | ProjectionType = projectionType; 89 | } 90 | 91 | public double getLaNO() { 92 | return LaNO; 93 | } 94 | 95 | public void setLaNO(double laNO) { 96 | double normalized = Normalize.normalize(laNO, 8); 97 | checkArgument(-90 <= normalized && normalized <= 90); 98 | LaNO = normalized; 99 | } 100 | 101 | public double getLoNO() { 102 | return LoNO; 103 | } 104 | 105 | public void setLoNO(double loNO) { 106 | double normalized = Normalize.normalize(loNO, 8); 107 | checkArgument(-180 <= normalized && normalized <= 180); 108 | LoNO = normalized; 109 | } 110 | 111 | public double getS() { 112 | return S; 113 | } 114 | 115 | public void setS(double s) { 116 | double normalized = Normalize.normalize(s, 6); 117 | checkArgument(0.993 <= normalized && normalized <= 1.003737418); 118 | this.S = normalized; 119 | } 120 | 121 | public double getFalseEasting() { 122 | return FalseEasting; 123 | } 124 | 125 | public void setFalseEasting(double falseEasting) { 126 | double normalized = Normalize.normalize(falseEasting, 4); 127 | checkArgument(0 <= normalized && normalized <= 68719476.735); 128 | FalseEasting = normalized; 129 | } 130 | 131 | public double getFalseNorthing() { 132 | return FalseNorthing; 133 | } 134 | 135 | public void setFalseNorthing(double falseNorthing) { 136 | double normalized = Normalize.normalize(falseNorthing, 4); 137 | checkArgument(-17179869.183 <= normalized && normalized <= 17179869.183); 138 | FalseNorthing = normalized; 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/protocols/rtcm/messages/MSG1002.java: -------------------------------------------------------------------------------- 1 | //package org.dav95s.openNTRIP.Tools.RTCM; 2 | // 3 | //import java.math.BigDecimal; 4 | //import java.math.RoundingMode; 5 | // 6 | //public class MSG1002 extends RTCM { 7 | // 8 | // private int messageNumber; 9 | // private int stationID; 10 | // private double TOW; 11 | // private boolean synchronous; 12 | // private int signalsProcessed; //No. of GPS Satellite Signals Processed 13 | // private boolean smoothingIndicator; 14 | // private int smoothingInterval; 15 | // private final double LightMilliSecond = 299792.458; 16 | // String[] smoothing = new String[]{ 17 | // "No smoothing", 18 | // "< 30 s", 19 | // "30-60 s", 20 | // "1-2 min", 21 | // "2-4 min", 22 | // "4-8 min", 23 | // ">8 min", 24 | // "Unlimited smoothing interval" 25 | // }; 26 | // 27 | // Sat1002[] listSatellites; 28 | // 29 | // public Sat1002[] getListSatellites() { 30 | // return listSatellites; 31 | // } 32 | // 33 | // public MSG1002(byte[] msg) { 34 | // 35 | // super.rawMsg = msg; 36 | // 37 | // super.setToBinaryBuffer(msg); 38 | // 39 | // messageNumber = Integer.parseUnsignedInt(binaryBuffer.substring(16, 28), 2);//1005 1006 40 | // stationID = Integer.parseUnsignedInt(binaryBuffer.substring(28, 40), 2); 41 | // TOW = toUnsignedInt(binaryBuffer.substring(40, 70)) / 1000.0d; 42 | // synchronous = binaryBuffer.charAt(70) == RTCM.BIT1; 43 | // signalsProcessed = toUnsignedInt(binaryBuffer.substring(71, 76)); 44 | // smoothingIndicator = binaryBuffer.charAt(76) == RTCM.BIT1; 45 | // smoothingInterval = toUnsignedInt(binaryBuffer.substring(77, 80)); 46 | // 47 | // listSatellites = new Sat1002[signalsProcessed]; 48 | // 49 | // for (int i = 0; i < signalsProcessed; i++) { 50 | // int shift = i * 74; 51 | // 52 | // Sat1002 s = new Sat1002(); 53 | // 54 | // s.setID(toUnsignedInt(getBits(80 + shift, 6))); 55 | // s.setCodeL1(toUnsignedInt(getBits(86 + shift, 1))); 56 | // s.setL1Psr(toUnsignedInt(getBits(87 + shift, 24))); 57 | // s.setL1Phr_L1Psr(toSignedInt(getBits(111 + shift, 20))); 58 | // s.setLockL1(toUnsignedInt(getBits(131 + shift, 7))); 59 | // s.setSNRL1(toUnsignedInt(getBits(138 + shift, 8))); 60 | // 61 | // listSatellites[i] = s; 62 | // } 63 | // } 64 | // 65 | // public class Sat1002 { 66 | // //Psr - PseudoRange 67 | // //Phr - PhaseRange 68 | // 69 | // String[] L1Indicator = new String[]{ 70 | // "C/A Code", 71 | // "P(Y) Code Direct" 72 | // }; 73 | // 74 | // String[] L2Indicator = new String[]{ 75 | // "C/A or L2C code", 76 | // "P(Y) code direct", 77 | // "P(Y) code cross-correlated", 78 | // "Correlated P/Y" 79 | // }; 80 | // 81 | // private int ID; 82 | // private int CodeL1; 83 | // private int L1Psr; 84 | // private int L1Phr_L1Psr; 85 | // private int LockL1; 86 | // private int AmbL1; 87 | // private int SNRL1; 88 | // 89 | // 90 | // @Override 91 | // public String toString() { 92 | // 93 | // String response = ""; 94 | // response += customFormat("##", ID) + "\t|\t"; 95 | // response += L1Indicator[CodeL1] + "\t|\t"; 96 | // //response += L1Psr + "\t|\t"; 97 | // response += new BigDecimal(L1Phr_L1Psr / 2000d).setScale(2, RoundingMode.HALF_EVEN) + "\t|\t"; 98 | // response += LockL1 + "\t|\t"; 99 | // response += new BigDecimal(AmbL1 * LightMilliSecond).setScale(2, RoundingMode.HALF_EVEN) + "\t|\t"; 100 | // response += new BigDecimal(SNRL1 / 4.0d).setScale(2, RoundingMode.HALF_EVEN) + "\t|\t"; 101 | // 102 | // return response; 103 | // } 104 | // 105 | // public int getID() { 106 | // return ID; 107 | // } 108 | // 109 | // public void setID(int ID) { 110 | // this.ID = ID; 111 | // } 112 | // 113 | // public int getCodeL1() { 114 | // return CodeL1; 115 | // } 116 | // 117 | // public void setCodeL1(int codeL1) { 118 | // CodeL1 = codeL1; 119 | // } 120 | // 121 | // public int getL1Psr() { 122 | // return L1Psr; 123 | // } 124 | // 125 | // public void setL1Psr(int l1Psr) { 126 | // L1Psr = l1Psr; 127 | // } 128 | // 129 | // public int getL1Phr_L1Psr() { 130 | // return L1Phr_L1Psr; 131 | // } 132 | // 133 | // public void setL1Phr_L1Psr(int l1Phr_L1Psr) { 134 | // this.L1Phr_L1Psr = l1Phr_L1Psr; 135 | // } 136 | // 137 | // public int getLockL1() { 138 | // return LockL1; 139 | // } 140 | // 141 | // public void setLockL1(int lockL1) { 142 | // LockL1 = lockL1; 143 | // } 144 | // 145 | // public int getAmbL1() { 146 | // return AmbL1; 147 | // } 148 | // 149 | // public void setAmbL1(int ambL1) { 150 | // AmbL1 = ambL1; 151 | // } 152 | // 153 | // public int getSNRL1() { 154 | // return SNRL1; 155 | // } 156 | // 157 | // public void setSNRL1(int SNRL1) { 158 | // this.SNRL1 = SNRL1; 159 | // } 160 | // 161 | // } 162 | //} 163 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/crs/geoids/GGF.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.crs.geoids; 2 | 3 | import org.dav95s.openNTRIP.utils.binaryParse.Normalize; 4 | 5 | import java.io.IOException; 6 | import java.io.RandomAccessFile; 7 | import java.nio.ByteBuffer; 8 | import java.nio.ByteOrder; 9 | import java.nio.channels.FileChannel; 10 | 11 | public class GGF implements IGeoid { 12 | 13 | Header header; 14 | float[][] model; 15 | 16 | public GGF(String path) { 17 | try (RandomAccessFile reader = new RandomAccessFile(path, "r")) { 18 | FileChannel channel = reader.getChannel(); 19 | ByteBuffer headerBuffer = ByteBuffer.allocate(146); 20 | channel.read(headerBuffer); 21 | 22 | header = new Header(headerBuffer); 23 | model = new float[header.countLat][header.countLon]; 24 | 25 | ByteBuffer buffer = ByteBuffer.allocate(header.countLon * 4); 26 | buffer.order(ByteOrder.LITTLE_ENDIAN); 27 | 28 | for (int row = 0; row < model.length; row++) { 29 | channel.read(buffer); // read 1 row 30 | buffer.flip(); 31 | for (int col = 0; col < model[0].length; col++) { 32 | model[row][col] = buffer.getFloat(); 33 | } 34 | buffer.clear(); 35 | } 36 | } catch (IOException e) { 37 | e.printStackTrace(); 38 | } 39 | } 40 | 41 | 42 | public double getValueByPoint(double lat, double lon) { 43 | if (lon < 0 || header.lonMax > 360) { 44 | lon += 360; 45 | } 46 | 47 | int latP = (int) Normalize.normalize((lat - header.latMin) / header.resolutionLat, 4); 48 | int lonP = (int) (Normalize.normalize((lon - header.lonMin) / header.resolutionLon, 4)); 49 | 50 | double dLon = lon - (lonP * header.resolutionLon + header.lonMin); 51 | double dLat = lat - (latP * header.resolutionLat + header.latMin); 52 | 53 | float[][] v = new float[][]{{model[latP][lonP], model[latP][lonP + 1]}, {model[latP + 1][lonP], model[latP + 1][lonP + 1]}}; 54 | 55 | return bilinear(dLat / header.resolutionLat, dLon / header.resolutionLon, v); 56 | } 57 | 58 | public static float bilinear(double x, double y, float[][] v) { 59 | return (float) (v[0][0] * (1 - x) * (1 - y) + v[1][0] * x * (1 - y) + v[0][1] * (1 - x) * y + v[1][1] * x * y); 60 | } 61 | 62 | 63 | @Override 64 | public String toString() { 65 | return header.toString(); 66 | } 67 | 68 | class Header { 69 | String description; 70 | double latMin, latMax; 71 | double lonMin, lonMax; 72 | double resolutionLat, resolutionLon; 73 | int countLat, countLon; 74 | double NorthPole, SouthPole, Missing, Scalar; 75 | int window; 76 | byte flag0; 77 | byte flag1; 78 | byte flag2; 79 | byte flag3; 80 | byte flag4; 81 | byte flag5; 82 | byte flag6; 83 | byte flag7; 84 | 85 | public Header(ByteBuffer buffer) { 86 | buffer.order(ByteOrder.LITTLE_ENDIAN); 87 | buffer.flip(); 88 | flag1 = buffer.get(); 89 | flag2 = buffer.get(); 90 | byte[] descriptionRaw = new byte[46]; 91 | buffer.get(descriptionRaw, 0, 46); 92 | description = new String(descriptionRaw); 93 | latMin = buffer.getDouble(); 94 | latMax = buffer.getDouble(); 95 | lonMin = buffer.getDouble(); 96 | lonMax = buffer.getDouble(); 97 | resolutionLat = buffer.getDouble(); 98 | resolutionLon = buffer.getDouble(); 99 | countLat = buffer.getInt(); 100 | countLon = buffer.getInt(); 101 | NorthPole = buffer.getDouble(); 102 | SouthPole = buffer.getDouble(); 103 | Missing = buffer.getDouble(); 104 | Scalar = buffer.getDouble(); 105 | window = buffer.getShort(); 106 | flag0 = buffer.get(); 107 | flag1 = buffer.get(); 108 | flag2 = buffer.get(); 109 | flag3 = buffer.get(); 110 | flag4 = buffer.get(); 111 | flag5 = buffer.get(); 112 | flag6 = buffer.get(); 113 | flag7 = buffer.get(); 114 | } 115 | 116 | public void qualityCheck() { 117 | 118 | } 119 | 120 | @Override 121 | public String toString() { 122 | return "Header{" + 123 | "description='" + description + '\'' + 124 | ", latMin=" + latMin + 125 | ", latMax=" + latMax + 126 | ", lonMin=" + lonMin + 127 | ", lonMax=" + lonMax + 128 | ", resolutionLat=" + resolutionLat + 129 | ", resolutionLon=" + resolutionLon + 130 | ", countLat=" + countLat + 131 | ", countLon=" + countLon + 132 | ", NorthPole=" + NorthPole + 133 | ", SouthPole=" + SouthPole + 134 | ", Missing=" + Missing + 135 | ", Scalar=" + Scalar + 136 | ", window=" + window + 137 | ", flag0=" + flag0 + 138 | ", flag1=" + flag1 + 139 | ", flag2=" + flag2 + 140 | ", flag3=" + flag3 + 141 | ", flag4=" + flag4 + 142 | ", flag5=" + flag5 + 143 | ", flag6=" + flag6 + 144 | ", flag7=" + flag7 + 145 | '}'; 146 | } 147 | } 148 | } 149 | 150 | 151 | 152 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/database/models/UserModel.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.database.models; 2 | 3 | import org.dav95s.openNTRIP.database.DataSource; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | 7 | import java.sql.Connection; 8 | import java.sql.PreparedStatement; 9 | import java.sql.ResultSet; 10 | import java.sql.SQLException; 11 | import java.util.HashSet; 12 | import java.util.Set; 13 | 14 | public class UserModel { 15 | final static private Logger logger = LoggerFactory.getLogger(UserModel.class.getName()); 16 | private int id; 17 | private String username; 18 | private String password; 19 | private String email; 20 | private Boolean active; 21 | final private Set listGroups = new HashSet<>(); 22 | 23 | public UserModel(String username) { 24 | this.username = username; 25 | } 26 | 27 | public UserModel() { 28 | 29 | } 30 | 31 | public void setPassword(String password) { 32 | this.password = password; 33 | } 34 | 35 | public boolean read() { 36 | String sql; 37 | String searchIndex; 38 | 39 | if (username != null) { 40 | sql = "SELECT * FROM users WHERE `username` = ?"; 41 | searchIndex = username; 42 | } else if (email != null) { 43 | sql = "SELECT * FROM users WHERE `email` = ?"; 44 | searchIndex = email; 45 | } else { 46 | logger.error("Need username of email, for the select query!"); 47 | return false; 48 | } 49 | 50 | try (Connection con = DataSource.getConnection(); 51 | PreparedStatement statement = con.prepareStatement(sql)) { 52 | 53 | statement.setString(1, searchIndex); 54 | 55 | try (ResultSet rs = statement.executeQuery()) { 56 | if (rs.next()) { 57 | id = rs.getInt("id"); 58 | username = rs.getString("username"); 59 | password = rs.getString("password"); 60 | email = rs.getString("email"); 61 | active = rs.getBoolean("active"); 62 | return true; 63 | } else { 64 | return false; 65 | } 66 | } 67 | 68 | } catch (SQLException e) { 69 | logger.error("SQL Error", e); 70 | return false; 71 | } 72 | } 73 | 74 | public boolean readGroups() { 75 | String sql = "SELECT groups.name, groups.description, groups.id FROM users_groups LEFT JOIN groups ON users_groups.group_id = groups.id WHERE users_groups.user_id = ?"; 76 | 77 | try (Connection con = DataSource.getConnection(); 78 | PreparedStatement statement = con.prepareStatement(sql)) { 79 | 80 | statement.setInt(1, id); 81 | 82 | try (ResultSet rs = statement.executeQuery()) { 83 | 84 | if (!rs.next()) 85 | return false; 86 | 87 | do { 88 | UserGroupModel group = new UserGroupModel(); 89 | group.setGroup_id(rs.getInt("id")); 90 | group.setName(rs.getString("name")); 91 | group.setDescription(rs.getString("description")); 92 | listGroups.add(group); 93 | } while (rs.next()); 94 | 95 | return true; 96 | } 97 | } catch (SQLException e) { 98 | logger.error("SQL Error", e); 99 | return false; 100 | } 101 | } 102 | 103 | public boolean deleteFromGroup(int group_id) { 104 | String sql = "DELETE FROM `users_groups` WHERE `users_groups.user_id` = ? AND `users_groups.group_id` = ?"; 105 | 106 | try (Connection con = DataSource.getConnection(); 107 | PreparedStatement statement = con.prepareStatement(sql)) { 108 | 109 | statement.setInt(1, id); 110 | statement.setInt(2, group_id); 111 | return statement.executeUpdate() > 0; 112 | } catch (SQLException e) { 113 | logger.error("SQL Error", e); 114 | return false; 115 | } 116 | } 117 | 118 | public boolean addToGroup(int group_id) { 119 | String sql = "INSERT INTO `users_groups`(`user_id`, `group_id`) VALUES (?,?)"; 120 | 121 | try (Connection con = DataSource.getConnection(); 122 | PreparedStatement statement = con.prepareStatement(sql)) { 123 | 124 | statement.setInt(1, id); 125 | statement.setInt(2, group_id); 126 | 127 | return statement.executeUpdate() > 0; 128 | } catch (SQLException e) { 129 | logger.error("SQL Error", e); 130 | return false; 131 | } 132 | } 133 | 134 | public int getId() { 135 | return this.id; 136 | } 137 | 138 | public String getUsername() { 139 | return this.username; 140 | } 141 | 142 | public String getPassword() { 143 | return this.password; 144 | } 145 | 146 | public String getEmail() { 147 | return this.email; 148 | } 149 | 150 | public Boolean getActive() { 151 | return this.active; 152 | } 153 | 154 | public Set getListGroups() { 155 | return this.listGroups; 156 | } 157 | 158 | public void setId(int id) { 159 | this.id = id; 160 | } 161 | 162 | public void setUsername(String username) { 163 | this.username = username; 164 | } 165 | 166 | public void setEmail(String email) { 167 | this.email = email; 168 | } 169 | 170 | public void setActive(Boolean active) { 171 | this.active = active; 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/protocols/rtcm/messages/MSG1022.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.protocols.rtcm.messages; 2 | 3 | import com.google.common.base.Preconditions; 4 | import com.google.common.primitives.Bytes; 5 | import org.dav95s.openNTRIP.protocols.rtcm.assets.CRS1; 6 | import org.dav95s.openNTRIP.utils.binaryParse.BitUtils; 7 | import org.dav95s.openNTRIP.utils.binaryParse.Crc24q; 8 | import org.dav95s.openNTRIP.utils.binaryParse.Normalize; 9 | 10 | public class MSG1022 extends MSG1021 implements CRS1 { 11 | 12 | double Xp; 13 | double Yp; 14 | double Zp; 15 | 16 | public MSG1022() { 17 | this.messageNumber = 1022; 18 | } 19 | 20 | public MSG1022(byte[] msg) { 21 | BitUtils bitUtils = new BitUtils(msg); 22 | bitUtils.setPointer(24); 23 | 24 | messageNumber = bitUtils.getUnsignedInt(12); 25 | SourceNameCounter = bitUtils.getUnsignedInt(5); 26 | setSourceName(bitUtils.getString(SourceNameCounter * 8)); 27 | TargetNameCounter = bitUtils.getUnsignedInt(5); 28 | setTargetName(bitUtils.getString(TargetNameCounter * 8)); 29 | setSystemIdentificationNumber(bitUtils.getUnsignedInt(8)); 30 | setUtilizedTransformationMessageIndicator(bitUtils.getUnsignedInt(10)); 31 | setPlateNumber(bitUtils.getUnsignedInt(5)); 32 | setComputationIndicator(bitUtils.getUnsignedInt(4)); 33 | setHeightIndicator(bitUtils.getUnsignedInt(2)); 34 | setLatValid(bitUtils.getSignedInt(19) * 2 / 3600d); 35 | setLonValid(bitUtils.getSignedInt(20) * 2 / 3600d); 36 | setdLatValid(bitUtils.getUnsignedInt(14) * 2 / 3600d); 37 | setdLonValid(bitUtils.getUnsignedInt(14) * 2 / 3600d); 38 | setdX(bitUtils.getSignedInt(23) * 0.0001); 39 | setdY(bitUtils.getSignedInt(23) * 0.0001); 40 | setdZ(bitUtils.getSignedInt(23) * 0.0001); 41 | setRx(bitUtils.getSignedInt(32) * 0.00002); 42 | setRy(bitUtils.getSignedInt(32) * 0.00002); 43 | setRz(bitUtils.getSignedInt(32) * 0.00002); 44 | setdS(bitUtils.getSignedInt(25) * 0.00001); 45 | setXp(bitUtils.getSignedLong(35) * 0.001); 46 | setYp(bitUtils.getSignedLong(35) * 0.001); 47 | setZp(bitUtils.getSignedLong(35) * 0.001); 48 | setAs(bitUtils.getUnsignedLong(24) * 0.001 + 6370000); 49 | setBs(bitUtils.getUnsignedLong(25) * 0.001 + 6350000); 50 | setAt(bitUtils.getUnsignedLong(24) * 0.001 + 6370000); 51 | setBt(bitUtils.getUnsignedLong(25) * 0.001 + 6350000); 52 | setHorizontalQuality(bitUtils.getUnsignedInt(3)); 53 | setVerticalQuality(bitUtils.getUnsignedInt(3)); 54 | } 55 | 56 | public byte[] getBytes() { 57 | BitUtils bitUtils = new BitUtils(); 58 | bitUtils.setBitString("11010011000000"); //preamble + 6 reserved bit 59 | bitUtils.setInt(65 + SourceNameCounter + TargetNameCounter, 10); 60 | bitUtils.setInt(messageNumber, 12); 61 | bitUtils.setInt(SourceNameCounter, 5); 62 | bitUtils.setString(SourceName); 63 | bitUtils.setInt(TargetNameCounter, 5); 64 | bitUtils.setString(TargetName); 65 | bitUtils.setInt(SystemIdentificationNumber, 8); 66 | bitUtils.setInt(UtilizedTransformationMessageIndicator, 10); 67 | bitUtils.setInt(PlateNumber, 5); 68 | bitUtils.setInt(ComputationIndicator, 4); 69 | bitUtils.setInt(HeightIndicator, 2); 70 | bitUtils.setInt((int) Math.round(LatValid * 3600 / 2), 19); 71 | bitUtils.setInt((int) Math.round(LonValid * 3600 / 2), 20); 72 | bitUtils.setInt((int) Math.round(dLatValid * 3600 / 2), 14); 73 | bitUtils.setInt((int) Math.round(dLonValid * 3600 / 2), 14); 74 | bitUtils.setInt((int) Math.round(dX * 10000), 23); 75 | bitUtils.setInt((int) Math.round(dY * 10000), 23); 76 | bitUtils.setInt((int) Math.round(dZ * 10000), 23); 77 | bitUtils.setInt((int) Math.round(Rx / 0.00002), 32); 78 | bitUtils.setInt((int) Math.round(Ry / 0.00002), 32); 79 | bitUtils.setInt((int) Math.round(Rz / 0.00002), 32); 80 | bitUtils.setInt((int) Math.round(dS * 100000), 25); 81 | bitUtils.setInt((int) Math.round(Xp * 1000), 35); 82 | bitUtils.setInt((int) Math.round(Yp * 1000), 35); 83 | bitUtils.setInt((int) Math.round(Zp * 1000), 35); 84 | bitUtils.setInt((int) Math.round((As - 6370000) * 1000), 24); 85 | bitUtils.setInt((int) Math.round((Bs - 6350000) * 1000), 25); 86 | bitUtils.setInt((int) Math.round((At - 6370000) * 1000), 24); 87 | bitUtils.setInt((int) Math.round((Bt - 6350000) * 1000), 25); 88 | bitUtils.setInt(HorizontalQuality, 3); 89 | bitUtils.setInt(VerticalQuality, 3); 90 | byte[] bytes = bitUtils.getByteArray(); 91 | return Bytes.concat(bytes, Crc24q.crc24q(bytes, bytes.length, 0)); 92 | } 93 | 94 | public double getXp() { 95 | return Xp; 96 | } 97 | 98 | public void setXp(double xp) { 99 | double normalized = Normalize.normalize(xp, 4); 100 | Preconditions.checkArgument(-17179869.184 <= normalized && normalized <= 17179869.184); 101 | Xp = normalized; 102 | } 103 | 104 | public double getYp() { 105 | return Yp; 106 | } 107 | 108 | public void setYp(double yp) { 109 | double normalized = Normalize.normalize(yp, 4); 110 | Preconditions.checkArgument(-17179869.184 <= normalized && normalized <= 17179869.184); 111 | Yp = normalized; 112 | } 113 | 114 | public double getZp() { 115 | return Zp; 116 | } 117 | 118 | public void setZp(double zp) { 119 | double normalized = Normalize.normalize(zp, 4); 120 | Preconditions.checkArgument(-17179869.184 <= normalized && normalized <= 17179869.184); 121 | Zp = normalized; 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/protocols/rtcm/messages/MSG1026.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.protocols.rtcm.messages; 2 | 3 | import com.google.common.primitives.Bytes; 4 | import org.dav95s.openNTRIP.protocols.rtcm.assets.CRS3; 5 | import org.dav95s.openNTRIP.utils.binaryParse.BitUtils; 6 | import org.dav95s.openNTRIP.utils.binaryParse.Crc24q; 7 | import org.dav95s.openNTRIP.utils.binaryParse.Normalize; 8 | 9 | import static com.google.common.base.Preconditions.checkArgument; 10 | 11 | public class MSG1026 implements CRS3 { 12 | 13 | private final int messageNumber; 14 | private int SystemIdentificationNumber; 15 | private int ProjectionType; 16 | double LaFO; // – Latitude of False Origin 17 | double LoFO; // – Longitude of False Origin 18 | double LaSP1; // – Latitude of Standard Parallel No. 1 19 | double LaSP2; // – Latitude of Standard Parallel No. 2 20 | double EFO; // – Easting of False Origin 21 | double NFO; // – Northing of False Origin 22 | 23 | public MSG1026() { 24 | messageNumber = 1026; 25 | } 26 | 27 | public MSG1026(byte[] msg) { 28 | BitUtils bitUtils = new BitUtils(msg); 29 | bitUtils.setPointer(24); 30 | messageNumber = bitUtils.getUnsignedInt(12); 31 | SystemIdentificationNumber = bitUtils.getUnsignedInt(8); 32 | ProjectionType = bitUtils.getUnsignedInt(6); 33 | setLaFO(bitUtils.getSignedLong(34) * 0.000000011); 34 | setLoFO(bitUtils.getSignedLong(35) * 0.000000011); 35 | setLaSP1(bitUtils.getSignedLong(34) * 0.000000011); 36 | setLaSP2(bitUtils.getSignedLong(34) * 0.000000011); 37 | setEFO(bitUtils.getUnsignedLong(36) * 0.001); 38 | setNFO(bitUtils.getSignedLong(35) * 0.001); 39 | } 40 | 41 | public byte[] getBytes() { 42 | BitUtils bitUtils = new BitUtils(); 43 | bitUtils.setBitString("11010011000000"); //preamble + 6 reserved bit 44 | bitUtils.setInt(30, 10);//todo length message !!!!!! 45 | bitUtils.setInt(messageNumber, 12); 46 | bitUtils.setInt(SystemIdentificationNumber, 8); 47 | bitUtils.setInt(ProjectionType, 6); 48 | bitUtils.setLong(Math.round(LaFO / 0.000000011), 34); 49 | bitUtils.setLong(Math.round(LoFO / 0.000000011), 35); 50 | bitUtils.setLong(Math.round(LaSP1 / 0.000000011), 34); 51 | bitUtils.setLong(Math.round(LaSP2 / 0.000000011), 34); 52 | bitUtils.setLong(Math.round(EFO / 0.001), 36); 53 | bitUtils.setLong(Math.round(NFO / 0.001), 35); 54 | 55 | byte[] bytes = bitUtils.getByteArray(); 56 | return Bytes.concat(bytes, Crc24q.crc24q(bytes, bytes.length, 0)); 57 | } 58 | 59 | public int getMessageNumber(){ 60 | return messageNumber; 61 | } 62 | 63 | public int getSystemIdentificationNumber() { 64 | return SystemIdentificationNumber; 65 | } 66 | 67 | public void setSystemIdentificationNumber(int systemIdentificationNumber) { 68 | checkArgument(0 <= systemIdentificationNumber && systemIdentificationNumber <= 255); 69 | SystemIdentificationNumber = systemIdentificationNumber; 70 | } 71 | 72 | public int getProjectionType() { 73 | return ProjectionType; 74 | } 75 | 76 | public void setProjectionType(int projectionType) { 77 | checkArgument(0 <= projectionType && projectionType <= 11); 78 | ProjectionType = projectionType; 79 | } 80 | 81 | public double getLaFO() { 82 | 83 | return LaFO; 84 | } 85 | 86 | public void setLaFO(double laFO) { 87 | double normalized = Normalize.normalize(laFO, 8); 88 | checkArgument(-90 <= normalized && normalized <= 90); 89 | LaFO = normalized; 90 | } 91 | 92 | public double getLoFO() { 93 | return LoFO; 94 | } 95 | 96 | public void setLoFO(double loFO) { 97 | double normalized = Normalize.normalize(loFO, 8); 98 | checkArgument(-180 <= normalized && normalized <= 180); 99 | LoFO = normalized; 100 | } 101 | 102 | public double getLaSP1() { 103 | return LaSP1; 104 | } 105 | 106 | public void setLaSP1(double laSP1) { 107 | double normalized = Normalize.normalize(laSP1, 8); 108 | checkArgument(-90 <= normalized && normalized <= 90); 109 | LaSP1 = normalized; 110 | 111 | } 112 | 113 | public double getLaSP2() { 114 | return LaSP2; 115 | } 116 | 117 | public void setLaSP2(double laSP2) { 118 | double normalized = Normalize.normalize(laSP2, 8); 119 | checkArgument(-90 <= normalized && normalized <= 90); 120 | LaSP2 = normalized; 121 | 122 | } 123 | 124 | public double getEFO() { 125 | return EFO; 126 | } 127 | 128 | public void setEFO(double EFO) { 129 | double normalized = Normalize.normalize(EFO, 4); 130 | checkArgument(0 <= normalized && normalized <= 68719476.735); 131 | this.EFO = normalized; 132 | } 133 | 134 | public double getNFO() { 135 | return NFO; 136 | } 137 | 138 | public void setNFO(double NFO) { 139 | double normalized = Normalize.normalize(NFO, 4); 140 | checkArgument(-17179869.183 <= normalized && normalized <= 17179869.183); 141 | this.NFO = normalized; 142 | } 143 | 144 | @Override 145 | public String toString() { 146 | return "MSG1026{" + 147 | "messageNumber=" + messageNumber + 148 | ", SystemIdentificationNumber=" + SystemIdentificationNumber + 149 | ", ProjectionType=" + ProjectionType + 150 | ", LaFO=" + LaFO + 151 | ", LoFO=" + LoFO + 152 | ", LaSP1=" + LaSP1 + 153 | ", LaSP2=" + LaSP2 + 154 | ", EFO=" + EFO + 155 | ", NFO=" + NFO + 156 | '}'; 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/protocols/rtcm/messages/MSG1003.java: -------------------------------------------------------------------------------- 1 | //package org.dav95s.openNTRIP.Tools.RTCM; 2 | // 3 | //import java.math.BigDecimal; 4 | //import java.math.RoundingMode; 5 | // 6 | //public class MSG1003 extends RTCM { 7 | // 8 | // private int messageNumber; 9 | // private int stationID; 10 | // private double TOW; 11 | // private boolean synchronous; 12 | // private int signalsProcessed; //No. of GPS Satellite Signals Processed 13 | // private boolean smoothingIndicator; 14 | // private int smoothingInterval; 15 | // private final double LightMilliSecond = 299792.458; 16 | // String[] smoothing = new String[]{ 17 | // "No smoothing", 18 | // "< 30 s", 19 | // "30-60 s", 20 | // "1-2 min", 21 | // "2-4 min", 22 | // "4-8 min", 23 | // ">8 min", 24 | // "Unlimited smoothing interval" 25 | // }; 26 | // 27 | // Sat1003[] listSatellites; 28 | // 29 | // public Sat1003[] getListSatellites() { 30 | // return listSatellites; 31 | // } 32 | // 33 | // public MSG1003(byte[] msg) { 34 | // 35 | // rawMsg = msg; 36 | // 37 | // for (int i = 1; i < msg.length; i++) { 38 | // binaryBuffer += toBinaryString(msg[i]); 39 | // } 40 | // 41 | // 42 | // messageNumber = Integer.parseUnsignedInt(binaryBuffer.substring(16, 28), 2);//1005 1006 43 | // stationID = Integer.parseUnsignedInt(binaryBuffer.substring(28, 40), 2); 44 | // TOW = toUnsignedInt(binaryBuffer.substring(40, 70)) / 1000.0d; 45 | // synchronous = binaryBuffer.charAt(70) == RTCM.BIT1; 46 | // signalsProcessed = toUnsignedInt(binaryBuffer.substring(71, 76)); 47 | // smoothingIndicator = binaryBuffer.charAt(76) == RTCM.BIT1; 48 | // smoothingInterval = toUnsignedInt(binaryBuffer.substring(77, 80)); 49 | // 50 | // listSatellites = new Sat1003[signalsProcessed]; 51 | // 52 | // for (int i = 0; i < signalsProcessed; i++) { 53 | // int shift = i * 101; 54 | // 55 | // Sat1003 s = new Sat1003(); 56 | // 57 | // s.setID(toUnsignedInt(getBits(80 + shift, 6))); 58 | // s.setCodeL1(toUnsignedInt(getBits(86 + shift, 1))); 59 | // s.setL1Psr(toUnsignedInt(getBits(87 + shift, 24))); 60 | // s.setL1Phr_L1Psr(toSignedInt(getBits(111 + shift, 20))); 61 | // s.setLockL1(toUnsignedInt(getBits(131 + shift, 7))); 62 | // s.setCodeL2(toUnsignedInt(getBits(138 + shift, 2))); 63 | // s.setL2Psr_L1Psr(toSignedInt(getBits(140 + shift, 14))); 64 | // s.setL2Phr_L1Psr(toSignedInt(getBits(154 + shift, 20))); 65 | // s.setLockL2(toUnsignedInt(getBits(174 + shift, 7))); 66 | // 67 | // 68 | // 69 | // listSatellites[i] = s; 70 | // } 71 | // } 72 | // 73 | // public class Sat1003 { 74 | // //Psr - PseudoRange 75 | // //Phr - PhaseRange 76 | // 77 | // String[] L1Indicator = new String[]{ 78 | // "C/A Code", 79 | // "P(Y) Code Direct" 80 | // }; 81 | // 82 | // String[] L2Indicator = new String[]{ 83 | // "C/A or L2C code", 84 | // "P(Y) code direct", 85 | // "P(Y) code cross-correlated", 86 | // "Correlated P/Y" 87 | // }; 88 | // 89 | // private int ID; 90 | // private int CodeL1; 91 | // private int L1Psr; 92 | // private int L1Phr_L1Psr; 93 | // private int LockL1; 94 | // private int CodeL2; 95 | // private int L2Psr_L1Psr; 96 | // private int L2Phr_L1Psr; 97 | // private int LockL2; 98 | // 99 | // 100 | // @Override 101 | // public String toString() { 102 | // 103 | // String response = ""; 104 | // response += customFormat("##", ID) + "\t|\t"; 105 | // response += L1Indicator[CodeL1] + "\t|\t"; 106 | // //response += L1Psr + "\t|\t"; 107 | // response += new BigDecimal(L1Phr_L1Psr / 2000d).setScale(2, RoundingMode.HALF_EVEN) + "\t|\t"; 108 | // response += LockL1 + "\t|\t"; 109 | // response += L2Indicator[CodeL2] + "\t|\t"; 110 | // response += new BigDecimal(L2Psr_L1Psr * 0.02d).setScale(2, RoundingMode.HALF_EVEN) + "\t|\t"; 111 | // response += new BigDecimal(L2Phr_L1Psr / 2000.0d).setScale(2, RoundingMode.HALF_EVEN) + "\t|\t"; 112 | // response += LockL2 + "\t|\t"; 113 | // 114 | // return response; 115 | // } 116 | // 117 | // public int getID() { 118 | // return ID; 119 | // } 120 | // 121 | // public void setID(int ID) { 122 | // this.ID = ID; 123 | // } 124 | // 125 | // public int getCodeL1() { 126 | // return CodeL1; 127 | // } 128 | // 129 | // public void setCodeL1(int codeL1) { 130 | // CodeL1 = codeL1; 131 | // } 132 | // 133 | // public int getL1Psr() { 134 | // return L1Psr; 135 | // } 136 | // 137 | // public void setL1Psr(int l1Psr) { 138 | // L1Psr = l1Psr; 139 | // } 140 | // 141 | // public int getL1Phr_L1Psr() { 142 | // return L1Phr_L1Psr; 143 | // } 144 | // 145 | // public void setL1Phr_L1Psr(int l1Phr_L1Psr) { 146 | // this.L1Phr_L1Psr = l1Phr_L1Psr; 147 | // } 148 | // 149 | // public int getLockL1() { 150 | // return LockL1; 151 | // } 152 | // 153 | // public void setLockL1(int lockL1) { 154 | // LockL1 = lockL1; 155 | // } 156 | // 157 | // public int getCodeL2() { 158 | // return CodeL2; 159 | // } 160 | // 161 | // public void setCodeL2(int codeL2) { 162 | // CodeL2 = codeL2; 163 | // } 164 | // 165 | // public int getL2Psr_L1Psr() { 166 | // return L2Psr_L1Psr; 167 | // } 168 | // 169 | // public void setL2Psr_L1Psr(int l2Psr_L1Psr) { 170 | // this.L2Psr_L1Psr = l2Psr_L1Psr; 171 | // } 172 | // 173 | // public int getL2Phr_L1Psr() { 174 | // return L2Phr_L1Psr; 175 | // } 176 | // 177 | // public void setL2Phr_L1Psr(int l2Phr_L1Psr) { 178 | // this.L2Phr_L1Psr = l2Phr_L1Psr; 179 | // } 180 | // 181 | // public int getLockL2() { 182 | // return LockL2; 183 | // } 184 | // 185 | // public void setLockL2(int lockL2) { 186 | // LockL2 = lockL2; 187 | // } 188 | // 189 | // } 190 | //} 191 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/protocols/rtcm/messages/MSG1020.java: -------------------------------------------------------------------------------- 1 | //package org.dav95s.openNTRIP.Tools.RTCM; 2 | // 3 | //public class MSG1020 extends RTCM { 4 | // private int MessageNumber; 5 | // private int SatelliteID; 6 | // private int SatelliteChannel; 7 | // private int almanacHealth; //almanac health (Cn word) 8 | // private int almanacAvailabilityIndicator; 9 | // private int P1; 10 | // private int tk; 11 | // private int MSB_of_Bn; 12 | // private int P2; 13 | // private int tb; 14 | // private int xn_f; //first derivative 15 | // private int xn; 16 | // private int xn_s; //second derivative 17 | // private int yn_f; //first derivative 18 | // private int yn; 19 | // private int yn_s; //second derivative 20 | // private int zn_f; //first derivative 21 | // private int zn; 22 | // private int zn_s; //second derivative 23 | // private int P3; 24 | // private int Gamma_n; 25 | // private int M_P; 26 | // private int M_ln; // (third string) 27 | // private int Tn; 28 | // private int M_dTn; 29 | // private int En; 30 | // private int M_P4; 31 | // private int M_FT; 32 | // private int M_NT; 33 | // private int M_M; 34 | // private int Availability_Additional_Data; 35 | // private int NA; // N^A 36 | // private int Tc; 37 | // private int M_N4; 38 | // private int M_Tgps; 39 | // private int M_ln_fi; // (fifth string) 40 | // private int reserved; 41 | // 42 | // public MSG1020(byte[] msg) { 43 | // MessageNumber = toUnsignedInt(getBits(16, 12)); 44 | // SatelliteID = toUnsignedInt(getBits(28, 6)); 45 | // SatelliteChannel = toUnsignedInt(getBits(34, 5)); 46 | // almanacHealth = toUnsignedInt(getBits(39, 1)); 47 | // almanacAvailabilityIndicator = toUnsignedInt(getBits(40, 1)); 48 | // P1 = toUnsignedInt(getBits(41, 2)); 49 | // tk = toUnsignedInt(getBits(43, 12)); 50 | // MSB_of_Bn = toUnsignedInt(getBits(55, 1)); 51 | // P2 = toUnsignedInt(getBits(56, 1)); 52 | // tb = toUnsignedInt(getBits(57, 7)); 53 | // xn_f = toIntS(getBits(64, 24)); 54 | // xn = toIntS(getBits(88, 27)); 55 | // xn_s = toIntS(getBits(115, 5)); 56 | // yn_f = toIntS(getBits(120, 24)); 57 | // yn = toIntS(getBits(144, 27)); 58 | // yn_s = toIntS(getBits(171, 5)); 59 | // zn_f = toIntS(getBits(176, 24)); 60 | // zn = toIntS(getBits(200, 27)); 61 | // zn_s = toIntS(getBits(227, 5)); 62 | // P3 = toUnsignedInt(getBits(232, 1)); 63 | // Gamma_n = toIntS(getBits(233, 11)); 64 | // M_P = toUnsignedInt(getBits(244, 2)); 65 | // M_ln = toUnsignedInt(getBits(246, 1)); 66 | // Tn = toIntS(getBits(247, 22)); 67 | // M_dTn = toIntS(getBits(269, 5)); 68 | // En = toUnsignedInt(getBits(274, 5)); 69 | // M_P4 = toUnsignedInt(getBits(279, 1)); 70 | // M_FT = toUnsignedInt(getBits(280, 4)); 71 | // M_NT = toUnsignedInt(getBits(284, 11)); 72 | // M_M = toUnsignedInt(getBits(295, 2)); 73 | // Availability_Additional_Data = toUnsignedInt(getBits(297, 1)); 74 | // NA = toUnsignedInt(getBits(298, 11)); 75 | // Tc = toIntS(getBits(309, 32)); 76 | // M_N4 = toUnsignedInt(getBits(341, 5)); 77 | // M_Tgps = toIntS(getBits(346, 22)); 78 | // M_ln_fi = toUnsignedInt(getBits(368, 1)); 79 | // reserved = toUnsignedInt(getBits(369, 7)); 80 | // } 81 | // 82 | // public int getMessageNumber() { 83 | // return MessageNumber; 84 | // } 85 | // 86 | // public int getSatelliteID() { 87 | // return SatelliteID; 88 | // } 89 | // 90 | // public int getSatelliteChannel() { 91 | // return SatelliteChannel; 92 | // } 93 | // 94 | // public int getAlmanacHealth() { 95 | // return almanacHealth; 96 | // } 97 | // 98 | // public int getAlmanacAvailabilityIndicator() { 99 | // return almanacAvailabilityIndicator; 100 | // } 101 | // 102 | // public int getP1() { 103 | // return P1; 104 | // } 105 | // 106 | // public int getTk() { 107 | // return tk; 108 | // } 109 | // 110 | // public int getMSB_of_Bn() { 111 | // return MSB_of_Bn; 112 | // } 113 | // 114 | // public int getP2() { 115 | // return P2; 116 | // } 117 | // 118 | // public int getTb() { 119 | // return tb; 120 | // } 121 | // 122 | // public int getXn_f() { 123 | // return xn_f; 124 | // } 125 | // 126 | // public int getXn() { 127 | // return xn; 128 | // } 129 | // 130 | // public int getXn_s() { 131 | // return xn_s; 132 | // } 133 | // 134 | // public int getYn_f() { 135 | // return yn_f; 136 | // } 137 | // 138 | // public int getYn() { 139 | // return yn; 140 | // } 141 | // 142 | // public int getYn_s() { 143 | // return yn_s; 144 | // } 145 | // 146 | // public int getZn_f() { 147 | // return zn_f; 148 | // } 149 | // 150 | // public int getZn() { 151 | // return zn; 152 | // } 153 | // 154 | // public int getZn_s() { 155 | // return zn_s; 156 | // } 157 | // 158 | // public int getP3() { 159 | // return P3; 160 | // } 161 | // 162 | // public int getGamma_n() { 163 | // return Gamma_n; 164 | // } 165 | // 166 | // public int getM_P() { 167 | // return M_P; 168 | // } 169 | // 170 | // public int getM_ln() { 171 | // return M_ln; 172 | // } 173 | // 174 | // public int getTn() { 175 | // return Tn; 176 | // } 177 | // 178 | // public int getM_dTn() { 179 | // return M_dTn; 180 | // } 181 | // 182 | // public int getEn() { 183 | // return En; 184 | // } 185 | // 186 | // public int getM_P4() { 187 | // return M_P4; 188 | // } 189 | // 190 | // public int getM_FT() { 191 | // return M_FT; 192 | // } 193 | // 194 | // public int getM_NT() { 195 | // return M_NT; 196 | // } 197 | // 198 | // public int getM_M() { 199 | // return M_M; 200 | // } 201 | // 202 | // public int getAvailability_Additional_Data() { 203 | // return Availability_Additional_Data; 204 | // } 205 | // 206 | // public int getNA() { 207 | // return NA; 208 | // } 209 | // 210 | // public int getTc() { 211 | // return Tc; 212 | // } 213 | // 214 | // public int getM_N4() { 215 | // return M_N4; 216 | // } 217 | // 218 | // public int getM_Tgps() { 219 | // return M_Tgps; 220 | // } 221 | // 222 | // public int getM_ln_fi() { 223 | // return M_ln_fi; 224 | // } 225 | // 226 | // public int getReserved() { 227 | // return reserved; 228 | // } 229 | //} 230 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/utils/binaryParse/BitUtils.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.utils.binaryParse; 2 | 3 | import com.google.common.base.Preconditions; 4 | import com.google.common.base.Splitter; 5 | import com.google.common.collect.Iterables; 6 | 7 | import java.nio.charset.StandardCharsets; 8 | import java.util.Iterator; 9 | 10 | public class BitUtils { 11 | 12 | String buffer; 13 | 14 | int pointer = 0; 15 | 16 | public BitUtils(byte[] arr) { 17 | StringBuilder sb = new StringBuilder(); 18 | for (byte b : arr) { 19 | sb.append(toBinaryString(b)); 20 | } 21 | buffer = sb.toString(); 22 | } 23 | 24 | public BitUtils(String bitString) { 25 | buffer = bitString; 26 | } 27 | 28 | public BitUtils() { 29 | buffer = ""; 30 | } 31 | 32 | public void setPointer(int i) { 33 | pointer = i; 34 | } 35 | 36 | public void clear() { 37 | buffer = ""; 38 | } 39 | 40 | private String toBinaryString(byte n) { 41 | StringBuilder sb = new StringBuilder("00000000"); 42 | for (int bit = 0; bit < 8; bit++) { 43 | if (((n >> bit) & 1) > 0) { 44 | sb.setCharAt(7 - bit, '1'); 45 | } 46 | } 47 | return sb.toString(); 48 | } 49 | 50 | public boolean getBoolean() { 51 | int pointer = this.pointer; 52 | this.pointer += 1; 53 | 54 | return buffer.substring(pointer, this.pointer).equals("1"); 55 | } 56 | 57 | public void setBoolean(boolean data) { 58 | buffer += data ? "1" : "0"; 59 | } 60 | 61 | public int getSignedInt(int length) { 62 | int pointer = this.pointer; 63 | this.pointer += length; 64 | 65 | return toSignedInt(buffer.substring(pointer, this.pointer)); 66 | } 67 | 68 | public long getSignedLong(int length) { 69 | int pointer = this.pointer; 70 | this.pointer += length; 71 | 72 | return toSignedLong(buffer.substring(pointer, this.pointer)); 73 | } 74 | 75 | public long getUnsignedLong(int length) { 76 | Preconditions.checkArgument(length < 64); 77 | int pointer = this.pointer; 78 | this.pointer += length; 79 | 80 | return Long.parseLong(buffer.substring(pointer, this.pointer), 2); 81 | } 82 | 83 | public int getUnsignedInt(int length) { 84 | Preconditions.checkArgument(length < 32); 85 | int pointer = this.pointer; 86 | this.pointer += length; 87 | 88 | return Integer.parseInt(buffer.substring(pointer, this.pointer), 2); 89 | } 90 | 91 | public void setInt(int data, int length) { 92 | StringBuilder stringBuilder = new StringBuilder(); 93 | for (int i = length - 1; i >= 0; i--) { 94 | int mask = 1 << i; 95 | stringBuilder.append((data & mask) != 0 ? "1" : "0"); 96 | } 97 | buffer += stringBuilder.toString(); 98 | } 99 | 100 | public void setLong(long data, int length) { 101 | StringBuilder stringBuilder = new StringBuilder(); 102 | for (int i = length - 1; i >= 0; i--) { 103 | long mask = 1L << i; 104 | stringBuilder.append((data & mask) != 0 ? "1" : "0"); 105 | } 106 | buffer += stringBuilder.toString(); 107 | } 108 | 109 | public void setString(String str) { 110 | byte[] bytes = str.getBytes(StandardCharsets.ISO_8859_1); 111 | StringBuilder stringBuilder = new StringBuilder(); 112 | for (byte b : bytes) { 113 | stringBuilder.append(toBinaryString(b)); 114 | } 115 | buffer += stringBuilder.toString(); 116 | } 117 | 118 | public void setBitString(String str) { 119 | buffer += str; 120 | } 121 | 122 | public String getString(int length) { 123 | int pointer = this.pointer; 124 | this.pointer += length; 125 | byte[] bString = getByteByString(buffer.substring(pointer, this.pointer)); 126 | return new String(bString, StandardCharsets.ISO_8859_1); 127 | } 128 | 129 | public byte[] getArrayFromBuffer() { 130 | return getByteByString(buffer); 131 | } 132 | 133 | private long toSignedLong(String bits) { 134 | int position = 0; 135 | long answer = 0; 136 | 137 | for (int i = bits.length() - 1; i > 0; i--) { 138 | if (bits.charAt(i) == '1') 139 | answer += (long) Math.pow(2, position); 140 | position++; 141 | } 142 | if (bits.charAt(0) == '1') 143 | answer += (long) Math.pow(2, position) * -1; 144 | return answer; 145 | } 146 | 147 | public int toSignedInt(String bits) { 148 | int position = 0; 149 | int answer = 0; 150 | 151 | for (int i = bits.length() - 1; i > 0; i--) { 152 | if (bits.charAt(i) == '1') 153 | answer += Math.pow(2, position); 154 | position++; 155 | } 156 | if (bits.charAt(0) == '1') 157 | answer += Math.pow(2, position) * -1; 158 | return answer; 159 | } 160 | 161 | private byte[] getByteByString(String binaryString) { 162 | Iterable iterable = Splitter.fixedLength(8).split(binaryString); 163 | byte[] ret = new byte[Iterables.size(iterable)]; 164 | Iterator iterator = iterable.iterator(); 165 | int i = 0; 166 | while (iterator.hasNext()) { 167 | Integer byteAsInt = Integer.parseInt(iterator.next(), 2); 168 | ret[i] = byteAsInt.byteValue(); 169 | i++; 170 | } 171 | return ret; 172 | } 173 | 174 | public byte[] getByteArray() { 175 | Iterable iterable = Splitter.fixedLength(8).split(buffer); 176 | byte[] ret = new byte[Iterables.size(iterable)]; 177 | Iterator iterator = iterable.iterator(); 178 | int i = 0; 179 | while (iterator.hasNext()) { 180 | Integer byteAsInt = Integer.parseInt(iterator.next().toString(), 2); 181 | ret[i] = byteAsInt.byteValue(); 182 | i++; 183 | } 184 | int shift = buffer.length() % 8; 185 | ret[i - 1] = (byte) (ret[i - 1] << (8 - shift)); 186 | 187 | return ret; 188 | } 189 | 190 | @Override 191 | public String toString() { 192 | return buffer; 193 | } 194 | 195 | public String toString(char splitter) { 196 | StringBuilder builder = new StringBuilder(); 197 | for (int i = 0; i < buffer.length(); i += 8) { 198 | builder.append(buffer, i, i + 8); 199 | builder.append(splitter); 200 | } 201 | return builder.toString(); 202 | } 203 | 204 | 205 | } 206 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/protocols/rtcm/messages/MSG1027.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.protocols.rtcm.messages; 2 | 3 | import com.google.common.primitives.Bytes; 4 | import org.dav95s.openNTRIP.protocols.rtcm.assets.CRS3; 5 | import org.dav95s.openNTRIP.utils.binaryParse.BitUtils; 6 | import org.dav95s.openNTRIP.utils.binaryParse.Crc24q; 7 | import org.dav95s.openNTRIP.utils.binaryParse.Normalize; 8 | 9 | import static com.google.common.base.Preconditions.checkArgument; 10 | 11 | public class MSG1027 implements CRS3 { 12 | 13 | private int messageNumber; 14 | private int SystemIdentificationNumber; 15 | private int ProjectionType; 16 | private boolean RectificationFlag = false; 17 | private double LaPC; 18 | private double LoPC; 19 | private double AzIL; 20 | private double RectifiedToSkew; 21 | private double SILppm; 22 | private double EPC; 23 | private double NPC; 24 | 25 | public MSG1027() { 26 | messageNumber = 1027; 27 | } 28 | 29 | public MSG1027(byte[] msg) { 30 | BitUtils bitUtils = new BitUtils(msg); 31 | bitUtils.setPointer(24); 32 | messageNumber = bitUtils.getUnsignedInt(12); 33 | SystemIdentificationNumber = bitUtils.getUnsignedInt(8); 34 | ProjectionType = bitUtils.getUnsignedInt(6); 35 | 36 | RectificationFlag = (bitUtils.getBoolean()); 37 | setLaPC(bitUtils.getSignedLong(34) * 0.000000011); 38 | setLoPC(bitUtils.getSignedLong(35) * 0.000000011); 39 | setAzIL(bitUtils.getUnsignedLong(35) * 0.000000011); 40 | if (RectificationFlag) { 41 | setRectifiedToSkew(bitUtils.getSignedInt(26) * 0.000000011 + AzIL); 42 | } else { 43 | setRectifiedToSkew(bitUtils.getSignedInt(26)); 44 | } 45 | setSILppm((bitUtils.getUnsignedLong(30) * 0.00001d + 993000) / 1000000); 46 | setEPC(bitUtils.getUnsignedLong(36) * 0.001); 47 | setNPC(bitUtils.getSignedLong(35) * 0.001); 48 | } 49 | 50 | public byte[] getBytes() { 51 | BitUtils bitUtils = new BitUtils(); 52 | bitUtils.setBitString("11010011000000"); //preamble + 6 reserved bit 53 | bitUtils.setInt(33, 10); 54 | bitUtils.setInt(messageNumber, 12); 55 | bitUtils.setInt(SystemIdentificationNumber, 8); 56 | bitUtils.setInt(ProjectionType, 6); 57 | bitUtils.setBoolean(RectificationFlag); 58 | bitUtils.setLong(Math.round(LaPC / 0.000000011), 34); 59 | bitUtils.setLong(Math.round(LoPC / 0.000000011), 35); 60 | bitUtils.setLong(Math.round(AzIL / 0.000000011), 35); 61 | if (RectificationFlag) { 62 | bitUtils.setLong(Math.round((RectifiedToSkew - AzIL) / 0.000000011), 26); 63 | } else { 64 | bitUtils.setLong(0, 26); 65 | } 66 | bitUtils.setLong(Math.round((SILppm * 1000000 - 993000) / 0.00001d), 30); 67 | bitUtils.setLong(Math.round(EPC / 0.001), 36); 68 | bitUtils.setLong(Math.round(NPC / 0.001), 35); 69 | 70 | byte[] bytes = bitUtils.getByteArray(); 71 | return Bytes.concat(bytes, Crc24q.crc24q(bytes, bytes.length, 0)); 72 | } 73 | 74 | public int getMessageNumber() { 75 | return messageNumber; 76 | } 77 | 78 | public int getSystemIdentificationNumber() { 79 | return SystemIdentificationNumber; 80 | } 81 | 82 | public void setSystemIdentificationNumber(int systemIdentificationNumber) { 83 | checkArgument(0 <= systemIdentificationNumber && systemIdentificationNumber <= 255); 84 | SystemIdentificationNumber = systemIdentificationNumber; 85 | } 86 | 87 | public int getProjectionType() { 88 | return ProjectionType; 89 | } 90 | 91 | public void setProjectionType(int projectionType) { 92 | checkArgument(0 <= projectionType && projectionType <= 11); 93 | ProjectionType = projectionType; 94 | } 95 | 96 | public double getLaPC() { 97 | return LaPC; 98 | } 99 | 100 | public void setLaPC(double laPC) { 101 | double normalized = Normalize.normalize(laPC, 8); 102 | checkArgument(-90 <= normalized && normalized <= 90); 103 | LaPC = normalized; 104 | } 105 | 106 | public double getLoPC() { 107 | return LoPC; 108 | } 109 | 110 | public void setLoPC(double loPC) { 111 | double normalized = Normalize.normalize(loPC, 8); 112 | checkArgument(-180 <= normalized && normalized <= 180); 113 | LoPC = normalized; 114 | } 115 | 116 | public double getAzIL() { 117 | return AzIL; 118 | } 119 | 120 | public void setAzIL(double azIL) { 121 | double normalized = Normalize.normalize(azIL, 8); 122 | checkArgument(0 <= normalized && normalized <= 360); 123 | AzIL = normalized; 124 | } 125 | 126 | public double getRectifiedToSkew() { 127 | return RectifiedToSkew; 128 | } 129 | 130 | public void setRectifiedToSkew(double rectifiedToSkew) { 131 | double normalized = Normalize.normalize(rectifiedToSkew, 8); 132 | checkArgument(-0.369098741 <= normalized - AzIL && normalized - AzIL <= 0.369098741); 133 | RectificationFlag = true; 134 | RectifiedToSkew = normalized; 135 | } 136 | 137 | public double getSILppm() { 138 | return SILppm; 139 | } 140 | 141 | public void setSILppm(double SILppm) { 142 | double normalized = Normalize.normalize(SILppm, 9); 143 | checkArgument(0.993 <= normalized && normalized <= 1.003737418); 144 | this.SILppm = normalized; 145 | } 146 | 147 | public double getEPC() { 148 | return EPC; 149 | } 150 | 151 | public void setEPC(double EPC) { 152 | double normalized = Normalize.normalize(EPC, 3); 153 | checkArgument(0 <= normalized && normalized <= 68719476.735); 154 | this.EPC = normalized; 155 | } 156 | 157 | public double getNPC() { 158 | return NPC; 159 | } 160 | 161 | public void setNPC(double NPC) { 162 | double normalized = Normalize.normalize(NPC, 3); 163 | checkArgument(-17179869.183 <= normalized && normalized <= 17179869.183); 164 | this.NPC = normalized; 165 | } 166 | 167 | @Override 168 | public String toString() { 169 | return "MSG1027{" + 170 | "messageNumber=" + messageNumber + 171 | ", SystemIdentificationNumber=" + SystemIdentificationNumber + 172 | ", ProjectionType=" + ProjectionType + 173 | ", RectificationFlag=" + RectificationFlag + 174 | ", LaPC=" + LaPC + 175 | ", LoPC=" + LoPC + 176 | ", AzIL=" + AzIL + 177 | ", RectifiedToSkew=" + RectifiedToSkew + 178 | ", SIL=" + SILppm + 179 | ", EPC=" + EPC + 180 | ", NPC=" + NPC + 181 | '}'; 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /src/test/java/org/dav95s/openNTRIP/utils/Geoids/GGFTest.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.utils.Geoids; 2 | 3 | import org.dav95s.openNTRIP.crs.geoids.GGF; 4 | import org.junit.Assert; 5 | import org.junit.Test; 6 | 7 | import static org.dav95s.openNTRIP.utils.geometry.AngleTools.dmsToDecimal; 8 | 9 | public class GGFTest { 10 | 11 | @Test 12 | public void testSpb() { 13 | GGF ggf = new GGF("src/test/resources/geoids/spb.GGF"); 14 | Assert.assertEquals(15.86201, ggf.getValueByPoint(60, 30), 0.00001); 15 | Assert.assertEquals(15.84909, ggf.getValueByPoint(dmsToDecimal(60, 1), dmsToDecimal(30, 1)), 0.00001); 16 | Assert.assertEquals(15.83819, ggf.getValueByPoint(dmsToDecimal(60, 2), dmsToDecimal(30, 2)), 0.00001); 17 | Assert.assertEquals(15.79763, ggf.getValueByPoint(dmsToDecimal(60, 2), dmsToDecimal(31, 2)), 0.00001); 18 | 19 | Assert.assertEquals(15.79657, ggf.getValueByPoint(dmsToDecimal(60, 2, 10), dmsToDecimal(31, 2, 10)), 0.00001); 20 | Assert.assertEquals(15.79553, ggf.getValueByPoint(dmsToDecimal(60, 2, 20), dmsToDecimal(31, 2, 20)), 0.00001); 21 | Assert.assertEquals(15.79450, ggf.getValueByPoint(dmsToDecimal(60, 2, 30), dmsToDecimal(31, 2, 30)), 0.00001); 22 | Assert.assertEquals(15.79349, ggf.getValueByPoint(dmsToDecimal(60, 2, 40), dmsToDecimal(31, 2, 40)), 0.00001); 23 | Assert.assertEquals(15.79250, ggf.getValueByPoint(dmsToDecimal(60, 2, 50), dmsToDecimal(31, 2, 50)), 0.00001); 24 | Assert.assertEquals(15.78683, ggf.getValueByPoint(dmsToDecimal(60, 3, 55), dmsToDecimal(31, 3, 55)), 0.00001); 25 | Assert.assertEquals(15.85548, ggf.getValueByPoint(dmsToDecimal(60, 0, 30), dmsToDecimal(30, 0, 30)), 0.00001); 26 | } 27 | 28 | @Test 29 | public void testEngland() { 30 | GGF ggf = new GGF("src/test/resources/geoids/england.GGF"); 31 | Assert.assertEquals(45.00320, ggf.getValueByPoint(51, 1), 0.00001); 32 | Assert.assertEquals(46.41333, ggf.getValueByPoint(51, -1), 0.00001); 33 | 34 | 35 | Assert.assertEquals(44.99883, ggf.getValueByPoint(dmsToDecimal(51, 3), dmsToDecimal(1, 3)), 0.00001); 36 | Assert.assertEquals(44.99875, ggf.getValueByPoint(dmsToDecimal(51, 3,10), dmsToDecimal(1, 3,10)), 0.00001); 37 | Assert.assertEquals(44.99867, ggf.getValueByPoint(dmsToDecimal(51, 3,20), dmsToDecimal(1, 3,20)), 0.00001); 38 | Assert.assertEquals(44.99857, ggf.getValueByPoint(dmsToDecimal(51, 3,30), dmsToDecimal(1, 3,30)), 0.00001); 39 | Assert.assertEquals(44.99847, ggf.getValueByPoint(dmsToDecimal(51, 3,40), dmsToDecimal(1, 3,40)), 0.00001); 40 | Assert.assertEquals(44.99836, ggf.getValueByPoint(dmsToDecimal(51, 3,50), dmsToDecimal(1, 3,50)), 0.00001); 41 | Assert.assertEquals(44.99830, ggf.getValueByPoint(dmsToDecimal(51, 3,55), dmsToDecimal(1, 3,55)), 0.00001); 42 | 43 | Assert.assertEquals(46.54407, ggf.getValueByPoint(dmsToDecimal(51, 3), dmsToDecimal(-1, 3)), 0.00001); 44 | Assert.assertEquals(46.55101, ggf.getValueByPoint(dmsToDecimal(51, 3,10), dmsToDecimal(-1, 3,10)), 0.00001); 45 | Assert.assertEquals(46.55794, ggf.getValueByPoint(dmsToDecimal(51, 3,20), dmsToDecimal(-1, 3,20)), 0.00001); 46 | Assert.assertEquals(46.56487, ggf.getValueByPoint(dmsToDecimal(51, 3,30), dmsToDecimal(-1, 3,30)), 0.00001); 47 | Assert.assertEquals(46.57180, ggf.getValueByPoint(dmsToDecimal(51, 3,40), dmsToDecimal(-1, 3,40)), 0.00001); 48 | Assert.assertEquals(46.57872, ggf.getValueByPoint(dmsToDecimal(51, 3,50), dmsToDecimal(-1, 3,50)), 0.00001); 49 | Assert.assertEquals(46.58218, ggf.getValueByPoint(dmsToDecimal(51, 3,55), dmsToDecimal(-1, 3,55)), 0.00001); 50 | } 51 | 52 | @Test 53 | public void testAustralia() { 54 | GGF ggf = new GGF("src/test/resources/geoids/australia.GGF"); 55 | Assert.assertEquals(35.06186, ggf.getValueByPoint(-16, 130), 0.00001); 56 | Assert.assertEquals(35.06186, ggf.getValueByPoint(-16, 130), 0.00001); 57 | 58 | Assert.assertEquals(29.24346, ggf.getValueByPoint(dmsToDecimal(-16,55, 2), dmsToDecimal(125,58, 23)), 0.00001); 59 | Assert.assertEquals(29.78914, ggf.getValueByPoint(dmsToDecimal(-16,30, 10), dmsToDecimal(125,30, 10)), 0.00001); 60 | Assert.assertEquals(29.78705, ggf.getValueByPoint(dmsToDecimal(-16,30, 20), dmsToDecimal(125,30, 20)), 0.00001); 61 | Assert.assertEquals(29.78502, ggf.getValueByPoint(dmsToDecimal(-16,30, 30), dmsToDecimal(125,30, 30)), 0.00001); 62 | Assert.assertEquals(29.78306, ggf.getValueByPoint(dmsToDecimal(-16,30, 40), dmsToDecimal(125,30, 40)), 0.00001); 63 | Assert.assertEquals(29.78115, ggf.getValueByPoint(dmsToDecimal(-16,30, 50), dmsToDecimal(125,30, 50)), 0.00001); 64 | Assert.assertEquals(29.78023, ggf.getValueByPoint(dmsToDecimal(-16,30, 55), dmsToDecimal(125,30, 55)), 0.00001); 65 | } 66 | 67 | @Test 68 | public void testFlorida() { 69 | GGF ggf = new GGF("src/test/resources/geoids/florida.GGF"); 70 | Assert.assertEquals(-27.37862, ggf.getValueByPoint(28, -82), 0.00001); 71 | Assert.assertEquals(-29.32500, ggf.getValueByPoint(28, -81), 0.00001); 72 | Assert.assertEquals(-29.06320, ggf.getValueByPoint(dmsToDecimal(28,30,10), dmsToDecimal(-81,30,10)), 0.00001); 73 | Assert.assertEquals(-29.05826, ggf.getValueByPoint(dmsToDecimal(28,30,20), dmsToDecimal(-81,30,20)), 0.00001); 74 | Assert.assertEquals(-29.05338, ggf.getValueByPoint(dmsToDecimal(28,30,30), dmsToDecimal(-81,30,30)), 0.00001); 75 | Assert.assertEquals(-29.04858, ggf.getValueByPoint(dmsToDecimal(28,30,40), dmsToDecimal(-81,30,40)), 0.00001); 76 | Assert.assertEquals(-29.04384, ggf.getValueByPoint(dmsToDecimal(28,30,50), dmsToDecimal(-81,30,50)), 0.00001); 77 | Assert.assertEquals(-29.04149, ggf.getValueByPoint(dmsToDecimal(28,30,55), dmsToDecimal(-81,30,55)), 0.00001); 78 | } 79 | 80 | @Test 81 | public void testBering() { 82 | GGF ggf = new GGF("src/test/resources/geoids/bering.GGF"); 83 | Assert.assertEquals(4.85217, ggf.getValueByPoint(63, 180), 0.00001); 84 | Assert.assertEquals(5.54611, ggf.getValueByPoint(63, 179), 0.00001); 85 | Assert.assertEquals(5.03305, ggf.getValueByPoint(63, -179), 0.00001); 86 | Assert.assertEquals(4.43816, ggf.getValueByPoint(dmsToDecimal(63,30,10), dmsToDecimal(-178,30,10)), 0.00001); 87 | Assert.assertEquals(4.43570, ggf.getValueByPoint(dmsToDecimal(63,30,20), dmsToDecimal(-178,30,20)), 0.00001); 88 | Assert.assertEquals(4.43325, ggf.getValueByPoint(dmsToDecimal(63,30,30), dmsToDecimal(-178,30,30)), 0.00001); 89 | Assert.assertEquals(4.43083, ggf.getValueByPoint(dmsToDecimal(63,30,40), dmsToDecimal(-178,30,40)), 0.00001); 90 | Assert.assertEquals(4.42842, ggf.getValueByPoint(dmsToDecimal(63,30,50), dmsToDecimal(-178,30,50)), 0.00001); 91 | Assert.assertEquals(4.42722, ggf.getValueByPoint(dmsToDecimal(63,30,55), dmsToDecimal(-178,30,55)), 0.00001); 92 | Assert.assertEquals(4.42710, ggf.getValueByPoint(dmsToDecimal(63,30, 55.5F), dmsToDecimal(-178,30,55.5F)), 0.00001); 93 | 94 | } 95 | 96 | } -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/crs/gridShift/ResidualsGrid.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.crs.gridShift; 2 | 3 | import com.harium.storage.kdtree.KDTree; 4 | import com.harium.storage.kdtree.KeyDuplicateException; 5 | import com.harium.storage.kdtree.KeySizeException; 6 | import org.dav95s.openNTRIP.crs.geoids.GGF; 7 | import org.dav95s.openNTRIP.crs.geoids.IGeoid; 8 | import org.dav95s.openNTRIP.database.models.CrsModel; 9 | import org.dav95s.openNTRIP.database.models.GridModel; 10 | import org.dav95s.openNTRIP.protocols.nmea.NMEA; 11 | import org.dav95s.openNTRIP.utils.binaryParse.Normalize; 12 | import org.json.JSONArray; 13 | import org.json.JSONObject; 14 | import org.slf4j.Logger; 15 | import org.slf4j.LoggerFactory; 16 | 17 | import java.util.ArrayList; 18 | import java.util.Arrays; 19 | import java.util.List; 20 | 21 | public class ResidualsGrid { 22 | private final Logger logger = LoggerFactory.getLogger(ResidualsGrid.class.getName()); 23 | //crs boundary box 24 | double area_top; 25 | double area_bottom; 26 | double area_left; 27 | double area_right; 28 | //number of points in the grid 29 | int colCount; 30 | int rowCount; 31 | //resolution of the grid 32 | double dLat0 = 0.004167; 33 | double dLon0 = 0.008333; 34 | 35 | IGeoid geoid; 36 | 37 | // [0],[1],[2],[3],[4],[5],[6],...[N] 38 | // [N+1],[N+2],[N+3],[N+4],[N+5],[N+6],[N+7],... 39 | GridNode[][] grid; 40 | 41 | public ResidualsGrid(int crs_id, JSONObject json, CrsModel model) { 42 | geoid = initGeoid(model.getGeoidPath()); 43 | JSONObject validArea = json.getJSONObject("AreaOfValidity"); 44 | double latC = validArea.getDouble("LatCenter"); 45 | double lonC = validArea.getDouble("LonCenter"); 46 | double height = validArea.getDouble("Height"); 47 | double width = validArea.getDouble("Width"); 48 | 49 | //crs boundary 50 | area_top = latC + height / 2; 51 | area_bottom = latC - height / 2; 52 | area_left = lonC - width / 2; 53 | area_right = lonC + width / 2; 54 | 55 | if (area_left < -180) 56 | area_left += 360; 57 | 58 | if (area_left > 180) 59 | area_left -= 360; 60 | 61 | if (area_right < -180) 62 | area_right += 360; 63 | 64 | if (area_right > 180) 65 | area_right -= 360; 66 | 67 | //resolution of crs grid 68 | colCount = (int) (Math.abs(area_right - area_left) / dLon0); 69 | rowCount = (int) (Math.abs(area_top - area_bottom) / dLat0); 70 | 71 | grid = new GridNode[rowCount][colCount]; 72 | 73 | initGrid(crs_id); 74 | backupGrid(model); 75 | 76 | } 77 | 78 | private void initGrid(int crs_id) { 79 | KDTree kdTree = new KDTree<>(2); 80 | GridModel gridModel = new GridModel(); 81 | 82 | //get from db all geodetic point 83 | ArrayList points = gridModel.getAddGeodeticPointByCrsId(crs_id); 84 | //create spatial index 85 | for (GeodeticPoint point : points) { 86 | try { 87 | kdTree.insert(new double[]{point.north, point.east}, point); 88 | } catch (KeySizeException | KeyDuplicateException e) { 89 | e.printStackTrace(); 90 | } 91 | } 92 | 93 | //delete array from memory 94 | points = null; 95 | 96 | //generate grid 97 | for (int row = 0; row < rowCount; row++) { 98 | for (int col = 0; col < colCount; col++) { 99 | try { 100 | double nodeLat = area_top - row * dLat0; 101 | double nodeLon = area_left + col * dLon0; 102 | //get nearest geodetic point for node of grid 103 | List nearestPoints = kdTree.nearest(new double[]{nodeLat, nodeLon}, 5); 104 | //init node of grid 105 | grid[row][col] = IDW(nearestPoints, nodeLat, nodeLon); 106 | grid[row][col].height = geoid.getValueByPoint(nodeLat, nodeLon); 107 | } catch (KeySizeException e) { 108 | e.printStackTrace(); 109 | } 110 | } 111 | } 112 | 113 | 114 | } 115 | 116 | private GridNode IDW(List gridNodes, double nodeLat, double nodeLon) { 117 | double sum = 0; 118 | for (GeodeticPoint gridNode : gridNodes) { 119 | sum += gridNode.distance(nodeLat, nodeLon); 120 | } 121 | 122 | sum = 1 / sum; 123 | 124 | for (GeodeticPoint GeodeticPoint : gridNodes) { 125 | GeodeticPoint.distance = 1 / GeodeticPoint.distance / sum; 126 | } 127 | 128 | GridNode response = new GridNode(); 129 | response.north = Normalize.normalize(nodeLat, 9); 130 | response.east = Normalize.normalize(nodeLon, 9); 131 | response.dEast = 0; 132 | response.dNorth = 0; 133 | 134 | for (GeodeticPoint gridNode : gridNodes) { 135 | response.dNorth += gridNode.dNorth * gridNode.distance; 136 | response.dEast += gridNode.dEast * gridNode.distance; 137 | } 138 | 139 | response.dNorth = Normalize.normalize(response.dNorth, 9); 140 | response.dEast = Normalize.normalize(response.dEast, 9); 141 | 142 | return response; 143 | } 144 | 145 | public void backupGrid(CrsModel model) { 146 | JSONObject jsonObject = new JSONObject(); 147 | jsonObject.put("top", area_top); 148 | jsonObject.put("bottom", area_bottom); 149 | jsonObject.put("left", area_left); 150 | jsonObject.put("right", area_right); 151 | jsonObject.put("gridWidth", dLon0); 152 | jsonObject.put("gridHeight", dLat0); 153 | jsonObject.put("zone", new JSONArray()); 154 | 155 | JSONArray gridJson = new JSONArray(); 156 | for (int row = 0; row < rowCount; row++) { 157 | for (int col = 0; col < colCount; col++) { 158 | JSONArray cell = new JSONArray(); 159 | cell.put(grid[row][col].dNorth); 160 | cell.put(grid[row][col].dEast); 161 | cell.put(grid[row][col].dH); 162 | gridJson.put(cell); 163 | } 164 | } 165 | jsonObject.put("grid", gridJson); 166 | model.setResidualGrid(jsonObject.toString()); 167 | model.update(); 168 | } 169 | 170 | public GridNode[] get16PointsAroundUser(NMEA.GPSPosition user) { 171 | ArrayList grid16 = new ArrayList<>(16); 172 | int lon = (int) Normalize.normalize((user.lon - area_left) / dLon0, 4) - 1; 173 | int lat = (int) Normalize.normalize((user.lat - area_top) / dLat0, 4) - 1; 174 | for (int x = 0; x < 4; x++) { 175 | grid16.addAll(Arrays.asList(grid[lat + x]).subList(lon, 4 + lon)); 176 | } 177 | return grid16.toArray(new GridNode[16]); 178 | } 179 | 180 | private IGeoid initGeoid(String geoidPath) { 181 | return new GGF(geoidPath); 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /src/main/java/org/dav95s/openNTRIP/database/models/MountPointModel.java: -------------------------------------------------------------------------------- 1 | package org.dav95s.openNTRIP.database.models; 2 | 3 | 4 | import org.dav95s.openNTRIP.database.DataSource; 5 | import org.dav95s.openNTRIP.database.models.assets.Authenticator; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | import java.sql.Connection; 10 | import java.sql.PreparedStatement; 11 | import java.sql.ResultSet; 12 | import java.sql.SQLException; 13 | import java.util.ArrayList; 14 | 15 | public class MountPointModel { 16 | final static private Logger logger = LoggerFactory.getLogger(MountPointModel.class.getName()); 17 | 18 | protected int id; 19 | protected String name; 20 | protected String identifier; 21 | protected String format; 22 | protected String format_details; 23 | protected int carrier; 24 | protected String nav_system; 25 | protected String network; 26 | protected String country; 27 | protected double lat; 28 | protected double lon; 29 | protected boolean nmea; 30 | protected boolean solution; 31 | protected String generator; 32 | protected String compression; 33 | protected Authenticator authenticator; 34 | protected boolean fee; 35 | protected int bitRate; 36 | protected String misc; 37 | protected int caster_id; 38 | protected boolean available; 39 | protected int plugin_id; 40 | protected ArrayList referenceStationIds = new ArrayList<>(); 41 | 42 | public MountPointModel(String name) { 43 | this.name = name; 44 | } 45 | 46 | @Override 47 | public String toString() { 48 | return "STR" + ';' + getName() + ';' + getIdentifier() + ';' + getFormat() + ';' + getFormat_details() + ';' + getCarrier() + ';' + getNav_system() + ';' + getNetwork() + ';' + getCountry() 49 | + ';' + String.format("%.2f", getLat()) + ';' + String.format("%.2f", getLon()) + ';' + (isNmea() ? 1 : 0) + ';' + (isSolution() ? 1 : 0) + ';' + getGenerator() + ';' + getCompression() 50 | + ';' + authenticator + ';' + (isFee() ? 'Y' : 'N') + ';' + getBitRate() + ';' + getMisc() + "\r\n"; 51 | } 52 | 53 | public boolean read() { 54 | String sql = "SELECT *, " + 55 | "(SELECT `name` FROM `reference_stations` WHERE `id` = station_id) AS `stations` " + 56 | "FROM mountpoints " + 57 | "LEFT JOIN mountpoints_stations " + 58 | "ON mountpoints.id=mountpoints_stations.mountpoint_id " + 59 | "WHERE `name` = ?;"; 60 | 61 | try (Connection con = DataSource.getConnection(); 62 | PreparedStatement statement = con.prepareStatement(sql)) { 63 | 64 | statement.setString(1, name); 65 | 66 | try (ResultSet rs = statement.executeQuery()) { 67 | if (rs.next()) { 68 | id = rs.getInt("id"); 69 | identifier = rs.getString("identifier"); 70 | format = rs.getString("format"); 71 | format_details = rs.getString("format_details"); 72 | carrier = rs.getInt("carrier"); 73 | nav_system = rs.getString("nav_system"); 74 | network = rs.getString("network"); 75 | country = rs.getString("country"); 76 | lat = rs.getDouble("latitude"); 77 | lon = rs.getDouble("longitude"); 78 | nmea = rs.getBoolean("nmea"); 79 | solution = rs.getBoolean("solution"); 80 | generator = rs.getString("generator"); 81 | compression = rs.getString("compression"); 82 | setAuthenticator(rs.getString("authenticator")); 83 | fee = rs.getBoolean("fee"); 84 | bitRate = rs.getInt("bitrate"); 85 | misc = rs.getString("misc"); 86 | caster_id = rs.getInt("caster_id"); 87 | available = rs.getBoolean("available"); 88 | plugin_id = rs.getInt("plugin_id"); 89 | referenceStationIds.add(rs.getString("stations")); 90 | } else { 91 | return false; 92 | } 93 | 94 | while (rs.next()) { 95 | referenceStationIds.add(rs.getString("stations")); 96 | } 97 | return true; 98 | } 99 | 100 | } catch (SQLException e) { 101 | logger.error("SQL Error", e); 102 | return false; 103 | } 104 | } 105 | 106 | public ArrayList getReferenceStationIds() { 107 | return referenceStationIds; 108 | } 109 | 110 | public int getId() { 111 | return this.id; 112 | } 113 | 114 | public String getName() { 115 | return this.name; 116 | } 117 | 118 | public String getIdentifier() { 119 | return this.identifier; 120 | } 121 | 122 | public String getFormat() { 123 | return this.format; 124 | } 125 | 126 | public String getFormat_details() { 127 | return this.format_details; 128 | } 129 | 130 | public int getCarrier() { 131 | return this.carrier; 132 | } 133 | 134 | public String getNav_system() { 135 | return this.nav_system; 136 | } 137 | 138 | public String getNetwork() { 139 | return this.network; 140 | } 141 | 142 | public String getCountry() { 143 | return this.country; 144 | } 145 | 146 | public double getLat() { 147 | return this.lat; 148 | } 149 | 150 | public double getLon() { 151 | return this.lon; 152 | } 153 | 154 | public boolean isNmea() { 155 | return this.nmea; 156 | } 157 | 158 | public boolean isSolution() { 159 | return this.solution; 160 | } 161 | 162 | public String getGenerator() { 163 | return this.generator; 164 | } 165 | 166 | public String getCompression() { 167 | return this.compression; 168 | } 169 | 170 | public Authenticator getAuthenticator() { 171 | return this.authenticator; 172 | } 173 | 174 | private void setAuthenticator(String authenticator) { 175 | switch (authenticator) { 176 | case "B": 177 | case "Basic": 178 | this.authenticator = Authenticator.Basic; 179 | break; 180 | case "D": 181 | case "Digest": 182 | this.authenticator = Authenticator.Digest; 183 | break; 184 | default: 185 | this.authenticator = Authenticator.None; 186 | break; 187 | } 188 | } 189 | 190 | public boolean isFee() { 191 | return this.fee; 192 | } 193 | 194 | public int getBitRate() { 195 | return this.bitRate; 196 | } 197 | 198 | public String getMisc() { 199 | return this.misc; 200 | } 201 | 202 | public int getCaster_id() { 203 | return this.caster_id; 204 | } 205 | 206 | public boolean isAvailable() { 207 | return this.available; 208 | } 209 | 210 | public int getPlugin_id() { 211 | return this.plugin_id; 212 | } 213 | } 214 | 215 | 216 | --------------------------------------------------------------------------------