RtcmMessageType.java

  1. /* Copyright 2002-2025 CS GROUP
  2.  * Licensed to CS GROUP (CS) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * CS licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *   http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.orekit.gnss.metric.parser;

  18. import java.util.ArrayList;
  19. import java.util.HashMap;
  20. import java.util.List;
  21. import java.util.Map;
  22. import java.util.regex.Matcher;
  23. import java.util.regex.Pattern;

  24. import org.orekit.errors.OrekitException;
  25. import org.orekit.errors.OrekitMessages;
  26. import org.orekit.gnss.SatelliteSystem;
  27. import org.orekit.gnss.metric.messages.ParsedMessage;
  28. import org.orekit.gnss.metric.messages.common.AccuracyProvider;
  29. import org.orekit.gnss.metric.messages.common.ClockCorrection;
  30. import org.orekit.gnss.metric.messages.common.GlonassUserRangeAccuracy;
  31. import org.orekit.gnss.metric.messages.common.OrbitCorrection;
  32. import org.orekit.gnss.metric.messages.common.SignalInSpaceAccuracy;
  33. import org.orekit.gnss.metric.messages.common.SsrUpdateInterval;
  34. import org.orekit.gnss.metric.messages.common.UserRangeAccuracy;
  35. import org.orekit.gnss.metric.messages.rtcm.correction.Rtcm1057;
  36. import org.orekit.gnss.metric.messages.rtcm.correction.Rtcm1058;
  37. import org.orekit.gnss.metric.messages.rtcm.correction.Rtcm1060;
  38. import org.orekit.gnss.metric.messages.rtcm.correction.Rtcm1063;
  39. import org.orekit.gnss.metric.messages.rtcm.correction.Rtcm1064;
  40. import org.orekit.gnss.metric.messages.rtcm.correction.Rtcm1066;
  41. import org.orekit.gnss.metric.messages.rtcm.correction.Rtcm1240;
  42. import org.orekit.gnss.metric.messages.rtcm.correction.Rtcm1241;
  43. import org.orekit.gnss.metric.messages.rtcm.correction.Rtcm1243;
  44. import org.orekit.gnss.metric.messages.rtcm.correction.RtcmClockCorrectionData;
  45. import org.orekit.gnss.metric.messages.rtcm.correction.RtcmCombinedCorrectionData;
  46. import org.orekit.gnss.metric.messages.rtcm.correction.RtcmCorrectionHeader;
  47. import org.orekit.gnss.metric.messages.rtcm.correction.RtcmOrbitCorrectionData;
  48. import org.orekit.gnss.metric.messages.rtcm.correction.RtcmOrbitCorrectionHeader;
  49. import org.orekit.gnss.metric.messages.rtcm.ephemeris.Rtcm1019;
  50. import org.orekit.gnss.metric.messages.rtcm.ephemeris.Rtcm1019Data;
  51. import org.orekit.gnss.metric.messages.rtcm.ephemeris.Rtcm1020;
  52. import org.orekit.gnss.metric.messages.rtcm.ephemeris.Rtcm1020Data;
  53. import org.orekit.gnss.metric.messages.rtcm.ephemeris.Rtcm1042;
  54. import org.orekit.gnss.metric.messages.rtcm.ephemeris.Rtcm1042Data;
  55. import org.orekit.gnss.metric.messages.rtcm.ephemeris.Rtcm1044;
  56. import org.orekit.gnss.metric.messages.rtcm.ephemeris.Rtcm1044Data;
  57. import org.orekit.gnss.metric.messages.rtcm.ephemeris.Rtcm1045;
  58. import org.orekit.gnss.metric.messages.rtcm.ephemeris.Rtcm1045Data;
  59. import org.orekit.propagation.analytical.gnss.data.BeidouLegacyNavigationMessage;
  60. import org.orekit.propagation.analytical.gnss.data.GLONASSNavigationMessage;
  61. import org.orekit.propagation.analytical.gnss.data.GPSLegacyNavigationMessage;
  62. import org.orekit.propagation.analytical.gnss.data.GalileoNavigationMessage;
  63. import org.orekit.propagation.analytical.gnss.data.QZSSLegacyNavigationMessage;
  64. import org.orekit.time.TimeScales;

  65. /** Enum containing the supported RTCM messages types.
  66. *
  67. * @author Luc Maisonobe
  68. * @author Bryan Cazabonne
  69. *
  70. * @see "RTCM STANDARD 10403.3, DIFFERENTIAL GNSS (GLOBAL NAVIGATION SATELLITE SYSTEMS) SERVICES – VERSION 3, October 2016."
  71. *
  72. * @since 11.0
  73. */
  74. public enum RtcmMessageType implements MessageType {

  75.     /** GPS Ephemeris message. */
  76.     RTCM_1019("1019") {

  77.         /** {@inheritDoc} */
  78.         @Override
  79.         public ParsedMessage parse(final EncodedMessage encodedMessage,
  80.                                    final int messageNumber,
  81.                                    final TimeScales timeScales) {

  82.             // Initialize data container and navigation message
  83.             final Rtcm1019Data         rtcm1019Data  = new Rtcm1019Data();
  84.             final GPSLegacyNavigationMessage gpsNavMessage =
  85.                 new GPSLegacyNavigationMessage(timeScales, SatelliteSystem.GPS);

  86.             // Set the satellite ID
  87.             final int gpsId = RtcmDataField.DF009.intValue(encodedMessage);
  88.             rtcm1019Data.setSatelliteID(gpsId);

  89.             // Week number
  90.             final int gpsWeekNumber = RtcmDataField.DF076.intValue(encodedMessage);
  91.             gpsNavMessage.setWeek(gpsWeekNumber);

  92.             // Accuracy provider
  93.             final AccuracyProvider gpsProvider = new UserRangeAccuracy(RtcmDataField.DF077.intValue(encodedMessage));
  94.             rtcm1019Data.setAccuracyProvider(gpsProvider);
  95.             gpsNavMessage.setSvAccuracy(gpsProvider.getAccuracy());

  96.             // GPS Code on L2
  97.             rtcm1019Data.setGpsCodeOnL2(RtcmDataField.DF078.intValue(encodedMessage));

  98.             // Fill navigation message
  99.             gpsNavMessage.setPRN(gpsId);
  100.             gpsNavMessage.setIDot(RtcmDataField.DF079.doubleValue(encodedMessage));
  101.             gpsNavMessage.setIODE(RtcmDataField.DF071.intValue(encodedMessage));
  102.             rtcm1019Data.setGpsToc(RtcmDataField.DF081.doubleValue(encodedMessage));
  103.             gpsNavMessage.setAf2(RtcmDataField.DF082.doubleValue(encodedMessage));
  104.             gpsNavMessage.setAf1(RtcmDataField.DF083.doubleValue(encodedMessage));
  105.             gpsNavMessage.setAf0(RtcmDataField.DF084.doubleValue(encodedMessage));
  106.             gpsNavMessage.setIODC(RtcmDataField.DF085.intValue(encodedMessage));
  107.             gpsNavMessage.setCrs(RtcmDataField.DF086.doubleValue(encodedMessage));
  108.             gpsNavMessage.setDeltaN0(RtcmDataField.DF087.doubleValue(encodedMessage));
  109.             gpsNavMessage.setM0(RtcmDataField.DF088.doubleValue(encodedMessage));
  110.             gpsNavMessage.setCuc(RtcmDataField.DF089.doubleValue(encodedMessage));
  111.             gpsNavMessage.setE(RtcmDataField.DF090.doubleValue(encodedMessage));
  112.             gpsNavMessage.setCus(RtcmDataField.DF091.doubleValue(encodedMessage));
  113.             gpsNavMessage.setSqrtA(RtcmDataField.DF092.doubleValue(encodedMessage));
  114.             gpsNavMessage.setTime(RtcmDataField.DF093.doubleValue(encodedMessage));
  115.             gpsNavMessage.setCic(RtcmDataField.DF094.doubleValue(encodedMessage));
  116.             gpsNavMessage.setOmega0(RtcmDataField.DF095.doubleValue(encodedMessage));
  117.             gpsNavMessage.setCis(RtcmDataField.DF096.doubleValue(encodedMessage));
  118.             gpsNavMessage.setI0(RtcmDataField.DF097.doubleValue(encodedMessage));
  119.             gpsNavMessage.setCrc(RtcmDataField.DF098.doubleValue(encodedMessage));
  120.             gpsNavMessage.setPa(RtcmDataField.DF099.doubleValue(encodedMessage));
  121.             gpsNavMessage.setOmegaDot(RtcmDataField.DF100.doubleValue(encodedMessage));
  122.             gpsNavMessage.setTGD(RtcmDataField.DF101.doubleValue(encodedMessage));
  123.             gpsNavMessage.setSvHealth(RtcmDataField.DF102.intValue(encodedMessage));

  124.             // Set the navigation message
  125.             rtcm1019Data.setGpsNavigationMessage(gpsNavMessage);

  126.             // L2 P data flag and fit interval
  127.             rtcm1019Data.setGpsL2PDataFlag(RtcmDataField.DF103.booleanValue(encodedMessage));
  128.             rtcm1019Data.setGpsFitInterval(RtcmDataField.DF137.intValue(encodedMessage));

  129.             // Return the parsed message
  130.             return new Rtcm1019(1019, rtcm1019Data);

  131.         }

  132.     },

  133.     /** GLONASS Ephemeris message. */
  134.     RTCM_1020("1020") {

  135.         /** {@inheritDoc} */
  136.         @Override
  137.         public ParsedMessage parse(final EncodedMessage encodedMessage,
  138.                                    final int messageNumber,
  139.                                    final TimeScales timeScales) {

  140.             // Initialize data container and navigation message
  141.             final Rtcm1020Data             rtcm1020Data      = new Rtcm1020Data();
  142.             final GLONASSNavigationMessage glonassNavMessage = new GLONASSNavigationMessage();

  143.             // Set the satellite ID
  144.             final int glonassId = RtcmDataField.DF038.intValue(encodedMessage);
  145.             rtcm1020Data.setSatelliteID(glonassId);

  146.             // Read data
  147.             glonassNavMessage.setPRN(glonassId);
  148.             glonassNavMessage.setFrequencyNumber(RtcmDataField.DF040.intValue(encodedMessage));
  149.             glonassNavMessage.setHealth(RtcmDataField.DF104.intValue(encodedMessage));
  150.             rtcm1020Data.setHealthAvailabilityIndicator(RtcmDataField.DF105.booleanValue(encodedMessage));
  151.             rtcm1020Data.setP1(RtcmDataField.DF106.intValue(encodedMessage));
  152.             rtcm1020Data.setTk(RtcmDataField.DF107.doubleValue(encodedMessage));
  153.             rtcm1020Data.setBN(RtcmDataField.DF108.intValue(encodedMessage));
  154.             rtcm1020Data.setP2(RtcmDataField.DF109.intValue(encodedMessage));
  155.             glonassNavMessage.setTime(RtcmDataField.DF110.doubleValue(encodedMessage));
  156.             glonassNavMessage.setXDot(RtcmDataField.DF111.doubleValue(encodedMessage));
  157.             glonassNavMessage.setX(RtcmDataField.DF112.doubleValue(encodedMessage));
  158.             glonassNavMessage.setXDotDot(RtcmDataField.DF113.doubleValue(encodedMessage));
  159.             glonassNavMessage.setYDot(RtcmDataField.DF114.doubleValue(encodedMessage));
  160.             glonassNavMessage.setY(RtcmDataField.DF115.doubleValue(encodedMessage));
  161.             glonassNavMessage.setYDotDot(RtcmDataField.DF116.doubleValue(encodedMessage));
  162.             glonassNavMessage.setZDot(RtcmDataField.DF117.doubleValue(encodedMessage));
  163.             glonassNavMessage.setZ(RtcmDataField.DF118.doubleValue(encodedMessage));
  164.             glonassNavMessage.setZDotDot(RtcmDataField.DF119.doubleValue(encodedMessage));
  165.             rtcm1020Data.setP3(RtcmDataField.DF120.intValue(encodedMessage));
  166.             glonassNavMessage.setGammaN(RtcmDataField.DF121.doubleValue(encodedMessage));
  167.             rtcm1020Data.setP(RtcmDataField.DF122.intValue(encodedMessage));
  168.             rtcm1020Data.setLNThirdString(RtcmDataField.DF123.intValue(encodedMessage));
  169.             glonassNavMessage.setTauN(RtcmDataField.DF124.doubleValue(encodedMessage));
  170.             rtcm1020Data.setDeltaTN(RtcmDataField.DF125.doubleValue(encodedMessage));
  171.             rtcm1020Data.setEn(RtcmDataField.DF126.intValue(encodedMessage));
  172.             rtcm1020Data.setP4(RtcmDataField.DF127.intValue(encodedMessage));

  173.             // Glonass accuracy
  174.             final int index = RtcmDataField.DF128.intValue(encodedMessage);
  175.             rtcm1020Data.setAccuracyProvider(new GlonassUserRangeAccuracy(index));
  176.             rtcm1020Data.setFT(index);

  177.             // Read other data
  178.             rtcm1020Data.setNt(RtcmDataField.DF129.intValue(encodedMessage));
  179.             rtcm1020Data.setM(RtcmDataField.DF130.intValue(encodedMessage));
  180.             rtcm1020Data.setAreAdditionalDataAvailable(RtcmDataField.DF131.booleanValue(encodedMessage));
  181.             rtcm1020Data.setNA(RtcmDataField.DF132.intValue(encodedMessage));
  182.             rtcm1020Data.setTauC(RtcmDataField.DF133.doubleValue(encodedMessage));
  183.             rtcm1020Data.setN4(RtcmDataField.DF134.intValue(encodedMessage));
  184.             rtcm1020Data.setTauGps(RtcmDataField.DF135.doubleValue(encodedMessage));
  185.             rtcm1020Data.setLNFifthString(RtcmDataField.DF136.intValue(encodedMessage));

  186.             // Set the navigation message
  187.             rtcm1020Data.setGlonassNavigationMessage(glonassNavMessage);

  188.             // Return the parsed message
  189.             return new Rtcm1020(1020, rtcm1020Data);
  190.         }


  191.     },

  192.     /** Beidou Ephemeris message. */
  193.     RTCM_1042("1042") {

  194.         /** {@inheritDoc} */
  195.         @Override
  196.         public ParsedMessage parse(final EncodedMessage encodedMessage,
  197.                                    final int messageNumber,
  198.                                    final TimeScales timeScales) {

  199.             // Initialize data container and navigation message
  200.             final Rtcm1042Data            rtcm1042Data  = new Rtcm1042Data();
  201.             final BeidouLegacyNavigationMessage beidouNavMessage =
  202.                 new BeidouLegacyNavigationMessage(timeScales, SatelliteSystem.BEIDOU);

  203.             // Set the satellite ID
  204.             final int beidouId = RtcmDataField.DF488.intValue(encodedMessage);
  205.             rtcm1042Data.setSatelliteID(beidouId);

  206.             // Week number
  207.             final int beidouWeekNumber = RtcmDataField.DF489.intValue(encodedMessage);
  208.             beidouNavMessage.setWeek(beidouWeekNumber);

  209.             // Accuracy provider
  210.             final AccuracyProvider beidouProvider = new UserRangeAccuracy(RtcmDataField.DF490.intValue(encodedMessage));
  211.             rtcm1042Data.setAccuracyProvider(beidouProvider);
  212.             beidouNavMessage.setSvAccuracy(beidouProvider.getAccuracy());

  213.             // Fill navigation message
  214.             beidouNavMessage.setPRN(beidouId);
  215.             beidouNavMessage.setIDot(RtcmDataField.DF491.doubleValue(encodedMessage));
  216.             beidouNavMessage.setAODE(RtcmDataField.DF492.intValue(encodedMessage));
  217.             rtcm1042Data.setBeidouToc(RtcmDataField.DF493.doubleValue(encodedMessage));
  218.             beidouNavMessage.setAf2(RtcmDataField.DF494.doubleValue(encodedMessage));
  219.             beidouNavMessage.setAf1(RtcmDataField.DF495.doubleValue(encodedMessage));
  220.             beidouNavMessage.setAf0(RtcmDataField.DF496.doubleValue(encodedMessage));
  221.             beidouNavMessage.setAODC(RtcmDataField.DF497.intValue(encodedMessage));
  222.             beidouNavMessage.setCrs(RtcmDataField.DF498.doubleValue(encodedMessage));
  223.             beidouNavMessage.setDeltaN0(RtcmDataField.DF499.doubleValue(encodedMessage));
  224.             beidouNavMessage.setM0(RtcmDataField.DF500.doubleValue(encodedMessage));
  225.             beidouNavMessage.setCuc(RtcmDataField.DF501.doubleValue(encodedMessage));
  226.             beidouNavMessage.setE(RtcmDataField.DF502.doubleValue(encodedMessage));
  227.             beidouNavMessage.setCus(RtcmDataField.DF503.doubleValue(encodedMessage));
  228.             beidouNavMessage.setSqrtA(RtcmDataField.DF504.doubleValue(encodedMessage));
  229.             beidouNavMessage.setTime(RtcmDataField.DF505.doubleValue(encodedMessage));
  230.             beidouNavMessage.setCic(RtcmDataField.DF506.doubleValue(encodedMessage));
  231.             beidouNavMessage.setOmega0(RtcmDataField.DF507.doubleValue(encodedMessage));
  232.             beidouNavMessage.setCis(RtcmDataField.DF508.doubleValue(encodedMessage));
  233.             beidouNavMessage.setI0(RtcmDataField.DF509.doubleValue(encodedMessage));
  234.             beidouNavMessage.setCrc(RtcmDataField.DF510.doubleValue(encodedMessage));
  235.             beidouNavMessage.setPa(RtcmDataField.DF511.doubleValue(encodedMessage));
  236.             beidouNavMessage.setOmegaDot(RtcmDataField.DF512.doubleValue(encodedMessage));
  237.             beidouNavMessage.setTGD1(RtcmDataField.DF513.doubleValue(encodedMessage));
  238.             beidouNavMessage.setTGD2(RtcmDataField.DF514.doubleValue(encodedMessage));
  239.             rtcm1042Data.setSvHealth(RtcmDataField.DF515.intValue(encodedMessage));

  240.             // Set the navigation message
  241.             rtcm1042Data.setBeidouNavigationMessage(beidouNavMessage);

  242.             // Return the parsed message
  243.             return new Rtcm1042(1042, rtcm1042Data);

  244.         }

  245.     },

  246.     /** QZSS Ephemeris message. */
  247.     RTCM_1044("1044") {

  248.         /** {@inheritDoc} */
  249.         @Override
  250.         public ParsedMessage parse(final EncodedMessage encodedMessage,
  251.                                    final int messageNumber, final TimeScales timeScales) {

  252.             // Initialize data container and navigation message
  253.             final Rtcm1044Data          rtcm1044Data   = new Rtcm1044Data();
  254.             final QZSSLegacyNavigationMessage qzssNavMessage =
  255.                 new QZSSLegacyNavigationMessage(timeScales, SatelliteSystem.QZSS);

  256.             // Set the satellite ID
  257.             final int qzssId = RtcmDataField.DF429.intValue(encodedMessage);
  258.             rtcm1044Data.setSatelliteID(qzssId);

  259.             // Fill navigation message
  260.             qzssNavMessage.setPRN(qzssId);
  261.             rtcm1044Data.setQzssToc(RtcmDataField.DF430.doubleValue(encodedMessage));
  262.             qzssNavMessage.setAf2(RtcmDataField.DF431.doubleValue(encodedMessage));
  263.             qzssNavMessage.setAf1(RtcmDataField.DF432.doubleValue(encodedMessage));
  264.             qzssNavMessage.setAf0(RtcmDataField.DF433.doubleValue(encodedMessage));
  265.             qzssNavMessage.setIODE(RtcmDataField.DF434.intValue(encodedMessage));
  266.             qzssNavMessage.setCrs(RtcmDataField.DF435.doubleValue(encodedMessage));
  267.             qzssNavMessage.setDeltaN0(RtcmDataField.DF436.doubleValue(encodedMessage));
  268.             qzssNavMessage.setM0(RtcmDataField.DF437.doubleValue(encodedMessage));
  269.             qzssNavMessage.setCuc(RtcmDataField.DF438.doubleValue(encodedMessage));
  270.             qzssNavMessage.setE(RtcmDataField.DF439.doubleValue(encodedMessage));
  271.             qzssNavMessage.setCus(RtcmDataField.DF440.doubleValue(encodedMessage));
  272.             qzssNavMessage.setSqrtA(RtcmDataField.DF441.doubleValue(encodedMessage));
  273.             qzssNavMessage.setTime(RtcmDataField.DF442.doubleValue(encodedMessage));
  274.             qzssNavMessage.setCic(RtcmDataField.DF443.doubleValue(encodedMessage));
  275.             qzssNavMessage.setOmega0(RtcmDataField.DF444.doubleValue(encodedMessage));
  276.             qzssNavMessage.setCis(RtcmDataField.DF445.doubleValue(encodedMessage));
  277.             qzssNavMessage.setI0(RtcmDataField.DF446.doubleValue(encodedMessage));
  278.             qzssNavMessage.setCrc(RtcmDataField.DF447.doubleValue(encodedMessage));
  279.             qzssNavMessage.setPa(RtcmDataField.DF448.doubleValue(encodedMessage));
  280.             qzssNavMessage.setOmegaDot(RtcmDataField.DF449.doubleValue(encodedMessage));
  281.             qzssNavMessage.setIDot(RtcmDataField.DF450.doubleValue(encodedMessage));

  282.             // QZSS Code on L2
  283.             rtcm1044Data.setQzssCodeOnL2(RtcmDataField.DF451.intValue(encodedMessage));

  284.             // Week number
  285.             qzssNavMessage.setWeek(RtcmDataField.DF452.intValue(encodedMessage));

  286.             // Accuracy provider
  287.             final AccuracyProvider qzssProvider = new UserRangeAccuracy(RtcmDataField.DF453.intValue(encodedMessage));
  288.             rtcm1044Data.setAccuracyProvider(qzssProvider);
  289.             qzssNavMessage.setSvAccuracy(qzssProvider.getAccuracy());

  290.             // Health
  291.             qzssNavMessage.setSvHealth(RtcmDataField.DF454.intValue(encodedMessage));

  292.             // Tgd, IODC, and fit interval
  293.             qzssNavMessage.setTGD(RtcmDataField.DF455.doubleValue(encodedMessage));
  294.             qzssNavMessage.setIODC(RtcmDataField.DF456.intValue(encodedMessage));
  295.             rtcm1044Data.setQzssFitInterval(RtcmDataField.DF457.intValue(encodedMessage));

  296.             // Set the navigation message
  297.             rtcm1044Data.setQzssNavigationMessage(qzssNavMessage);

  298.             // Return the parsed message
  299.             return new Rtcm1044(1044, rtcm1044Data);

  300.         }

  301.     },

  302.     /** Galileo F/NAV Ephemeris message. */
  303.     RTCM_1045("1045") {

  304.         /** {@inheritDoc} */
  305.         @Override
  306.         public ParsedMessage parse(final EncodedMessage encodedMessage,
  307.                                    final int messageNumber,
  308.                                    final TimeScales timeScales) {

  309.             // Initialize data container and navigation message
  310.             final Rtcm1045Data             rtcm1045Data      = new Rtcm1045Data();
  311.             final GalileoNavigationMessage galileoNavMessage =
  312.                 new GalileoNavigationMessage(timeScales, SatelliteSystem.GALILEO);

  313.             // Set the satellite ID
  314.             final int galileoId = RtcmDataField.DF252.intValue(encodedMessage);
  315.             rtcm1045Data.setSatelliteID(galileoId);

  316.             // Week number
  317.             final int galileoWeekNumber = RtcmDataField.DF289.intValue(encodedMessage);
  318.             galileoNavMessage.setWeek(galileoWeekNumber);

  319.             // IODNav
  320.             galileoNavMessage.setIODNav(RtcmDataField.DF290.intValue(encodedMessage));

  321.             // Accuracy provider
  322.             final AccuracyProvider galileoProvider = new SignalInSpaceAccuracy(RtcmDataField.DF291.intValue(encodedMessage));
  323.             rtcm1045Data.setAccuracyProvider(galileoProvider);
  324.             galileoNavMessage.setSisa(galileoProvider.getAccuracy());

  325.             // Fill navigation message
  326.             galileoNavMessage.setPRN(galileoId);
  327.             galileoNavMessage.setIDot(RtcmDataField.DF292.doubleValue(encodedMessage));
  328.             rtcm1045Data.setGalileoToc(RtcmDataField.DF293.doubleValue(encodedMessage));
  329.             galileoNavMessage.setAf2(RtcmDataField.DF294.doubleValue(encodedMessage));
  330.             galileoNavMessage.setAf1(RtcmDataField.DF295.doubleValue(encodedMessage));
  331.             galileoNavMessage.setAf0(RtcmDataField.DF296.doubleValue(encodedMessage));
  332.             galileoNavMessage.setCrs(RtcmDataField.DF297.doubleValue(encodedMessage));
  333.             galileoNavMessage.setDeltaN0(RtcmDataField.DF298.doubleValue(encodedMessage));
  334.             galileoNavMessage.setM0(RtcmDataField.DF299.doubleValue(encodedMessage));
  335.             galileoNavMessage.setCuc(RtcmDataField.DF300.doubleValue(encodedMessage));
  336.             galileoNavMessage.setE(RtcmDataField.DF301.doubleValue(encodedMessage));
  337.             galileoNavMessage.setCus(RtcmDataField.DF302.doubleValue(encodedMessage));
  338.             galileoNavMessage.setSqrtA(RtcmDataField.DF303.doubleValue(encodedMessage));
  339.             galileoNavMessage.setTime(RtcmDataField.DF304.doubleValue(encodedMessage));
  340.             galileoNavMessage.setCic(RtcmDataField.DF305.doubleValue(encodedMessage));
  341.             galileoNavMessage.setOmega0(RtcmDataField.DF306.doubleValue(encodedMessage));
  342.             galileoNavMessage.setCis(RtcmDataField.DF307.doubleValue(encodedMessage));
  343.             galileoNavMessage.setI0(RtcmDataField.DF308.doubleValue(encodedMessage));
  344.             galileoNavMessage.setCrc(RtcmDataField.DF309.doubleValue(encodedMessage));
  345.             galileoNavMessage.setPa(RtcmDataField.DF310.doubleValue(encodedMessage));
  346.             galileoNavMessage.setOmegaDot(RtcmDataField.DF311.doubleValue(encodedMessage));
  347.             galileoNavMessage.setBGDE1E5a(RtcmDataField.DF312.doubleValue(encodedMessage));
  348.             galileoNavMessage.setSvHealth(RtcmDataField.DF314.intValue(encodedMessage));

  349.             // Set the navigation message
  350.             rtcm1045Data.setGalileoNavigationMessage(galileoNavMessage);

  351.             // NAV data validity status
  352.             rtcm1045Data.setGalileoDataValidityStatus(RtcmDataField.DF315.intValue(encodedMessage));

  353.             // Return the parsed message
  354.             return new Rtcm1045(1045, rtcm1045Data);

  355.         }

  356.     },

  357.     /** GPS Orbit Correction. */
  358.     RTCM_1057("1057") {

  359.         /** {@inheritDoc} */
  360.         @Override
  361.         public ParsedMessage parse(final EncodedMessage encodedMessage, final int messageNumber,
  362.                                    final TimeScales timeScales) {

  363.             // Header data
  364.             final RtcmOrbitCorrectionHeader rtcm1057Header = new RtcmOrbitCorrectionHeader();
  365.             rtcm1057Header.setEpochTime1s(RtcmDataField.DF385.intValue(encodedMessage));
  366.             rtcm1057Header.setSsrUpdateInterval(new SsrUpdateInterval(RtcmDataField.DF391.intValue(encodedMessage)));
  367.             rtcm1057Header.setMultipleMessageIndicator(RtcmDataField.DF388.intValue(encodedMessage));
  368.             rtcm1057Header.setSatelliteReferenceDatum(RtcmDataField.DF375.intValue(encodedMessage));
  369.             rtcm1057Header.setIodSsr(RtcmDataField.DF413.intValue(encodedMessage));
  370.             rtcm1057Header.setSsrProviderId(RtcmDataField.DF414.intValue(encodedMessage));
  371.             rtcm1057Header.setSsrSolutionId(RtcmDataField.DF415.intValue(encodedMessage));

  372.             // Number of satellites
  373.             final int satNumber = RtcmDataField.DF387.intValue(encodedMessage);
  374.             rtcm1057Header.setNumberOfSatellites(satNumber);

  375.             // Initialize list of data
  376.             final List<RtcmOrbitCorrectionData> rtcm1057Data = new ArrayList<>();

  377.             // Loop on satellites and fill data
  378.             for (int index = 0; index < satNumber; index++) {

  379.                 // Satellite ID
  380.                 final int rtcm1057SatId = RtcmDataField.DF068.intValue(encodedMessage);

  381.                 // GNSS IOD
  382.                 final int rtcm1057Iod = RtcmDataField.DF071.intValue(encodedMessage);

  383.                 // Orbit correction
  384.                 final OrbitCorrection rtcm1057OrbitCorr =
  385.                                 new OrbitCorrection(RtcmDataField.DF365.doubleValue(encodedMessage),
  386.                                                     RtcmDataField.DF366.doubleValue(encodedMessage),
  387.                                                     RtcmDataField.DF367.doubleValue(encodedMessage),
  388.                                                     RtcmDataField.DF368.doubleValue(encodedMessage),
  389.                                                     RtcmDataField.DF369.doubleValue(encodedMessage),
  390.                                                     RtcmDataField.DF370.doubleValue(encodedMessage));

  391.                 // Initialize a new container and fill data
  392.                 final RtcmOrbitCorrectionData currentRtcm1057Data = new RtcmOrbitCorrectionData();
  393.                 currentRtcm1057Data.setSatelliteID(rtcm1057SatId);
  394.                 currentRtcm1057Data.setGnssIod(rtcm1057Iod);
  395.                 currentRtcm1057Data.setOrbitCorrection(rtcm1057OrbitCorr);

  396.                 // Update the list
  397.                 rtcm1057Data.add(currentRtcm1057Data);

  398.             }

  399.             // Return the parsed message
  400.             return new Rtcm1057(messageNumber, rtcm1057Header, rtcm1057Data);

  401.         }

  402.     },

  403.     /** GPS Clock Correction. */
  404.     RTCM_1058("1058") {

  405.         /** {@inheritDoc} */
  406.         @Override
  407.         public ParsedMessage parse(final EncodedMessage encodedMessage, final int messageNumber,
  408.                                    final TimeScales timeScales) {

  409.             // Header data
  410.             final RtcmCorrectionHeader rtcm1058Header = new RtcmCorrectionHeader();
  411.             rtcm1058Header.setEpochTime1s(RtcmDataField.DF385.intValue(encodedMessage));
  412.             rtcm1058Header.setSsrUpdateInterval(new SsrUpdateInterval(RtcmDataField.DF391.intValue(encodedMessage)));
  413.             rtcm1058Header.setMultipleMessageIndicator(RtcmDataField.DF388.intValue(encodedMessage));
  414.             rtcm1058Header.setIodSsr(RtcmDataField.DF413.intValue(encodedMessage));
  415.             rtcm1058Header.setSsrProviderId(RtcmDataField.DF414.intValue(encodedMessage));
  416.             rtcm1058Header.setSsrSolutionId(RtcmDataField.DF415.intValue(encodedMessage));

  417.             // Number of satellites
  418.             final int satNumber = RtcmDataField.DF387.intValue(encodedMessage);
  419.             rtcm1058Header.setNumberOfSatellites(satNumber);

  420.             // Initialize list of data
  421.             final List<RtcmClockCorrectionData> rtcm1058Data = new ArrayList<>();

  422.             // Loop on satellites and fill data
  423.             for (int index = 0; index < satNumber; index++) {

  424.                 // Satellite ID
  425.                 final int rtcm1058SatId = RtcmDataField.DF068.intValue(encodedMessage);

  426.                 // Clock correction
  427.                 final ClockCorrection rtcm1058ClockCorr =
  428.                                 new ClockCorrection(RtcmDataField.DF376.doubleValue(encodedMessage),
  429.                                                     RtcmDataField.DF377.doubleValue(encodedMessage),
  430.                                                     RtcmDataField.DF378.doubleValue(encodedMessage));

  431.                 // Initialize a new container and fill data
  432.                 final RtcmClockCorrectionData currentRtcm1058Data = new RtcmClockCorrectionData();
  433.                 currentRtcm1058Data.setSatelliteID(rtcm1058SatId);
  434.                 currentRtcm1058Data.setClockCorrection(rtcm1058ClockCorr);

  435.                 // Update the list
  436.                 rtcm1058Data.add(currentRtcm1058Data);

  437.             }

  438.             // Return the parsed message
  439.             return new Rtcm1058(messageNumber, rtcm1058Header, rtcm1058Data);

  440.         }

  441.     },

  442.     /** GPS Combined Orbit and Clock Correction. */
  443.     RTCM_1060("1060") {

  444.         /** {@inheritDoc} */
  445.         @Override
  446.         public ParsedMessage parse(final EncodedMessage encodedMessage, final int messageNumber,
  447.                                    final TimeScales timeScales) {

  448.             // Header data
  449.             final RtcmOrbitCorrectionHeader rtcm1060Header = new RtcmOrbitCorrectionHeader();
  450.             rtcm1060Header.setEpochTime1s(RtcmDataField.DF385.intValue(encodedMessage));
  451.             rtcm1060Header.setSsrUpdateInterval(new SsrUpdateInterval(RtcmDataField.DF391.intValue(encodedMessage)));
  452.             rtcm1060Header.setMultipleMessageIndicator(RtcmDataField.DF388.intValue(encodedMessage));
  453.             rtcm1060Header.setSatelliteReferenceDatum(RtcmDataField.DF375.intValue(encodedMessage));
  454.             rtcm1060Header.setIodSsr(RtcmDataField.DF413.intValue(encodedMessage));
  455.             rtcm1060Header.setSsrProviderId(RtcmDataField.DF414.intValue(encodedMessage));
  456.             rtcm1060Header.setSsrSolutionId(RtcmDataField.DF415.intValue(encodedMessage));

  457.             // Number of satellites
  458.             final int satNumber = RtcmDataField.DF387.intValue(encodedMessage);
  459.             rtcm1060Header.setNumberOfSatellites(satNumber);

  460.             // Initialize list of data
  461.             final List<RtcmCombinedCorrectionData> rtcm1060Data = new ArrayList<>();

  462.             // Loop on satellites and fill data
  463.             for (int index = 0; index < satNumber; index++) {

  464.                 // Satellite ID
  465.                 final int rtcm1060SatId = RtcmDataField.DF068.intValue(encodedMessage);

  466.                 // GNSS IOD
  467.                 final int rtcm1060Iod = RtcmDataField.DF071.intValue(encodedMessage);

  468.                 // Orbit correction
  469.                 final OrbitCorrection rtcm1060OrbitCorr =
  470.                                 new OrbitCorrection(RtcmDataField.DF365.doubleValue(encodedMessage),
  471.                                                     RtcmDataField.DF366.doubleValue(encodedMessage),
  472.                                                     RtcmDataField.DF367.doubleValue(encodedMessage),
  473.                                                     RtcmDataField.DF368.doubleValue(encodedMessage),
  474.                                                     RtcmDataField.DF369.doubleValue(encodedMessage),
  475.                                                     RtcmDataField.DF370.doubleValue(encodedMessage));

  476.                 // Clock correction
  477.                 final ClockCorrection rtcm1060ClockCorr =
  478.                                 new ClockCorrection(RtcmDataField.DF376.doubleValue(encodedMessage),
  479.                                                     RtcmDataField.DF377.doubleValue(encodedMessage),
  480.                                                     RtcmDataField.DF378.doubleValue(encodedMessage));

  481.                 // Initialize a new container and fill data
  482.                 final RtcmCombinedCorrectionData currentRtcm1060Data = new RtcmCombinedCorrectionData();
  483.                 currentRtcm1060Data.setSatelliteID(rtcm1060SatId);
  484.                 currentRtcm1060Data.setGnssIod(rtcm1060Iod);
  485.                 currentRtcm1060Data.setOrbitCorrection(rtcm1060OrbitCorr);
  486.                 currentRtcm1060Data.setClockCorrection(rtcm1060ClockCorr);

  487.                 // Update the list
  488.                 rtcm1060Data.add(currentRtcm1060Data);

  489.             }

  490.             // Return the parsed message
  491.             return new Rtcm1060(messageNumber, rtcm1060Header, rtcm1060Data);

  492.         }

  493.     },

  494.     /** GLONASS Orbit Correction. */
  495.     RTCM_1063("1063") {

  496.         /** {@inheritDoc} */
  497.         @Override
  498.         public ParsedMessage parse(final EncodedMessage encodedMessage, final int messageNumber,
  499.                                    final TimeScales timeScales) {

  500.             // Header data
  501.             final RtcmOrbitCorrectionHeader rtcm1063Header = new RtcmOrbitCorrectionHeader();
  502.             rtcm1063Header.setEpochTime1s(RtcmDataField.DF386.intValue(encodedMessage));
  503.             rtcm1063Header.setSsrUpdateInterval(new SsrUpdateInterval(RtcmDataField.DF391.intValue(encodedMessage)));
  504.             rtcm1063Header.setMultipleMessageIndicator(RtcmDataField.DF388.intValue(encodedMessage));
  505.             rtcm1063Header.setSatelliteReferenceDatum(RtcmDataField.DF375.intValue(encodedMessage));
  506.             rtcm1063Header.setIodSsr(RtcmDataField.DF413.intValue(encodedMessage));
  507.             rtcm1063Header.setSsrProviderId(RtcmDataField.DF414.intValue(encodedMessage));
  508.             rtcm1063Header.setSsrSolutionId(RtcmDataField.DF415.intValue(encodedMessage));

  509.             // Number of satellites
  510.             final int satNumber = RtcmDataField.DF387.intValue(encodedMessage);
  511.             rtcm1063Header.setNumberOfSatellites(satNumber);

  512.             // Initialize list of data
  513.             final List<RtcmOrbitCorrectionData> rtcm1063Data = new ArrayList<>();

  514.             // Loop on satellites and fill data
  515.             for (int index = 0; index < satNumber; index++) {

  516.                 // Satellite ID
  517.                 final int rtcm1063SatId = RtcmDataField.DF384.intValue(encodedMessage);

  518.                 // GNSS IOD
  519.                 final int rtcm1063Iod = RtcmDataField.DF392.intValue(encodedMessage);

  520.                 // Orbit correction
  521.                 final OrbitCorrection rtcm1063OrbitCorr =
  522.                                 new OrbitCorrection(RtcmDataField.DF365.doubleValue(encodedMessage),
  523.                                                     RtcmDataField.DF366.doubleValue(encodedMessage),
  524.                                                     RtcmDataField.DF367.doubleValue(encodedMessage),
  525.                                                     RtcmDataField.DF368.doubleValue(encodedMessage),
  526.                                                     RtcmDataField.DF369.doubleValue(encodedMessage),
  527.                                                     RtcmDataField.DF370.doubleValue(encodedMessage));

  528.                 // Initialize a new container and fill data
  529.                 final RtcmOrbitCorrectionData currentRtcm1063Data = new RtcmOrbitCorrectionData();
  530.                 currentRtcm1063Data.setSatelliteID(rtcm1063SatId);
  531.                 currentRtcm1063Data.setGnssIod(rtcm1063Iod);
  532.                 currentRtcm1063Data.setOrbitCorrection(rtcm1063OrbitCorr);

  533.                 // Update the list
  534.                 rtcm1063Data.add(currentRtcm1063Data);

  535.             }

  536.             // Return the parsed message
  537.             return new Rtcm1063(messageNumber, rtcm1063Header, rtcm1063Data);

  538.         }

  539.     },

  540.     /** GLONASS Clock Correction. */
  541.     RTCM_1064("1064") {

  542.         /** {@inheritDoc} */
  543.         @Override
  544.         public ParsedMessage parse(final EncodedMessage encodedMessage, final int messageNumber,
  545.                                    final TimeScales timeScales) {

  546.             // Header data
  547.             final RtcmCorrectionHeader rtcm1064Header = new RtcmCorrectionHeader();
  548.             rtcm1064Header.setEpochTime1s(RtcmDataField.DF386.intValue(encodedMessage));
  549.             rtcm1064Header.setSsrUpdateInterval(new SsrUpdateInterval(RtcmDataField.DF391.intValue(encodedMessage)));
  550.             rtcm1064Header.setMultipleMessageIndicator(RtcmDataField.DF388.intValue(encodedMessage));
  551.             rtcm1064Header.setIodSsr(RtcmDataField.DF413.intValue(encodedMessage));
  552.             rtcm1064Header.setSsrProviderId(RtcmDataField.DF414.intValue(encodedMessage));
  553.             rtcm1064Header.setSsrSolutionId(RtcmDataField.DF415.intValue(encodedMessage));

  554.             // Number of satellites
  555.             final int satNumber = RtcmDataField.DF387.intValue(encodedMessage);
  556.             rtcm1064Header.setNumberOfSatellites(satNumber);

  557.             // Initialize list of data
  558.             final List<RtcmClockCorrectionData> rtcm1064Data = new ArrayList<>();

  559.             // Loop on satellites and fill data
  560.             for (int index = 0; index < satNumber; index++) {

  561.                 // Satellite ID
  562.                 final int rtcm1064SatId = RtcmDataField.DF384.intValue(encodedMessage);

  563.                 // Clock correction
  564.                 final ClockCorrection rtcm1064ClockCorr =
  565.                                 new ClockCorrection(RtcmDataField.DF376.doubleValue(encodedMessage),
  566.                                                     RtcmDataField.DF377.doubleValue(encodedMessage),
  567.                                                     RtcmDataField.DF378.doubleValue(encodedMessage));

  568.                 // Initialize a new container and fill data
  569.                 final RtcmClockCorrectionData currentRtcm1058Data = new RtcmClockCorrectionData();
  570.                 currentRtcm1058Data.setSatelliteID(rtcm1064SatId);
  571.                 currentRtcm1058Data.setClockCorrection(rtcm1064ClockCorr);

  572.                 // Update the list
  573.                 rtcm1064Data.add(currentRtcm1058Data);

  574.             }

  575.             // Return the parsed message
  576.             return new Rtcm1064(messageNumber, rtcm1064Header, rtcm1064Data);

  577.         }

  578.     },

  579.     /** GLONASS Combined Orbit and Clock Correction. */
  580.     RTCM_1066("1066") {

  581.         /** {@inheritDoc} */
  582.         @Override
  583.         public ParsedMessage parse(final EncodedMessage encodedMessage, final int messageNumber,
  584.                                    final TimeScales timeScales) {

  585.             // Header data
  586.             final RtcmOrbitCorrectionHeader rtcm1066Header = new RtcmOrbitCorrectionHeader();
  587.             rtcm1066Header.setEpochTime1s(RtcmDataField.DF386.intValue(encodedMessage));
  588.             rtcm1066Header.setSsrUpdateInterval(new SsrUpdateInterval(RtcmDataField.DF391.intValue(encodedMessage)));
  589.             rtcm1066Header.setMultipleMessageIndicator(RtcmDataField.DF388.intValue(encodedMessage));
  590.             rtcm1066Header.setSatelliteReferenceDatum(RtcmDataField.DF375.intValue(encodedMessage));
  591.             rtcm1066Header.setIodSsr(RtcmDataField.DF413.intValue(encodedMessage));
  592.             rtcm1066Header.setSsrProviderId(RtcmDataField.DF414.intValue(encodedMessage));
  593.             rtcm1066Header.setSsrSolutionId(RtcmDataField.DF415.intValue(encodedMessage));

  594.             // Number of satellites
  595.             final int satNumber = RtcmDataField.DF387.intValue(encodedMessage);
  596.             rtcm1066Header.setNumberOfSatellites(satNumber);

  597.             // Initialize list of data
  598.             final List<RtcmCombinedCorrectionData> rtcm1066Data = new ArrayList<>();

  599.             // Loop on satellites and fill data
  600.             for (int index = 0; index < satNumber; index++) {

  601.                 // Satellite ID
  602.                 final int rtcm1066SatId = RtcmDataField.DF384.intValue(encodedMessage);

  603.                 // GNSS IOD
  604.                 final int rtcm1066Iod = RtcmDataField.DF392.intValue(encodedMessage);

  605.                 // Orbit correction
  606.                 final OrbitCorrection rtcm1066OrbitCorr =
  607.                                 new OrbitCorrection(RtcmDataField.DF365.doubleValue(encodedMessage),
  608.                                                     RtcmDataField.DF366.doubleValue(encodedMessage),
  609.                                                     RtcmDataField.DF367.doubleValue(encodedMessage),
  610.                                                     RtcmDataField.DF368.doubleValue(encodedMessage),
  611.                                                     RtcmDataField.DF369.doubleValue(encodedMessage),
  612.                                                     RtcmDataField.DF370.doubleValue(encodedMessage));

  613.                 // Clock correction
  614.                 final ClockCorrection rtcm1066ClockCorr =
  615.                                 new ClockCorrection(RtcmDataField.DF376.doubleValue(encodedMessage),
  616.                                                     RtcmDataField.DF377.doubleValue(encodedMessage),
  617.                                                     RtcmDataField.DF378.doubleValue(encodedMessage));

  618.                 // Initialize a new container and fill data
  619.                 final RtcmCombinedCorrectionData currentRtcm1066Data = new RtcmCombinedCorrectionData();
  620.                 currentRtcm1066Data.setSatelliteID(rtcm1066SatId);
  621.                 currentRtcm1066Data.setGnssIod(rtcm1066Iod);
  622.                 currentRtcm1066Data.setOrbitCorrection(rtcm1066OrbitCorr);
  623.                 currentRtcm1066Data.setClockCorrection(rtcm1066ClockCorr);

  624.                 // Update the list
  625.                 rtcm1066Data.add(currentRtcm1066Data);

  626.             }

  627.             // Return the parsed message
  628.             return new Rtcm1066(messageNumber, rtcm1066Header, rtcm1066Data);

  629.         }

  630.     },

  631.     /** Galileo Orbit Correction Message. */
  632.     RTCM_1240("1240") {

  633.         /** {@inheritDoc} */
  634.         @Override
  635.         public ParsedMessage parse(final EncodedMessage encodedMessage, final int messageNumber,
  636.                                    final TimeScales timeScales) {

  637.             // Header data
  638.             final RtcmOrbitCorrectionHeader rtcm1240Header = new RtcmOrbitCorrectionHeader();
  639.             rtcm1240Header.setEpochTime1s(RtcmDataField.DF458.intValue(encodedMessage));
  640.             rtcm1240Header.setSsrUpdateInterval(new SsrUpdateInterval(RtcmDataField.DF391.intValue(encodedMessage)));
  641.             rtcm1240Header.setMultipleMessageIndicator(RtcmDataField.DF388.intValue(encodedMessage));
  642.             rtcm1240Header.setSatelliteReferenceDatum(RtcmDataField.DF375.intValue(encodedMessage));
  643.             rtcm1240Header.setIodSsr(RtcmDataField.DF413.intValue(encodedMessage));
  644.             rtcm1240Header.setSsrProviderId(RtcmDataField.DF414.intValue(encodedMessage));
  645.             rtcm1240Header.setSsrSolutionId(RtcmDataField.DF415.intValue(encodedMessage));

  646.             // Number of satellites
  647.             final int satNumber = RtcmDataField.DF387.intValue(encodedMessage);
  648.             rtcm1240Header.setNumberOfSatellites(satNumber);

  649.             // Initialize list of data
  650.             final List<RtcmOrbitCorrectionData> rtcm1240Data = new ArrayList<>();

  651.             // Loop on satellites and fill data
  652.             for (int index = 0; index < satNumber; index++) {

  653.                 // Satellite ID
  654.                 final int rtcm1240SatId = RtcmDataField.DF252.intValue(encodedMessage);

  655.                 // GNSS IOD
  656.                 final int rtcm1240Iod = RtcmDataField.DF290.intValue(encodedMessage);

  657.                 // Orbit correction
  658.                 final OrbitCorrection rtcm1240OrbitCorr =
  659.                                 new OrbitCorrection(RtcmDataField.DF365.doubleValue(encodedMessage),
  660.                                                     RtcmDataField.DF366.doubleValue(encodedMessage),
  661.                                                     RtcmDataField.DF367.doubleValue(encodedMessage),
  662.                                                     RtcmDataField.DF368.doubleValue(encodedMessage),
  663.                                                     RtcmDataField.DF369.doubleValue(encodedMessage),
  664.                                                     RtcmDataField.DF370.doubleValue(encodedMessage));

  665.                 // Initialize a new container and fill data
  666.                 final RtcmOrbitCorrectionData currentRtcm1240Data = new RtcmOrbitCorrectionData();
  667.                 currentRtcm1240Data.setSatelliteID(rtcm1240SatId);
  668.                 currentRtcm1240Data.setGnssIod(rtcm1240Iod);
  669.                 currentRtcm1240Data.setOrbitCorrection(rtcm1240OrbitCorr);

  670.                 // Update the list
  671.                 rtcm1240Data.add(currentRtcm1240Data);

  672.             }

  673.             // Return the parsed message
  674.             return new Rtcm1240(messageNumber, rtcm1240Header, rtcm1240Data);

  675.         }

  676.     },

  677.     /** Galileo Clock Correction Message. */
  678.     RTCM_1241("1241") {

  679.         /** {@inheritDoc} */
  680.         @Override
  681.         public ParsedMessage parse(final EncodedMessage encodedMessage, final int messageNumber,
  682.                                    final TimeScales timeScales) {

  683.             // Header data
  684.             final RtcmCorrectionHeader rtcm1241Header = new RtcmCorrectionHeader();
  685.             rtcm1241Header.setEpochTime1s(RtcmDataField.DF458.intValue(encodedMessage));
  686.             rtcm1241Header.setSsrUpdateInterval(new SsrUpdateInterval(RtcmDataField.DF391.intValue(encodedMessage)));
  687.             rtcm1241Header.setMultipleMessageIndicator(RtcmDataField.DF388.intValue(encodedMessage));
  688.             rtcm1241Header.setIodSsr(RtcmDataField.DF413.intValue(encodedMessage));
  689.             rtcm1241Header.setSsrProviderId(RtcmDataField.DF414.intValue(encodedMessage));
  690.             rtcm1241Header.setSsrSolutionId(RtcmDataField.DF415.intValue(encodedMessage));

  691.             // Number of satellites
  692.             final int satNumber = RtcmDataField.DF387.intValue(encodedMessage);
  693.             rtcm1241Header.setNumberOfSatellites(satNumber);

  694.             // Initialize list of data
  695.             final List<RtcmClockCorrectionData> rtcm1241Data = new ArrayList<>();

  696.             // Loop on satellites and fill data
  697.             for (int index = 0; index < satNumber; index++) {

  698.                 // Satellite ID
  699.                 final int rtcm1241SatId = RtcmDataField.DF252.intValue(encodedMessage);

  700.                 // Clock correction
  701.                 final ClockCorrection rtcm1241ClockCorr =
  702.                                 new ClockCorrection(RtcmDataField.DF376.doubleValue(encodedMessage),
  703.                                                     RtcmDataField.DF377.doubleValue(encodedMessage),
  704.                                                     RtcmDataField.DF378.doubleValue(encodedMessage));

  705.                 // Initialize a new container and fill data
  706.                 final RtcmClockCorrectionData currentRtcm1241Data = new RtcmClockCorrectionData();
  707.                 currentRtcm1241Data.setSatelliteID(rtcm1241SatId);
  708.                 currentRtcm1241Data.setClockCorrection(rtcm1241ClockCorr);

  709.                 // Update the list
  710.                 rtcm1241Data.add(currentRtcm1241Data);

  711.             }

  712.             // Return the parsed message
  713.             return new Rtcm1241(messageNumber, rtcm1241Header, rtcm1241Data);

  714.         }

  715.     },

  716.     /** Galileo Combined Orbit and Clock Correction Message. */
  717.     RTCM_1243("1243") {

  718.         /** {@inheritDoc} */
  719.         @Override
  720.         public ParsedMessage parse(final EncodedMessage encodedMessage, final int messageNumber,
  721.                                    final TimeScales timeScales) {

  722.             // Header data
  723.             final RtcmOrbitCorrectionHeader rtcm1243Header = new RtcmOrbitCorrectionHeader();
  724.             rtcm1243Header.setEpochTime1s(RtcmDataField.DF458.intValue(encodedMessage));
  725.             rtcm1243Header.setSsrUpdateInterval(new SsrUpdateInterval(RtcmDataField.DF391.intValue(encodedMessage)));
  726.             rtcm1243Header.setMultipleMessageIndicator(RtcmDataField.DF388.intValue(encodedMessage));
  727.             rtcm1243Header.setSatelliteReferenceDatum(RtcmDataField.DF375.intValue(encodedMessage));
  728.             rtcm1243Header.setIodSsr(RtcmDataField.DF413.intValue(encodedMessage));
  729.             rtcm1243Header.setSsrProviderId(RtcmDataField.DF414.intValue(encodedMessage));
  730.             rtcm1243Header.setSsrSolutionId(RtcmDataField.DF415.intValue(encodedMessage));

  731.             // Number of satellites
  732.             final int satNumber = RtcmDataField.DF387.intValue(encodedMessage);
  733.             rtcm1243Header.setNumberOfSatellites(satNumber);

  734.             // Initialize list of data
  735.             final List<RtcmCombinedCorrectionData> rtcm1243Data = new ArrayList<>();

  736.             // Loop on satellites and fill data
  737.             for (int index = 0; index < satNumber; index++) {

  738.                 // Satellite ID
  739.                 final int rtcm1243SatId = RtcmDataField.DF252.intValue(encodedMessage);

  740.                 // GNSS IOD
  741.                 final int rtcm1243Iod = RtcmDataField.DF290.intValue(encodedMessage);

  742.                 // Orbit correction
  743.                 final OrbitCorrection rtcm1243OrbitCorr =
  744.                                 new OrbitCorrection(RtcmDataField.DF365.doubleValue(encodedMessage),
  745.                                                     RtcmDataField.DF366.doubleValue(encodedMessage),
  746.                                                     RtcmDataField.DF367.doubleValue(encodedMessage),
  747.                                                     RtcmDataField.DF368.doubleValue(encodedMessage),
  748.                                                     RtcmDataField.DF369.doubleValue(encodedMessage),
  749.                                                     RtcmDataField.DF370.doubleValue(encodedMessage));

  750.                 // Clock correction
  751.                 final ClockCorrection rtcm1243ClockCorr =
  752.                                 new ClockCorrection(RtcmDataField.DF376.doubleValue(encodedMessage),
  753.                                                     RtcmDataField.DF377.doubleValue(encodedMessage),
  754.                                                     RtcmDataField.DF378.doubleValue(encodedMessage));

  755.                 // Initialize a new container and fill data
  756.                 final RtcmCombinedCorrectionData currentRtcm1243Data = new RtcmCombinedCorrectionData();
  757.                 currentRtcm1243Data.setSatelliteID(rtcm1243SatId);
  758.                 currentRtcm1243Data.setGnssIod(rtcm1243Iod);
  759.                 currentRtcm1243Data.setOrbitCorrection(rtcm1243OrbitCorr);
  760.                 currentRtcm1243Data.setClockCorrection(rtcm1243ClockCorr);

  761.                 // Update the list
  762.                 rtcm1243Data.add(currentRtcm1243Data);

  763.             }

  764.             // Return the parsed message
  765.             return new Rtcm1243(messageNumber, rtcm1243Header, rtcm1243Data);

  766.         }

  767.     };

  768.     /** Codes map. */
  769.     private static final Map<Pattern, RtcmMessageType> CODES_MAP = new HashMap<>();
  770.     static {
  771.         for (final RtcmMessageType type : values()) {
  772.             CODES_MAP.put(type.getPattern(), type);
  773.         }
  774.     }

  775.     /** Message pattern (i.e. allowed message numbers). */
  776.     private final Pattern pattern;

  777.     /** Simple constructor.
  778.      * @param messageRegex message regular expression
  779.      */
  780.     RtcmMessageType(final String messageRegex) {
  781.         this.pattern = Pattern.compile(messageRegex);
  782.     }

  783.     /** Get the message number.
  784.      * @return message number
  785.      */
  786.     public Pattern getPattern() {
  787.         return pattern;
  788.     }

  789.     /** Get the message type corresponding to a message number.
  790.      * @param rtcmNumber message number
  791.      * @return the message type corresponding to the message number
  792.      */
  793.     public static RtcmMessageType getMessageType(final String rtcmNumber) {
  794.         // Try to find a match with an existing message type
  795.         for (Map.Entry<Pattern, RtcmMessageType> rtcmEntry : CODES_MAP.entrySet()) {
  796.             // Matcher
  797.             final Matcher matcher = rtcmEntry.getKey().matcher(rtcmNumber);
  798.             // Check the match !
  799.             if (matcher.matches()) {
  800.                 // return the message type
  801.                 return rtcmEntry.getValue();
  802.             }
  803.         }
  804.         // No match found
  805.         throw new OrekitException(OrekitMessages.UNKNOWN_ENCODED_MESSAGE_NUMBER, rtcmNumber);
  806.     }

  807. }