BLE provides low-latency wireless control with automatic reconnection and state synchronization.
Before you begin
To connect to your OSSM via BLE, ensure:- Your device supports Bluetooth Low Energy (BLE 4.0+)
- The OSSM is powered on and not connected to another BLE client
- You’re within approximately 10 meters of the device
Service architecture
The OSSM implements a custom BLE service with multiple characteristics organized into functional groups.Primary service UUID
Characteristic reference
Command characteristics (writable)
Use these characteristics to send commands and configure the OSSM.Primary command characteristic
Command format
Response format
Speed knob configuration characteristic
Configuration values
- Knob as limit (default)
- Independent mode
When set to
true, BLE speed commands (0-100) are treated as a percentage of the current physical knob position.Example: Knob at 50%, BLE command set:speed:80 → Effective speed = 40%This mode provides a hardware safety limit that users can control physically.Latency compensation configuration characteristic
Configuration values
- Enabled
- Disabled
When set to
true, the OSSM expects to receive the exact commands and times from the funscript and that the commands are sent
with the same delay between commands as the time value. By calculating the time between received commands and the time variable
the OSSM is able to determine the latency introduced by BLE and correct for it with slight changes to the speed of the motion.
If the time between commands does not match the intime variable this should not be enabled. The buffer setting is used to artificially
add delay to all movements. This gives the OSSM time to receive the next command before the previous has been completed. This allows
the removal of any delay introduced by late commands, as well as smoothing motion by combining movements travelling in the same direction.
Funscript players should add this buffer value to their playback offset and include an additional setting for fine tuning playback offset
to account for transmission time and any delay inherent to the funscript itself.WiFi configuration characteristic
Write format
|) is used as a delimiter between SSID and password. This allows both SSID and password to contain colons.
Read format (JSON)
ssid field will contain the last saved SSID (if any), ip will be empty, and rssi will be 0.
Response format
Example usage
State characteristics (read-only)
Subscribe to these characteristics to monitor the OSSM’s current state.Current state characteristic
State JSON format
Available states
Available states
For the complete state machine implementation, see OSSM.h in the source repository.
- State changes trigger immediate notifications
- Periodic notifications every 1000ms when no state change occurs
- Notifications stop when no clients are connected
Pattern information characteristics
Pattern list characteristic
Response format
Pattern description characteristic
To retrieve a pattern description:
1
Write the pattern index
Write the index number (0-6) to the characteristic.
2
Read the description
Read the characteristic to receive the pattern description string.
Streaming commands (experimental)
When in streaming mode (go:streaming), the OSSM accepts real-time position commands that enable synchronized playback with external content such as funscripts.
Stream position command
Example commands
- Enter streaming mode with
go:streaming - The OSSM homes to position 0 (fully retracted)
- Send
stream:<pos>:<time>commands to control motion - The firmware calculates the required speed to reach the target position within the specified time
- Motion uses maximum acceleration for responsive feel
Position 0 represents fully retracted (home), and position 100 represents fully extended. The time parameter indicates how long the motion should take, allowing the OSSM to calculate appropriate speed for smooth playback.
- Firmware version 3.0 or later
- OSSM must be in streaming mode (state:
streamingorstreaming.idle) - Commands sent via the primary command characteristic
GPIO characteristics
GPIO control characteristic
Write commands in the format
<pin>:<state> where pin is 1-4 and state is high/low or 1/0.
Pin mapping:
Response format:
For detailed GPIO documentation including hardware integration examples, see GPIO Control.
Fleshy Thrust Sync emulation (testing only)
The OSSM firmware can optionally emulate the Fleshy Thrust Sync (FTS) BLE protocol for compatibility testing with applications like faptap.net. This feature is disabled by default and requires compiling firmware with thePRETEND_TO_BE_FLESHY_THRUST_SYNC flag.
FTS service
Binary protocol format
FTS uses a compact binary format rather than text commands:
Position mapping: 0 = fully retracted, 180 = fully extended
Time format: 16-bit unsigned integer in big-endian (network byte order)
Example
To move to position 90 (50% extended) in 250ms:The FTS emulation uses the same underlying streaming mechanism as the native
stream:pos:time command. The OSSM must be in streaming mode for commands to take effect.Why not recommended
- The FTS protocol is a third-party specification not controlled by the OSSM project
- Protocol changes in FTS-compatible applications may break compatibility
- The native OSSM streaming protocol (
stream:pos:time) is preferred for new integrations - This feature exists primarily for testing compatibility with existing FTS ecosystems
Device information service
The OSSM implements the standard BLE Device Information Service for identification.UUID namespace structure
The OSSM uses a structured UUID namespace for organized expansion.Service UUID
Namespace ranges
Current characteristic assignments
- Commands (0x1xxx)
- State (0x2xxx)
- Patterns (0x3xxx)
- GPIO (0x4xxx)
Connection management
Advertising
Security
The OSSM uses “Just Works” pairing for ease of use. Anyone within BLE range can connect when the device is advertising.
Disconnection safety
When a BLE connection is lost unexpectedly, the OSSM automatically ramps down speed to prevent runaway operation. Ramp-down behavior:- Connection lost detected
- 1 second delay — allows for brief signal dropouts without triggering
- 2 second ramp — speed decreases from current value to zero using ease-in-out-sine curve
- Device continues at zero speed until reconnected or manually stopped
The ease-in-out-sine curve provides smooth deceleration that feels natural and reduces mechanical stress. If speed was already zero at disconnect, no ramp occurs.
- Implement connection monitoring to detect disconnects quickly
- Consider automatic reconnection logic
- Local controls (potentiometer, encoder) remain active during and after disconnect
- Users can manually stop via the speed knob or long-press for emergency stop
Client implementation guide
Connection flow
Follow these steps to establish a connection and begin controlling your OSSM:1
Scan for the device
Scan for BLE devices with the name “OSSM”.
Device appears in scan results.
2
Connect to the device
Initiate a GATT connection to the OSSM.
3
Discover services
Discover all services and characteristics on the device.
Primary service UUID
522b443a-4f53-534d-0001-420badbabe69 is found.4
Subscribe to state notifications
Enable notifications on the state characteristic to receive real-time updates.
5
Read initial state
Read the current state and pattern list to initialize your application.
6
Send commands
Begin sending commands to control the OSSM.
Best practices
Command handling
- Validate command format before sending
- Handle both
ok:andfail:responses - Implement retry logic for critical commands
- Monitor state changes to confirm command execution
State monitoring
- Subscribe to state characteristic notifications
- Parse JSON state updates reliably
- Handle state transitions appropriately
- Implement timeout handling for missing updates
Example code
Troubleshooting
Connection fails
Connection fails
Symptoms: Unable to discover or connect to the OSSM.Solutions:
- Ensure the OSSM is powered on and within range (~10 meters)
- Check that no other device is currently connected to the OSSM
- Restart the OSSM to reset the BLE stack
- Try moving closer to the device
Commands not working
Commands not working
Symptoms: Commands return
fail: or have no effect.Solutions:- Verify the command format matches the specification exactly
- Check that the OSSM is in a state that accepts commands (e.g.,
strokeEngineorsimplePenetration) - Use
go:strokeEngineorgo:simplePenetrationfirst if in menu state - Read the current state to understand which commands are valid
No state updates
No state updates
Symptoms: State characteristic never updates after subscribing.Solutions:
- Verify notification subscription was successful
- Check that your BLE library supports notifications
- Ensure you’re reading notifications from the correct characteristic UUID
- Try disconnecting and reconnecting
Invalid responses
Invalid responses
Symptoms: Receiving unexpected or malformed data.Solutions:
- Ensure you’re decoding responses as UTF-8 text
- Verify JSON parsing handles the state format correctly
- Check for encoding issues in your BLE library

