DotnetWorkoutKit 1.0.2.12
dotnet add package DotnetWorkoutKit --version 1.0.2.12
NuGet\Install-Package DotnetWorkoutKit -Version 1.0.2.12
<PackageReference Include="DotnetWorkoutKit" Version="1.0.2.12" />
<PackageVersion Include="DotnetWorkoutKit" Version="1.0.2.12" />
<PackageReference Include="DotnetWorkoutKit" />
paket add DotnetWorkoutKit --version 1.0.2.12
#r "nuget: DotnetWorkoutKit, 1.0.2.12"
#:package DotnetWorkoutKit@1.0.2.12
#addin nuget:?package=DotnetWorkoutKit&version=1.0.2.12
#tool nuget:?package=DotnetWorkoutKit&version=1.0.2.12
DotnetWorkoutKit
| Package | Latest Release |
|---|---|
| DotnetWorkoutKit |
What is DotnetWorkoutKit?
DotnetWorkoutKit is a cross-platform .NET library that provides a way to create custom workout files for Apple Watch.
Goals
Apple announced the library WorkoutKit in WWDC 2023, which allows developers to create and preview workouts in your iOS and watchOS apps. Refer to the WWDC23 session 10016(timecode: 09:43), the .workout file can be in both binary and JSON format.
However, Apple changed their decision, when the WorkoutKit was officially released, the .workout file is in binary format only. See this reply for more information. This means that developers can't create custom workouts outside of Xcode and MacOS.
So I decoded the binary format of the .workout file and created this library to provide a way to create custom workout files.
Features
- Create a
CustomWorkoutwith C# code. - Save
CustomWorkoutas a.workoutfile, which can be previewed on your iPhone and imported to Apple Watch. - Save
CustomWorkoutas a JSON file, which can be shared with others. - Load a
CustomWorkoutfrom a JSON file.
Supported Activity Types
Running, Cycling, Walking, Hiking, Swimming, Elliptical, Rowing, Yoga, CoreTraining, HighIntensityIntervalTraining, FunctionalStrengthTraining, TraditionalStrengthTraining, StairClimbing, CrossTraining
Supported Goals
| Goal | Units |
|---|---|
| Distance | Kilometers, Meters, Miles, Feet, Yards |
| Time | Seconds, Minutes, Hours |
| Open | (no target) |
Supported Alerts
| Alert | Options |
|---|---|
| Heart Rate Range | Lower/Upper bound (BPM) |
| Speed Range | m/s, km/h, mph; Current or Average metric; Pace string ("5'00"") |
| Cadence Range | Min/Max cadence (SPM) |
| Power Range | Min/Max power (Watts); Current or Average metric |
Using DotnetWorkoutKit
- Create a
CustomWorkoutor load it from a JSON file.
// Create a custom workout
var customWorkout = new CustomWorkout(
activity: CustomWorkout.ActivityType.Running,
location: CustomWorkout.LocationType.Outdoor,
displayName: "sample",
warmUp: new WorkoutStep(new DistanceGoal(3, DistanceGoal.DistanceUnit.Kilometers), new HeartRateRangeAlert(144, 153), "Warm Up"),
blocks: [
new IntervalBlock([
new (IntervalStep.PurposeType.Work, new (new DistanceGoal(3, DistanceGoal.DistanceUnit.Kilometers), new SpeedRangeAlert("4'46\"", "4'38\""))),
new (IntervalStep.PurposeType.Recovery, new (new TimeGoal(TimeSpan.FromMinutes(2))))
], 2),
new IntervalBlock([
new (IntervalStep.PurposeType.Work, new (new DistanceGoal(200, DistanceGoal.DistanceUnit.Meters), new SpeedRangeAlert("4'09\"", "3'59\""))),
new (IntervalStep.PurposeType.Recovery, new (new DistanceGoal(200, DistanceGoal.DistanceUnit.Meters)))
], 6)
],
coolDown: new WorkoutStep(new DistanceGoal(3, DistanceGoal.DistanceUnit.Kilometers), new HeartRateRangeAlert(144, 153), "Cool Down"));
// Or load from JSON
var json = """
{
"Activity": "Running",
"Location": "Outdoor",
"DisplayName": "simple",
"WarmUp": {
"Goal": {
"Distance": 3,
"Unit": "Kilometers"
},
"Alert": {
"MinSpeed": "5'40\"",
"MaxSpeed": "5'00\""
},
"DisplayName": "Warm Up"
},
"Blocks": []
}
"""
var customWorkout = json.LoadFromJson();
The
WorkoutKit.ConsoleAppproject provides a small CLI for local testing:# Convert a workout JSON file into an Apple .workout binary dotnet run --project WorkoutKit.ConsoleApp -- generate input.json output.workout # Round-trip a workout JSON file through the model dotnet run --project WorkoutKit.ConsoleApp -- tojson input.json output.json # Byte-compare two .workout binaries (skipping the per-serialization UUID) dotnet run --project WorkoutKit.ConsoleApp -- compare a.workout b.workoutThe
WorkoutKit.WebAppproject provides an interactive Blazor Server UI for designing workouts in the browser and downloading them as.workoutor.json:dotnet run --project WorkoutKit.WebApp
- Save the
CustomWorkoutas a.workoutfile or a JSON file.
// Save as JSON
File.WriteAllText($"{customWorkout.DisplayName}.workout.json", customWorkout.JsonRepresentation());
// Save as binary
File.WriteAllBytes($"{customWorkout.DisplayName}.workout", customWorkout.DataRepresentation());
Share the
.workoutfile to your iPhone through AirDrop or other methods.You can preview the workout on your iPhone and import it to Apple Watch.
<img src="https://raw.githubusercontent.com/changeforan/DotnetWorkoutKit/refs/heads/main/IMG_6B672CFD47B3-1.jpeg" alt="Import" width="250" />
Project Structure
DotnetWorkoutKit/
├── DotnetWorkoutKit/ # Main library
│ ├── Models/ # Public models (CustomWorkout, goals, alerts)
│ ├── Extensions/ # DataRepresentation/JsonRepresentation
│ ├── protobuf/ # Proto definitions and generated code
│ │ ├── CustomWorkout/ # Proto files for workout structure
│ │ │ └── Alert/ # Proto files for alert types
│ │ └── Models/ # Auto-generated C# from .proto files
│ └── JsonConverters/ # Custom JSON serializers
├── WorkoutKit.ConsoleApp/ # Console app for local testing
├── WorkoutKit.WebApp/ # Blazor Server UI for building & downloading workouts
├── test/DotnetWorkoutKitTest/ # Unit tests (xUnit v3)
└── tools/WorkoutBinaryGenerator/ # Swift tool to generate Apple reference binaries
Testing
# Run unit tests
dotnet test test/DotnetWorkoutKitTest
# Run with Apple binary comparison (requires macOS with Xcode)
xcodebuild -project tools/WorkoutBinaryGenerator/WorkoutBinaryGenerator.xcodeproj -scheme WorkoutBinaryGenerator -configuration Debug build
BUILT_PRODUCTS_DIR=$(xcodebuild -project tools/WorkoutBinaryGenerator/WorkoutBinaryGenerator.xcodeproj -scheme WorkoutBinaryGenerator -configuration Debug -showBuildSettings 2>/dev/null | grep ' BUILT_PRODUCTS_DIR =' | sed 's/.*= //')
"$BUILT_PRODUCTS_DIR/WorkoutBinaryGenerator" /tmp/apple_workouts
APPLE_WORKOUT_DIR=/tmp/apple_workouts dotnet test test/DotnetWorkoutKitTest
The CI pipeline runs on macos-15 to build the Swift tool and compare DotnetWorkoutKit output byte-for-byte against Apple's WorkoutKit.
License
MIT License
Copyright (C) 2013-2024 .NET Foundation and Contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- Google.Protobuf (>= 3.29.2)
- Google.Protobuf.Tools (>= 3.29.2)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
DotnetWorkoutKit 1.0.2.12
========================
- Add Cadence range alert and Power range alert
- Add Blazor Server WebApp (WorkoutKit.WebApp) for building and downloading workouts in the browser
- Refactor WorkoutKit.ConsoleApp CLI (`generate`, `tojson`, `compare` subcommands)
- Apple binary comparison tests against Apple's WorkoutKit reference output