Metadata-Version: 2.4
Name: SiteLogParser
Version: 1.2.0rc1
Summary: Parsing IGS Sitelog files (supports version 2+3)
Project-URL: Homepage, https://gitlab.com/dach.pos/sitelogparser
Project-URL: Issues, https://gitlab.com/dach.pos/sitelogparser/-/issues
Author-email: Juergen Fredriksson <juergen.fredriksson@bev.gv.at>
License-File: LICENSE.txt
Keywords: beidou,galileo,glonass,gnss,gps,parser,sitelog
Classifier: Development Status :: 3 - Alpha
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Topic :: Scientific/Engineering :: Interface Engine/Protocol Translator
Requires-Python: !=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,<4,>=2.7
Description-Content-Type: text/markdown

# SitelogParser

A Python library and command-line tool for parsing, validating, and exporting IGS (International GNSS Service) sitelog files. SitelogParser converts sitelog text files into structured Python dataclasses, enables programmatic manipulation of sitelog data, and exports them back to the IGS sitelog v2.0 format.

## Features

- **Parse IGS sitelog files** into type-safe Python dataclasses
- **Export sitelog data** back to IGS sitelog v2.0 format with automatic metadata updates
- **Command-line interface** for validation, listing, and preparing sitelog files
- **Type hints** throughout for better IDE support and type checking
- **Automatic form metadata** computation (latest modification dates and changed sections)
- **Timestamp handling** with UTC timezone support

## Installation

```bash
pip install sitelogparser
```

For development:
```bash
git clone <repository-url>
cd SitelogParser
pip install -e .
```

## Command-Line Usage

The `slp` command provides three main operations:

### Validate a sitelog file

```bash
slp validate tests/AMST_20190705.txt
```

**Output:**
```
✓ Valid sitelog: tests/AMST_20190705.txt

📊 Statistics:
  Site: Amsterdam, Netherlands (AMST)
  DOMES: 13502M001
  Location: Amsterdam, Netherlands
  Receivers: 20
  Antennas: 6
  Last Modified: 2018-11-28
  Modified Sections: 3.19, 3.20
```

### List receivers, antennas, or metadata

```bash
# List all receivers
slp list tests/AMST_20190705.txt --type receivers

# List all antennas
slp list tests/AMST_20190705.txt --type antennas

# Show site metadata
slp list tests/AMST_20190705.txt --type metadata

# Show everything (default)
slp list tests/AMST_20190705.txt
```

**Example output (receivers):**
```

📡 GNSS Receivers:
#    Type                      Serial          Installed            Removed
-------------------------------------------------------------------------------------
1    TRIMBLE NETRS             4439239154      2005-04-13T12:00Z    2005-12-15T10:00Z
2    TRIMBLE NETRS             4439239154      2005-12-15T10:00Z    2010-03-15T08:30Z
3    LEICA GRX1200+GNSS        495553          2010-03-15T08:30Z    2010-09-06T08:35Z
4    LEICA GRX1200+GNSS        495553          2010-09-06T08:35Z    2010-10-28T11:40Z
5    LEICA GRX1200+GNSS        495553          2010-10-28T11:50Z    2010-11-15T10:30Z
6    LEICA GRX1200+GNSS        495553          2010-11-15T10:30Z    2011-01-20T07:40Z
7    LEICA GRX1200+GNSS        495553          2011-01-20T07:50Z    2011-06-01T07:50Z
8    LEICA GRX1200+GNSS        495553          2011-06-01T07:50Z    2011-08-31T05:30Z
9    TRIMBLE NETR9             5106K73572      2011-08-31T05:30Z    2011-09-13T11:00Z
10   LEICA GRX1200+GNSS        495553          2011-09-13T11:00Z    2011-11-18T14:00Z
11   TPS GB-1000               8RXJKJ48V7K     2011-11-18T14:00Z    2012-08-22T07:30Z
12   TPS NET-G3A               618-00899       2012-08-22T07:30Z    2012-09-19T15:25Z
13   TPS NET-G3A               618-00899       2012-09-19T15:25Z    2013-10-31T15:23Z
14   TPS NET-G3A               618-00899       2013-10-31T15:34Z    2014-05-23T12:08Z
15   TPS NET-G3A               618-00899       2014-05-23T12:25Z    2017-03-17T13:12Z
16   LEICA GR30                1705298         2017-03-17T13:13Z    2017-10-10T05:17Z
17   TPS NET-G3A               618-00899       2017-10-10T06:07Z    2017-11-17T13:11Z
18   LEICA GR30                1705298         2017-11-17T14:24Z    2018-06-21T06:02Z
19   LEICA GR30                1705298         2018-06-21T06:04Z    2018-11-28T07:23Z
20   LEICA GR30                1705298         2018-11-28T07:25Z    (CCYY-MM-DDThh:mmZ)

```

