Skip to main content

Python SDK for Anova Precision Oven

Project description

Anova Precision Oven SDK

⚠️ DISCLAIMER

This software is provided "as is" without warranty of any kind, express or implied. The authors and contributors are not liable for any damages, losses, or issues arising from the use of this software, including but not limited to:

  • Device malfunction or damage
  • Property damage
  • Food safety issues
  • Data loss
  • Service interruptions

Use at your own risk. Always supervise cooking operations and follow manufacturer guidelines for your Anova Precision Oven. This is unofficial software not endorsed by Anova Culinary.


Python SDK for controlling Anova Precision Ovens using the official Anova API (https://developer.anovaculinary.com/docs/devices/wifi/oven-commands). The goal of this final project is to create an integration for Home Assistant which leverages this SDK for operation. The majority of this code was written using Anthropic Claude (https://claude.ai)

Installation

# Using pip
pip install .

Configuration

Settings File

Create settings.yaml:

default:
  log_level: INFO
  supported_accessories:
    - APO

Authentication

Create .secrets.yaml (add to .gitignore):

default:
  token: "anova-your-token-here"

Or use environment variables:

export ANOVA_TOKEN="anova-your-token-here"

Quick Start

from anova_oven_sdk import AnovaOven
from anova_oven_sdk import CookingPresets

async def main():
    async with AnovaOven() as oven:
        # Discover devices
        devices = await oven.discover_devices()
        device_id = devices[0].id
        
        # Simple roast
        await oven.start_cook(
            device_id=device_id,
            temperature=200,
            duration=1800  # 30 minutes
        )
        
        # Or use presets
        await CookingPresets.roast(
            oven, device_id,
            temperature=200,
            duration_minutes=30
        )

import asyncio
asyncio.run(main())

Environment Configuration

Switch environments using ANOVA_ENV:

# Development (debug logging, more retries)
export ANOVA_ENV=development
python your_script.py

# Production (warning logging, optimized)
export ANOVA_ENV=production
python your_script.py

Command Line Interface (CLI)

The anova_oven_cli.py provides a powerful command-line interface for controlling your oven and managing recipes.

Global Options

# Specify custom recipe file location
python anova_oven_cli.py --recipe-file /path/to/recipes.yml <command>

# Set environment
python anova_oven_cli.py --env development <command>

Device Discovery

# Discover devices
python anova_oven_cli.py discover

# With custom timeout
python anova_oven_cli.py discover --timeout 10.0

# Output as JSON (for scripting)
python anova_oven_cli.py discover --json

Example output:

Discovering devices...

Found 1 device(s):

  Name:    My Anova Oven
  ID:      anova-abc123def456
  Type:    APO
  State:   idle
  Temp:    25°C

Recipe Management

List Available Recipes

# List all recipes
python anova_oven_cli.py recipes list

# Output as JSON
python anova_oven_cli.py recipes list --json

Example output:

Available recipes from recipes.yml:

  perfect_toast_v1
    Name:         Perfect Toast (V1 Oven)
    Description:  Replicate the Anova V1 Toast Recipe
    Stages:       2
    Oven Version: v1

  sous_vide_steak
    Name:         Sous Vide Steak
    Description:  Perfectly cooked steak with steam
    Stages:       2
    Oven Version: any

Show Recipe Details

# Show detailed recipe information
python anova_oven_cli.py recipes show perfect_toast_v1

# Output as JSON
python anova_oven_cli.py recipes show perfect_toast_v1 --json

Example output:

Recipe: Perfect Toast (V1 Oven)
ID: perfect_toast_v1
Description: Replicate the Anova V1 Toast Recipe
Oven Version: v1

Stages (2):

  Stage 1: Preheat
    Temperature: 450°F
    Mode: DRY
    Timer: 3m 0s
    Heating: top, bottom
    Fan Speed: 100%

  Stage 2: Toast
    Temperature: 450°F
    Mode: DRY
    Timer: 4m 0s
    Heating: top, bottom
    Fan Speed: 100%

Recipe File Format

The CLI automatically searches for recipe files in the following locations:

  1. recipes.yml (current directory)
  2. recipes.yaml (current directory)
  3. ~/.anova/recipes.yml (user home directory)
  4. recipes.yml (same directory as anova_oven_cli.py)

Create a recipes.yml file with your custom recipes:

recipes:
  my_roast:
    name: "Perfect Roast Chicken"
    description: "Juicy roast chicken with crispy skin"
    oven_version: "v2"  # or "v1", or omit for any version
    stages:
      - name: "Roast"
        temperature:
          value: 180
          temperature_unit: "C"
          mode: "DRY"
        heating_elements:
          top: true
          bottom: true
          rear: true
        fan_speed: 100
        timer:
          seconds: 3600  # 1 hour
      
      - name: "Crisp Skin"
        temperature:
          value: 220
          temperature_unit: "C"
          mode: "DRY"
        heating_elements:
          top: true
          bottom: false
          rear: false
        fan_speed: 100
        timer:
          seconds: 600  # 10 minutes

  sous_vide_salmon:
    name: "Sous Vide Salmon"
    description: "Perfectly cooked salmon with steam"
    stages:
      - name: "Sous Vide"
        temperature:
          value: 50
          temperature_unit: "C"
          mode: "WET"
        heating_elements:
          rear: true
        fan_speed: 100
        steam:
          steam_percentage: 100
        timer:
          seconds: 1800  # 30 minutes

Python SDK Usage

Multi-Stage Cooking

from anova_oven_sdk import (
    AnovaOven, CookStage, Temperature, Timer,
    SteamSettings, SteamMode, HeatingElements,
    TemperatureMode, TimerStartType
)

async with AnovaOven() as oven:
    devices = await oven.discover_devices()
    
    # Sous vide then sear
    stages = [
        CookStage(
            temperature=Temperature.from_celsius(60),
            mode=TemperatureMode.WET,
            timer=Timer(initial=3600),
            steam=SteamSettings(
                mode=SteamMode.STEAM_PERCENTAGE,
                steam_percentage=100
            ),
            title="Sous Vide"
        ),
        CookStage(
            temperature=Temperature.from_celsius(250),
            timer=Timer(
                initial=300,
                start_type=TimerStartType.WHEN_PREHEATED
            ),
            heating_elements=HeatingElements(
                top=True,
                bottom=True,
                rear=False
            ),
            title="Sear"
        )
    ]
    
    await oven.start_cook(devices[0].id, stages=stages)

Using Recipe Library in Code

from anova_oven_sdk import AnovaOven, RecipeLibrary

async with AnovaOven() as oven:
    # Load recipes from file
    library = RecipeLibrary.from_yaml_file('recipes.yml')
    
    # Get a specific recipe
    recipe = library.get_recipe('perfect_toast_v1')
    
    # Validate recipe for device
    devices = await oven.discover_devices()
    device = devices[0]
    recipe.validate_for_oven(device.oven_version)
    
    # Convert recipe to cook stages
    stages = recipe.to_cook_stages()
    
    # Start cooking
    await oven.start_cook(device.id, stages=stages)

Settings Configuration

See settings.yaml for all available configuration options:

  • WebSocket settings (timeout, retries)
  • Logging configuration (level, file, rotation)
  • Environment-specific overrides
  • Feature flags

Model Validation

All models are validated automatically:

from anova_oven_sdk import Temperature, HeatingElements

# Automatic validation
temp = Temperature(celsius=200)  # ✓ Valid
# temp = Temperature(celsius=-300)  # ✗ ValidationError

# Heating elements validation
heating = HeatingElements(rear=True)  # ✓ Valid
# heating = HeatingElements(top=True, bottom=True, rear=True)  # ✗ ValidationError

Error Handling

from anova_oven_sdk import (
    AnovaOven, ConfigurationError,
    DeviceNotFoundError
)

try:
    async with AnovaOven() as oven:
        devices = await oven.discover_devices()
        await oven.start_cook(devices[0].id, temperature=200)
except ConfigurationError as e:
    print(f"Config error: {e}")
except DeviceNotFoundError as e:
    print(f"Device not found: {e}")
except ValueError as e:
    print(f"Invalid parameters: {e}")

Testing

import pytest
from anova_oven_sdk import Temperature, CookStage, HeatingElements, AnovaOven

def test_temperature_validation():
    temp = Temperature.from_celsius(200)
    assert temp.celsius == 200
    assert temp.fahrenheit == 392

def test_heating_elements_validation():
    # Valid configuration
    heating = HeatingElements(rear=True)
    assert heating.rear is True
    
    # Invalid - all elements
    with pytest.raises(ValueError):
        HeatingElements(top=True, bottom=True, rear=True)

@pytest.mark.asyncio
async def test_oven_connection():
    async with AnovaOven() as oven:
        devices = await oven.discover_devices()
        assert len(devices) > 0

Project Structure

anova-oven-project/
├── settings.yaml          # Main configuration
├── .secrets.yaml          # Secrets (gitignored)
├── recipes.yml            # Recipe definitions
├── .env                   # Environment variables (gitignored)
├── .gitignore             # Git ignore file
├── pyproject.toml         # Project configuration
├── anova_oven_cli.py      # Anova SDK Command-line Interface (CLI)
├── logs/                  # Log files (gitignored)
│   ├── anova_dev.log
│   └── anova_prod.log
└── tests/                 # Test files
    ├── __init__.py
    ├── conftest.py
    ├── test_client.py
    ├── test_commands.py
    ├── test_exceptions.py
    ├── test_logging_config.py
    ├── test_models.py
    ├── test_oven_part1.py
    ├── test_oven_part2.py
    ├── test_presets.py
    ├── test_settings.py
    └── test_utils.py

CLI Examples Workflow

Complete Workflow Example

# 1. Discover your oven
python anova_oven_cli.py discover
# Output: Note your device ID (e.g., anova-abc123def456)

# 2. List available recipes
python anova_oven_cli.py recipes list

# 3. View recipe details
python anova_oven_cli.py recipes show perfect_toast_v1

# 4. Start cooking with a recipe
python anova_oven_cli.py cook --device anova-abc123def456 --recipe perfect_toast_v1

# 5. Stop cooking when done
python anova_oven_cli.py stop --device anova-abc123def456

Scripting with JSON Output

# Get device ID programmatically
DEVICE_ID=$(python anova_oven_cli.py discover --json | jq -r '.[0].id')

# List recipes as JSON
python anova_oven_cli.py recipes list --json | jq '.[] | {id, name, stages}'

# Start cook with the device ID
python anova_oven_cli.py cook --device "$DEVICE_ID" --recipe sous_vide_steak

Tips and Best Practices

Recipe Development

  1. Start with simple single-stage recipes to test your setup
  2. Use recipes show to validate recipe structure before cooking
  3. Test new recipes with the oven door open to verify timing
  4. Always validate recipes are compatible with your oven version

CLI Usage

  • Use --json flag for integration with other tools
  • Set --recipe-file to manage multiple recipe collections
  • Use --env development for more detailed logging during testing

Safety

  • Always supervise cooking operations
  • Test new recipes with attention to timing and temperature
  • Keep recipe files in version control for repeatability
  • Validate device IDs before starting cooks

License & Credits

This project uses the Anova Precision Oven API documented at https://developer.anovaculinary.com.

The majority of this code was created using Anthropic Claude AI assistant (https://claude.ai).

This is unofficial software not affiliated with or endorsed by Anova Culinary.

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

anova_precision_oven_sdk-2025.11.8.tar.gz (67.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

anova_precision_oven_sdk-2025.11.8-py3-none-any.whl (38.3 kB view details)

Uploaded Python 3

File details

Details for the file anova_precision_oven_sdk-2025.11.8.tar.gz.

File metadata

File hashes

Hashes for anova_precision_oven_sdk-2025.11.8.tar.gz
Algorithm Hash digest
SHA256 5ab49cdad1056113d059df2dded59008b29788557214e497aaaf40629ece07a5
MD5 5f457e2ee87490912d450fb5dade4f59
BLAKE2b-256 f437cdb22a643c4a7af95609bfe44ed072fe54ae6d48bc99bfae776464a221f0

See more details on using hashes here.

File details

Details for the file anova_precision_oven_sdk-2025.11.8-py3-none-any.whl.

File metadata

File hashes

Hashes for anova_precision_oven_sdk-2025.11.8-py3-none-any.whl
Algorithm Hash digest
SHA256 850b078189fc01a9b88e0f3acd87e25e62f26c201eaa4cb6dfbfddf943f5c194
MD5 60a9a1abf532acb876e6f22520863a53
BLAKE2b-256 708497c5fa1ac35ab42c5bbb310707147f3f04438b14a11f0d4a1d5b686d9e0e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page