from struct import unpack_from, calcsize LOG_GNSS_POSITION_REPORT = 0x1476 LOG_GNSS_GPS_MEASUREMENT_REPORT = 0x1477 LOG_GNSS_CLOCK_REPORT = 0x1478 LOG_GNSS_GLONASS_MEASUREMENT_REPORT = 0x1480 LOG_GNSS_BDS_MEASUREMENT_REPORT = 0x1756 LOG_GNSS_GAL_MEASUREMENT_REPORT = 0x1886 LOG_GNSS_OEMDRE_MEASUREMENT_REPORT = 0x14DE LOG_GNSS_OEMDRE_SVPOLY_REPORT = 0x14E1 LOG_GNSS_ME_DPO_STATUS = 0x1838 LOG_GNSS_CD_DB_REPORT = 0x147B LOG_GNSS_PRX_RF_HW_STATUS_REPORT = 0x147E LOG_CGPS_SLOW_CLOCK_CLIB_REPORT = 0x1488 LOG_GNSS_CONFIGURATION_STATE = 0x1516 oemdre_measurement_report = """ uint8_t version; uint8_t reason; uint8_t sv_count; uint8_t seq_num; uint8_t seq_max; uint16_t rf_loss; uint8_t system_rtc_valid; uint32_t f_count; uint32_t clock_resets; uint64_t system_rtc_time; uint8_t gps_leap_seconds; uint8_t gps_leap_seconds_uncertainty; float gps_to_glonass_time_bias_milliseconds; float gps_to_glonass_time_bias_milliseconds_uncertainty; uint16_t gps_week; uint32_t gps_milliseconds; uint32_t gps_time_bias; uint32_t gps_clock_time_uncertainty; uint8_t gps_clock_source; uint8_t glonass_clock_source; uint8_t glonass_year; uint16_t glonass_day; uint32_t glonass_milliseconds; float glonass_time_bias; float glonass_clock_time_uncertainty; float clock_frequency_bias; float clock_frequency_uncertainty; uint8_t frequency_source; uint32_t cdma_clock_info[5]; uint8_t source; """ oemdre_svpoly_report = """ uint8_t version; uint16_t sv_id; int8_t frequency_index; uint8_t flags; uint16_t iode; double t0; double xyz0[3]; double xyzN[9]; float other[4]; float position_uncertainty; float iono_delay; float iono_dot; float sbas_iono_delay; float sbas_iono_dot; float tropo_delay; float elevation; float elevation_dot; float elevation_uncertainty; double velocity_coeff[12]; """ oemdre_measurement_report_sv = """ uint8_t sv_id; uint8_t unkn; int8_t glonass_frequency_index; uint32_t observation_state; uint8_t observations; uint8_t good_observations; uint8_t filter_stages; uint8_t predetect_interval; uint8_t cycle_slip_count; uint16_t postdetections; uint32_t measurement_status; uint32_t measurement_status2; uint16_t carrier_noise; uint16_t rf_loss; int16_t latency; float filtered_measurement_fraction; uint32_t filtered_measurement_integral; float filtered_time_uncertainty; float filtered_speed; float filtered_speed_uncertainty; float unfiltered_measurement_fraction; uint32_t unfiltered_measurement_integral; float unfiltered_time_uncertainty; float unfiltered_speed; float unfiltered_speed_uncertainty; uint8_t multipath_estimate_valid; uint32_t multipath_estimate; uint8_t direction_valid; float azimuth; float elevation; float doppler_acceleration; float fine_speed; float fine_speed_uncertainty; uint64_t carrier_phase; uint32_t f_count; uint16_t parity_error_count; uint8_t good_parity; """ glonass_measurement_report = """ uint8_t version; uint32_t f_count; uint8_t glonass_cycle_number; uint16_t glonass_number_of_days; uint32_t milliseconds; float time_bias; float clock_time_uncertainty; float clock_frequency_bias; float clock_frequency_uncertainty; uint8_t sv_count; """ glonass_measurement_report_sv = """ uint8_t sv_id; int8_t frequency_index; uint8_t observation_state; // SVObservationStates uint8_t observations; uint8_t good_observations; uint8_t hemming_error_count; uint8_t filter_stages; uint16_t carrier_noise; int16_t latency; uint8_t predetect_interval; uint16_t postdetections; uint32_t unfiltered_measurement_integral; float unfiltered_measurement_fraction; float unfiltered_time_uncertainty; float unfiltered_speed; float unfiltered_speed_uncertainty; uint32_t measurement_status; uint8_t misc_status; uint32_t multipath_estimate; float azimuth; float elevation; int32_t carrier_phase_cycles_integral; uint16_t carrier_phase_cycles_fraction; float fine_speed; float fine_speed_uncertainty; uint8_t cycle_slip_count; uint32_t pad; """ gps_measurement_report = """ uint8_t version; uint32_t f_count; uint16_t week; uint32_t milliseconds; float time_bias; float clock_time_uncertainty; float clock_frequency_bias; float clock_frequency_uncertainty; uint8_t sv_count; """ gps_measurement_report_sv = """ uint8_t sv_id; // SV PRN uint8_t observation_state; // SV Observation state uint8_t observations; // Count of all observation (both success and failure) uint8_t good_observations; // Count of Good observations uint16_t parity_error_count; // Carrier to Code filtering N count uint8_t filter_stages; // Pre-Detection (Coherent) Interval (msecs) uint16_t carrier_noise; // CNo. Units of 0.1 dB int16_t latency; // Age of the measurement in msecs (+ve meas Meas precedes ref time) uint8_t predetect_interval; // Pre-Detection (Coherent) Interval (msecs) uint16_t postdetections; // Num Post-Detections (uints of PreInts uint32_t unfiltered_measurement_integral; // Range of 0 thru (WEEK_MSECS-1) [msecs] float unfiltered_measurement_fraction; // Range of 0 thru 0.99999 [msecs] float unfiltered_time_uncertainty; // Time uncertainty (msec) float unfiltered_speed; // Speed estimate (meters/sec) float unfiltered_speed_uncertainty; // Speed uncertainty estimate (meters/sec) uint32_t measurement_status; uint8_t misc_status; uint32_t multipath_estimate; float azimuth; // Azimuth (radians) float elevation; // Elevation (radians) int32_t carrier_phase_cycles_integral; uint16_t carrier_phase_cycles_fraction; float fine_speed; // Carrier phase derived speed float fine_speed_uncertainty; // Carrier phase derived speed UNC uint8_t cycle_slip_count; // Increments when a CSlip is detected uint32_t pad; """ position_report = """ uint8 u_Version; /* Version number of DM log */ uint32 q_Fcount; /* Local millisecond counter */ uint8 u_PosSource; /* Source of position information */ /* 0: None 1: Weighted least-squares 2: Kalman filter 3: Externally injected 4: Internal database */ uint32 q_Reserved1; /* Reserved memory field */ uint16 w_PosVelFlag; /* Position velocity bit field: (see DM log 0x1476 documentation) */ uint32 q_PosVelFlag2; /* Position velocity 2 bit field: (see DM log 0x1476 documentation) */ uint8 u_FailureCode; /* Failure code: (see DM log 0x1476 documentation) */ uint16 w_FixEvents; /* Fix events bit field: (see DM log 0x1476 documentation) */ uint32 _fake_align_week_number; uint16 w_GpsWeekNumber; /* GPS week number of position */ uint32 q_GpsFixTimeMs; /* GPS fix time of week of in milliseconds */ uint8 u_GloNumFourYear; /* Number of Glonass four year cycles */ uint16 w_GloNumDaysInFourYear; /* Glonass calendar day in four year cycle */ uint32 q_GloFixTimeMs; /* Glonass fix time of day in milliseconds */ uint32 q_PosCount; /* Integer count of the number of unique positions reported */ uint64 t_DblFinalPosLatLon[2]; /* Final latitude and longitude of position in radians */ uint32 q_FltFinalPosAlt; /* Final height-above-ellipsoid altitude of position */ uint32 q_FltHeadingRad; /* User heading in radians */ uint32 q_FltHeadingUncRad; /* User heading uncertainty in radians */ uint32 q_FltVelEnuMps[3]; /* User velocity in east, north, up coordinate frame. In meters per second. */ uint32 q_FltVelSigmaMps[3]; /* Gaussian 1-sigma value for east, north, up components of user velocity */ uint32 q_FltClockBiasMeters; /* Receiver clock bias in meters */ uint32 q_FltClockBiasSigmaMeters; /* Gaussian 1-sigma value for receiver clock bias in meters */ uint32 q_FltGGTBMeters; /* GPS to Glonass time bias in meters */ uint32 q_FltGGTBSigmaMeters; /* Gaussian 1-sigma value for GPS to Glonass time bias uncertainty in meters */ uint32 q_FltGBTBMeters; /* GPS to BeiDou time bias in meters */ uint32 q_FltGBTBSigmaMeters; /* Gaussian 1-sigma value for GPS to BeiDou time bias uncertainty in meters */ uint32 q_FltBGTBMeters; /* BeiDou to Glonass time bias in meters */ uint32 q_FltBGTBSigmaMeters; /* Gaussian 1-sigma value for BeiDou to Glonass time bias uncertainty in meters */ uint32 q_FltFiltGGTBMeters; /* Filtered GPS to Glonass time bias in meters */ uint32 q_FltFiltGGTBSigmaMeters; /* Filtered Gaussian 1-sigma value for GPS to Glonass time bias uncertainty in meters */ uint32 q_FltFiltGBTBMeters; /* Filtered GPS to BeiDou time bias in meters */ uint32 q_FltFiltGBTBSigmaMeters; /* Filtered Gaussian 1-sigma value for GPS to BeiDou time bias uncertainty in meters */ uint32 q_FltFiltBGTBMeters; /* Filtered BeiDou to Glonass time bias in meters */ uint32 q_FltFiltBGTBSigmaMeters; /* Filtered Gaussian 1-sigma value for BeiDou to Glonass time bias uncertainty in meters */ uint32 q_FltSftOffsetSec; /* SFT offset as computed by WLS in seconds */ uint32 q_FltSftOffsetSigmaSec; /* Gaussian 1-sigma value for SFT offset in seconds */ uint32 q_FltClockDriftMps; /* Clock drift (clock frequency bias) in meters per second */ uint32 q_FltClockDriftSigmaMps; /* Gaussian 1-sigma value for clock drift in meters per second */ uint32 q_FltFilteredAlt; /* Filtered height-above-ellipsoid altitude in meters as computed by WLS */ uint32 q_FltFilteredAltSigma; /* Gaussian 1-sigma value for filtered height-above-ellipsoid altitude in meters */ uint32 q_FltRawAlt; /* Raw height-above-ellipsoid altitude in meters as computed by WLS */ uint32 q_FltRawAltSigma; /* Gaussian 1-sigma value for raw height-above-ellipsoid altitude in meters */ uint32 align_Flt[14]; uint32 q_FltPdop; /* 3D position dilution of precision as computed from the unweighted uint32 q_FltHdop; /* Horizontal position dilution of precision as computed from the unweighted least-squares covariance matrix */ uint32 q_FltVdop; /* Vertical position dilution of precision as computed from the unweighted least-squares covariance matrix */ uint8 u_EllipseConfidence; /* Statistical measure of the confidence (percentage) associated with the uncertainty ellipse values */ uint32 q_FltEllipseAngle; /* Angle of semimajor axis with respect to true North, with increasing angles moving clockwise from North. In units of degrees. */ uint32 q_FltEllipseSemimajorAxis; /* Semimajor axis of final horizontal position uncertainty error ellipse. In units of meters. */ uint32 q_FltEllipseSemiminorAxis; /* Semiminor axis of final horizontal position uncertainty error ellipse. In units of meters. */ uint32 q_FltPosSigmaVertical; /* Gaussian 1-sigma value for final position height-above-ellipsoid altitude in meters */ uint8 u_HorizontalReliability; /* Horizontal position reliability 0: Not set 1: Very Low 2: Low 3: Medium 4: High */ uint8 u_VerticalReliability; /* Vertical position reliability */ uint16 w_Reserved2; /* Reserved memory field */ uint32 q_FltGnssHeadingRad; /* User heading in radians derived from GNSS only solution */ uint32 q_FltGnssHeadingUncRad; /* User heading uncertainty in radians derived from GNSS only solution */ uint32 q_SensorDataUsageMask; /* Denotes which additional sensor data were used to compute this position fix. BIT[0] 0x00000001 <96> Accelerometer BIT[1] 0x00000002 <96> Gyro 0x0000FFFC - Reserved A bit set to 1 indicates that certain fields as defined by the SENSOR_AIDING_MASK were aided with sensor data*/ uint32 q_SensorAidMask; /* Denotes which component of the position report was assisted with additional sensors defined in SENSOR_DATA_USAGE_MASK BIT[0] 0x00000001 <96> Heading aided with sensor data BIT[1] 0x00000002 <96> Speed aided with sensor data BIT[2] 0x00000004 <96> Position aided with sensor data BIT[3] 0x00000008 <96> Velocity aided with sensor data 0xFFFFFFF0 <96> Reserved */ uint8 u_NumGpsSvsUsed; /* The number of GPS SVs used in the fix */ uint8 u_TotalGpsSvs; /* Total number of GPS SVs detected by searcher, including ones not used in position calculation */ uint8 u_NumGloSvsUsed; /* The number of Glonass SVs used in the fix */ uint8 u_TotalGloSvs; /* Total number of Glonass SVs detected by searcher, including ones not used in position calculation */ uint8 u_NumBdsSvsUsed; /* The number of BeiDou SVs used in the fix */ uint8 u_TotalBdsSvs; /* Total number of BeiDou SVs detected by searcher, including ones not used in position calculation */ """ # noqa: E501 def name_to_camelcase(nam): ret = [] i = 0 while i < len(nam): if nam[i] == "_": ret.append(nam[i+1].upper()) i += 2 else: ret.append(nam[i]) i += 1 return ''.join(ret) def parse_struct(ss): st = "<" nams = [] for l in ss.strip().split("\n"): if len(l.strip()) == 0: continue typ, nam = l.split(";")[0].split() #print(typ, nam) if typ == "float" or '_Flt' in nam: st += "f" elif typ == "double" or '_Dbl' in nam: st += "d" elif typ in ["uint8", "uint8_t"]: st += "B" elif typ in ["int8", "int8_t"]: st += "b" elif typ in ["uint32", "uint32_t"]: st += "I" elif typ in ["int32", "int32_t"]: st += "i" elif typ in ["uint16", "uint16_t"]: st += "H" elif typ in ["int16", "int16_t"]: st += "h" elif typ in ["uint64", "uint64_t"]: st += "Q" else: raise RuntimeError(f"unknown type {typ}") if '[' in nam: cnt = int(nam.split("[")[1].split("]")[0]) st += st[-1]*(cnt-1) for i in range(cnt): nams.append("%s[%d]" % (nam.split("[")[0], i)) else: nams.append(nam) return st, nams def dict_unpacker(ss, camelcase = False): st, nams = parse_struct(ss) if camelcase: nams = [name_to_camelcase(x) for x in nams] sz = calcsize(st) return lambda x: dict(zip(nams, unpack_from(st, x), strict=True)), sz def relist(dat): list_keys = set() for key in dat.keys(): if '[' in key: list_keys.add(key.split('[')[0]) list_dict = {} for list_key in list_keys: list_dict[list_key] = [] i = 0 while True: key = list_key + f'[{i}]' if key not in dat: break list_dict[list_key].append(dat[key]) del dat[key] i += 1 return {**dat, **list_dict}