**Example output (receivers):**
```

📶 GNSS Antennas:
#    Type                      Serial          Installed            Removed
-------------------------------------------------------------------------------------
1    TRM41249.00     TZGD      12696814        2005-04-13T12:00Z    2010-03-15T08:30Z
2    LEIAR25.R3      LEIT      09480032        2010-03-15T08:30Z    2011-08-31T05:30Z
3    TRM57971.00     TZGD      1441101374      2011-08-31T05:30Z    2011-09-13T11:00Z
4    LEIAR25.R3      LEIT      09470019        2011-09-13T11:00Z    2012-08-22T07:30Z
5    TPSCR.G3        TPSH      383-2172        2012-08-22T07:30Z    2017-10-10T06:07Z
6    LEIAR25.R4      LEIT      726448          2017-10-10T06:07Z    (CCYY-MM-DDThh:mmZ)

```

**Example output (metadata):**
```
📋 Site Metadata:

Site Name: Amsterdam, Netherlands
Four Character ID: AMST
DOMES Number: 13502M001
Location: Amsterdam, Netherlands
Coordinates:
  Latitude: +52.3712800855
  Longitude: +4.8563185513
  Elevation: 1.0 m

On-Site Agency: Technische Universiteit Delft
Responsible Agency: Technische Universiteit Delft
```

### Prepare/export a sitelog file

```bash
# Read and export with auto-generated filename
slp prepare tests/AMST_20190705.txt

# Specify output file
slp prepare tests/AMST_20190705.txt -o output/AMST_prepared.log
```

**Output:**
```
✓ Parsed sitelog: tests/AMST_20190705.txt
✓ Exported to: output/AMST_prepared.log
```

The prepared file will be in IGS sitelog v2.0 format with:
- Automatically updated form metadata (date prepared, modified sections)
- Normalized formatting and field alignment
- UTC timestamps in `CCYY-MM-DDThh:mmZ` format

### Show version

```bash
slp --version
```

## API Usage

### Basic Parsing

```python
from sitelogparser.common.sitelog import SiteLogParser

# Parse a sitelog file
parser = SiteLogParser(sitelog_file="path/to/sitelog.txt")
sitelog = parser.sitelog

# Access site information
print(f"Site: {sitelog.site_identification.site_name}")
print(f"Four-char ID: {sitelog.site_identification.four_character_id}")
print(f"DOMES: {sitelog.site_identification.iers_domes_number}")

# Access location data
location = sitelog.site_location
print(f"Location: {location.city}, {location.country}")
print(f"Coordinates: {location.latitude}, {location.longitude}")

# Iterate over receivers
for receiver in sitelog.gnss_receivers:
    print(f"Receiver {receiver.number}: {receiver.receiver_type}")
    print(f"  Serial: {receiver.serial_number}")
    print(f"  Firmware: {receiver.firmware_version}")

# Iterate over antennas
for antenna in sitelog.gnss_antennas:
    print(f"Antenna {antenna.number}: {antenna.antenna_type}")
    print(f"  Serial: {antenna.serial_number}")
    print(f"  Radome: {antenna.antenna_radome_type}")

# Access agency information
print(f"On-site agency: {sitelog.on_site_agency.name}")
print(f"Primary contact: {sitelog.on_site_agency.primary_contact.name}")
print(f"Email: {sitelog.on_site_agency.primary_contact.email}")
```

### Exporting Sitelog Data

```python
from sitelogparser.common.sitelog import SiteLogParser

# Parse existing sitelog
parser = SiteLogParser(sitelog_file="input.txt")

# Modify data programmatically
parser.sitelog.site_identification.site_name = "Updated Site Name"

# Export to new file (automatically updates form metadata)
output_text = parser.export_sitelog()
with open("output.txt", "w") as f:
    f.write(output_text)
```

### Creating a New Sitelog

