# HR OSC for VRChat

HR OSC for VRChat is a Windows WPF bridge that reads heart-rate data from a Bluetooth LE heart-rate monitor and sends it to VRChat through OSC avatar parameters.

The app is intended for VRChat avatars that expose heart-rate driven parameters, such as a BPM number, pulse animation, material effect, or any other animator logic that can react to OSC input.

## What it does

- Finds paired Bluetooth LE devices that expose the standard GATT Heart Rate service.
- Reads live BPM values from the selected sensor.
- Sends OSC messages to `127.0.0.1:{port}`.
- Uses port `9000` by default, matching VRChat's default OSC receive port.
- Sends an integer BPM parameter and a normalized float parameter.
- Includes a built-in test mode for trying OSC output without a sensor.
- Writes a short in-app activity feed and rotating activity log files for troubleshooting.

VRChat receives avatar parameters through OSC addresses in the form `/avatar/parameters/{name}`. See the official VRChat OSC documentation for more detail:

- [OSC Overview](https://docs.vrchat.com/docs/osc-overview)
- [OSC Avatar Parameters](https://docs.vrchat.com/docs/osc-avatar-parameters)

## Requirements

- Windows with Bluetooth support.
- .NET 8 Desktop Runtime to run a published build, or .NET 8 SDK to build from source.
- VRChat with OSC enabled.
- A Bluetooth LE heart-rate sensor paired in Windows.
- A VRChat avatar with matching OSC avatar parameters.

## Quick start

1. Pair your Bluetooth LE heart-rate monitor in Windows.
2. Enable OSC in VRChat.
3. Run HR OSC for VRChat.
4. Choose the paired heart-rate device in the app.
5. Confirm the OSC port and parameter names match your avatar.
6. Start the connection and verify that BPM updates appear in VRChat.

If you do not have a sensor available, enable **Use test mode** in the app or launch with `--test` to generate sample BPM values.

## OSC parameters

By default, the app sends both parameters to `127.0.0.1:9000`.

| Setting | Default OSC address | Type | Value |
| --- | --- | --- | --- |
| Int BPM parameter | `/avatar/parameters/HR` | `int` | Current BPM |
| Float BPM parameter | `/avatar/parameters/HRPercent` | `float` | Normalized BPM from `0.0` to `1.0` |

The float value is normalized from the configured BPM range. The default range is `80` BPM to `160` BPM, so `80` maps to `0.0` and `160` maps to `1.0`.

You can customize these settings in the app:

- `VrChatPort`
- `HrIntAddress`
- `HrFloatAddress`
- Minimum and maximum BPM normalization range
- Automatic recovery settings
- Verbose Bluetooth diagnostics
- Test mode

Only enter the parameter name in the app, such as `HR` or `HRPercent`. The app adds the `/avatar/parameters/` OSC prefix when sending.

## Settings and logs

Settings are saved to:

```text
%LOCALAPPDATA%\HR-OSC-VRChat\settings.json
```

Activity logs are written to:

```text
%LOCALAPPDATA%\HR-OSC-VRChat\logs\activity-*.log
```

The app keeps the most recent activity log files and prunes older ones automatically.

## Test mode

Test mode uses the built-in BPM generator instead of Bluetooth. It is useful for checking VRChat OSC setup, avatar parameter names, and animator behavior before connecting a real sensor.

Start in test mode from the command line:

```powershell
dotnet run --project HR-OSC-VRChat.csproj -- --test
```

You can also enable **Use test mode** in the app.

## Build from source

Restore and build:

```powershell
dotnet build HR-OSC-VRChat.csproj
```

Run:

```powershell
dotnet run --project HR-OSC-VRChat.csproj
```

Run in test mode:

```powershell
dotnet run --project HR-OSC-VRChat.csproj -- --test
```

### Create a distributable build

Publish a self-contained single-file build for 64-bit Windows:

```powershell
dotnet publish HR-OSC-VRChat.csproj -c Release -r win-x64 --self-contained true -p:PublishSingleFile=true -p:IncludeNativeLibrariesForSelfExtract=true
```

The published files are created in:

```text
bin\Release\net8.0-windows10.0.19041.0\win-x64\publish\
```

The publish folder contains `HR-OSC-VRChat.exe`, which is suitable for distribution to 64-bit Windows users without requiring them to install the .NET runtime separately. A `.pdb` file may also be generated for debugging; it is optional for normal user distribution.

This repository currently has a single WPF project and no automated test project.

## Troubleshooting

### No device found

Pair the heart-rate monitor in Windows first. The app discovers paired Bluetooth LE devices that expose the Heart Rate service.

### OSC is not visible in VRChat

Check that OSC is enabled in VRChat, the app is sending to the same port VRChat is listening on, and your avatar parameters match the configured names and types. The defaults are `HR` as an `int` and `HRPercent` as a `float`.

### BPM appears in the app but not on the avatar

Verify that the avatar has OSC parameters with the same names and compatible types. The app sends to `/avatar/parameters/{name}`, so an app setting of `HR` becomes `/avatar/parameters/HR`.

### Bluetooth connection is unstable

Use **Reconnect Sensor** to reconnect manually. Automatic recovery can reconnect after repeated sensor errors, and verbose Bluetooth diagnostics can write more detail to the activity log file.

### Test mode works but the sensor does not

The VRChat OSC side is likely configured correctly. Check the Windows Bluetooth pairing, sensor battery, sensor contact, and whether another app is already connected to the monitor.

## License

This project is licensed under the GNU General Public License version 3.0 only. See LICENSE for details.
