Skip to main content

Unofficial Python library for controlling ClicBot modular robots over TCP/UDP

Project description

ClicBot for Python (Unofficial)

PyPI version

Unofficial library — not affiliated with, endorsed by, or associated with KEYi Technology or ClicBot. Protocol inferred from network traffic generated by my own device and the official app, solely for interoperability purposes.

Python library for controlling ClicBot modular robots — motor control, structure discovery, and event-driven programming over TCP/UDP.

Install

pip install clicbot-unofficial
from clicbot_unofficial import ClicBot, discover_first

Connecting to the robot

The robot communicates over TCP. Your computer and the robot must be on the same IP network.

There are two network setups:

WiFi (recommended)

The robot stores WiFi credentials and reconnects automatically on every boot. The QR code step is only needed once when joining a new network for the first time.

First time — provision the robot onto your WiFi:

from clicbot_unofficial import build_qr_content, show_qr_code, wait_for_robot

content = build_qr_content("MyWifi", "secret")
show_qr_code(content)        # terminal (default), or mode="file"/"text"
device = wait_for_robot()

Hold the QR code in front of the robot's camera. It joins your network, announces its address, and remembers the credentials from then on.

Already provisioned — just discover it:

from clicbot_unofficial import discover_first

device = discover_first(timeout=5.0)

Robot hotspot

The robot can also expose its own WiFi access point. Connect your computer to it, then discover the robot via UDP or connect directly to its known IP.

Connecting

Once you have the device from either method above:

from clicbot_unofficial import ClicBot, BrainState

bot = ClicBot()
bot.connect(device.ip, device.port)
bot.send_client_info()
bot.set_brain_state(BrainState.CUSTOM)

modules = bot.get_structure()  # blocks until the robot replies
for joint in bot.servo_joints:
    joint.rotate_to(90, speed=60)

Authentication

This library connects in guest mode only, using the built-in tourist username and userId: 0. No account or login is required. This is sufficient for all supported robot control operations.

Discovery

Function Description
discover_all(timeout=3.0) Return all robots found on the local network within the timeout
discover_first(timeout=5.0) Return the first robot found, or raise TimeoutError
discover_via_qrcode(ssid, password, qr_output=...) Show a QR code; wait for the robot to join WiFi and announce its address

ClicBot API

Connection

bot.connect(host, port)                     # open TCP connection
bot.send_client_info()                      # handshake (call once after connect)
bot.set_brain_state(BrainState.CUSTOM)      # enable motion commands
bot.disconnect()

Structure

modules = bot.get_structure()        # request tree and block until received
bot.set_structure_watchdog(True)     # continuous change notifications
bot.request_angles()                 # triggers on_angles callback

Motor control

# Servo joints — absolute angle (degrees)
bot.rotate_to(module_id, angle, speed=50)
bot.rotate_to_many([{"module_id": 1, "angle": 90, "speed": 50}])

# Continuous rotation (wheels or joints)
bot.rotate_start(module_id, forward=True, speed=60)
bot.rotate_start_many([{"module_id": 2, "forward": True, "speed": 60}])
bot.rotate_stop()           # stop all rotating modules

# Push-rotate mode
bot.set_push_rotate(module_id, enabled=True)

# Lock / unlock
bot.lock(module_id)
bot.unlock(module_id)
bot.lock_all()
bot.lock_all(locked=False)  # unlock all

# Emergency stop
bot.full_stop(lock=False)

Module accessors

After get_structure() the robot tree is available:

bot.root          # BrainModule (id 0)
bot.servo_joints  # List[ServoJointModule]
bot.servo_wheels  # List[ServoWheelModule]
bot.get_module(module_id)

Each module exposes the same controls directly:

joint.rotate_to(90, speed=50)
joint.rotate_start(forward=True, speed=60)
joint.rotate_stop()
joint.set_push_rotate(enabled=True)
joint.lock()
joint.unlock()
wheel.rotate_start(forward=False, speed=80)
wheel.rotate_stop()

Callbacks

Assign a function to any of these attributes to receive events:

bot.on_battery          = lambda level: print(f"Battery: {level:.0%}")
bot.on_structure_changed = lambda modules: print(f"{len(modules)} modules")
bot.on_angles           = lambda angles: print(angles)
bot.on_close            = lambda: print("disconnected")
bot.on_error            = lambda exc: print("error:", exc)
Attribute Arguments Description
on_close Connection closed
on_error exc Socket error
on_battery level (0.0–1.0) Battery level update
on_structure_changed modules (dict[id, Module]) Module tree updated
on_angles angles (dict[id, float]) Joint angle update

Examples

File Description
examples/01_discovery.py Scan the network and list all robots
examples/02_tree.py Print the module tree
examples/03_servo.py Move servo joints to 0° then 90°
examples/04_rotate.py Spin wheel modules for 2 seconds
examples/05_qrcode.py Connect a new robot via QR code
examples/06_mermaid.py Save module tree as a Mermaid diagram

Structure visualization

to_mermaid(structure) converts the raw module tree into a Mermaid graph. Each module becomes a labelled subgraph with one node per port; edges show parent–child connections. See examples/06_mermaid.py — it saves structure.md and reminds you to paste the content into mermaid.live.

Example output for a simple arm assembly:

