Skip to main content

The .lotnb Format

LoT Notebook files use the .lotnb extension and follow a JSON-based structure compatible with VS Code’s notebook API. Each file contains an array of cells—documentation and code blocks that make up your notebook.
You don’t need to edit the JSON directly. VS Code’s notebook interface handles the structure automatically. This page is for understanding what’s happening under the hood.

File Structure

A .lotnb file is a JSON array where each element represents a cell:
[
  {
    "kind": 1,
    "language": "markdown",
    "value": "# My First Notebook\n\nThis is a markdown cell with documentation."
  },
  {
    "kind": 2,
    "language": "lot",
    "value": "DEFINE ACTION Heartbeat\nON EVERY 10 SECONDS DO\n    PUBLISH TOPIC \"system/heartbeat\" WITH TIMESTAMP \"UTC\""
  },
  {
    "kind": 2,
    "language": "python",
    "value": "# Script Name: DataProcessor\ndef calculate_average(values):\n    return sum(values) / len(values)"
  }
]

Cell Properties

Each cell has three required properties:
PropertyTypeDescription
kindintegerCell type: 1 = Markdown, 2 = Code
languagestringCell language: "markdown", "lot", or "python"
valuestringCell content (use \n for line breaks)

Kind Values

KindTypePurpose
1MarkdownDocumentation, explanations, headers
2CodeExecutable LoT or Python code

Language Values

LanguageCell KindDescription
markdown1Rich text documentation
lot2LoT definitions (Actions, Models, Routes, Rules)
python2Python scripts for broker execution

Cell Types in Detail

Markdown Cells

