Metadata-Version: 2.2
Name: pyeilik
Version: 0.3.0
Summary: Control an Eilik desk robot from Python: servos, screen and video
Keywords: eilik,robot,robotics,serial,hardware,usb
License: MIT
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: C
Classifier: Topic :: System :: Hardware :: Hardware Drivers
Classifier: Topic :: Software Development :: Embedded Systems
Classifier: Operating System :: MacOS :: MacOS X
Project-URL: Homepage, https://eiliksdk.com
Project-URL: Documentation, https://eiliksdk.com
Project-URL: Source, https://github.com/aklto/eilik
Project-URL: Issues, https://github.com/aklto/eilik/issues
Requires-Python: >=3.9
Provides-Extra: image
Requires-Dist: pillow>=9; extra == "image"
Provides-Extra: dev
Requires-Dist: pytest>=7; extra == "dev"
Requires-Dist: pillow>=9; extra == "dev"
Description-Content-Type: text/markdown

# PyEilik

[![PyPI](https://img.shields.io/pypi/v/pyeilik.svg)](https://pypi.org/project/pyeilik/)
[![Python versions](https://img.shields.io/pypi/pyversions/pyeilik.svg)](https://pypi.org/project/pyeilik/)
[![License](https://img.shields.io/pypi/l/pyeilik.svg)](https://github.com/aklto/eilik/blob/main/LICENSE)

Control an Eilik desk robot from Python — its servos, its screen, and video
playback with the robot dancing along.

The robot ships sealed, with an app and no documented interface. The protocol
this speaks was recovered by reverse engineering and checked against real
hardware; it is written up in full at
[eiliksdk.com/protocol](https://eiliksdk.com/protocol/).

A C core with a stable ABI does the work; the Python package is a thin wrapper
over it.

> **macOS only, and deliberately so.** The robot runs at 125000 baud, which is
> not a standard rate: setting it needs an Apple-specific ioctl, and there is no
> equivalent elsewhere. On another platform the port would open at some default
> rate and put garbage on the wire, which is worse than not shipping at all.

## Install

```bash
pip install pyeilik
```

The distribution is `pyeilik`; the import is `eilik`, the way `pyserial`
imports as `serial`.

One wheel covers Apple silicon and Intel on any Python 3.9 or newer: it carries
a plain shared library rather than a CPython extension, so it is not tied to an
interpreter version.

Showing a PNG needs a decoder, which Python has none of built in:

```bash
pip install 'pyeilik[image]'
```

## Quick start

```python
import eilik

with eilik.connect() as robot:
    robot.arm_left.to(1800)
    robot.head.to(1600)
    robot.commit()          # both joints move together, in one packet

    print(robot.positions())
    robot.rest()
```

Sides are the **robot's own**, the way anatomy is normally named: `arm_left` is
the robot's left arm, which is the one you see on your right when facing it.

## What it does

**Servos.** Four joints, with their real travel limits enforced. Targets are
staged and then committed, because one packet can carry all four and that is the
only way to move them in step.

**The screen.** 128×64, one bit per pixel, in both directions.

```python
robot.screen.show("face.png")     # scaled, thresholded, rotated for you
saved = robot.screen.read()       # 1024 bytes, the panel's own order
robot.screen.clear()
```

**Video, and dancing to it.** Needs `ffmpeg` on PATH.

```python
robot.play("clip.mp4")                    # picture and sound
robot.play("clip.mp4", dance="simple")    # and the robot moves to it
robot.play("clip.mp4", dance="guitar")
```

Sound comes out of *your computer*. The robot has a speaker, but no command
exists to send audio to it — not in this protocol, and not in the
manufacturer's own software either.

## Worth knowing

- **`ServoFaultError` means a power cycle, not a bug hunt.** When every joint
  reads position 0 the servo controller has stopped. Unplugging USB will not fix
  it: the robot has an internal battery, so it has to be switched off at the
  power switch.
- **Only one process can hold the port.** A second connection raises
  `PortBusyError`. Use the context manager so the port is always released.
- **Every command waits for its acknowledgement.** Sending a second command
  while the firmware is still reading a 1032-byte display frame drops the device
  off the USB bus. The library waits so you do not have to.

## Links

- [Documentation](https://eiliksdk.com)
- [Protocol reference](https://eiliksdk.com/protocol/)
- [Source](https://github.com/aklto/eilik)
- [Issues](https://github.com/aklto/eilik/issues)

## Not affiliated

Eilik is a product of its respective manufacturer. This project is independent,
unofficial, and not endorsed by them. The name is used only to say which device
the library talks to.

## License

MIT.

## Development

```bash
cmake -S . -B build -DBUILD_SHARED_LIBS=ON && cmake --build build
pip install -e '.[dev]'
ctest --test-dir build     # C, no robot needed
pytest                     # Python, no robot needed
pytest -m hardware         # needs a robot
```

The documentation site lives in [`site/`](https://github.com/aklto/eilik/tree/main/site).
