Axilio mobile device driver — keyboard, touch, and screen capture for sandboxed mobile devices
Project description
Axilio Mobile Driver
axilio-mobile is the Axilio mobile-device driver — the Python package that user code imports inside a sandbox to drive a paired mobile device. Tap, swipe, type, key-press, screenshot.
It's one of a family of Axilio driver packages — axilio-mobile (this), axilio-browser (future), axilio-desktop (future) — that share a single axilio.* import namespace. For managing the platform from outside the sandbox (workflows, runs, devices, usage) see axilio-platform.
Installation
pip install axilio-mobile
Quick start
from axilio.drivers import mobile
mobile.tap(coords={"x": 540, "y": 1200})
mobile.swipe(start={"x": 100, "y": 800}, end={"x": 100, "y": 200})
mobile.type_text(text="hello")
mobile.key_press(key=mobile.Key.HOME)
png_bytes = mobile.screenshot()
open("frame.png", "wb").write(png_bytes)
All primitives are keyword-only — pass everything by name. The driver is meant to run inside an Axilio sandbox VM — code authored in the dashboard editor, scheduled via the dashboard, or run in our hosted runtime — where the daemon listening on /run/axilio/sdk.sock is paired to a real device. There is no API key, no authentication step, no allocation lifecycle to manage from user code; the daemon handles all of that.
Where to run it
The driver only works inside an Axilio sandbox VM (today). If you import it locally and call mobile.tap(...), you'll get a mobile.ConnectionError because there's no daemon listening on the socket.
To experiment without a sandbox, you can point the driver at a custom socket:
export AXILIO_SDK_SOCKET=/tmp/axilio-test.sock
…and run a fake server on that socket. The tests/conftest.py in this repo has a reference implementation.
Class-based API
For tests or callers who want explicit lifecycle:
from axilio.drivers.mobile import Device
dev = Device(socket_path="/run/axilio/sdk.sock")
dev.tap(coords={"x": 540, "y": 1200})
dev.close()
Errors
Errors raised by the driver are subclasses of mobile.AxilioError:
from axilio.drivers import mobile
try:
mobile.tap(coords={"x": 540, "y": 1200})
except mobile.NoAllocationError:
print("No active allocation — daemon hasn't been paired with a device.")
except mobile.DeviceOfflineError as e:
if e.retryable:
# transient — try again in a moment
...
except mobile.AxilioError as e:
# catch-all
print(f"axilio: {e.code}: {e}")
The exception hierarchy mirrors the daemon's wire-level error codes:
| Exception | Wire code |
Retryable? | Notes |
|---|---|---|---|
NoAllocationError |
no_allocation |
no | Daemon hasn't received SetAllocation |
DeviceOfflineError |
device_offline |
yes | Driver not bound or capturer not started |
UnauthorizedError |
unauthorized |
no | Session token rejected by Atlas |
InvalidArgsError |
invalid_args |
no | Programming error in args |
UnknownOpError |
unknown_op |
no | SDK/daemon version skew |
NotConnectedError |
not_connected |
no | Daemon couldn't reach Atlas |
CanceledError |
canceled |
sometimes | Deadline exceeded |
InternalError |
internal |
no | Unclassified daemon failure |
ConnectionError |
(n/a) | no | SDK couldn't open the Unix socket |
Reference: primitives
All primitives are keyword-only (note the leading * in each signature). Future params (query, region, wait_for) are present in the signatures already but raise NotImplementedError until the device side catches up.
class Coords(TypedDict):
x: int
y: int
class Region(TypedDict):
x: int
y: int
width: int
height: int
mobile.tap(
*,
coords: Coords | None = None,
query: str | None = None, # not yet supported
region: Region | None = None, # not yet supported
wait_for: int | None = None, # not yet supported (ms)
) -> None
mobile.swipe(
*,
start: Coords,
end: Coords,
duration_ms: int = 300,
) -> None
mobile.key_press(*, key: int) -> None
mobile.type_text(*, text: str) -> None
mobile.screenshot(
*,
region: Region | None = None, # not yet supported
) -> bytes # PNG-encoded
Coords are frame-space pixels (the cropped video output). key_press takes a 16-bit USB HID consumer-page code; common codes are exposed as mobile.Key.HOME, mobile.Key.BACK, etc.
Environment
| Variable | Description |
|---|---|
AXILIO_SDK_SOCKET |
Override the daemon socket path. Default: /run/axilio/sdk.sock |
What's not in this driver
- Workflow / run / device management — that's the
axilio-platformSDK. - Allocation /
connectlifecycle — sandbox VMs are pre-allocated; user code doesn't manage it. - Local mode (running on a laptop driving a remote device) — defer until customer demand surfaces.
- OCR-anchored helpers (
tap_at("Sign in"),wait_for_element(...)) — defer until the underlying atlas-side element discovery lands. - Async API — sync only for now.
- Op-set extensions (
long_press,drag,pinch, app management,read_screen,find) — land as the underlying atlas / firmware infra exists. - Browser / desktop control — different surfaces get different drivers (
axilio-browser,axilio-desktop— both future).
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file axilio_mobile-0.1.0.tar.gz.
File metadata
- Download URL: axilio_mobile-0.1.0.tar.gz
- Upload date:
- Size: 25.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
93a37d94a653a795f898d1b59ca823dbdfd06d8025647f66a1f478b76576f875
|
|
| MD5 |
b2f1a5fc1d882653785e28bbeab14859
|
|
| BLAKE2b-256 |
132e943ff58b82f13a2211cfdf057e0587670a1f61ab16f75509e04e27fa0c67
|
File details
Details for the file axilio_mobile-0.1.0-py3-none-any.whl.
File metadata
- Download URL: axilio_mobile-0.1.0-py3-none-any.whl
- Upload date:
- Size: 12.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1f3a0b574933778e4024a2959357bc17e49ae7b5e886b5c525ec236c3f817c93
|
|
| MD5 |
278cba43cb241b288616564241e1fe71
|
|
| BLAKE2b-256 |
3b13f4e25e4f703918af75fcc4e5906217ebc384e168ce7f574303092e718931
|