# scentience

Python client for [Scentience](https://scentience.github.io) olfaction instruments over BLE Bluetooth.

## Installation

```bash
pip install scentience
```

## Requirements

- Python 3.8+
- Bluetooth 4.0+ adapter
- A Scentience developer API key (obtain from the Scentience portal)

## Quick start

```python
import scentience as scn

# Initialize with your developer API key
device = scn.ScentienceDevice(api_key="YOUR_API_KEY")

# Connect via BLE (scans for the first available Scentience device)
device.connect_ble(char_uuid="YOUR_CHAR_UUID")

# Take a single reading
data = device.sample_ble()
print(data)

# Start continuous streaming (non-blocking)
device.stream_ble(callback=lambda d: print(d))

# Stop streaming and disconnect
device.stop_stream()
device.disconnect()
```

## Targeting a specific device

Pass the device UID (serial number or BLE address) to connect to a particular instrument:

```python
device.connect_ble(char_uuid="YOUR_CHAR_UUID", device_uid="YOUR_DEVICE_UID")
```

## Context manager

```python
with scn.ScentienceDevice(api_key="YOUR_API_KEY") as device:
    device.connect_ble(char_uuid="YOUR_CHAR_UUID")
    data = device.sample_ble()
```

## Response payload

`sample_ble()` and the streaming callback receive a dict that may contain:

| Key | Description |
|-----|-------------|
| `UID` | Device serial number |
| `TIMESTAMP` | Reading timestamp |
| `ENV_temperatureC` | Ambient temperature (°C) |
| `ENV_humidity` | Relative humidity (%) |
| `ENV_pressureHpa` | Barometric pressure (hPa) |
| `BATT_health` | Battery health |
| `BATT_v` | Battery voltage |
| `BATT_charge` | Battery charge (%) |
| `BATT_time` | Estimated battery time remaining |
| `STATUS_opuA` | Operational status |
| `CO2`, `NH3`, `NO`, `NO2`, `CO`, `C2H5OH` | Chemical compounds (non-zero only) |
| `H2`, `CH4`, `C3H8`, `C4H10`, `H2S`, `HCHO`, `SO2`, `VOC` | Chemical compounds (non-zero only) |

## Logging and export

All readings from `sample_ble()` and `stream_ble()` are automatically buffered in memory.

```python
# Access the in-memory log at any time
print(device.log)          # list of dicts

# Export to JSON
device.export_json("readings.json")

# Export to CSV
device.export_csv("readings.csv")

# Clear the buffer
device.clear_log()
```

The CSV uses `UID` and `TIMESTAMP` as the first columns (when present), followed by all other fields in alphabetical order.  Readings that are missing a field are written with an empty value for that column.

## API reference

See the full [BLE API documentation](https://scentience.github.io/docs-api/ble-api).

## License

MIT
