Python client for Scentience olfaction instruments over BLE Bluetooth
Project description
scentience
Python client for Scentience olfaction instruments over BLE Bluetooth.
Installation
BLE only:
pip install scentience
BLE + COLIP embedding models:
pip install "scentience[models]"
Requirements
- Python 3.8+
- Bluetooth 4.0+ adapter
- A Scentience developer API key (obtain from the Scentience portal)
- For embedding models:
torch,torchvision,transformers,huggingface-hub,Pillow(installed via[models]extra)
Quick start
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:
device.connect_ble(char_uuid="YOUR_CHAR_UUID", device_uid="YOUR_DEVICE_UID")
Context manager
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.
# 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.
COLIP embedding models
ColipModel integrates the Olfaction-Vision-Language Embeddings to produce joint embeddings across olfaction, vision, and language modalities.
Four variants are available:
| Variant | Embed dim | Architecture | Best for |
|---|---|---|---|
colip-small-base |
512 | base GNN | Fast inference / edge devices |
colip-small-gat |
512 | GAT | Higher accuracy on edge devices |
colip-large-base |
2048 | base GNN | Accuracy-critical tasks |
colip-large-gat |
2048 | GAT | Highest accuracy, slower inference |
Weights are downloaded from HuggingFace Hub and cached locally on first use.
Example — small base model
import scentience as scn
from PIL import Image
# Load the small base model (512-dim embeddings, fastest)
model = scn.ColipModel.from_pretrained("colip-small-base")
print(model)
# ColipModel(variant='colip-small-base', embed_dim=512, device='cpu')
image = Image.open("scene.jpg")
olf_vec = [0.0] * 138 # 138-dimensional olfactory descriptor
# Returns a torch.Tensor of shape (512,)
embedding = model.embed(image, olf_vec)
# Or as a NumPy array
arr = model.embed_numpy(image, olf_vec)
Example — large GAT model
import scentience as scn
from PIL import Image
# Load the large GAT model (2048-dim embeddings, highest accuracy)
model = scn.ColipModel.from_pretrained("colip-large-gat")
image = Image.open("scene.jpg")
olf_vec = [0.0] * 138
# Returns a torch.Tensor of shape (2048,)
embedding = model.embed(image, olf_vec)
Example — combined BLE streaming + real-time embedding
import scentience as scn
from PIL import Image
model = scn.ColipModel.from_pretrained("colip-small-base")
device = scn.ScentienceDevice(api_key="YOUR_API_KEY")
device.connect_ble(char_uuid="YOUR_CHAR_UUID")
scene = Image.open("scene.jpg")
def on_sample(data):
olf_vec = [data.get(k, 0.0) for k in sorted(data.keys()) if k not in ("UID", "TIMESTAMP")]
embedding = model.embed(scene, olf_vec)
print(f"embedding shape: {embedding.shape}, norm: {embedding.norm():.4f}")
device.stream_ble(callback=on_sample)
Targeting a specific device or compute backend
# Target GPU explicitly
model = scn.ColipModel.from_pretrained("colip-large-base", device="cuda")
# Or use the constructor directly
model = scn.ColipModel(variant="colip-small-gat", device="mps")
API reference
See the full BLE API documentation.
License
Apache 2.0
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file scentience-0.3.0.tar.gz.
File metadata
- Download URL: scentience-0.3.0.tar.gz
- Upload date:
- Size: 15.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
85cb5947c32f0456dae197ffb4db3b111a01cb250d437c6aebdbcb53a4667a9e
|
|
| MD5 |
ed343185d8529eed9e4a2746fb1d6831
|
|
| BLAKE2b-256 |
00c9a6647a9d516a3c803de95e7abbb9c7fc59257962d55ee09ed4a314825bcc
|
File details
Details for the file scentience-0.3.0-py3-none-any.whl.
File metadata
- Download URL: scentience-0.3.0-py3-none-any.whl
- Upload date:
- Size: 17.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
936a930bb3acb528d3b9f966bf8dabd726e20b6f029e787e7e041a11d32dfdeb
|
|
| MD5 |
f78b9206e94fc5e9d3bc9eedbcd2c185
|
|
| BLAKE2b-256 |
839209a08ec01e51d17096014467dbc84f0eda63ab821b95dee2b22962325eb5
|