Metadata-Version: 2.4
Name: orbitable
Version: 0.3.0
Summary: Orbital element database management tool
Author-email: Jonathan Olsten <jolsten@gmail.com>
Requires-Python: >=3.11
Requires-Dist: loguru>=0.7.3
Requires-Dist: pydantic-settings>=2.9.1
Requires-Dist: sgp4>=2.24
Requires-Dist: sqlalchemy>=2.0.40
Provides-Extra: mysql
Requires-Dist: pymysql>=1.1; extra == 'mysql'
Description-Content-Type: text/markdown

# Orbitable

Orbital element database manager. Ingests TLE (Two-Line Element) and OMM (Orbit Mean-Elements Message) files into a database and generates organized output files by date and satellite.

## Installation

```bash
pip install orbitable

# For MariaDB/MySQL support:
pip install orbitable[mysql]
```

Or with [uv](https://docs.astral.sh/uv/):

```bash
uv add orbitable
```

## Quick Start

### 1. Scaffold configuration

```bash
orbitable init
```

This creates two files:

- `./config.toml` -- main configuration (database, ingest sources, output settings)
- `~/.config/orbitable.toml` -- user-local database credentials

Use `-c` to specify a different config path:

```bash
orbitable -c /etc/orbitable/config.toml init
```

### 2. Configure

Edit `config.toml` to set your database and ingest sources. The generated file is fully commented -- see below for a summary.

**SQLite (default):**

```toml
[database]
drivername = "sqlite"
name = "orbitable.db"
```

**MariaDB/MySQL:**

```toml
[database]
drivername = "mysql+pymysql"
host = "localhost"
port = 3306
name = "orbitable"
secrets_file = "/etc/orbitable/secrets.toml"
```

Then add your credentials to `~/.config/orbitable.toml`:

```toml
username = "myuser"
password = "mypassword"
```

### 3. Ingest TLE/OMM files

Scan configured source directories:

```bash
orbitable ingest
```

Or ingest specific files:

```bash
orbitable ingest /path/to/20260327.tle /path/to/20260327.json
```

File format is auto-detected by extension:

| Extension          | Format              |
| ------------------ | ------------------- |
| `.tle`, `.txt`, `.3le` | Two-Line Element |
| `.json`            | Space-Track OMM JSON |
| `.csv`             | OMM CSV              |
| `.xml`             | OMM XML              |

Ingestion is idempotent -- duplicate records are silently skipped.

### 4. Generate output files

```bash
orbitable generate
```

This produces files in the configured output directory:

- **Date files** (`YYYYMMDD.tle` / `YYYYMMDD.omm`) -- one TLE per satellite for each date (latest epoch that day)
- **Object files** (`25544.tle` / `25544.omm`) -- all TLEs for a single satellite, ordered by epoch

## Automating with Cron

Orbitable is designed to run via cron rather than as a long-running service. Both `ingest` and `generate` are idempotent and safe to re-run.

**Ingest and generate every 4 hours:**

```cron
0 */4 * * * orbitable -c /etc/orbitable/config.toml ingest && orbitable -c /etc/orbitable/config.toml generate
```

**Ingest hourly, generate once daily at 03:00 UTC:**

```cron
0 * * * * orbitable -c /etc/orbitable/config.toml ingest
0 3 * * * orbitable -c /etc/orbitable/config.toml generate
```

**With logging to a file:**

```cron
0 */4 * * * orbitable -c /etc/orbitable/config.toml ingest >> /var/log/orbitable.log 2>&1 && orbitable -c /etc/orbitable/config.toml generate >> /var/log/orbitable.log 2>&1
```

## Credential Resolution

Database credentials are resolved in priority order:

1. **Environment variables** -- `ORBITABLE_DATABASE__USERNAME` / `ORBITABLE_DATABASE__PASSWORD`
2. **User secrets file** -- `~/.config/orbitable.toml`
3. **System secrets file** -- path set via `secrets_file` in `config.toml`
4. **config.toml values** -- not recommended for credentials

For cron jobs, either use the user secrets file or export environment variables in the crontab:

```cron
ORBITABLE_DATABASE__USERNAME=myuser
ORBITABLE_DATABASE__PASSWORD=mypassword
0 */4 * * * orbitable -c /etc/orbitable/config.toml ingest && orbitable -c /etc/orbitable/config.toml generate
```

## CLI Reference

```
orbitable [-c CONFIG] COMMAND

Commands:
  init       Scaffold config.toml and ~/.config/orbitable.toml
  ingest     Ingest TLE/OMM files into the database
  generate   Generate output TLE/OMM files from the database

Options:
  -c, --config PATH   Path to config.toml (default: ./config.toml)
```

## Configuration Reference

### `[database]`

| Field          | Default      | Description                                |
| -------------- | ------------ | ------------------------------------------ |
| `drivername`   | `"sqlite"`   | SQLAlchemy driver (`sqlite`, `mysql+pymysql`) |
| `name`         | `":memory:"` | Database name or file path                 |
| `host`         |              | Database host                              |
| `port`         |              | Database port                              |
| `username`     |              | Database username (prefer secrets file)    |
| `password`     |              | Database password (prefer secrets file)    |
| `secrets_file` |              | Path to a TOML file with username/password |

### `[[ingest.sources]]`

| Field     | Default   | Description                        |
| --------- | --------- | ---------------------------------- |
| `path`    |           | Directory to scan for files        |
| `pattern` | `"*.tle"` | Glob pattern for matching files    |

### `[output]`

| Field   | Default      | Description                     |
| ------- | ------------ | ------------------------------- |
| `dir`   | `"./output"` | Output directory                |

### `[output.formats]`

| Field | Default | Description                 |
| ----- | ------- | --------------------------- |
| `tle` | `true`  | Generate .tle output files  |
| `omm` | `true`  | Generate .omm (CSV) output  |

### `[output.types]`

| Field          | Default | Description                                        |
| -------------- | ------- | -------------------------------------------------- |
| `date_files`   | `true`  | YYYYMMDD files with latest TLE per satellite       |
| `object_files` | `true`  | Per-satellite files with all TLEs ordered by epoch  |

### `[logging]`

| Field   | Default  | Description                                    |
| ------- | -------- | ---------------------------------------------- |
| `level` | `"INFO"` | Log level: DEBUG, INFO, WARNING, ERROR, CRITICAL |

## Development

### Running tests

Tests are parametrized to run against SQLite, MariaDB, and PostgreSQL. SQLite runs unconditionally; MariaDB and PostgreSQL tests are skipped unless `ORBITABLE_TEST_MARIADB_URL` / `ORBITABLE_TEST_POSTGRES_URL` are set.

SQLite only:

```bash
uv run pytest tests/
```

MariaDB (requires Docker):

```bash
docker run -d --name orbitable-mariadb \
  -e MARIADB_ROOT_PASSWORD=rootpass \
  -e MARIADB_DATABASE=orbitable_test \
  -e MARIADB_USER=orbitable \
  -e MARIADB_PASSWORD=orbitable \
  -p 3306:3306 \
  mariadb:11

export ORBITABLE_TEST_MARIADB_URL="mysql+pymysql://orbitable:orbitable@127.0.0.1:3306/orbitable_test"
uv run pytest tests/

docker rm -f orbitable-mariadb
```

PostgreSQL (requires Docker):

```bash
docker run -d --name orbitable-postgres \
  -e POSTGRES_DB=orbitable_test \
  -e POSTGRES_USER=orbitable \
  -e POSTGRES_PASSWORD=orbitable \
  -p 5432:5432 \
  postgres:16

export ORBITABLE_TEST_POSTGRES_URL="postgresql+psycopg://orbitable:orbitable@127.0.0.1:5432/orbitable_test"
uv run pytest tests/

docker rm -f orbitable-postgres
```
