# 🐀 Labrat Sensor Logger

Connect sensors and log data to a database, file, or both.

## Table of Contents

- [Quick Start](#quick-start)
- [Connection Modes](#connection-modes)
- [All Options](#all-options)
- [Setup & First Run](#setup--first-run)
  - [1. Create a Secrets File](#1-create-a-secrets-file)
  - [2. Set Up a Database](#2-set-up-a-database)
  - [3. Run](#3-run)
- [Running as a Daemon](#running-as-a-daemon)

---

## Quick Start

Not sure where to begin? Run the setup wizard:

```bash
python labrat_log.py -secrets "mypath/secrets.toml" quick_start
```

---

## Connection Modes

The required `CONN` argument sets which data source to use:

| Mode          | Description                        |
|---------------|------------------------------------|
| `mqtt`        | Subscribe to an MQTT broker        |
| `serial`      | Read from a wired serial port      |
| `flask`       | Receive data via a Flask API       |
| `quick_start` | Run the interactive setup wizard   |

---

## All Options

```
usage: labrat_log.py [-h] [-sql SQL] [-secrets SECRETS] [-setupsql] [--createdb]
                     [--dev_file DEVFILE] [-file FILE] [--setfile]
                     [-ser_port SER_PORT] [-baud BAUD] CONN
```

| Flag                  | Description                                                                 |
|-----------------------|-----------------------------------------------------------------------------|
| `CONN`                | **Required.** Connection mode: `mqtt`, `serial`, `flask`, or `quick_start`  |
| `-secrets SECRETS`    | Path to the TOML secrets file (logins, broker details, etc.)                |
| `-sql SQL`            | Absolute path to the SQLite database file                                   |
| `-setupsql`           | Run database setup (use with `--dev_file` and optionally `--createdb`)      |
| `--createdb`          | Create a new database if one doesn't exist at the given path                |
| `--dev_file DEVFILE`  | Path to the JSON device info file, used during database setup               |
| `-file FILE`          | Absolute path to a text file for logging data                               |
| `--setfile`           | Run file setup (writes headers etc.) before logging                         |
| `-ser_port SER_PORT`  | COM port for serial connections (e.g. `COM3` or `/dev/ttyUSB0`)             |
| `-baud BAUD`          | Baud rate for the serial connection                                         |

---

## Setup & First Run

### 1. Create a Secrets File

Create a `.toml` file with your credentials and connection details:

```toml
MQTT_USERNAME = ""
MQTT_KEY      = ""
MQTT_BROKER   = ""
MQTT_PORT     = ""
MQTT_TOPIC    = ""
INATOR_NAME   = ""
FLASK_KEY     = ""
FLASK_ROUTE   = ""
```

Only the values relevant to your chosen connection mode are required.

### 2. Set Up a Database

If logging to SQLite, initialise the database with your device configuration:

```bash
# Create a new DB and load device info from a JSON file
python labrat_log.py -secrets "secrets.toml" -sql "/abs/path/to/data.db" \
    -setupsql --createdb --dev_file "/abs/path/to/devices.json" mqtt
```

> Omit `--createdb` if the database already exists.

The device file must conform to the [Inator DB schema](https://inator-project.org/Protocols/pro_database.html).

<details>
<summary><strong>Device file JSON schema</strong></summary>

```json
{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "properties": {
    "devices": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "device_name":     { "type": "string" },
          "device_guid":     { "type": "string" },
          "num_sensors":     { "type": "integer" },
          "device_info":     { "type": "string" },
          "device_type":     { "type": "string" },
          "device_location": { "type": "string" },
          "device_active":   { "type": "integer" },
          "connection": {
            "type": "string",
            "enum": ["Serial", "MQTT", "Other"]
          },
          "sensors": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "sens_name": { "type": "string" },
                "measures":  { "type": "string" },
                "returns":   { "type": "string" },
                "calib":     { "type": "string" },
                "range":     { "type": "string" },
                "info":      { "type": "string" },
                "comments":  { "type": "string" }
              },
              "required": ["sens_name", "measures", "returns", "calib", "range", "info", "comments"]
            }
          }
        },
        "required": [
          "device_name", "device_guid", "num_sensors", "device_info",
          "device_type", "device_location", "device_active", "connection", "sensors"
        ]
      }
    }
  },
  "required": ["devices"]
}
```

</details>

### 3. Run

**MQTT:**
```bash
python labrat_log.py -secrets "secrets.toml" -sql "/abs/path/to/data.db" mqtt
```

**Serial:**
```bash
python labrat_log.py -secrets "secrets.toml" -sql "/abs/path/to/data.db" \
    -ser_port /dev/ttyUSB0 -baud 9600 serial
```

**Flask API:**
```bash
python labrat_log.py -secrets "secrets.toml" -sql "/abs/path/to/data.db" flask
```

**Log to a text file instead of (or alongside) a database:**
```bash
# First-time setup of the file (writes headers):
python labrat_log.py -secrets "secrets.toml" -file "/abs/path/to/log.txt" --setfile mqtt

# Subsequent runs:
python labrat_log.py -secrets "secrets.toml" -file "/abs/path/to/log.txt" mqtt
```

---

## Running as a Daemon

Run the logger as a persistent background service using [Supervisor](http://supervisord.org/).

### 1. Install

```bash
sudo apt update && sudo apt install supervisor
```

### 2. Configure

Edit the provided `supervisord.conf` file, updating these fields:

| Field             | What to set                                                   |
|-------------------|---------------------------------------------------------------|
| `command=`        | Full command with all required paths and flags                |
| `user=`           | System user to run the process as                             |
| `stdout_logfile=` | Absolute path and filename for log output                     |
| `directory=`      | Working directory (home directory for MQTT)                   |

### 3. Start

```bash
supervisord -c /path/to/supervisord.conf
```

### 4. Monitor & Control

Use [`supervisorctl`](https://supervisord.org/running.html#running-supervisorctl) to manage the process:

```bash
supervisorctl status          # check if running
supervisorctl restart labrat  # restart the service
supervisorctl stop labrat     # stop the service
```