Database support, initial
This commit is contained in:
parent
02721701a0
commit
32ad481fcf
2 changed files with 655 additions and 0 deletions
293
exercises/18_GPS_Field_QA/sql/satellite_data_schema.sql
Normal file
293
exercises/18_GPS_Field_QA/sql/satellite_data_schema.sql
Normal file
|
|
@ -0,0 +1,293 @@
|
|||
-- 20260406 ChatGPT
|
||||
-- $Header$
|
||||
--
|
||||
-- Example:
|
||||
-- createdb satellite_data
|
||||
-- psql -d satellite_data -f satellite_data_schema.sql
|
||||
--
|
||||
-- Purpose:
|
||||
-- Schema for importing GNSS field QA CSV logs generated by T-Beam units.
|
||||
-- A log file is recorded in table logs, and each CSV row is stored in
|
||||
-- table log_data with a foreign-key reference back to logs.
|
||||
|
||||
BEGIN;
|
||||
|
||||
-- Optional convenience note:
|
||||
-- CREATE DATABASE satellite_data;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS logs (
|
||||
log_id bigserial PRIMARY KEY,
|
||||
source_filename text NOT NULL,
|
||||
source_path text,
|
||||
file_sha256 text,
|
||||
file_size_bytes bigint,
|
||||
raw_header_text text,
|
||||
csv_header_line text NOT NULL,
|
||||
imported_at timestamptz NOT NULL DEFAULT now(),
|
||||
import_notes text,
|
||||
|
||||
board_id text,
|
||||
gnss_chip text,
|
||||
firmware_exercise_name text,
|
||||
firmware_version text,
|
||||
boot_timestamp_utc timestamptz,
|
||||
run_id text,
|
||||
first_timestamp_utc timestamptz,
|
||||
last_timestamp_utc timestamptz,
|
||||
|
||||
row_count integer NOT NULL DEFAULT 0,
|
||||
sample_count integer NOT NULL DEFAULT 0,
|
||||
satellite_count integer NOT NULL DEFAULT 0,
|
||||
|
||||
CONSTRAINT logs_source_filename_ck CHECK (btrim(source_filename) <> ''),
|
||||
CONSTRAINT logs_csv_header_line_ck CHECK (btrim(csv_header_line) <> ''),
|
||||
CONSTRAINT logs_row_count_ck CHECK (row_count >= 0),
|
||||
CONSTRAINT logs_sample_count_ck CHECK (sample_count >= 0),
|
||||
CONSTRAINT logs_satellite_count_ck CHECK (satellite_count >= 0)
|
||||
);
|
||||
|
||||
COMMENT ON TABLE logs IS
|
||||
'One row per imported CSV file. Stores file-level provenance, importer notes, raw hash-prefixed header text, the effective CSV column header line, and summary counts for the import.';
|
||||
|
||||
COMMENT ON COLUMN logs.log_id IS
|
||||
'Surrogate primary key for one imported log file.';
|
||||
COMMENT ON COLUMN logs.source_filename IS
|
||||
'Base filename of the imported CSV file, such as 20260406_175441_GUY.csv.';
|
||||
COMMENT ON COLUMN logs.source_path IS
|
||||
'Full or relative filesystem path used at import time.';
|
||||
COMMENT ON COLUMN logs.file_sha256 IS
|
||||
'SHA-256 digest of the file contents for provenance and duplicate detection.';
|
||||
COMMENT ON COLUMN logs.file_size_bytes IS
|
||||
'File size in bytes at import time.';
|
||||
COMMENT ON COLUMN logs.raw_header_text IS
|
||||
'All leading lines in the source file whose first character is #. This is the free-form metadata header preserved exactly as found.';
|
||||
COMMENT ON COLUMN logs.csv_header_line IS
|
||||
'The effective CSV column header line used for import. This may come from the file itself or from the importer''s expected header when the file has no explicit header row.';
|
||||
COMMENT ON COLUMN logs.imported_at IS
|
||||
'UTC timestamp when the file was imported into PostgreSQL.';
|
||||
COMMENT ON COLUMN logs.import_notes IS
|
||||
'Optional notes about the import, schema assumptions, or anomalies observed during ingestion.';
|
||||
COMMENT ON COLUMN logs.board_id IS
|
||||
'Identifier of the T-Beam or other logger board, for example GUY, AMY, or CY, copied from the data rows when available.';
|
||||
COMMENT ON COLUMN logs.gnss_chip IS
|
||||
'GNSS receiver model reported by the firmware, such as MAX-M10S or L76K.';
|
||||
COMMENT ON COLUMN logs.firmware_exercise_name IS
|
||||
'Firmware exercise or program name that generated the log, useful for tracking logger behavior across exercises.';
|
||||
COMMENT ON COLUMN logs.firmware_version IS
|
||||
'Firmware version string or build identifier reported by the logger.';
|
||||
COMMENT ON COLUMN logs.boot_timestamp_utc IS
|
||||
'UTC timestamp that the device believed it booted. Useful for relating run timing back to power-up timing.';
|
||||
COMMENT ON COLUMN logs.run_id IS
|
||||
'Run/session identifier generated by the firmware for this data collection session.';
|
||||
COMMENT ON COLUMN logs.first_timestamp_utc IS
|
||||
'Earliest timestamp_utc found in the imported data rows.';
|
||||
COMMENT ON COLUMN logs.last_timestamp_utc IS
|
||||
'Latest timestamp_utc found in the imported data rows.';
|
||||
COMMENT ON COLUMN logs.row_count IS
|
||||
'Total number of imported data rows for this file, including both sample and satellite rows.';
|
||||
COMMENT ON COLUMN logs.sample_count IS
|
||||
'Count of rows whose record_type is sample.';
|
||||
COMMENT ON COLUMN logs.satellite_count IS
|
||||
'Count of rows whose record_type is satellite.';
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS logs_source_sha256_uq
|
||||
ON logs (file_sha256)
|
||||
WHERE file_sha256 IS NOT NULL;
|
||||
|
||||
CREATE INDEX IF NOT EXISTS logs_run_id_idx
|
||||
ON logs (run_id);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS logs_board_id_idx
|
||||
ON logs (board_id);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS log_data (
|
||||
log_data_id bigserial PRIMARY KEY,
|
||||
log_id bigint NOT NULL REFERENCES logs(log_id) ON DELETE CASCADE,
|
||||
row_num integer NOT NULL,
|
||||
|
||||
record_type text NOT NULL,
|
||||
timestamp_utc timestamptz,
|
||||
board_id text,
|
||||
gnss_chip text,
|
||||
firmware_exercise_name text,
|
||||
firmware_version text,
|
||||
boot_timestamp_utc timestamptz,
|
||||
run_id text,
|
||||
|
||||
fix_type text,
|
||||
fix_dimension smallint,
|
||||
sats_in_view integer,
|
||||
sat_seen integer,
|
||||
sats_used integer,
|
||||
hdop numeric(8,3),
|
||||
vdop numeric(8,3),
|
||||
pdop numeric(8,3),
|
||||
latitude numeric(11,8),
|
||||
longitude numeric(11,8),
|
||||
altitude_m numeric(10,2),
|
||||
speed_mps numeric(10,3),
|
||||
course_deg numeric(7,3),
|
||||
pps_seen boolean,
|
||||
quality_class text,
|
||||
|
||||
gps_count integer,
|
||||
galileo_count integer,
|
||||
glonass_count integer,
|
||||
beidou_count integer,
|
||||
navic_count integer,
|
||||
qzss_count integer,
|
||||
sbas_count integer,
|
||||
|
||||
mean_cn0 numeric(8,3),
|
||||
max_cn0 numeric(8,3),
|
||||
age_of_fix_ms integer,
|
||||
ttff_ms integer,
|
||||
longest_no_fix_ms integer,
|
||||
|
||||
sat_talker text,
|
||||
sat_constellation text,
|
||||
sat_prn integer,
|
||||
sat_elevation_deg integer,
|
||||
sat_azimuth_deg integer,
|
||||
sat_snr numeric(8,3),
|
||||
sat_used_in_solution boolean,
|
||||
|
||||
CONSTRAINT log_data_log_id_row_num_uq UNIQUE (log_id, row_num),
|
||||
CONSTRAINT log_data_row_num_ck CHECK (row_num >= 1),
|
||||
CONSTRAINT log_data_record_type_ck CHECK (record_type IN ('sample', 'satellite')),
|
||||
CONSTRAINT log_data_fix_dimension_ck CHECK (fix_dimension IS NULL OR fix_dimension BETWEEN 0 AND 9),
|
||||
CONSTRAINT log_data_latitude_ck CHECK (latitude IS NULL OR latitude BETWEEN -90 AND 90),
|
||||
CONSTRAINT log_data_longitude_ck CHECK (longitude IS NULL OR longitude BETWEEN -180 AND 180),
|
||||
CONSTRAINT log_data_course_deg_ck CHECK (course_deg IS NULL OR course_deg >= 0 AND course_deg < 360),
|
||||
CONSTRAINT log_data_sat_elevation_deg_ck CHECK (sat_elevation_deg IS NULL OR sat_elevation_deg BETWEEN 0 AND 90),
|
||||
CONSTRAINT log_data_sat_azimuth_deg_ck CHECK (sat_azimuth_deg IS NULL OR sat_azimuth_deg BETWEEN 0 AND 359),
|
||||
CONSTRAINT log_data_sat_counts_nonnegative_ck CHECK (
|
||||
coalesce(sats_in_view, 0) >= 0 AND
|
||||
coalesce(sat_seen, 0) >= 0 AND
|
||||
coalesce(sats_used, 0) >= 0 AND
|
||||
coalesce(gps_count, 0) >= 0 AND
|
||||
coalesce(galileo_count, 0) >= 0 AND
|
||||
coalesce(glonass_count, 0) >= 0 AND
|
||||
coalesce(beidou_count, 0) >= 0 AND
|
||||
coalesce(navic_count, 0) >= 0 AND
|
||||
coalesce(qzss_count, 0) >= 0 AND
|
||||
coalesce(sbas_count, 0) >= 0
|
||||
),
|
||||
CONSTRAINT log_data_ms_nonnegative_ck CHECK (
|
||||
coalesce(age_of_fix_ms, 0) >= 0 AND
|
||||
coalesce(ttff_ms, 0) >= 0 AND
|
||||
coalesce(longest_no_fix_ms, 0) >= 0
|
||||
)
|
||||
);
|
||||
|
||||
COMMENT ON TABLE log_data IS
|
||||
'One row per CSV data record. Stores both sample rows and per-satellite rows, preserving the file''s mixed row model in one typed table.';
|
||||
|
||||
COMMENT ON COLUMN log_data.log_data_id IS
|
||||
'Surrogate primary key for one imported data row.';
|
||||
COMMENT ON COLUMN log_data.log_id IS
|
||||
'Foreign key back to logs.log_id identifying which source file this row came from.';
|
||||
COMMENT ON COLUMN log_data.row_num IS
|
||||
'1-based row number within the imported data file, excluding comment lines and any header line.';
|
||||
COMMENT ON COLUMN log_data.record_type IS
|
||||
'Kind of row: sample for one epoch summary row, or satellite for one satellite observed at that epoch.';
|
||||
COMMENT ON COLUMN log_data.timestamp_utc IS
|
||||
'UTC timestamp attached to the row by the GNSS logger.';
|
||||
COMMENT ON COLUMN log_data.board_id IS
|
||||
'Identifier of the data-collecting board, such as GUY, AMY, or CY.';
|
||||
COMMENT ON COLUMN log_data.gnss_chip IS
|
||||
'GNSS receiver model, such as MAX-M10S or L76K.';
|
||||
COMMENT ON COLUMN log_data.firmware_exercise_name IS
|
||||
'Firmware exercise/program name that emitted the row.';
|
||||
COMMENT ON COLUMN log_data.firmware_version IS
|
||||
'Firmware version/build identifier used when the row was logged.';
|
||||
COMMENT ON COLUMN log_data.boot_timestamp_utc IS
|
||||
'Device boot timestamp in UTC as reported by the logger.';
|
||||
COMMENT ON COLUMN log_data.run_id IS
|
||||
'Run/session identifier assigned by the firmware.';
|
||||
COMMENT ON COLUMN log_data.fix_type IS
|
||||
'GNSS fix classification such as NO_FIX, 2D, 3D, DGPS, or similar receiver-reported state.';
|
||||
COMMENT ON COLUMN log_data.fix_dimension IS
|
||||
'Numeric dimensionality of the solution. Typical values are 1 for no fix, 2 for horizontal-only, and 3 for full 3D.';
|
||||
COMMENT ON COLUMN log_data.sats_in_view IS
|
||||
'Receiver-reported total satellites in view at the epoch, if provided by the firmware.';
|
||||
COMMENT ON COLUMN log_data.sat_seen IS
|
||||
'Count of satellites actually emitted as satellite rows or otherwise counted by the logger at the epoch. May differ from sats_in_view depending on receiver API behavior.';
|
||||
COMMENT ON COLUMN log_data.sats_used IS
|
||||
'Number of satellites used by the receiver in the navigation solution at the epoch.';
|
||||
COMMENT ON COLUMN log_data.hdop IS
|
||||
'Horizontal Dilution of Precision. Lower values indicate better horizontal geometry.';
|
||||
COMMENT ON COLUMN log_data.vdop IS
|
||||
'Vertical Dilution of Precision. Lower values indicate better vertical geometry.';
|
||||
COMMENT ON COLUMN log_data.pdop IS
|
||||
'Position Dilution of Precision, a combined geometry indicator for 3D positioning.';
|
||||
COMMENT ON COLUMN log_data.latitude IS
|
||||
'Latitude in decimal degrees referenced to the receiver''s current navigation solution.';
|
||||
COMMENT ON COLUMN log_data.longitude IS
|
||||
'Longitude in decimal degrees referenced to the receiver''s current navigation solution.';
|
||||
COMMENT ON COLUMN log_data.altitude_m IS
|
||||
'Altitude in meters as reported by the GNSS receiver.';
|
||||
COMMENT ON COLUMN log_data.speed_mps IS
|
||||
'Ground speed in meters per second.';
|
||||
COMMENT ON COLUMN log_data.course_deg IS
|
||||
'Course over ground in degrees clockwise from true north.';
|
||||
COMMENT ON COLUMN log_data.pps_seen IS
|
||||
'Boolean indicator that a one-pulse-per-second timing event was observed for the epoch.';
|
||||
COMMENT ON COLUMN log_data.quality_class IS
|
||||
'Firmware-defined coarse quality label such as POOR, FAIR, GOOD, or similar.';
|
||||
COMMENT ON COLUMN log_data.gps_count IS
|
||||
'Number of GPS satellites counted at the epoch.';
|
||||
COMMENT ON COLUMN log_data.galileo_count IS
|
||||
'Number of Galileo satellites counted at the epoch.';
|
||||
COMMENT ON COLUMN log_data.glonass_count IS
|
||||
'Number of GLONASS satellites counted at the epoch.';
|
||||
COMMENT ON COLUMN log_data.beidou_count IS
|
||||
'Number of BeiDou satellites counted at the epoch.';
|
||||
COMMENT ON COLUMN log_data.navic_count IS
|
||||
'Number of NavIC/IRNSS satellites counted at the epoch.';
|
||||
COMMENT ON COLUMN log_data.qzss_count IS
|
||||
'Number of QZSS satellites counted at the epoch.';
|
||||
COMMENT ON COLUMN log_data.sbas_count IS
|
||||
'Number of SBAS satellites counted at the epoch.';
|
||||
COMMENT ON COLUMN log_data.mean_cn0 IS
|
||||
'Mean carrier-to-noise-density ratio, typically in dB-Hz, across the satellites considered by the firmware at the epoch.';
|
||||
COMMENT ON COLUMN log_data.max_cn0 IS
|
||||
'Maximum carrier-to-noise-density ratio, typically in dB-Hz, seen at the epoch.';
|
||||
COMMENT ON COLUMN log_data.age_of_fix_ms IS
|
||||
'Age in milliseconds of the current fix solution when logged.';
|
||||
COMMENT ON COLUMN log_data.ttff_ms IS
|
||||
'Time To First Fix in milliseconds for the run or receiver state being reported.';
|
||||
COMMENT ON COLUMN log_data.longest_no_fix_ms IS
|
||||
'Longest interval in milliseconds spent without a usable fix during the run so far.';
|
||||
COMMENT ON COLUMN log_data.sat_talker IS
|
||||
'Talker or source prefix for the satellite row, for example GP, GL, GA, GB, or similar receiver-provided code.';
|
||||
COMMENT ON COLUMN log_data.sat_constellation IS
|
||||
'Human-readable constellation name for the satellite row, such as GPS, GALILEO, GLONASS, or BEIDOU.';
|
||||
COMMENT ON COLUMN log_data.sat_prn IS
|
||||
'PRN or SVID number identifying the satellite within its constellation.';
|
||||
COMMENT ON COLUMN log_data.sat_elevation_deg IS
|
||||
'Satellite elevation angle in degrees above the horizon.';
|
||||
COMMENT ON COLUMN log_data.sat_azimuth_deg IS
|
||||
'Satellite azimuth angle in degrees clockwise from north.';
|
||||
COMMENT ON COLUMN log_data.sat_snr IS
|
||||
'Satellite signal-to-noise or similar quality metric as reported by the firmware, commonly in dB-Hz.';
|
||||
COMMENT ON COLUMN log_data.sat_used_in_solution IS
|
||||
'Boolean indicator that this satellite was used in the navigation solution for the epoch.';
|
||||
|
||||
CREATE INDEX IF NOT EXISTS log_data_log_id_timestamp_idx
|
||||
ON log_data (log_id, timestamp_utc);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS log_data_run_id_idx
|
||||
ON log_data (run_id);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS log_data_board_id_idx
|
||||
ON log_data (board_id);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS log_data_record_type_idx
|
||||
ON log_data (record_type);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS log_data_satellite_lookup_idx
|
||||
ON log_data (sat_constellation, sat_prn, timestamp_utc)
|
||||
WHERE record_type = 'satellite';
|
||||
|
||||
COMMIT;
|
||||
Loading…
Add table
Add a link
Reference in a new issue