An open interoperability layer for digital olfaction.
OpenSmell provides a device-independent way to represent, exchange, validate, and request the rendering of digital olfactory information across software, data sources, scientific models, and heterogeneous devices.
OpenSmell does not define how an odor must physically be reproduced. It provides an interoperability layer between systems that produce, store, transform, interpret, or render olfactory information.
Digital olfaction already spans odor datasets, chemical information, machine- learning models, electronic noses, research software, and scent-display hardware. These systems may use different representations, vocabularies, data models, and device interfaces. OpenSmell explores a common layer that lets them exchange olfactory information without requiring one universal physical smell reproduction technology.
Dataset A ─┐
Model B ─┼──► different representations ──► OpenSmell ──► applications / devices
Sensor C ─┘
An .osmell document can carry multiple representations of the same conceptual
odor. Applications use the representations they understand and preserve the
ones they do not.
import opensmell
odor = opensmell.load("examples/coffee.osmell")
print(odor.id)
print(odor.metadata.labels.get("en"))
for representation in odor.representations:
print(representation.type, representation.scheme.id)OpenSmell can therefore transport semantic, perceptual, chemical, mixture, or future representations while keeping physical rendering decisions outside the Core format.
| Area | Status |
|---|---|
| OpenSmell Core 0.1 format and JSON Schema | Implemented |
| Python reference implementation | Implemented |
| Forward-compatible schemes and extension preservation | Implemented |
| Experimental ResourceGraph interoperability | Implemented and tested |
| Portable Python/JavaScript interoperability vectors | Implemented |
| Experimental rendering and device architecture | Documented through RFC-0012 |
| Device Protocol 0.1 and serial transport | Implemented experimentally |
| Automated Python test suite | More than 1,700 tests passing in the latest audited local run |
| Physical hardware validation | ESP32/LED control path validated experimentally |
Important
OpenSmell is an early-stage experimental project. Version 0.1 is
pre-alpha and must not be treated as a stable standard. Experimental graph,
rendering, device, and protocol APIs may change.
OpenSmell is an interoperability framework. It is not an electronic nose, a chemical analysis platform, an odor-prediction model, a physical scent diffuser, or a claim that arbitrary smells can already be perfectly digitized and reproduced. Those technologies may produce or consume information through OpenSmell, but they remain separate systems.
- Why OpenSmell?
- Core principle
- What OpenSmell 0.1 provides
.osmelldocuments- Python reference implementation
- Architecture
- RFCs
- Roadmap
- Relationship with existing work
- Contributing
Digital olfaction is an emerging field involving technologies such as:
- electronic noses and chemical sensors;
- machine-learning models for odor perception;
- digital odor databases;
- scent displays and olfactory interfaces;
- VR/AR olfactory experiences;
- remote odor reproduction;
- odor digitization research. Several projects and standards already address parts of this ecosystem. However, these systems may represent odors differently and may rely on different hardware, models, vocabularies, measurement protocols, or delivery technologies. OpenSmell explores a simple question:
Can digital odor information be represented and exchanged independently from the technology that eventually interprets or renders it? The project aims to investigate and implement this interoperability layer.
OpenSmell must not assume how an odor is physically reproduced. A future olfactory display might use:
- a small number of odor primaries;
- hundreds of chemical cartridges;
- predefined scent cartridges;
- dynamically generated mixtures;
- technologies that do not exist yet. OpenSmell should therefore describe olfactory information without forcing every device to use the same physical reproduction mechanism. Conceptually:
Scientific data / Models / Sensors
│
▼
Digital odor information
│
▼
┌───────────┐
│ OpenSmell │
└───────────┘
│
┌──────┼──────┐
▼ ▼ ▼
Application Mapper Storage
│
▼
Device adapter
│
▼
Olfactory device
OpenSmell focuses primarily on the interoperability layer, not on the physical diffuser itself.
The current reference implementation includes:
- a JSON-based
.osmelldocument format; - JSON Schema validation;
- Python data models;
.osmellloading and serialization;- multiple representations per odor;
- representation scheme validation;
- a scheme registry;
- semantic descriptor representations;
- chemical SMILES representations;
- builders for creating OpenSmell objects;
- forward-compatible handling of unknown schemes;
- preservation of unknown extension fields;
- document-level lossless round trips;
- an experimental OdorNet adapter;
- experimental semantic annotation modeling based on real OdorNet data;
- an experimental Keller/Vosshall adapter for quantitative perceptual measurements;
- optional PubChem chemical identity enrichment;
- an experimental Geraniol
.osmellfixture and deterministic regeneration path from a locally prepared external OdorNet + PubChem enrichment dataset; - experimental rendering requests, rendering plans, semantic channel mapping, device capabilities, and device adapters;
- experimental Device Protocol 0.1 with transport-independent adapters;
- optional serial transport using PySerial;
- a physically validated ESP32/LED control-path prototype;
- experimental deterministic resource identification based on canonical source identity and UUIDs;
- cross-language Python/JavaScript identifier interoperability tests;
- an experimental generic resource model with
Stimulus,ObservationTarget,Observation, versionedResultScheme, and scheme-definedResultobjects; - an experimental flat
ResourceGraphwith Resource-ID references and unresolved-reference preservation; - an experimental JSON ResourceGraph serialization format;
- dataset-scale ResourceGraph round-trip validation across human psychophysics, biological physiology, and electronic olfaction;
- automated tests and CI;
- an RFC-based design process. The current implementation deliberately keeps these experimental graph concepts outside OpenSmell 0.1 Core. OpenSmell 0.1 does not attempt to solve physical odor reproduction.
An OpenSmell odor may contain multiple representations of the same conceptual odor. For example:
Odor
│
┌────────────┼────────────┐
▼ ▼ ▼
Semantic Perceptual Chemical
│ │ │
└────────────┼────────────┘
▼
OpenSmell
Different applications can use the representations they understand. OpenSmell 0.1 recognizes the following broad representation type names:
semantic
perceptual
chemical
mixture
These are broad categories only. The actual interpretation of a representation is defined by its scheme. Unknown representation types and unknown schemes are allowed so that OpenSmell can evolve without requiring every implementation to understand every possible representation.
Every representation identifies a scheme.
A scheme defines how the representation's data field should be interpreted.
Example:
{
"type": "semantic",
"scheme": {
"id": "org.opensmell.semantic.descriptors",
"version": "0.1"
},
"data": {
"descriptors": [
{
"value": "coffee",
"language": "en"
},
{
"value": "roasted",
"language": "en"
}
]
}
}Here:
type
identifies the broad representation family.
scheme
defines the specific rules used to interpret the data. This separation allows OpenSmell to transport representations produced by different scientific models, datasets, organizations, and future technologies.
Version:
0.1
Representation type:
semantic
This scheme represents an odor using human-readable semantic descriptors. Example:
{
"type": "semantic",
"scheme": {
"id": "org.opensmell.semantic.descriptors",
"version": "0.1"
},
"data": {
"descriptors": [
{
"value": "coffee",
"language": "en"
},
{
"value": "roasted",
"language": "en"
},
{
"value": "bitter",
"language": "en"
}
]
}
}This representation describes an odor. It does not specify how a physical device should reproduce it.
Version:
0.1
Representation type:
chemical
This scheme associates molecular structure information with an OpenSmell odor using SMILES. Example:
{
"type": "chemical",
"scheme": {
"id": "org.opensmell.chemical.smiles",
"version": "0.1"
},
"data": {
"smiles": "O=C1OC2=CC=CC=C2C=C1"
}
}OpenSmell Core verifies that the SMILES value is a non-empty string. It does not attempt to prove chemical validity. A chemical representation also does not imply that the represented molecule alone is sufficient to reproduce the perceived odor.
Experimental RFCs currently investigate richer representation schemes that are deliberately kept outside the normative OpenSmell 0.1 Core.
RFC-0004 investigates:
org.opensmell.semantic.annotations
The model distinguishes categorical states such as:
present
absent
unknown
This distinction is important for datasets where missing information must not automatically be interpreted as absence. The model has been tested using OdorNet data.
RFC-0005 investigates:
org.opensmell.perceptual.measurements
The model represents quantitative perceptual measurements while preserving an important distinction:
measurement absent ≠ measured value 0
The model has been tested against the Keller/Vosshall DREAM Olfaction Prediction Challenge dataset. These schemes remain experimental and are not automatically part of OpenSmell 0.1 Core.
OpenSmell 0.1 uses UTF-8 JSON. The recommended file extension is:
.osmell
Example:
{
"opensmell": "0.1",
"odor": {
"id": "urn:uuid:550e8400-e29b-41d4-a716-446655440000",
"metadata": {
"labels": {
"en": "Coumarin",
"fr": "Coumarine"
},
"description": "Example odor with chemical and semantic representations."
},
"representations": [
{
"type": "chemical",
"scheme": {
"id": "org.opensmell.chemical.smiles",
"version": "0.1"
},
"data": {
"smiles": "O=C1OC2=CC=CC=C2C=C1"
}
},
{
"type": "semantic",
"scheme": {
"id": "org.opensmell.semantic.descriptors",
"version": "0.1"
},
"data": {
"descriptors": [
{
"value": "sweet",
"language": "en"
},
{
"value": "vanilla-like",
"language": "en"
}
]
}
}
]
}
}The same odor can therefore carry chemical and semantic information without requiring either representation to be derived from the other.
OpenSmell is designed so that information unknown to one implementation can still be transported. Conceptually:
Known scheme + valid data
│
▼
ACCEPT
Known scheme + invalid data
│
▼
REJECT
Unknown scheme
│
▼
ACCEPT
│
▼
Preserve opaque data
The Python implementation can preserve unknown extension fields at the following levels:
Document
├── extra
└── Odor
├── extra
├── Metadata
│ └── extra
└── Representation
├── extra
└── Scheme
└── extra
This allows newer or experimental information to survive a read/write cycle
even when the implementation does not understand its meaning.
Official OpenSmell fields always take precedence over extension fields.
Applications that require preservation of document-level extension fields
should use the complete Document API rather than discarding the root
document structure.
OpenSmell currently provides a Python reference implementation. Supported versions:
Python 3.10+
Clone the repository:
git clone https://github.com/YAAASSS/OpenSmell.git
cd OpenSmellCreate a virtual environment:
python -m venv .venvActivate it. Windows PowerShell:
.venv\Scripts\Activate.ps1Linux/macOS:
source .venv/bin/activateInstall OpenSmell with development dependencies:
python -m pip install -e ".[dev]"The simple API returns the odor contained in an OpenSmell document:
import opensmell
odor = opensmell.load("examples/coffee.osmell")
print(odor.id)Access metadata:
print(odor.metadata.labels["en"])Access representations:
representation = odor.representations[0]
print(representation.type)
print(representation.scheme.id)
print(representation.scheme.version)Applications such as editors, converters, proxies, or interoperability tools may need to preserve information they do not understand. For those applications, OpenSmell provides:
import opensmell
document = opensmell.load_document(
"examples/coffee.osmell"
)
opensmell.dump(
document,
"coffee-copy.osmell"
)load_document() returns the complete OpenSmell document model rather than
only its odor.
This allows document-level extension fields to survive the round trip.
The original API remains available:
odor = opensmell.load("examples/coffee.osmell")so existing code does not need to migrate to Document unless document-level
preservation is required.
OpenSmell includes builders for common representations. Example:
from opensmell import builders
semantic = builders.semantic_descriptors(
"coffee",
"roasted",
language="en",
)
chemical = builders.chemical_smiles(
"CCO"
)
odor = builders.odor(
representations=[
semantic,
chemical,
]
)An identifier can be generated automatically for newly created odor objects. The resulting odor can be serialized:
import opensmell
opensmell.dump(
odor,
"example.osmell"
)OpenSmell currently performs two levels of validation.
The complete document is first required to belong to the strict JSON data domain and is then validated against the OpenSmell 0.1 JSON Schema.
The reference implementation rejects non-standard JSON numeric values such as
NaN, Infinity, and -Infinity, including non-finite values produced while
parsing numeric input. Serialization likewise rejects values that cannot be
represented as strict JSON.
Schema validation then verifies structural requirements such as:
- OpenSmell version;
- odor identifier;
- representations;
- scheme identifiers and versions;
- metadata structure;
- required JSON types.
If OpenSmell recognizes a representation scheme, its data is validated using the corresponding scheme validator. Conceptually:
.osmell
│
▼
JSON Schema validation
│
▼
Representation schemes
│
├── known ──────► validate scheme data
│
└── unknown ────► preserve opaque data
│
▼
Python objects
For registered schemes, OpenSmell also verifies that the representation type matches the type expected by the scheme. Unknown schemes are not rejected merely because the implementation does not recognize them. Experimental scheme validators may exist without being registered as normative OpenSmell 0.1 schemes.
The Python implementation contains a Scheme Registry. It maps:
scheme ID + version
to scheme-specific validation behavior. For example:
org.opensmell.semantic.descriptors
+
0.1
│
▼
Scheme Registry
│
▼
semantic descriptor validator
This avoids hard-coding every future representation into the core parser.
OpenSmell includes an experimental adapter for importing records from OdorNet. OdorNet provides molecular structures together with olfactory category labels. The adapter can convert an OdorNet record into OpenSmell representations. Conceptually:
OdorNet record
│
├── SMILES
│ │
│ ▼
│ chemical representation
│
└── odor annotations
│
▼
semantic representation
│
▼
OpenSmell Odor
The adapter does not make OdorNet part of the OpenSmell Core specification. OdorNet is an external source of olfactory information. The adapter is located at:
src/opensmell/adapters/odornet.py
OpenSmell experiments preserve the distinction between positive, negative, and unresolved OdorNet annotation states rather than assuming that missing information means absence.
OpenSmell has also been tested against quantitative human olfactory measurements from the Keller/Vosshall DREAM Olfaction Prediction Challenge dataset. The experimental adapter is located at:
src/opensmell/adapters/keller_vosshall.py
This work motivated RFC-0005 and the distinction between:
semantic annotation
≠
quantitative perceptual measurement
It also preserves the distinction between:
measurement not performed
≠
measured value 0
The Keller/Vosshall dataset remains an external scientific dataset and is not part of the OpenSmell source distribution or Core specification.
Representation-level provenance is being investigated through RFC-0003. Example:
{
"provenance": {
"source": "OdorNet"
}
}This information can be preserved through the OpenSmell extension mechanism. Provenance is currently experimental. It is not yet a normative OpenSmell 0.1 Core field.
OpenSmell contains an optional PubChem enrichment utility. It can resolve a SMILES structure to chemical identity information such as:
PubChem title
IUPAC name
canonical/connectivity SMILES
InChIKey
Conceptually:
SMILES
│
▼
PubChem
│
├── Title
├── IUPAC name
├── canonical/connectivity SMILES
└── InChIKey
PubChem enrichment is intentionally separate from OpenSmell Core.
OpenSmell does not require PubChem, network access, or any particular external
chemical database to parse an .osmell document.
The repository contains a development tool:
tools/enrich_odornet.py
It can enrich a local OdorNet dataset with PubChem chemical identity information. The tool supports:
- persistent caching;
- interruption and resume;
- duplicate SMILES avoidance;
- request throttling;
- retries for temporary network/server failures;
- periodic checkpoints;
- enriched CSV generation. Generated datasets and PubChem caches are local development artifacts and are excluded from Git. The tool is not part of the OpenSmell Core protocol.
RFC-0006 investigates a resource identification model for future OpenSmell resource graphs. The current experimental design distinguishes:
Scheme identifier
OpenSmell Resource ID
External/source identifier
Reference
These concepts serve different purposes and should not be conflated.
The current experimental candidate uses canonical lowercase UUID strings. Two generation modes are investigated:
UUIDv4
for newly created resources without deterministic source identity, and:
UUIDv5
for deterministic imports of resources with stable source identity.
RFC-0006 remains experimental and does not change the unrestricted
non-empty-string odor.id rule of OpenSmell 0.1.
Dataset imports can derive an experimental Resource ID from:
dataset
resource type
source identity
Source identity may be atomic:
"113L_038"or composite:
{
"stimulus": "1001_3.12e-13",
"target": "111L_001"
}Composite structural keys are deliberately restricted to:
^[a-z][a-z0-9_.-]\*$
while values may contain Unicode scalar strings. This restriction resulted from cross-language interoperability experiments showing that unconstrained Unicode object-key ordering can produce different canonical byte sequences in different runtimes. No implicit Unicode normalization is currently performed. Therefore canonically equivalent Unicode strings with different code-point sequences remain distinct source identities.
The experimental identifier implementation is located under:
src/opensmell/experimental/
The repository contains Python and JavaScript interoperability tooling. Golden and torture vectors test:
- deterministic canonical serialization;
- UTF-8 generation octets;
- UUIDv5 generation;
- quotes and backslashes;
- JSON control-character escaping;
- Unicode values;
- CJK text;
- emoji;
- Unicode normalization differences;
- composite identity ordering;
- delimiter-boundary ambiguity;
- invalid surrogate code points. The current torture-vector suite contains 17 vectors. Python and JavaScript reproduce identical canonical text, UTF-8 octets, and UUIDv5 values for all current vectors. These results are experimental evidence for RFC-0006, not a declaration that the identification model is final.
OpenSmell also uses the Burton 2022 dataset distributed through Pyrfume as a real-world stress test for resource identity, graph structure, physiological Result data, and ResourceGraph serialization. This dataset contains physiological mouse olfactory-bulb response data. It is intentionally not treated as human perceptual measurement data. The experiment distinguishes:
Molecule
│
▼
Stimulus
│
▼
Observation ─────► ObservationTarget
│
▼
Result
The deterministic identity experiment generated:
Molecules: 186
Stimuli: 227
Targets: 1,008
Observations: 187,748
------------------------
Total IDs: 189,169
with:
Unique generation names: 189,169
Unique Resource IDs: 189,169
Observed name collisions: 0
Observed UUID collisions: 0
The materialized experimental ResourceGraph deliberately does not invent a generic Chemical resource class for the 186 referenced molecule identities. Its dataset-scale JSON round-trip therefore contains:
Materialized resources: 188,983
Stimulus resources: 227
Observation targets: 1,008
Observations: 187,748
Result objects: 187,748
Unresolved molecule IDs: 186
Source-less stimuli: 1
Stimuli without conditions: 2
DeltaF values: 187,748
Zero DeltaF: 184,356
Non-zero DeltaF: 3,392
Compact JSON bytes: 81,220,605
The complete graph survived:
ResourceGraph -> JSON -> ResourceGraph
with resource order, structural references, unresolved references, Result schemes, Result data, and DeltaF values preserved. A second serialization was also stable. The experiment preserves unresolved source references rather than inventing missing metadata or silently discarding them. The Burton dataset remains external to OpenSmell and is excluded from the source distribution.
The current architecture can be summarized as:
External data / research
│
├── OdorNet
├── Keller/Vosshall
├── Burton / Pyrfume
├── UCI Gas Sensor Array Drift
├── OpenPOM
├── chemical databases
├── scientific datasets
└── future models
│
▼
┌──────────────────────────────────────────┐
│ OpenSmell │
│ │
│ Core 0.1 │
│ .osmell / JSON Schema │
│ models / parser / serializer │
│ Scheme Registry / validation / builders │
│ │
│ Experimental interoperability │
│ Resource identity │
│ Generic ResourceGraph │
│ Molecule / Annotation resources │
│ Structural reference discovery │
│ Dataset adapters / bridges │
└──────────────────────────────────────────┘
│
▼
RenderRequest
│
▼
SemanticChannelMapper
│
▼
RenderingPlan
│
▼
DeviceCapabilities / DeviceAdapter
│
▼
Device Protocol JSON 0.1
│
▼
DeviceTransport
│
├── MemoryDeviceTransport
└── SerialDeviceTransport
│
▼
physical device
The experimental resource architecture separates resource identity, graph transport, structural references, and scheme-defined interpretation. The rendering architecture separately converts selected graph information into a device-specific plan.
OpenSmell does not assume that a semantic descriptor, molecule, annotation, or other resource corresponds directly to a physical device channel. Mapping is explicitly device- or application-specific.
The rendering and device layers are experimental and are not part of OpenSmell 0.1 Core. Current serial work validates software interoperability and physical actuation paths; it does not demonstrate faithful odor reproduction.
OpenSmell/
├── .github/workflows/tests.yml
├── examples/
│ ├── *.osmell
│ ├── geraniol.osmell
│ ├── generate_geraniol_osmell.py
│ ├── geraniol_esp32_render.py
│ ├── *_conformance_vectors.json
│ ├── *_interop_vectors.json
│ └── rendering / OdorNet demonstrations
├── rfcs/
│ ├── RFC-0001.md ... RFC-0008.md
│ ├── RFC-0009.md # Molecule Resource Type
│ ├── RFC-0010.md # Generic Annotation Resource
│ ├── RFC-0011.md # Structural Reference Discovery
│ └── RFC-0012.md # Rendering and Device Interoperability Architecture
├── schema/
│ ├── opensmell-0.1.schema.json
│ ├── experimental-resource-graph-0.1.schema.json
│ ├── experimental-generic-resource-graph-0.1.schema.json
│ ├── experimental-molecule-0.1.schema.json
│ └── experimental-annotation-0.1.schema.json
├── spec/opensmell-0.1.md
├── src/opensmell/
│ ├── adapters/
│ ├── enrichment/
│ ├── experimental/
│ │ ├── identifiers.py
│ │ ├── graph.py / graph_serialization.py
│ │ ├── generic_graph.py
│ │ ├── molecule.py / annotation.py
│ │ ├── reference_discovery.py
│ │ ├── odor_graph_bridge.py
│ │ ├── odornet_enriched_adapter.py
│ │ ├── rendering.py
│ │ ├── semantic_channel_mapper.py
│ │ ├── device_capabilities.py
│ │ ├── device_adapter.py
│ │ ├── render_pipeline.py
│ │ ├── device_protocol.py
│ │ ├── device_transport.py
│ │ ├── protocol_device_adapter.py
│ │ ├── serial_device_transport.py
│ │ └── simulated_diffuser.py
│ ├── schemas/
│ ├── schemes/
│ ├── builders.py
│ ├── models.py
│ ├── parser.py
│ ├── serializer.py
│ └── validation.py
├── hardware/
│ └── esp32/
│ ├── README.md
│ ├── esp32_physical_render.py
│ └── opensmell_device_protocol_0_1/
│ └── opensmell_device_protocol_0_1.ino
├── tests/
├── tools/
├── LICENSE
├── pyproject.toml
└── README.md
Some experimental tools and adapters operate on external scientific datasets. Those datasets are not part of the OpenSmell source distribution and are excluded from Git where required.
Install development dependencies and run:
python -m pip install -e ".[dev]"
python -m pytestSerial support is optional for normal OpenSmell users:
python -m pip install -e ".[serial]"The latest audited local run passes more than 1,700 automated Python tests. Exact counts are not treated as a stable project property because the suite grows as experimental interoperability work is added.
The audited suite includes the Geraniol software rendering-pipeline regression test. Physical ESP32 validation is intentionally manual and is not part of the normal automated test suite.
The suite covers Core and experimental behavior, including parsing, serialization, builders, JSON Schema consistency, known and unknown schemes, extension preservation, lossless document round trips, dataset adapters, deterministic resource identity, ResourceGraph serialization, portable conformance vectors, Python/JavaScript interoperability, Molecule and Annotation resources, structural reference discovery, rendering, device capabilities, device adapters, the experimental JSON device protocol, transport boundaries, and serial protocol integration.
GitHub Actions runs the Python suite against Python 3.10, 3.11, 3.12, and 3.13. Cross-language interoperability checks use Node.js where applicable.
Some dataset-scale experiments are development tools rather than normal unit tests because the underlying external datasets are not distributed with OpenSmell.
Three complete experimental RFC-0007 ResourceGraph JSON round trips have succeeded:
UCI Gas Sensor Array Drift
resources: 14,144
JSON bytes: 61,600,816
Keller/Vosshall
resources: 56,015
JSON bytes: 47,993,421
Burton 2022
resources: 188,983
JSON bytes: 81,220,605
Combined:
Materialized resources: 259,142
Compact JSON bytes: 190,814,842
These experiments cover electronic olfaction, human psychophysics, and biological physiology. Additional RFC-0008 experiments validate extensible resource types, unknown-resource preservation, Molecule and Annotation resources, and structural reference discovery.
OpenSmell now includes an experimental physical endpoint validation using an ESP32 and an LED as an observable stand-in actuator.
The generic hardware validation can be run with:
python hardware\esp32\esp32_physical_render.py --port COM8Replace COM8 with the serial port assigned to the ESP32.
The firmware is located at:
hardware/esp32/opensmell_device_protocol_0_1/
opensmell_device_protocol_0_1.ino
The tested prototype exposes Device Protocol 0.1 over newline-delimited UTF-8
JSON at 115200 baud. It advertises device ID opensmell-esp32-led-001,
channel 0, normalized intensity 0.0 through 1.0, and rendering durations
from 0.1 through 30.0 seconds.
A valid render request is acknowledged without blocking for the complete rendering duration, after which timed actuator execution continues independently. The physical device validates channel, intensity, and duration independently of client-side checks.
The current ESP32 firmware also bounds each newline-delimited serial message to
1024 bytes. Oversized frames are discarded through their terminating newline
and rejected with message_too_large, allowing the following frame to be
processed normally. This limit is specific to the experimental ESP32 prototype
and is not a universal Device Protocol 0.1 limit.
Oversized-frame rejection and subsequent frame resynchronization have been validated on the physical ESP32.
A longer demonstration uses the committed Geraniol example:
python examples\geraniol_esp32_render.py --port COM8The demonstrated path is:
geraniol.osmell
-> Core OpenSmell Odor
-> ResourceGraph
-> SemanticChannelMapper
-> RenderingPlan
-> Device Protocol 0.1
-> SerialDeviceTransport
-> ESP32
-> LED
For this demonstration only, application policy maps:
floral -> channel 0
This mapping is not a universal OpenSmell channel meaning. The LED validates the software-to-hardware control path; it does not reproduce Geraniol or any other physical odor.
See hardware/esp32/README.md and RFC-0012 for the prototype boundaries,
validation evidence, and remaining open questions.
OpenSmell does not assume that digital olfaction begins with this project. Existing research, standards, datasets, models, and olfactory interfaces already address important parts of the problem. Relevant work includes:
MPEG-V defines representations and control mechanisms for sensory effects, including olfactory effects. OpenSmell should investigate interoperability with MPEG-V rather than duplicate existing standardization work.
OWidgets explored device-independent olfactory experience design and communication with scent-delivery devices. Its work on mapping, scheduling, and uniform device interfaces is relevant prior art for OpenSmell.
OpenPOM provides open-source machine-learning tools related to perceptual odor mapping. Future OpenSmell representations could potentially transport outputs from models of this kind.
OdorNet provides molecular olfactory labels and datasets. OpenSmell currently includes an experimental adapter for converting OdorNet records into OpenSmell representations. OdorNet remains an external data source rather than part of the OpenSmell specification.
The Keller/Vosshall DREAM Olfaction Prediction Challenge dataset contains quantitative human olfactory measurements. OpenSmell uses this dataset experimentally to test the distinction between categorical semantic information and quantitative perceptual measurements. The dataset remains external to OpenSmell.
Pyrfume provides structured olfactory datasets. The Burton 2022 archive is used experimentally to investigate molecules, stimuli, biological observations, source identifiers, and deterministic resource identity. The physiological DeltaF responses in this dataset are not treated as human perceptual measurements.
D2Smell is ongoing research into the digitization and remote reproduction of smell. Future results from projects such as D2Smell may help define useful perceptual or renderable representations.
Scentree is an open-source olfactory display project and represents the type of hardware that could eventually be explored through an OpenSmell device adapter. OpenSmell's objective is therefore interoperability, not claiming invention of digital smell transmission.
Significant architectural decisions are documented and explored through RFCs. Current RFCs:
RFC-0001 OpenSmell Vision and Scope
RFC-0002 Odor Representation Model
RFC-0003 Representation Provenance
RFC-0004 Semantic Annotation Model
RFC-0005 Quantitative Perceptual Measurement Model
RFC-0006 Resource Identification and Deterministic Source Identity
RFC-0007 Stimulus and Observation Resource Model
RFC-0008 Generic Resource Graph and Extensible Resource Types
RFC-0009 Molecule Resource Type
RFC-0010 Generic Annotation Resource
RFC-0011 Structural Reference Discovery and Graph Navigation
RFC-0012 Experimental Rendering and Device Interoperability Architecture
RFCs allow experimental concepts to be investigated without prematurely making them part of the OpenSmell Core specification.
RFC-0003 investigates provenance without making provenance a normative Core 0.1 field. RFC-0004 preserves present, absent, and unknown semantic annotation states. RFC-0005 investigates quantitative perceptual measurements. RFC-0006 investigates deterministic resource identity and cross-language generation. RFC-0007 introduced Stimulus/Observation resources and the first experimental ResourceGraph. RFC-0008 generalizes that graph so unknown future resource types can be preserved. RFC-0009 adds an experimental Molecule resource. RFC-0010 adds a generic Annotation resource. RFC-0011 adds registered structural reference discovery and graph navigation without scanning arbitrary opaque JSON. RFC-0012 documents the experimental rendering, device, protocol, and transport architecture and records the first physical ESP32/LED validation without making those layers part of Core 0.1.
All of these RFCs remain experimental Draft work unless explicitly incorporated into a future OpenSmell specification. Experimental RFCs do not automatically modify OpenSmell 0.1 Core.
Completed:
-
.osmellJSON representation and Core JSON Schema - Python data models, parser, serializer, builders, and validation
- representation Scheme Registry and built-in schemes
- unknown scheme support and extension preservation
- lossless Document model
- OpenSmell 0.1 specification
- Python packaging and multi-version CI
- RFC process
- OdorNet, Keller/Vosshall, and PubChem experiments
- semantic annotation model and OdorNet annotation round trip
- quantitative perceptual measurement model and Keller/Vosshall round trip
- deterministic resource identity and Python/JavaScript identifier tests
- RFC-0007 Stimulus/Observation ResourceGraph experiments
- dataset-scale UCI, Keller/Vosshall, and Burton graph round trips
- RFC-0007 structural schema and portable conformance vectors
- Python/JavaScript ResourceGraph interoperability
- RFC-0008 Generic ResourceGraph and ResourceTypeRegistry
- unknown future resource preservation
- RFC-0008 generic graph schema and portable conformance vectors
- RFC-0009 Molecule resource, schema, conformance, and real-data validation
- RFC-0010 Annotation resource, schema, conformance, and real-data validation
- RFC-0011 structural reference discovery and cross-language vectors
- Core Odor to ResourceGraph bridge experiment
- enriched OdorNet ResourceGraph adapter
- rendering request / plan model
- semantic channel mapper
- device capability and adapter boundaries
- simulated and multi-device rendering experiments
- experimental JSON device protocol 0.1
- protocol-backed device adapter
- transport abstraction and in-memory transport
- optional serial transport using PySerial
- serial protocol integration without physical hardware
- physical ESP32/LED validation of the serial/device control path
- Geraniol
.osmellto ResourceGraph to mapper to ESP32/LED demonstration
- validate the current serial/device path on physical ESP32 hardware
- document rendering and device interoperability through RFC-0012
- create portable Device Protocol 0.1 conformance artifacts
- extend CI across the existing independent JavaScript verifiers
- investigate provenance integration with resource graphs
- define resource type namespace/version governance
- investigate streaming or partial loading for large ResourceGraphs
- investigate normative serialization and canonicalization requirements
- investigate mixture and renderable representations
- investigate MPEG-V interoperability
- add CLI tooling
- publish project documentation through opensmell.org
- define the OpenSmell 0.2 roadmap
The roadmap is intentionally incremental. New concepts should demonstrate a real interoperability need through experiments and real data before being incorporated into OpenSmell Core.
OpenSmell is currently not:
- a physical smell generator;
- an electronic nose;
- a chemical analysis platform;
- an odor prediction model;
- a finished networking protocol;
- a replacement for MPEG-V;
- a standardized set of universal odor primaries;
- a universal database of odor molecules;
- a claim that arbitrary smells can currently be perfectly digitized and reproduced. OpenSmell is an experimental interoperability framework intended to connect technologies that address parts of those problems.
OpenSmell is currently in pre-alpha experimental development.
The first public development release is:
v0.1.0
Development on main has progressed substantially beyond that release. The
current repository contains experimental work through RFC-0012, including the
Generic ResourceGraph, Molecule and Annotation resources, structural reference
discovery, dataset bridges, rendering plans, device capabilities, device
adapters, an experimental JSON device protocol, transport-independent protocol
adapters, and optional serial transport.
The latest audited local run passes more than 1,700 automated Python tests. Portable conformance and independent Python/JavaScript checks exercise several experimental interoperability contracts, including Device Protocol 0.1.
Dataset-scale ResourceGraph experiments span human psychophysics, biological physiology, and electronic olfaction.
The format and APIs may still change before a stable 1.0 specification. Do
not rely on the current experimental graph, rendering, device, or protocol APIs
for production systems.
The first physical device-boundary milestone has now been completed with an
ESP32 and LED stand-in actuator. The experiment validated serial communication,
device discovery and capabilities, plan delivery, device-side validation, and
timed physical output. A Geraniol example also exercised the longer path from
an .osmell document through ResourceGraph, semantic mapping, Device Protocol
0.1, serial transport, and the ESP32.
The demonstration used the application-level policy floral -> channel 0.
This is not a universal channel meaning and does not constitute physical odor
reproduction.
The rendering/device architecture and the physical validation evidence are documented by RFC-0012. Experimental concepts will only be considered for a future OpenSmell Core after sufficient independent evidence.
The project controls:
opensmell.org
The OpenSmell 0.1 JSON Schema therefore uses the identifier:
https://opensmell.org/schema/opensmell-0.1.schema.json
The domain is intended to provide a stable namespace for future specifications, schemas, RFCs, and documentation. The project website and documentation infrastructure are not yet deployed.
OpenSmell is being developed openly. Contributions, technical discussions, prior-art references, experiments, and criticism of the architecture are welcome. Areas of particular interest include:
- digital olfaction research;
- olfactory perception;
- odor representation;
- machine learning for olfaction;
- scent display hardware;
- interoperability;
- sensory standards;
- VR/AR olfactory interfaces;
- serialization and protocol design. Because OpenSmell is experimental, proposals should preferably be supported by concrete interoperability requirements, existing research, real datasets, or reproducible experiments.
OpenSmell is licensed under the Apache License 2.0. See the LICENSE file for details. External scientific datasets used for experiments retain their respective licenses and are not automatically covered by the OpenSmell license.
OpenSmell is developed as an independent open-source experiment into interoperability for digital olfaction. Repository:
YAAASSS/OpenSmell
Project namespace:
opensmell.org
OpenSmell — an open interoperability layer for digital olfaction.
