Python HTTP
The ESP32 web server exposes a REST endpoint that accepts JSON commands via HTTP GET. This is the simplest way to control the arm wirelessly from any language or tool that can make HTTP requests.
Endpoint
Section titled “Endpoint”GET http://<arm-ip>/js?json=<url-encoded-json>The arm’s IP depends on the WiFi mode:
- AP mode:
192.168.4.1 - STA mode: Assigned by your router (check with
{"T":405}over serial)
Python Setup
Section titled “Python Setup”pip install requestsBasic Usage
Section titled “Basic Usage”import requestsimport jsonfrom urllib.parse import quote
ARM_IP = "192.168.4.1"
def send_command(cmd: dict) -> dict | None: """Send a JSON command via HTTP and return the response.""" url = f"http://{ARM_IP}/js?json={quote(json.dumps(cmd))}" try: resp = requests.get(url, timeout=2) return resp.json() except (requests.RequestException, json.JSONDecodeError): return None
# Move to homesend_command({"T": 100})
# Get position feedbackpos = send_command({"T": 105})if pos: print(f"Position: ({pos['x']:.1f}, {pos['y']:.1f}, {pos['z']:.1f})")
# Move to coordinatessend_command({"T": 104, "x": 200, "y": 50, "z": 150, "t": 1.57, "spd": 0.25})
# Open grippersend_command({"T": 106, "cmd": 1.57, "spd": 0, "acc": 0})Pick-and-Place Example
Section titled “Pick-and-Place Example”import time
def pick_and_place(pick_x, pick_y, place_x, place_y, height=150, grab_height=50): """Pick an object and place it at a new location.""" # Move above pick position send_command({"T": 104, "x": pick_x, "y": pick_y, "z": height, "t": 3.14, "spd": 0.25}) time.sleep(1)
# Open gripper send_command({"T": 106, "cmd": 1.57, "spd": 0, "acc": 0}) time.sleep(0.5)
# Lower to grab send_command({"T": 104, "x": pick_x, "y": pick_y, "z": grab_height, "t": 3.14, "spd": 0.15}) time.sleep(1)
# Close gripper send_command({"T": 106, "cmd": 3.14, "spd": 0, "acc": 0}) time.sleep(0.5)
# Lift send_command({"T": 104, "x": pick_x, "y": pick_y, "z": height, "t": 3.14, "spd": 0.25}) time.sleep(1)
# Move to place position send_command({"T": 104, "x": place_x, "y": place_y, "z": height, "t": 3.14, "spd": 0.25}) time.sleep(1)
# Lower to place send_command({"T": 104, "x": place_x, "y": place_y, "z": grab_height, "t": 3.14, "spd": 0.15}) time.sleep(1)
# Release send_command({"T": 106, "cmd": 1.57, "spd": 0, "acc": 0}) time.sleep(0.5)
# Return to safe height send_command({"T": 104, "x": place_x, "y": place_y, "z": height, "t": 3.14, "spd": 0.25})
# Usagepick_and_place(200, -50, 200, 50)Using curl
Section titled “Using curl”You can also control the arm directly from the command line:
# Home positioncurl "http://192.168.4.1/js?json=%7B%22T%22%3A100%7D"
# Get feedbackcurl "http://192.168.4.1/js?json=%7B%22T%22%3A105%7D"
# With jq for pretty outputcurl -s "http://192.168.4.1/js?json=%7B%22T%22%3A105%7D" | jq .Rate Limiting
Section titled “Rate Limiting”Session-Based Control
Section titled “Session-Based Control”For applications that send many commands, use a requests.Session to reuse the TCP connection:
import requestsimport jsonfrom urllib.parse import quote
session = requests.Session()session.timeout = 2
ARM_IP = "192.168.4.1"
def send(cmd: dict): url = f"http://{ARM_IP}/js?json={quote(json.dumps(cmd))}" return session.get(url)Comparing HTTP vs UART
Section titled “Comparing HTTP vs UART”| Feature | HTTP | UART |
|---|---|---|
| Connection | Wireless (WiFi) | Wired (USB) |
| Latency | ~10-50ms | ~5-10ms |
| Reliability | Network-dependent | Very reliable |
| Range | WiFi range | Cable length |
| Multi-client | Yes (multiple browsers) | Single connection |
| Setup | WiFi config required | Plug and play |
HTTP control reference from the Waveshare Python HTTP guide and firmware source.