Skip to content

Connecting to the S120

This guide shows you how to establish a BLE connection to the Huepar S120 laser distance meter.

  • Bluetooth adapter with BLE support
  • S120 device powered on
  • Platform-specific BLE library installed

The S120 advertises as LDM-S120 xxxx where xxxx is the last 4 hex digits of its MAC address.

Terminal window
# Start scanning
bluetoothctl scan on
# Look for output like:
# [NEW] Device 5B:A6:86:38:FA:CA LDM-S120 faca
# Stop scanning
bluetoothctl scan off
  1. Trust the device

    Terminal window
    bluetoothctl trust 5B:A6:86:38:FA:CA
  2. Connect

    Terminal window
    bluetoothctl connect 5B:A6:86:38:FA:CA
  3. Verify connection

    Terminal window
    bluetoothctl info 5B:A6:86:38:FA:CA
    # Should show "Connected: yes"
import asyncio
from bleak import BleakClient
ADDRESS = "5B:A6:86:38:FA:CA"
async def connect():
async with BleakClient(ADDRESS) as client:
print(f"Connected: {client.is_connected}")
# Your code here
asyncio.run(connect())

After connecting, discover GATT services:

async def discover_services(client):
for service in client.services:
print(f"Service: {service.uuid}")
for char in service.characteristics:
print(f" Char: {char.uuid} - {char.properties}")

Expected output:

Service: 00001800-0000-1000-8000-00805f9b34fb (Generic Access)
Service: 00001801-0000-1000-8000-00805f9b34fb (Generic Attribute)
Service: 0000ae30-0000-1000-8000-00805f9b34fb (Laser Meter)
Char: 0000ae01-... - ['write-without-response']
Char: 0000ae02-... - ['notify']
Char: 0000ae05-... - ['indicate']

Before sending commands, enable notifications on the data characteristic:

CHAR_RX = "0000ae02-0000-1000-8000-00805f9b34fb"
def notification_handler(sender, data):
print(f"Received: {data.hex()}")
async def setup_notifications(client):
await client.start_notify(CHAR_RX, notification_handler)

Verify the connection by requesting the device MAC:

CHAR_TX = "0000ae01-0000-1000-8000-00805f9b34fb"
async def get_mac(client):
cmd = bytes([0xF1, 0x03, 0x02, 0x05]) # GET_DEVICE_MAC
await client.write_gatt_char(CHAR_TX, cmd)
# Response arrives via notification handler

Expected response:

Received: f103000c356261363836333866616361...
└─ "5ba68638faca" in ASCII
import asyncio
from bleak import BleakClient
ADDRESS = "5B:A6:86:38:FA:CA"
SERVICE = "0000ae30-0000-1000-8000-00805f9b34fb"
CHAR_TX = "0000ae01-0000-1000-8000-00805f9b34fb"
CHAR_RX = "0000ae02-0000-1000-8000-00805f9b34fb"
def handle_notification(sender, data):
print(f"← {data.hex()}")
async def main():
async with BleakClient(ADDRESS) as client:
print(f"Connected: {client.is_connected}")
# Enable notifications
await client.start_notify(CHAR_RX, handle_notification)
# Get device MAC
print("Requesting MAC address...")
await client.write_gatt_char(CHAR_TX, bytes([0xF1, 0x03, 0x02, 0x05]))
await asyncio.sleep(1)
# Get firmware version
print("Requesting firmware version...")
await client.write_gatt_char(CHAR_TX, bytes([0xF1, 0x03, 0x03, 0x06]))
await asyncio.sleep(1)
# Trigger measurement
print("Triggering measurement...")
await client.write_gatt_char(CHAR_TX, bytes([0xF1, 0x04, 0x01, 0x01, 0x06]))
await asyncio.sleep(2)
asyncio.run(main())
Terminal window
# Trust the device first
bluetoothctl trust 5B:A6:86:38:FA:CA

The device may timeout if idle. Send commands within 10 seconds of connecting.

Ensure you’ve enabled notifications on 0xAE02:

await client.start_notify(CHAR_RX, handler)
  • Ensure the S120 is powered on (hold measure button)
  • Check the device is in range (under 10m)
  • Verify Bluetooth is enabled on your system