Skip to content

Commit 0b6aafb

Browse files
authored
Doc client service (#30)
* add docs for client service * add missing files
1 parent 551a8cb commit 0b6aafb

File tree

3 files changed

+431
-0
lines changed

3 files changed

+431
-0
lines changed

docs/how-to/client_service.md

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# Client Service Setup
2+
3+
The `client-service` command provides a Unix socket interface for attaching and detaching USB devices programmatically. This is useful when you want to integrate USB device attachment/detachment into other applications or services.
4+
5+
## Overview
6+
7+
The client service:
8+
- Runs as a long-lived process (foreground or systemd service)
9+
- Listens on a Unix socket for JSON commands
10+
- Accepts `attach` and `detach` requests
11+
- Returns JSON responses with device information and local device paths
12+
- Automatically detects the appropriate socket path based on execution context:
13+
- `/run/usb-remote-client/usb-remote-client.sock` when running as a systemd service
14+
- `/tmp/usb-remote-client.sock` when running in foreground
15+
16+
## Running in Foreground
17+
18+
To run the client service directly in your terminal:
19+
20+
```bash
21+
usb-remote client-service
22+
```
23+
24+
This is useful for testing or development. The service will listen on `/tmp/usb-remote-client.sock`.
25+
26+
## Running as a Systemd Service
27+
28+
For production use, it's recommended to run the client service as a systemd service so it starts automatically at boot.
29+
30+
### Installation
31+
32+
#### System-wide Service (Recommended)
33+
34+
For speed and ease of use, you can install the client service using the `uv` tool as described below. However, if you prefer to use official package repositories, a good alternative is `pipx`. `pipx` allows you to install and run Python applications in isolated environments and is available on most Linux distributions.
35+
36+
1. Install `uv` (if not already installed).
37+
38+
```bash
39+
curl -LsSfO https://astral.sh/uv/install.sh
40+
sudo bash install.sh
41+
```
42+
43+
2. Install the client service:
44+
45+
```bash
46+
sudo -s # uv (installed by root) requires the root profile so use sudo -s
47+
uvx usb-remote install-service --service-type client
48+
systemctl enable --now usb-remote-client.service
49+
exit
50+
```
51+
52+
Check service status:
53+
54+
```bash
55+
sudo systemctl status usb-remote-client.service
56+
```
57+
58+
View service logs:
59+
60+
```bash
61+
journalctl -u usb-remote-client.service -f
62+
```
63+
64+
65+
### Uninstallation
66+
67+
To uninstall the systemd service:
68+
69+
System-wide service:
70+
```bash
71+
sudo -s
72+
uvx usb-remote uninstall-service client
73+
exit
74+
```
75+
76+
## Configuration
77+
78+
The client service uses the same configuration file format as the regular `usb-remote` client commands, see [Client Configuration File](../reference/config.md).
79+
80+
IMPORTANT: when running as a systemd service, the configuration file is read from the system-wide location:
81+
`/etc/usb-remote-client/usb-remote.config`
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
2+
# Client Service Socket API
3+
4+
The client service accepts JSON requests on the Unix socket and returns JSON responses.
5+
6+
## Request Format
7+
8+
All requests follow this JSON structure:
9+
10+
```json
11+
{
12+
"command": "attach",
13+
"id": "1-1.4",
14+
"bus": null,
15+
"serial": null,
16+
"desc": null,
17+
"first": false,
18+
"host": null
19+
}
20+
```
21+
22+
**Fields:**
23+
- `command`: Either `"attach"` or `"detach"` (required)
24+
- `id`: Bus ID of the device (e.g., "1-1.4")
25+
- `bus`: Bus number filter
26+
- `serial`: Serial number filter
27+
- `desc`: Description filter (substring match)
28+
- `first`: If true, use first matching device if multiple matches
29+
- `host`: Specific server hostname/IP to query (if null, queries all configured servers)
30+
31+
You must provide at least one of: `id`, `bus`, `serial`, or `desc` to identify the device.
32+
33+
## Response Format
34+
35+
### Success Response
36+
37+
```json
38+
{
39+
"status": "success",
40+
"data": {
41+
"bus_id": "1-1.4",
42+
"device_id": "vid=0x1234 pid=0x5678",
43+
"description": "USB Device Description"
44+
},
45+
"server": "192.168.1.100",
46+
"local_devices": ["/dev/ttyUSB0", "/dev/ttyUSB1"]
47+
}
48+
```
49+
50+
**Fields:**
51+
- `status`: Always `"success"` for successful operations
52+
- `data`: The USB device information
53+
- `bus_id`: The USB bus ID on the remote server
54+
- `device_id`: Vendor and product IDs
55+
- `description`: Human-readable device description
56+
- `server`: The server hostname/IP where the device was found
57+
- `local_devices`: List of local device files created (for attach operations)
58+
59+
### Error Response
60+
61+
```json
62+
{
63+
"status": "error",
64+
"message": "Error description"
65+
}
66+
```
67+
68+
**Status values:**
69+
- `"error"`: General error (invalid request, connection error, etc.)
70+
- `"not_found"`: No device matching the criteria was found
71+
- `"multiple_matches"`: Multiple devices matched and `first` was not set to `true`
72+
73+
## Usage Examples
74+
75+
### Using netcat
76+
77+
Attach a device:
78+
```bash
79+
echo '{"command":"attach","desc":"Arduino","first":true}' | nc -U /tmp/usb-remote-client.sock
80+
```
81+
82+
Detach a device by bus ID:
83+
```bash
84+
echo '{"command":"detach","id":"1-1.4"}' | nc -U /tmp/usb-remote-client.sock
85+
```
86+
87+
### Using Python
88+
89+
```python
90+
import json
91+
import socket
92+
93+
# Connect to the client service socket
94+
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
95+
sock.connect("/tmp/usb-remote-client.sock")
96+
97+
# Send attach request
98+
request = {
99+
"command": "attach",
100+
"desc": "Arduino",
101+
"first": True
102+
}
103+
sock.sendall(json.dumps(request).encode() + b'\n')
104+
105+
# Receive response
106+
response = sock.recv(4096).decode()
107+
result = json.loads(response)
108+
109+
if result["status"] == "success":
110+
print(f"Attached device: {result['data']['description']}")
111+
print(f"Local devices: {result['local_devices']}")
112+
else:
113+
print(f"Error: {result['message']}")
114+
115+
sock.close()
116+
```
117+
118+
### Using curl (with socat)
119+
120+
You can use `socat` to create a bridge between HTTP and the Unix socket for testing:
121+
122+
```bash
123+
# Terminal 1: Start socat bridge
124+
socat TCP-LISTEN:8080,reuseaddr,fork UNIX-CONNECT:/tmp/usb-remote-client.sock
125+
126+
# Terminal 2: Send requests via HTTP
127+
curl -X POST http://localhost:8080 -d '{"command":"attach","desc":"Arduino","first":true}'
128+
```
129+
130+
## See Also
131+
132+
- [Client Service Socket API](client_service_api.md) - Client service API documentation
133+
- [Server Setup](../how-to/server_setup.md) - Server installation and configuration
134+
- [Architecture](architecture.md) - System architecture overview

0 commit comments

Comments
 (0)