Markdown cells support standard Markdown syntax plus some extensions:
{
  "kind": 1,
  "language": "markdown",
  "value": "## Temperature Monitoring System\n\nThis notebook implements a complete temperature monitoring solution:\n\n- **Sensors**: Read from `sensors/+/temperature`\n- **Alerts**: Publish to `alerts/high-temp` when threshold exceeded\n- **Logging**: Store all readings in database\n\n### Architecture\n\n| Component | Topic | Purpose |\n|-----------|-------|--------|\n| Sensor Reader | sensors/+/temperature | Ingest data |\n| Alert Generator | alerts/+ | Notify operators |"
}
Supported Markdown features:
  • Headers (#, ##, ###)
  • Bold, italic, code formatting
  • Bullet and numbered lists
  • Tables
  • Code blocks (for examples, not execution)
  • Links and images

LoT Code Cells

LoT cells contain executable Language of Things definitions:
{
  "kind": 2,
  "language": "lot",
  "value": "DEFINE ACTION TemperatureMonitor\nON TOPIC \"sensors/+/temperature\" DO\n    SET \"sensor_id\" WITH TOPIC POSITION 2\n    IF PAYLOAD > 80 THEN\n        PUBLISH TOPIC \"alerts/high-temp/\" + {sensor_id} WITH \"Critical: \" + PAYLOAD + \"°C\""
}
Valid LoT definitions:
DefinitionSyntax
ActionDEFINE ACTION ActionName
ModelDEFINE MODEL ModelName WITH TOPIC "..."
RouteDEFINE ROUTE RouteName WITH TYPE ...
RuleDEFINE RULE RuleName

Python Cells

Python cells contain scripts that run inside the broker when called from LoT:
{
  "kind": 2,
  "language": "python",
  "value": "# Script Name: Validators\ndef validate_temperature(value, min_temp, max_temp):\n    \"\"\"Check if temperature is within acceptable range\"\"\"\n    try:\n        temp = float(value)\n        return {\n            \"valid\": min_temp <= temp <= max_temp,\n            \"value\": temp,\n            \"range\": f\"{min_temp}-{max_temp}\"\n        }\n    except (ValueError, TypeError):\n        return {\"valid\": False, \"error\": \"Invalid temperature value\"}"
}
Required format: Python scripts must start with # Script Name: YourScriptName as the first line. This header tells the broker how to register and reference the script.

Creating a New Notebook

Method 1: VS Code Interface

  1. Create a new file with .lotnb extension
  2. VS Code automatically opens it in notebook mode
  3. Use the + Code and + Markdown buttons to add cells
  4. Select cell language from the dropdown (lot, python, markdown)

Method 2: Manual Creation

Create a file with minimal JSON structure:
[
  {
    "kind": 1,
    "language": "markdown",
    "value": "# My Notebook\n\nAdd your documentation here."
  },
  {
    "kind": 2,
    "language": "lot",
    "value": "DEFINE ACTION MyFirstAction\nON EVERY 10 SECONDS DO\n    PUBLISH TOPIC \"test/hello\" WITH \"Hello World\""
  }
]
Save with .lotnb extension and open in VS Code.

Example: Complete Notebook

Here’s a full example showing all cell types working together:
[
  {
    "kind": 1,
    "language": "markdown",
    "value": "# Production Monitoring System\n\nThis notebook implements production line monitoring with:\n- Real-time part counting\n- Quality validation using Python\n- Alert generation for anomalies"
  },
  {
    "kind": 1,
    "language": "markdown",
    "value": "## Python Validators\n\nFirst, we define our validation functions:"
  },
  {
    "kind": 2,
    "language": "python",
    "value": "# Script Name: QualityChecker\ndef check_dimensions(length, width, tolerance=0.5):\n    \"\"\"Validate part dimensions against specifications\"\"\"\n    target_length = 100.0\n    target_width = 50.0\n    \n    length_ok = abs(float(length) - target_length) <= tolerance\n    width_ok = abs(float(width) - target_width) <= tolerance\n    \n    return {\n        \"passed\": length_ok and width_ok,\n        \"length_deviation\": float(length) - target_length,\n        \"width_deviation\": float(width) - target_width\n    }"
  },
  {
    "kind": 1,
    "language": "markdown",
    "value": "## Part Counter Action\n\nCounts produced parts and tracks hourly production:"
  },
  {
    "kind": 2,
    "language": "lot",
    "value": "DEFINE ACTION PartCounter\nON TOPIC \"production/line1/part-complete\" DO\n    SET \"count\" WITH (GET TOPIC \"production/line1/count\" AS INT) + 1\n    PUBLISH TOPIC \"production/line1/count\" WITH {count}\n    PUBLISH TOPIC \"production/line1/last-update\" WITH TIMESTAMP \"UTC\""
  },
  {
    "kind": 1,
    "language": "markdown",
    "value": "## Quality Check Action\n\nValidates each part using our Python function:"
  },
  {
    "kind": 2,
    "language": "lot",
    "value": "DEFINE ACTION QualityValidator\nON TOPIC \"production/line1/measurement\" DO\n    SET \"length\" WITH (GET JSON \"length\" IN PAYLOAD AS DOUBLE)\n    SET \"width\" WITH (GET JSON \"width\" IN PAYLOAD AS DOUBLE)\n    \n    CALL PYTHON \"QualityChecker.check_dimensions\"\n        WITH ({length}, {width})\n        RETURN AS {result}\n    \n    IF (GET JSON \"passed\" IN {result} AS BOOL) EQUALS TRUE THEN\n        PUBLISH TOPIC \"production/line1/quality/passed\" WITH {result}\n    ELSE\n        PUBLISH TOPIC \"production/line1/quality/failed\" WITH {result}\n        PUBLISH TOPIC \"alerts/quality\" WITH \"Part failed inspection\""
  }
]

Best Practices

Start notebooks with a title and overview. Use headers to organize sections logically.
Keep each Action, Model, Route, or Rule in its own cell. This makes debugging and selective execution easier.
Write a markdown cell explaining what the next code cell does before writing the code. This helps you think through the logic.
Follow a naming convention for your Actions, Models, and Python scripts. Example: SensorTemperatureMonitor, ProductionPartCounter.

Troubleshooting

  • Verify the file has .lotnb extension (not .lotnb.json)
  • Check that the LoT Notebooks extension is installed
  • Ensure the file contains valid JSON (use a JSON validator)
Common issues:
  • Missing commas between cells
  • Unescaped quotes in value strings (use \")
  • Unescaped newlines (use \n)
  • Missing closing brackets
Check the language property matches the content type. VS Code should auto-detect, but you can manually switch using the language selector in the cell toolbar.

Next Steps