Cette page a été traduite par une machine et n'a pas encore été révisée par une personne. L'anglais est la référence ; les corrections sont les bienvenues sur GitHub. GitHub

Cookwala / SDK et scénarios / 034

The fryer robot plans koshari with every heat step verified by a sensor

With estimates forbidden, a robot that has a pan thermometer, a liquid thermometer and an oil thermometer still plans all twenty steps of koshari, none by estimate and none by a person. Then check the recipe's own frying target against the envelope.

Audience: robot maker · Objectif: Aider à éradiquer la faim, Des robots pour les gens · Niveau: beginner

Lire d'abord: /docs/CORE/ /docs/QUICKSTART/

Étapes

  1. Estimates forbidden: boiling by liquid thermometer, heating by pan thermometer, deep frying by oil thermometer. dryRun

  2. The recipe asks for oil at 175 plus or minus 10 degC and limits each batch to 130 g. getRecipe

  3. A trace that holds the recipe target passes the envelope and the target. checkEnvelope

  4. Twenty steps, the deep fry by the device.

Résultat

You have the sensor list a koshari robot needs to run with no estimates and no person doing a step, and the target it must hold. Next: scenario 022 shows the limit above that target.

Ligne de commande

cookwala dryrun examples/koshari.cookwala.json --device examples/capabilities/demo-fryer-robot.json --human-present --no-model
curl -s http://localhost:7878/v1/tools/recipes/koshari
printf '[{"t": 0, "tempC": 160}, {"t": 30, "tempC": 172}, {"t": 60, "tempC": 176}, {"t": 90, "tempC": 174}]' > trace.json && cookwala envelope cw.op.deep_fry trace.json --target 175 --tolerance 10

Sortie enregistrée

Statut: ok

[1] dryRun: {"state": "accepted", "plan": [{"node": "n1", "op": "cw.op.boil", "by": "device", "verifiedBy": "sensor", "rung": "cw.sense.liquid_temp"}, {"node": "n2", "op": "cw.op.simmer", "by": "device", "verifiedBy": "sensor", "rung": "cw.sense.liquid_temp"}, {"node": "n3", "op": "cw.op.drain", "by": "device", "verifiedBy": "time", "rung": "time"}, {"node": "n4", "op": "cw.op.boil", "by": "device", "verifiedBy": "sensor", "rung": "cw.sense.liquid_temp"}, {"node": "n5", "op": "cw.op.boil", "by": "device", "verifiedBy": "sensor", "rung": "cw.sense.liquid_temp"}, {"node": "n6", "op": "cw.op.drain", "by": "d…
[2] getRecipe: {"$schema": "https://cookwala.ai/v1/schemas/recipe.schema.json", "cookwala": "0.2.0", "id": "example-koshari", "revision": 1, "updated": "2026-10-04", "verification": {"level": "V1", "evidence": {"simulatorRuns": 0, "humanReviews": 1, "fieldReports": 0}, "reviewedBy": "cookwala.ai editorial (structure only)", "notes": "Example recipe written to exercise the standard: structured steps, end conditions, hazards and critical control points. Not simulated and not field-verified; values are typical home-cooking values, not measurements."}, "dish": {"names": {"en": "Koshari", "ar": "كشري"}, "cuisine"…
[3] checkEnvelope: {"envelopeOk": true, "targetOk": true, "reason": "ok"}

Code

Exécuter: python scenarios/out/034-fryer-robot-without-estimates/python.py

# Scenario 034: The fryer robot plans koshari with every heat step verified by a sensor
# With estimates forbidden, a robot that has a pan thermometer, a liquid thermometer and an oil thermometer still plans all twenty steps of koshari, none by estimate and none by a person. Then check the recipe's own frying target against the envelope.
# Run a hub first: python hub/cookwala_hub.py --recipes examples
import json, os
from cookwala.client import CookwalaClient, CookwalaProblem

def load(path):
    with open(path, encoding="utf-8") as f:
        return json.load(f)

def pick(obj, path):
    for part in path.replace("]", "").replace("[", ".").split("."):
        obj = obj[int(part)] if part.isdigit() else (len(obj) if part == "length" else obj.get(part))
    return obj

c = CookwalaClient(os.environ.get("COOKWALA_HUB", "http://localhost:7878"))


# Step 1: Estimates forbidden: boiling by liquid thermometer, heating by pan thermometer, deep frying by oil thermometer.
plan = c.dry_run(recipe_id="koshari", device_id="demo-fryer-robot", human_present=True, allow_model=False)
assert pick(plan, "state") == "accepted", pick(plan, "state")
print("ok", "state", "=", "accepted")
assert pick(plan, "plan.length") == 20, pick(plan, "plan.length")
print("ok", "plan.length", "=", 20)
assert pick(plan, "plan[0].rung") == "cw.sense.liquid_temp", pick(plan, "plan[0].rung")
print("ok", "plan[0].rung", "=", "cw.sense.liquid_temp")
assert pick(plan, "plan[6].rung") == "cw.sense.pan_surface_temp", pick(plan, "plan[6].rung")
print("ok", "plan[6].rung", "=", "cw.sense.pan_surface_temp")
assert pick(plan, "plan[13].rung") == "cw.sense.oil_temp", pick(plan, "plan[13].rung")
print("ok", "plan[13].rung", "=", "cw.sense.oil_temp")
assert pick(plan, "plan[10].rung") == "cw.sense.vision", pick(plan, "plan[10].rung")
print("ok", "plan[10].rung", "=", "cw.sense.vision")

# Step 2: The recipe asks for oil at 175 plus or minus 10 degC and limits each batch to 130 g.
koshari = c.get_recipe("koshari")
assert pick(koshari, "process.nodes[13].op") == "cw.op.deep_fry", pick(koshari, "process.nodes[13].op")
print("ok", "process.nodes[13].op", "=", "cw.op.deep_fry")
assert pick(koshari, "process.nodes[13].params.target.value") == 175, pick(koshari, "process.nodes[13].params.target.value")
print("ok", "process.nodes[13].params.target.value", "=", 175)
assert pick(koshari, "process.nodes[13].params.target.tolerance") == 10, pick(koshari, "process.nodes[13].params.target.tolerance")
print("ok", "process.nodes[13].params.target.tolerance", "=", 10)
assert pick(koshari, "process.nodes[13].params.batchMaxG") == 130, pick(koshari, "process.nodes[13].params.batchMaxG")
print("ok", "process.nodes[13].params.batchMaxG", "=", 130)

# Step 3: A trace that holds the recipe target passes the envelope and the target.
trace = c.check_envelope("cw.op.deep_fry", [{"t": 0, "tempC": 160}, {"t": 60, "tempC": 172}, {"t": 120, "tempC": 176}, {"t": 180, "tempC": 174}], {"value": 175, "tolerance": 10})
assert pick(trace, "envelopeOk") == True, pick(trace, "envelopeOk")
print("ok", "envelopeOk", "=", True)
assert pick(trace, "targetOk") == True, pick(trace, "targetOk")
print("ok", "targetOk", "=", True)
assert pick(trace, "reason") == "ok", pick(trace, "reason")
print("ok", "reason", "=", "ok")

# Step 4: Twenty steps, the deep fry by the device.
assert pick(plan, "plan[13].by") == "device", pick(plan, "plan[13].by")
print("ok", "plan[13].by", "=", "device")
assert pick(plan, "plan[13].verifiedBy") == "sensor", pick(plan, "plan[13].verifiedBy")
print("ok", "plan[13].verifiedBy", "=", "sensor")

print("scenario complete")

scenarios/034-fryer-robot-without-estimates.json

Précédent: 033 Suivant: 035