```python
from sitelogparser.common.models import (
    Sitelog, FormInformation, SiteIdentification, SiteLocation,
    GNSSReceiver, GNSSAntenna, Agency, Contact
)
from sitelogparser.common.sitelog import SiteLogParser
from datetime import datetime, timezone

# Create sitelog structure
sitelog = Sitelog()

# Fill form information
sitelog.form_information = FormInformation(
    prepared_by="John Doe",
    report_type="NEW"
)

# Fill site identification
sitelog.site_identification = SiteIdentification(
    site_name="Example Site",
    four_character_id="EXMP",
    iers_domes_number="12345M001",
    date_installed=datetime(2025, 1, 1, tzinfo=timezone.utc).timestamp()
)

# Fill location
sitelog.site_location = SiteLocation(
    city="Example City",
    country="Example Country",
    latitude="+12.3456789012",
    longitude="+123.4567890123",
    elevation="100.0"
)

# Add receivers
receiver = GNSSReceiver(
    number=1,
    receiver_type="EXAMPLE RECEIVER",
    satellite_system="GPS",
    serial_number="12345",
    firmware_version="1.0.0",
    elevation_cutoff_setting="0",
    date_installed=datetime(2025, 1, 1, tzinfo=timezone.utc).timestamp(),
    date_removed=0.0,  # 0.0 means not removed yet
    temperature_stabilization="none"
)
sitelog.gnss_receivers.append(receiver)

# Add antennas
antenna = GNSSAntenna(
    number=1,
    antenna_type="EXAMPLE ANTENNA",
    serial_number="ANT123",
    antenna_reference_point="BPA",
    marker_arp_up_ecc="0.0000",
    marker_arp_north_ecc="0.0000",
    marker_arp_east_ecc="0.0000",
    alignment_of_true_n="0",
    antenna_radome_type="NONE",
    radome_serial_number="",
    antenna_cable_type="",
    antenna_cable_length="",
    date_installed=datetime(2025, 1, 1, tzinfo=timezone.utc).timestamp(),
    date_removed=0.0
)
sitelog.gnss_antennas.append(antenna)

# Add agency information
sitelog.on_site_agency = Agency(
    section="11",
    name="Example Organization",
    abbreviation="EXORG",
    mail_address="123 Example St, Example City, Country",
    primary_contact=Contact(
        name="Jane Doe",
        phone1="+1-555-0100",
        email="jane.doe@example.org"
    )
)

# Export to sitelog format
parser = SiteLogParser(sitelog_text="")
parser.sitelog = sitelog
output_text = parser.export_sitelog()

with open("new_sitelog.txt", "w") as f:
    f.write(output_text)
```

### Working with Timestamps

Dates in the dataclasses are stored as float timestamps (seconds since Unix epoch):

```python
from datetime import datetime, timezone

# Convert datetime to timestamp (for setting dates)
dt = datetime(2025, 1, 15, 12, 30, tzinfo=timezone.utc)
timestamp = dt.timestamp()
receiver.date_installed = timestamp

# Convert timestamp to datetime (for reading dates)
from sitelogparser.common.sitelog import SiteLogParser
parser = SiteLogParser(sitelog_file="sitelog.txt")
receiver = parser.sitelog.gnss_receivers[0]

if receiver.date_installed > 0:
    dt = datetime.fromtimestamp(receiver.date_installed, tz=timezone.utc)
    print(f"Installed: {dt.strftime('%Y-%m-%d %H:%M:%S %Z')}")

# Dates are exported in IGS format: CCYY-MM-DDThh:mmZ
# Empty dates (0.0) are shown as: (CCYY-MM-DDThh:mmZ)
```

### Data Models

The library uses Python dataclasses for type-safe data representation:

- **`Sitelog`**: Top-level container for all sitelog data
- **`FormInformation`**: Section 0 - Form metadata
- **`SiteIdentification`**: Section 1 - Site identification
- **`SiteLocation`**: Section 2 - Site location information
- **`GNSSReceiver`**: Section 3.x - Individual receiver configuration
- **`GNSSAntenna`**: Section 4.x - Individual antenna configuration
- **`Agency`**: Sections 11-12 - Agency information with contacts
- **`Contact`**: Contact person information

All dataclasses have full type hints and can be converted to dictionaries using the `to_dict()` method.

## Requirements

- Python >= 3.8
- No external dependencies (uses only Python standard library)

## Development

Run tests:
```bash
python -m unittest discover tests/ -v
```

Run specific test:
```bash
python -m unittest tests.test_parser
python -m unittest tests.test_generate
```

## License

See [LICENSE.txt](LICENSE.txt) for details.

## Contributing

Contributions are welcome! Please ensure all tests pass before submitting pull requests.