[{"data":1,"prerenderedAt":484},["ShallowReactive",2],{"docs-\u002Fdocs\u002Fsdks\u002Fpython":3},{"id":4,"title":5,"body":6,"description":477,"extension":478,"meta":479,"navigation":75,"path":480,"seo":481,"stem":482,"__hash__":483},"content\u002Fdocs\u002Fsdks\u002Fpython.md","Python SDK",{"type":7,"value":8,"toc":467},"minimark",[9,13,33,38,114,118,219,223,230,299,315,319,348,352,418,422,433,437,448,452,463],[10,11,5],"h1",{"id":12},"python-sdk",[14,15,16,20,21,24,25,28,29,32],"p",{},[17,18,19],"code",{},"conduyt-py"," is the official Python SDK. It's pure Python (no C extensions), uses ",[17,22,23],{},"asyncio",", and runs on CPython 3.11+ as well as PyPy. Optional extras pull in ",[17,26,27],{},"pyserial-asyncio"," for serial transport and ",[17,30,31],{},"aiomqtt"," for MQTT bridging.",[34,35,37],"h2",{"id":36},"install","Install",[39,40,45],"pre",{"className":41,"code":42,"language":43,"meta":44,"style":44},"language-bash shiki shiki-themes github-light github-dark","# Just the protocol primitives (wire\u002FCOBS\u002FCRC8)\npip install conduyt-py\n\n# With serial transport\npip install conduyt-py[serial]\n\n# Everything (serial + MQTT)\npip install conduyt-py[all]\n","bash","",[17,46,47,56,70,77,83,93,98,104],{"__ignoreMap":44},[48,49,52],"span",{"class":50,"line":51},"line",1,[48,53,55],{"class":54},"sJ8bj","# Just the protocol primitives (wire\u002FCOBS\u002FCRC8)\n",[48,57,59,63,67],{"class":50,"line":58},2,[48,60,62],{"class":61},"sScJk","pip",[48,64,66],{"class":65},"sZZnC"," install",[48,68,69],{"class":65}," conduyt-py\n",[48,71,73],{"class":50,"line":72},3,[48,74,76],{"emptyLinePlaceholder":75},true,"\n",[48,78,80],{"class":50,"line":79},4,[48,81,82],{"class":54},"# With serial transport\n",[48,84,86,88,90],{"class":50,"line":85},5,[48,87,62],{"class":61},[48,89,66],{"class":65},[48,91,92],{"class":65}," conduyt-py[serial]\n",[48,94,96],{"class":50,"line":95},6,[48,97,76],{"emptyLinePlaceholder":75},[48,99,101],{"class":50,"line":100},7,[48,102,103],{"class":54},"# Everything (serial + MQTT)\n",[48,105,107,109,111],{"class":50,"line":106},8,[48,108,62],{"class":61},[48,110,66],{"class":65},[48,112,113],{"class":65}," conduyt-py[all]\n",[34,115,117],{"id":116},"quick-start","Quick start",[39,119,123],{"className":120,"code":121,"language":122,"meta":44,"style":44},"language-python shiki shiki-themes github-light github-dark","import asyncio\nfrom conduyt import ConduytDevice\nfrom conduyt.transports.serial import SerialTransport\n\n\nasync def main():\n    transport = SerialTransport('\u002Fdev\u002Fcu.usbmodem14101', baudrate=115200)\n    device = ConduytDevice(transport)\n    await device.connect()\n    print(f\"connected to {device.firmware_name}\")\n\n    await device.pin_mode(13, 'output')\n    await device.pin_write(13, 1)\n\n    await device.disconnect()\n\n\nasyncio.run(main())\n","python",[17,124,125,130,135,140,144,148,153,158,163,169,175,180,186,192,197,203,208,213],{"__ignoreMap":44},[48,126,127],{"class":50,"line":51},[48,128,129],{},"import asyncio\n",[48,131,132],{"class":50,"line":58},[48,133,134],{},"from conduyt import ConduytDevice\n",[48,136,137],{"class":50,"line":72},[48,138,139],{},"from conduyt.transports.serial import SerialTransport\n",[48,141,142],{"class":50,"line":79},[48,143,76],{"emptyLinePlaceholder":75},[48,145,146],{"class":50,"line":85},[48,147,76],{"emptyLinePlaceholder":75},[48,149,150],{"class":50,"line":95},[48,151,152],{},"async def main():\n",[48,154,155],{"class":50,"line":100},[48,156,157],{},"    transport = SerialTransport('\u002Fdev\u002Fcu.usbmodem14101', baudrate=115200)\n",[48,159,160],{"class":50,"line":106},[48,161,162],{},"    device = ConduytDevice(transport)\n",[48,164,166],{"class":50,"line":165},9,[48,167,168],{},"    await device.connect()\n",[48,170,172],{"class":50,"line":171},10,[48,173,174],{},"    print(f\"connected to {device.firmware_name}\")\n",[48,176,178],{"class":50,"line":177},11,[48,179,76],{"emptyLinePlaceholder":75},[48,181,183],{"class":50,"line":182},12,[48,184,185],{},"    await device.pin_mode(13, 'output')\n",[48,187,189],{"class":50,"line":188},13,[48,190,191],{},"    await device.pin_write(13, 1)\n",[48,193,195],{"class":50,"line":194},14,[48,196,76],{"emptyLinePlaceholder":75},[48,198,200],{"class":50,"line":199},15,[48,201,202],{},"    await device.disconnect()\n",[48,204,206],{"class":50,"line":205},16,[48,207,76],{"emptyLinePlaceholder":75},[48,209,211],{"class":50,"line":210},17,[48,212,76],{"emptyLinePlaceholder":75},[48,214,216],{"class":50,"line":215},18,[48,217,218],{},"asyncio.run(main())\n",[34,220,222],{"id":221},"modules","Modules",[14,224,225,226,229],{},"Typed module wrappers are in ",[17,227,228],{},"conduyt.modules",". Import only what you use:",[39,231,233],{"className":120,"code":232,"language":122,"meta":44,"style":44},"from conduyt.modules import (\n    ConduytServo,\n    ConduytNeoPixel,\n    ConduytOLED,\n    ConduytDHT,\n    ConduytEncoder,\n    ConduytStepper,\n    ConduytPID,\n)\n\nservo = ConduytServo(device, module_id=0)\nawait servo.attach(pin=9)\nawait servo.write(angle=90)\n",[17,234,235,240,245,250,255,260,265,270,275,280,284,289,294],{"__ignoreMap":44},[48,236,237],{"class":50,"line":51},[48,238,239],{},"from conduyt.modules import (\n",[48,241,242],{"class":50,"line":58},[48,243,244],{},"    ConduytServo,\n",[48,246,247],{"class":50,"line":72},[48,248,249],{},"    ConduytNeoPixel,\n",[48,251,252],{"class":50,"line":79},[48,253,254],{},"    ConduytOLED,\n",[48,256,257],{"class":50,"line":85},[48,258,259],{},"    ConduytDHT,\n",[48,261,262],{"class":50,"line":95},[48,263,264],{},"    ConduytEncoder,\n",[48,266,267],{"class":50,"line":100},[48,268,269],{},"    ConduytStepper,\n",[48,271,272],{"class":50,"line":106},[48,273,274],{},"    ConduytPID,\n",[48,276,277],{"class":50,"line":165},[48,278,279],{},")\n",[48,281,282],{"class":50,"line":171},[48,283,76],{"emptyLinePlaceholder":75},[48,285,286],{"class":50,"line":177},[48,287,288],{},"servo = ConduytServo(device, module_id=0)\n",[48,290,291],{"class":50,"line":182},[48,292,293],{},"await servo.attach(pin=9)\n",[48,295,296],{"class":50,"line":188},[48,297,298],{},"await servo.write(angle=90)\n",[14,300,301,302,305,306,309,310,314],{},"Pass the module ID returned by ",[17,303,304],{},"HELLO_RESP.modules"," (often ",[17,307,308],{},"0"," if you only registered one module). See the per-module pages under ",[311,312,222],"a",{"href":313},"\u002Fdocs\u002Fmodules\u002Fservo"," for full command references.",[34,316,318],{"id":317},"datastreams","Datastreams",[39,320,322],{"className":120,"code":321,"language":122,"meta":44,"style":44},"def on_temp(value):\n    print(f\"temperature: {value}°C\")\n\ndevice.on_datastream('temperature', on_temp)\nawait device.stream_start()\n",[17,323,324,329,334,338,343],{"__ignoreMap":44},[48,325,326],{"class":50,"line":51},[48,327,328],{},"def on_temp(value):\n",[48,330,331],{"class":50,"line":58},[48,332,333],{},"    print(f\"temperature: {value}°C\")\n",[48,335,336],{"class":50,"line":72},[48,337,76],{"emptyLinePlaceholder":75},[48,339,340],{"class":50,"line":79},[48,341,342],{},"device.on_datastream('temperature', on_temp)\n",[48,344,345],{"class":50,"line":85},[48,346,347],{},"await device.stream_start()\n",[34,349,351],{"id":350},"transports","Transports",[353,354,355,371],"table",{},[356,357,358],"thead",{},[359,360,361,365,368],"tr",{},[362,363,364],"th",{},"Transport",[362,366,367],{},"Import path",[362,369,370],{},"Extra install",[372,373,374,390,405],"tbody",{},[359,375,376,380,385],{},[377,378,379],"td",{},"Serial",[377,381,382],{},[17,383,384],{},"conduyt.transports.serial.SerialTransport",[377,386,387],{},[17,388,389],{},"pip install conduyt-py[serial]",[359,391,392,395,400],{},[377,393,394],{},"MQTT",[377,396,397],{},[17,398,399],{},"conduyt.transports.mqtt.MqttTransport",[377,401,402],{},[17,403,404],{},"pip install conduyt-py[mqtt]",[359,406,407,410,415],{},[377,408,409],{},"Mock",[377,411,412],{},[17,413,414],{},"conduyt.transports.mock.MockTransport",[377,416,417],{},"(built-in, for tests)",[34,419,421],{"id":420},"sync-vs-async","Sync vs async",[14,423,424,425,428,429,432],{},"The SDK is ",[17,426,427],{},"async","-first because the wire protocol is event-driven (datastreams, module events, NAKs all arrive unsolicited). For one-off scripts, wrap in ",[17,430,431],{},"asyncio.run(main())",". For long-running apps, treat the device like any other async resource.",[34,434,436],{"id":435},"type-checking","Type checking",[14,438,439,440,443,444,447],{},"The SDK ships ",[17,441,442],{},"py.typed",". Install ",[17,445,446],{},"mypy"," and you'll get full inference on every method, packet shape, and module command.",[34,449,451],{"id":450},"versioning","Versioning",[14,453,454,455,458,459,462],{},"The SDK follows the protocol version. ",[17,456,457],{},"conduyt-py 1.x"," requires firmware running protocol version 2. The version byte is ",[17,460,461],{},"conduyt.core.constants.PROTOCOL_VERSION",".",[464,465,466],"style",{},"html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":44,"searchDepth":58,"depth":58,"links":468},[469,470,471,472,473,474,475,476],{"id":36,"depth":58,"text":37},{"id":116,"depth":58,"text":117},{"id":221,"depth":58,"text":222},{"id":317,"depth":58,"text":318},{"id":350,"depth":58,"text":351},{"id":420,"depth":58,"text":421},{"id":435,"depth":58,"text":436},{"id":450,"depth":58,"text":451},"Async Python client for CONDUYT — serial, MQTT bridges, and typed module wrappers.","md",{},"\u002Fdocs\u002Fsdks\u002Fpython",{"title":5,"description":477},"docs\u002Fsdks\u002Fpython","qyxwFamIccwegENKEXL5kAWCTvEM6s7LZULmOyMmQVc",1777412315699]