A .NET client library for controlling ZSA keyboards through the Keymapp application's gRPC API.
Keymapp.NET provides a comprehensive C# wrapper around the Keymapp gRPC service, allowing you to programmatically control ZSA keyboards (like the Moonlander, Planck EZ, and Ergodox EZ) from your .NET applications.
- Keyboard Management: Connect to and manage multiple ZSA keyboards
- Layer Control: Set and unset keyboard layers programmatically
- RGB LED Control: Control individual LEDs or all LEDs with custom colors
- Status LED Control: Manage status LEDs on supported keyboards
- Brightness Control: Adjust keyboard brightness levels
- Async/Await Support: Full async support with cancellation tokens
- Dependency Injection: Built-in support for Microsoft.Extensions.DependencyInjection
- Extension Methods: Convenient extension methods for common operations
Add the project reference to your application:
<ProjectReferenceInclude="path/to/Keymapp.NET/Keymapp.NET.csproj"/>- Keymapp application must be running with gRPC API enabled (typically on
http://127.0.0.1:50051) - A compatible ZSA keyboard connected to your system
usingKeymapp.NET;usingMicrosoft.Extensions.DependencyInjection;usingGrpc.Net.Client;varservices=newServiceCollection().AddKeymappServices(GrpcChannel.ForAddress("http://127.0.0.1:50051")).BuildServiceProvider();usingvarscope=services.CreateScope();varkeymappApi=scope.ServiceProvider.GetRequiredService<IKeymappApi>();usingGrpc.Net.Client;usingKeymapp.NET;usingvarchannel=GrpcChannel.ForAddress("http://127.0.0.1:50051");awaitusingvarapi=newKeymappApi(channel);varstatus=awaitkeymappApi.GetStatusAsync();Console.WriteLine($"Keymapp Version: {status.KeymappVersion}");if(status.ConnectedKeyboard!=null){Console.WriteLine($"Connected: {status.ConnectedKeyboard.FriendlyName}");}// Connect to any available keyboardvarconnectResult=awaitkeymappApi.ConnectAnyKeyboardAsync();// Or connect to a specific keyboardvarkeyboards=awaitkeymappApi.GetKeyboardsAsync();if(keyboards.Length>0){varrequest=newConnectKeyboardRequest{Id=keyboards[0].Id};varresult=awaitkeymappApi.ConnectKeyboardAsync(request);}// Set a specific LED to redvarredColor=Color.FromArgb(255,0,0);awaitkeymappApi.SetRGBLedAsync(0,redColor,1000);// LED 0, red, 1 second// Set all LEDs to bluevarblueColor=Color.FromArgb(0,0,255);awaitkeymappApi.SetRGBAllAsync(blueColor,2000);// All LEDs, blue, 2 seconds// Restore original colorsawaitkeymappApi.RestoreKeyboardColorsAsync();// Activate layer 1awaitkeymappApi.SetLayerAsync(1);// Deactivate layer 1awaitkeymappApi.UnsetLayerAsync(1);// Increase brightnessawaitkeymappApi.IncreaseBrightnessAsync();// Decrease brightnessawaitkeymappApi.DecreaseBrightnessAsync();// Bulk brightness update (extension method)awaitkeymappApi.UpdateBrightnessAsync(increase:true,steps:3);ConnectAsync(GrpcChannel channel, CancellationToken ct = default)- Initialize connectionConnectKeyboardAsync(ConnectKeyboardRequest request, CancellationToken ct = default)- Connect specific keyboardConnectAnyKeyboardAsync(CancellationToken ct = default)- Connect any available keyboardDisconnectKeyboardAsync(CancellationToken ct = default)- Disconnect current keyboard
GetStatusAsync(CancellationToken ct = default)- Get Keymapp status and connected keyboard infoGetKeyboardsAsync(CancellationToken ct = default)- List all available keyboards
SetLayerAsync(int layer, CancellationToken ct = default)- Activate a keyboard layerUnsetLayerAsync(int layer, CancellationToken ct = default)- Deactivate a keyboard layer
SetRGBLedAsync(int led, Color color, int sustain = 0, CancellationToken ct = default)- Control individual RGB LEDSetRGBAllAsync(Color color, int sustain = 0, CancellationToken ct = default)- Control all RGB LEDsSetStatusLedAsync(int led, bool on, int sustain = 0, CancellationToken ct = default)- Control status LEDs
IncreaseBrightnessAsync(CancellationToken ct = default)- Increase brightness by one stepDecreaseBrightnessAsync(CancellationToken ct = default)- Decrease brightness by one step
The library includes helpful extension methods in KeymappExtensions:
RestoreKeyboardColorsAsync()- Restore all RGB LEDs to defaultRestoreStatusLedAsync()- Restore status LED to defaultUpdateBrightnessAsync(bool increase, int steps)- Bulk brightness adjustment
All API methods properly handle gRPC exceptions and cancellation tokens. Wrap calls in try-catch blocks to handle network issues:
try{varstatus=awaitkeymappApi.GetStatusAsync();// Handle success}catch(RpcExceptionex){// Handle gRPC communication errorsConsole.WriteLine($"gRPC Error: {ex.Message}");}catch(OperationCanceledException){// Handle cancellationConsole.WriteLine("Operation was cancelled");}- Google.Protobuf
- Grpc.Net.Client
- Microsoft.Extensions.DependencyInjection.Abstractions
- Microsoft.Extensions.Logging.Abstractions
- Microsoft.Extensions.Options.ConfigurationExtensions
This project integrates with ZSA's Keymapp ecosystem. The protobuf definitions are sourced from the official ZSA Kontroll repository.
- Sample - Comprehensive example application demonstrating all API features
- Integration Tests - Test suite for API functionality