Metadata-Version: 2.4
Name: sylvac-measure
Version: 0.1.0
Summary: Python package for Sylvac Bluetooth measurement instruments
License: Apache-2.0
License-File: COPYING
Requires-Python: >=3.11
Requires-Dist: bleak>=0.22
Description-Content-Type: text/markdown

# sylvac-python

[![PyPI](https://img.shields.io/pypi/v/sylvac-measure)](https://pypi.org/project/sylvac-measure/)
[![License](https://img.shields.io/pypi/l/sylvac-measure)](COPYING)
[![Liberapay](https://img.shields.io/liberapay/receives/stv0g)](https://liberapay.com/stv0g/)

Python package for reading measurements from [Sylvac](https://www.sylvac.ch) Bluetooth Low Energy measurement instruments (calipers, gauges, micrometers, …).

Communication uses the **Sylvac SDS (Simple Data Service)** and **SMS (Sylvac Metrology Service)** GATT profiles over BLE via [bleak](https://github.com/hbldh/bleak), based on the official [Sylvac Bluetooth developer tools](https://github.com/SylvacDev/BluetoothDevTools). SDS provides real-time measurement notifications, while SMS allows querying and configuring instrument settings via ASCII commands.

## Tested devices

Sylvac's Bluetooth interface is largely consistent across their product range,
so this library should work with most BLE-enabled Sylvac instruments.
The following devices have been confirmed to work:

| Device | Product page |
| --- | --- |
| Sylvac S_Cal EVO | _discontinued_ |

(Please create a GitHub issue to report more tested devices.)

## Requirements

- Python 3.11+
- A Sylvac BLE instrument advertising in **SIMPLE** profile (the factory default — no pairing required)

## Installation

```sh
pip install sylvac-measure
```

Or from source:

```sh
git clone https://codeberg.org/stv0g/sylvac-python
cd sylvac-python
pip install -e .
```

## Quick start

### Command-line

The `sylvac` command provides several subcommands for interacting with Sylvac BLE instruments.

#### Scanning for devices

```sh
# List all available Sylvac BLE devices
sylvac list

# Scan for longer duration
sylvac list --timeout 20

# Filter by device name prefix (default: "SY")
sylvac list --prefix SY
```

Output:
```text
726B9552-D5B0-4BE6-C974-C8BCA6C2F2C9 SY295
```

#### Device information

```sh
# Show device identification and status (default command)
sylvac info

# Connect to a specific device by address
sylvac info --address AA:BB:CC:DD:EE:FF

# Output as JSON
sylvac info --json

# Verbose BLE debug output
sylvac info --log-level DEBUG
```

#### Taking measurements

```sh
# Take a single measurement
sylvac measure

# Stream measurements continuously (Ctrl-C to stop)
sylvac measure --follow

# Output measurements as JSON
sylvac measure --json

# Omit the unit from output
sylvac measure --no-unit

# Stream measurements from a specific device
sylvac measure --address AA:BB:CC:DD:EE:FF --follow
```

Output (one measurement per line on stdout):

```text
20.58 mm
20.59 mm
20.58 mm  [max]
```

#### Reading configuration

```sh
# Show all configuration settings
sylvac config get

# Show a specific setting
sylvac config get unit
sylvac config get resolution
sylvac config get preset
sylvac config get display
sylvac config get eco
sylvac config get keyboard-locked
sylvac config get last-calibration
sylvac config get next-calibration
sylvac config get id
sylvac config get number
sylvac config get favorites
sylvac config get standby-timeout
```

#### Writing configuration

```sh
# Set the display unit
sylvac config set unit mm
sylvac config set unit in

# Lock or unlock unit changes
sylvac config set unit-locked true
sylvac config set unit-locked false

# Lock or unlock keyboard
sylvac config set keyboard-locked true
sylvac config set keyboard-locked false

# Set a preset value
sylvac config set preset 10.5

# Freeze or unfreeze the display
sylvac config set display frozen
sylvac config set display live

# Set calibration dates (YYYY-MM-DD format)
sylvac config set last-calibration 2026-01-15
sylvac config set next-calibration 2027-01-15

# Enable or disable economy mode
sylvac config set eco true
sylvac config set eco false

# Set instrument number
sylvac config set number "MY-INSTRUMENT"

# Set standby timeout (minutes)
sylvac config set standby-timeout 30
```

#### Device control

```sh
# Put the instrument into sleep mode
sylvac poweroff

# Put the instrument into standby mode
sylvac standby

# Reset instrument user settings
sylvac reset
```

#### Connection options

All commands support the following connection options:

```sh
# Specify device address (skips scanning)
sylvac <command> --address AA:BB:CC:DD:EE:FF

# Set scan timeout when address is not specified (default: 10s)
sylvac <command> --timeout 20
```

### Python API

```python
import asyncio
from sylvac import SylvacDevice, scan

async def main():
    device = await scan(timeout=10)
    if device is None:
        print("No device found")
        return

    async with SylvacDevice(device.address) as dev:
        async for m in dev.measurements():
            print(f"{m.format()}  (mode: {m.mode})")

asyncio.run(main())
```

#### Scan for all visible instruments

```python
from sylvac import scan_all

async for d in scan_all(timeout=10):
    print(d.name, d.address)
```

#### Send instrument commands

```python
async with SylvacDevice(address) as dev:
    await dev.send_command("SVR1")   # enable saver mode (notify on change only)
    await dev.send_command("UNI?")   # query current unit
```

## `Measurement` dataclass

| Field | Type | Description |
| --- | --- | --- |
| `value` | `float` | Measurement in `unit` |
| `unit` | `str` | `"mm"`, `"in"`, `"°"`, `"rad"`, … |
| `resolution` | `float \| None` | Smallest increment (same unit), e.g. `0.01` |
| `mode` | `str` | `"normal"`, `"min"`, `"max"`, `"delta"` |

`Measurement.format()` returns a string rounded to the instrument's resolution, e.g. `"20.58 mm"`.

## Protocol notes

Sylvac instruments expose two relevant GATT characteristics inside the **SDS** service (`0x5000`, standard BLE base UUID):

| Characteristic | UUID     | Description                                      |
|----------------|----------|--------------------------------------------------|
| Measurement    | `0x5020` | Notify — signed 32-bit LE integer, SI-scaled     |
| Parameters     | `0x5021` | Notify — unit, resolution, and mode bitmap       |

Polling the Measurement characteristic returns a sentinel value (`0x7FFFFFFF`); **notifications must be enabled** to receive valid data.

The instrument must be in **SIMPLE** Bluetooth profile (no pairing/encryption). This is the factory default. If the instrument has been switched to PAIR or HID profile, restore it via:

```text
CFG BT SIMPLE   (sent as ASCII to SMS RemoteRequest characteristic 0x5012)
```

or use the factory reset: `FAC RST`.

### Sylvac Metrology Service Commands

| Command | Description |
| --- | --- |
| `ID?` | Transmits instrument identification (SY276) |
| `BAT?` | Transmits battery status (BAT1=ok or BAT0=low) |
| `VER?` | Transmit program version and date (Vx.x DD.MM.YYYY) |
| `UNI?` | Transmit unit of measure (IN or MM) |
| `UNI0` / `UNI1` | Lock / unlock unit change function |
| `MM` | Activates mm unit |
| `IN` | Activates Inch unit |
| `KEY?` | Transmits keyboard status (KEY0 or KEY1) |
| `KEY0` / `KEY1` | Disables/enables keypad (except Send Data) |
| `RST` | Reset instrument (user settings) |
| `OFF` | Instrument sleep mode |
| `SBY` | Instrument stand-by (SIS) |
| `SBY XX` | xx number of minutes before stand-by |
| `ECO?` | Current economy mode |
| `ECO1` / `ECO0` | Enables / disables economy mode |
| `RES?` | Current resolution mode |
| `RES2` / `RES3` | Change resolution |
| `LCAL?` | Transmit date of last calibration (DD.MM.YYYY) |
| `LCAL JJ.MM.[AA]AA` | Enter date of last calibration |
| `NCAL?` | Transmit date of next calibration (DD.MM.YYYY) |
| `NCAL JJ.MM.[AA]AA` | Enter date of next calibration |
| `NUM?` | Transmit instrument number |
| `NUMX..X` (jusqu’à 20car) | Modifies instrument number (10 characters) |
| `OUT0` / `OUT1` | Disables/enables continuous data output |
| `PRE?` | Transmit preset value (±xxx.yyy[yy]) |
| `PRE ±XXX.YYYYYY` | Enter preset value (max. 199.999mm / 7.83'') |
| `PRE OFF` / `PRE ON` | Activates/deactivates Preset function |
| `?` | Transmits displayed value |
| `SET?` | Transmit instrument configuration (IN or MM, STO0 or STO1, KEY0 or KEY1, BAT1 or BAT0) |
| `STO?` | Transmits display status |
| `STO0` / `STO1` | Release/freeze display |
| `BT0` / `BT1` | Disables Bluetooth® module |
| `BTRST` | Reset Matching |
| `MAC?` | Transmits Bluetooth® module MAC address |
| `FMIN?` | Returns FMIN value |
| `FMIN0` / `FMIN1` | Disable/enable FMIN function |
| `FCT?` | Favorites function active? |
| `FCT0…9…A…F` | "Favorite" function assignment |

## Specifications and references

- [MEM-PM 292-1806-01 — Bluetooth Profile Specifications](https://github.com/SylvacDev/BluetoothDevTools/blob/main/Sylvac-Custom-Bluetooth-GATT-Profiles/MEM-PM%20292-1806-01-Bluetooth%20Profile%20Specifications.pdf)
- [SPE-PM 292-1744-01 — SDS Specification](https://github.com/SylvacDev/BluetoothDevTools/blob/main/Sylvac-Custom-Bluetooth-GATT-Profiles/Spec/SPE-PM%20292-1744-01%20SDS%20Specification.pdf)
- [SPE-PM 292-1746-01 — SMS Specification](https://github.com/SylvacDev/BluetoothDevTools/blob/main/Sylvac-Custom-Bluetooth-GATT-Profiles/Spec/SPE-PM%20292-1746-01%20SMS%20Specification.pdf)
- [S_Mike PRO Instruction Manual](https://www.sylvac.ch/wp-content/uploads/2023/12/MAN-SMikePro_v3_NEU_EFDIS_681-276-06.pdf)
- [P12D — Interface description](https://www.sylvac.ch/wp-content/uploads/2024/01/Manuel_Interface_P12D_WEB.pdf)

## Credits

Steffen Vogel (<post@steffenvogel.de>)

If you find this project useful, consider [sponsoring its development on Liberapay](https://liberapay.com/stv0g/).

## License

Apache-2.0 — see [COPYING](COPYING).