graph TD
    subgraph BRAIN 0
        direction LR
        0_conn0(Port 0)
    end
    subgraph DISTANCE_BAR 1
        direction LR
        1_conn0(Port 0)
        1_conn1(Port 1)
    end
    0_conn0 --> 1_conn0
    subgraph SERVO_JOINT 2
        direction LR
        2_conn0(Port 0)
        2_conn1(Port 1)
        2_conn2(Port 2)
        2_conn3(Port 3)
    end
    1_conn1 --> 2_conn2
    subgraph SERVO_JOINT 3
        direction LR
        3_conn0(Port 0)
        3_conn1(Port 1)
        3_conn2(Port 2)
        3_conn3(Port 3)
    end
    2_conn0 --> 3_conn1
    subgraph SERVO_JOINT 4
        direction LR
        4_conn0(Port 0)
        4_conn1(Port 1)
        4_conn2(Port 2)
        4_conn3(Port 3)
    end
    3_conn0 --> 4_conn0
    subgraph SERVO_JOINT 5
        direction LR
        5_conn0(Port 0)
        5_conn1(Port 1)
        5_conn2(Port 2)
        5_conn3(Port 3)
    end
    3_conn2 --> 5_conn1
    subgraph SERVO_WHEEL 6
        direction LR
        6_conn0(Port 0)
    end
    4_conn2 --> 6_conn0
    subgraph SERVO_WHEEL 7
        direction LR
        7_conn0(Port 0)
    end
    5_conn3 --> 7_conn0

Not supported

The following features are absent from this library and will not be added without significant further reverse-engineering:

  • Official programs — the built-in robot configurations shipped by KEYi (commands 300, 400, 401, 1034–1037). These require an authenticated account and upload opaque binary assets.
  • Pro actions / face animations — the "Pro" timeline system sends a ZIP to the brain (cmd 13) that can include servo splines, video, audio, and SCREEN keyframe curves that animate the brain's face display. The wire format of the SCREEN block is not fully understood.
  • Brain face display — the brain's built-in LCD shows animated eye/face expressions. Expressions are controlled via Pro-action SCREEN data or pre-loaded assets uploaded by the official app. There is no standalone "show expression X" command.
  • Steering / locomotion — the drive mode for wheeled robots (cmds 1012/1013). The wire format is not known.
  • Guide / activate flow — the factory calibration guide channels (cmd 300). Account-gated and device-specific.
  • Veriface / face asset sync — the brain sends a ZIP of face-expression images and audio to the app (cmd 14) for preview purposes. Not handled.

Building and publishing

Build a wheel and source distribution:

pip install build twine
python -m build
# → dist/clicbot_unofficial-0.1.0-py3-none-any.whl
# → dist/clicbot_unofficial-0.1.0.tar.gz

Upload to PyPI:

twine upload dist/*

Install the wheel directly without publishing:

pip install dist/clicbot_unofficial-0.1.0-py3-none-any.whl

Or install in editable mode from the project root for development:

pip install -e .

Requirements

  • Python ≥ 3.10
  • qrcode — included automatically; needed for show_qr_code terminal mode
  • Pillow — optional, only needed for PNG export (mode="file"); install via pip install "clicbot-unofficial[png]"

License

MIT © 2026 Hannes Rüger

Legal / Interoperability Notice

This is an independent, unofficial Python library for ClicBot-compatible devices. It is not affiliated with, endorsed by, sponsored by, or associated with KEYi Technology or the ClicBot brand.

The protocol implementation was independently developed by observing network traffic generated by my own device and the official app, solely for the purpose of interoperability. No source code, firmware, binaries, assets, icons, trademarks, private keys, certificates, or other proprietary materials from KEYi Technology are included in this project.

This project is intended to enable lawful control of devices owned by the user. It is not intended to bypass authentication, digital rights management, copy protection, access controls, or any other technical protection measures.

"ClicBot" and related names may be trademarks of their respective owners and are used here only to identify compatibility.

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

clicbot_unofficial-1.0.3.tar.gz (15.5 kB view details)

Uploaded Source

Built Distribution

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

clicbot_unofficial-1.0.3-py3-none-any.whl (17.7 kB view details)

Uploaded Python 3

File details

Details for the file clicbot_unofficial-1.0.3.tar.gz.

File metadata

  • Download URL: clicbot_unofficial-1.0.3.tar.gz
  • Upload date:
  • Size: 15.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.5

File hashes

Hashes for clicbot_unofficial-1.0.3.tar.gz
Algorithm Hash digest
SHA256 27ff5495b4adac79eb607a1ae021c840ecf8747872c15c466ea4cb758e558367
MD5 2206297711cfba5f8434ed968fecb950
BLAKE2b-256 e6be0442b6d9081fc581d4cb31a279c208267991f7e5f84cb0b6f9cefa1294f7

See more details on using hashes here.

File details

Details for the file clicbot_unofficial-1.0.3-py3-none-any.whl.

File metadata

File hashes

Hashes for clicbot_unofficial-1.0.3-py3-none-any.whl
Algorithm Hash digest
SHA256 dffe561d8ebb66fb150c4b5a725551fba189821b9c3871f4bb485c96e2caf439
MD5 be6c0107bd4e2bcb91a38c52c8a0a9dd
BLAKE2b-256 38344169b15bf2b1fc2f67eaa504fd5fe39e50a2f0276572d121ccd0e554b545

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