Cookwala / SDK and scenarios / 005
Read what a device says about itself: capabilities, safety limits, conformance, recalls
The four GET endpoints of the Core API answer before any cooking: what the device can do, which limits it enforces locally, what it claims to conform to, and which recipe revisions are recalled.
Read first: /docs/CORE/ /docs/QUICKSTART/
Steps
The reference hub simulates the example robot arm: three operations and one vision sensor.
capabilitiesThe draft default limits pack: fourteen limits, the first one cuts heat when frying oil passes 200 degC.
safetyLimitsThe hub declares the executor class itself; it has no third-party report, and says so.
conformanceNo recall is in force for the hub.
recalls
Outcome
You know the shape of a capability document and a SafetyLimits pack, and that the disclaimer in the pack asks makers to replace it with limits from their own safety case. Next: scenario 006 lists the demo devices and the operation vocabulary.
Command line
curl -s http://localhost:7878/v1/capabilities
curl -s http://localhost:7878/v1/safety-limits
curl -s http://localhost:7878/v1/conformance
curl -s http://localhost:7878/v1/recallsRecorded output
Status: ok
[1] capabilities: {"cookwala": "0.1.0", "actor": {"kind": "robot", "id": "robot:arm-1", "vendor": "Example Robotics", "model": "CounterArm 2"}, "roles": ["executor"], "location": {"zone": "counter-left", "mobile": false}, "capabilities": {"ops": [{"op": "cw.op.cut", "params": {"shape": ["dice", "slice", "mince", "julienne"]}, "ingredientClasses": ["cw.ing.class.vegetable_firm", "cw.ing.class.herb"], "reliability": 0.97}, {"op": "cw.op.crack", "reliability": 0.95}, {"op": "cw.op.transfer", "maxMassG": 3000}], "sensors": [{"sensor": "cw.sense.vision", "visionCues": ["cw.sense.translucent", "cw.sense.egg_whites_se…
[2] safetyLimits: {"core": "0.2.0", "kind": "SafetyLimits", "id": "cookwala-default", "version": "0.2.0", "status": "draft", "limits": [{"id": "oil.max_temp", "kind": "max_temp", "action": "cut_heat", "message": "Cut heat above 200 °C: most cooking oils smoke and fire risk rises.", "source": "Common frying-oil smoke points; fire-safety practice", "appliesTo": {"medium": "oil", "ops": ["cw.op.fry", "cw.op.deep_fry"]}, "max": 200, "unit": "degC"}, {"id": "pan.max_surface", "kind": "max_temp", "action": "cut_heat", "message": "Cut heat above 280 °C pan surface (coatings degrade, oil ignites).", "source": "Cookware…
[3] conformance: {"claims": ["executor"], "report": null, "note": "reference hub, self-declared; run tools/run_conformance.py --report"}
[4] recalls: []Code
Run: python scenarios/out/005-read-capabilities-and-safety-limits/python.py
# Scenario 005: Read what a device says about itself: capabilities, safety limits, conformance, recalls
# The four GET endpoints of the Core API answer before any cooking: what the device can do, which limits it enforces locally, what it claims to conform to, and which recipe revisions are recalled.
# 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: The reference hub simulates the example robot arm: three operations and one vision sensor.
caps = c.capabilities()
assert pick(caps, "actor.id") == "robot:arm-1", pick(caps, "actor.id")
print("ok", "actor.id", "=", "robot:arm-1")
assert pick(caps, "actor.kind") == "robot", pick(caps, "actor.kind")
print("ok", "actor.kind", "=", "robot")
assert pick(caps, "roles[0]") == "executor", pick(caps, "roles[0]")
print("ok", "roles[0]", "=", "executor")
assert pick(caps, "capabilities.ops.length") == 3, pick(caps, "capabilities.ops.length")
print("ok", "capabilities.ops.length", "=", 3)
assert pick(caps, "capabilities.sensors.length") == 1, pick(caps, "capabilities.sensors.length")
print("ok", "capabilities.sensors.length", "=", 1)
# Step 2: The draft default limits pack: fourteen limits, the first one cuts heat when frying oil passes 200 degC.
limits = c.safety_limits()
assert pick(limits, "id") == "cookwala-default", pick(limits, "id")
print("ok", "id", "=", "cookwala-default")
assert pick(limits, "status") == "draft", pick(limits, "status")
print("ok", "status", "=", "draft")
assert pick(limits, "limits.length") == 14, pick(limits, "limits.length")
print("ok", "limits.length", "=", 14)
assert pick(limits, "limits[0].id") == "oil.max_temp", pick(limits, "limits[0].id")
print("ok", "limits[0].id", "=", "oil.max_temp")
assert pick(limits, "limits[0].max") == 200, pick(limits, "limits[0].max")
print("ok", "limits[0].max", "=", 200)
assert pick(limits, "limits[0].action") == "cut_heat", pick(limits, "limits[0].action")
print("ok", "limits[0].action", "=", "cut_heat")
# Step 3: The hub declares the executor class itself; it has no third-party report, and says so.
conf = c.conformance()
assert pick(conf, "claims[0]") == "executor", pick(conf, "claims[0]")
print("ok", "claims[0]", "=", "executor")
assert pick(conf, "report") == None, pick(conf, "report")
print("ok", "report", "=", None)
# Step 4: No recall is in force for the hub.
recalls = c.recalls()
assert pick(recalls, "length") == 0, pick(recalls, "length")
print("ok", "length", "=", 0)
print("scenario complete")