Funscripted

Euphoria F1 API Reference

The Euphoria F1 exposes three local interfaces: BLE GATT services for wireless sensor streaming, a REST API over WiFi for device configuration, and a WebSocket endpoint for real-time data.

Connecting to the Device

The Euphoria F1 runs a WiFi access point and a BLE server simultaneously. You can use either interface depending on your use case.

WiFi (REST API + WebSocket)

Connect to the device's WiFi network. The default SSID is Euphoria F1 (configurable). The device IP is always 192.168.4.1.

Once connected, a captive portal opens automatically on most devices. The REST API and WebSocket are available on port 80.

Bluetooth Low Energy

The device advertises as Euphoria F1 (or Euphoria F1 HID in HID mode). Manufacturer data contains company ID 0x0FD5 (Telemacy Ltd).

Pairing uses Secure Connections with passkey 123456. The user must confirm by pressing the physical button on the device. Once paired, bonding information is stored persistently.

Authentication

Protected REST endpoints require a session token. The token is obtained through a physical button approval flow.

Step 1: Open a WebSocket connection

// Connect to the device WebSocket
const ws = new WebSocket('ws://192.168.4.1/ws');

You need this open before requesting auth, because the token is delivered over WebSocket.

Step 2: Request authentication

GET /api/auth/request

// Response:
{ "status": "ok", "message": "Press button on device" }

The device LED starts blinking. You have 30 seconds to press the button.

Step 3: User presses the physical button

// WebSocket receives:
{ "type": "auth_success", "token": "a1b2c3d4e5f6...64 hex chars" }

Short press = approve. Long press = reject. Store this token for subsequent API calls.

Step 4: Use the token

GET /api/wifi/scan
Authorization: a1b2c3d4e5f6...

Token expires after 10 minutes of inactivity. Max 4 concurrent sessions.

Check auth status

GET /api/auth/status

// Response:
{ "authenticated": true, "status": "authenticated" }

BLE GATT Services

All custom services use the base UUID 0000XXXX-6136-4d92-9bb7-5bab7345fa61 where XXXX is the 16-bit service/characteristic ID.

Device Information Service

0x180A (Standard)
Manufacturer Name0x2A29
Read"Telemacy Ltd"
Model Number0x2A24
Read"F1"
Firmware Revision0x2A26
ReadVersion string
Hardware Revision0x2A27
ReadHardware version
PnP ID0x2A50
ReadDevice identifiers

Sensor Data Service

0x0004 (Custom)
Sensor Values0x0401Read + Notify

8 FSR pressure sensor values streamed at up to 50Hz.

// Notification payload (JSON string):
{ "timestamp": 12345, "values": [100, 200, 150, 175, 220, 180, 190, 210] }

Values range 0-2500 (ADC units, averaged over 10 readings).

Sensor Sum0x0402Read

Sum of all 8 sensor values as a uint16 (little-endian, 2 bytes). Range: 0-20000.

Button Events Service

0x0006 (Custom)
Button Event0x0601Notify
// Notification payload (JSON string):
{ "event": "short_press", "timestamp": 54321 }

Events: short_press, double_press, long_press

Device Mode Service

0x0007 (Custom)
Device Mode0x0701Read + Notify
{ "mode": "normal" }

Modes: normal, config, factory_reset_confirm

WebSocket API

Endpoint

ws://192.168.4.1/ws

Subscribe to sensor stream

// Send:
{ "type": "subscribe", "channel": "sensors" }
// You'll receive updates every ~50ms:
{
  "type": "sensor_update",
  "timestamp": 12345,
  "sensors": [100, 200, 150, 175, 220, 180, 190, 210],
  "sum": 1425
}

Unsubscribe

{ "type": "unsubscribe", "channel": "sensors" }

Button events (automatic)

Button events are broadcast to all connected WebSocket clients without subscribing.

{ "type": "button_event", "event": "short_press" }

Full example

const ws = new WebSocket('ws://192.168.4.1/ws');

ws.onopen = () => {
  // Subscribe to sensor data
  ws.send(JSON.stringify({
    type: 'subscribe',
    channel: 'sensors'
  }));
};

ws.onmessage = (event) => {
  const data = JSON.parse(event.data);

  if (data.type === 'sensor_update') {
    // data.sensors = [s0, s1, s2, s3, s4, s5, s6, s7]
    // Each value: 0-2500
    console.log('Pressure:', data.sensors);
  }

  if (data.type === 'button_event') {
    console.log('Button:', data.event);
  }
};

REST API

Base URL: http://192.168.4.1. Endpoints marked with a lock require an auth token in the Authorization header.

Authentication

GET/api/auth/request

Request authentication. Device LED blinks, waiting for button press.

GET/api/auth/status

Check current authentication status.

Device Status

GET/api/status

Device info, firmware version, current mode.

GET/api/sensors/current

Current sensor readings (one-shot, not streaming).

WiFi

GET/api/wifi/scanrequires auth

Scan for available WiFi networks.

POST/api/wifi/connectrequires auth

Connect to a WiFi network.

GET/api/wifi/status

Current WiFi connection status.

DELETE/api/wifi/disconnectrequires auth

Disconnect from WiFi network.

Configuration

GET/api/configrequires auth

Get all device configuration.

POST/api/config/devicerequires auth

Set device name and identifiers. All fields optional.

POST/api/config/audiorequires auth

Configure audio/mute settings.

POST/api/config/sleeprequires auth

Configure sleep timeout. All fields optional.

POST/api/config/hid-startuprequires auth

Configure whether device boots into HID mode.

Control

POST/api/control/calibraterequires auth

Calibrate sensors (reset baseline to current pressure).

POST/api/control/restartrequires auth

Restart the device.

POST/api/control/resetrequires auth

Factory reset. Clears all settings and bonding data.

POST/api/control/forget-bondsrequires auth

Remove all paired BLE devices.

GET/api/control/list-bondsrequires auth

List all paired BLE devices.

DELETE/api/control/delete-bondrequires auth

Remove a specific paired device. Pass ?address=AA:BB:CC:DD:EE:FF as query parameter.

HID

GET/api/hid/statusrequires auth

HID mode status.

POST/api/hid/enablerequires auth

Enable HID mode. Device will re-advertise as HID.

POST/api/hid/disablerequires auth

Disable HID mode. Returns to normal BLE mode.

GET/api/hid/configrequires auth

Get all trigger configurations.

POST/api/hid/triggerrequires auth

Create or update a trigger.

DELETE/api/hid/triggerrequires auth

Delete a trigger. Pass ?id=0 as query parameter.

GET/api/hid/presetsrequires auth

List available trigger presets.

POST/api/hid/presetrequires auth

Load a trigger preset.

HID Mode (Dick Interface Device)

In HID mode, the Euphoria F1 acts as a Bluetooth keyboard and mouse. It advertises as Euphoria F1 HID and supports up to 11 configurable triggers that map pressure and button inputs to keystrokes or mouse clicks.

Trigger input types

Pressure Increase

Triggered when pressure rises on a sensor.

Pressure Decrease

Triggered when pressure drops on a sensor.

Sustained Pressure

Triggered when pressure is held above a threshold.

Pressure Release

Triggered when pressure drops below threshold.

Pressure Threshold

Triggered when pressure crosses a specific value.

Button Short Press

Physical button quick press.

Button Double Press

Physical button pressed twice quickly.

Button Long Press

Physical button held for 2+ seconds.

Trigger output types

Keyboard Key

Any HID key code with optional modifiers (Ctrl, Shift, Alt, Win).

Mouse Click

Left, right, or middle mouse button click.

Key Repeat

Hold a key while trigger is active, release when trigger stops.

Built-in presets

gamingpresentationmusicsimple_clicker

Switching modes

Enter HID mode via the configuration portal or REST API. Exit by holding the button for 7 seconds. The device will disconnect all BLE clients and re-advertise in the new mode.

Physical Button Reference

Short pressGeneral action / confirm auth / BLE pairing reject
Double pressInitiate shutdown sequence
Long press (2s)Calibrate sensors / confirm BLE pairing
Very long press (7s)Exit HID mode
4 pressesEnter config mode
5 presses in config modeFactory reset confirmation
8 presses within 8sEmergency factory reset