Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
8cbe8d1
Fix code analysis warnings
bytedreamer May 28, 2025
43b8b1f
Improve the structure of the connection classes
bytedreamer Jun 9, 2025
3ef9764
Simple PD Console app is added
bytedreamer Jun 10, 2025
fddbfc2
Only show the title of command
bytedreamer Jun 15, 2025
3659b7e
Create a command details dialog box
bytedreamer Jun 15, 2025
a59d174
Add ToString() implementation to all the rest of CommandData classes
bytedreamer Jun 15, 2025
e5cf078
Switch to MVC pattern for PDConsole
bytedreamer Jun 16, 2025
494e7f2
Remove usage of the logger
bytedreamer Jun 16, 2025
1e635cd
Update .gitignore
bytedreamer Jun 17, 2025
768f83b
Update build.yml
bytedreamer Jun 17, 2025
7bdd14d
Update build.yml
bytedreamer Jun 17, 2025
64b6029
Update build.yml
bytedreamer Jun 17, 2025
50c1851
Fix code inspection issue
bytedreamer Jun 17, 2025
0c4875a
Remove local claude settings
bytedreamer Jun 19, 2025
ef4ec85
Remove Ukraine banner
bytedreamer Jun 29, 2025
04e3eb0
Update README.md
bytedreamer Jun 29, 2025
fb865a6
Add some more examples
bytedreamer Jun 29, 2025
6bc1c0e
Refactor secure channel processing
bytedreamer Aug 6, 2025
8c90c96
Refactor Console to ACUConsole and implement MVP pattern
bytedreamer Aug 20, 2025
da3186a
Implement automated versioning system with GitVersion
bytedreamer Aug 20, 2025
41a10e9
Optimize GitVersion execution and relocate config file
bytedreamer Aug 20, 2025
b52bd1d
Restore command dialog boxes removed during MVP refactoring
bytedreamer Aug 20, 2025
f6d014d
Add save confirmation dialog when quitting application
bytedreamer Aug 20, 2025
a38ae29
Implement device discovery cancellation functionality
bytedreamer Aug 20, 2025
3d862a6
Refactor ACUConsole to use proper MVP naming convention
bytedreamer Aug 20, 2025
b2f862f
Implement IACUConsoleView interface and extract SerialConnectionDialog
bytedreamer Aug 21, 2025
6a54fb4
Extract TCP connection and device management dialogs
bytedreamer Aug 21, 2025
c0b4f85
Extract connection settings and reader control dialogs
bytedreamer Aug 21, 2025
e53d995
Reorganize dialog data models to Model/DialogInputs directory
bytedreamer Aug 21, 2025
6bf0a41
Extract remaining complex dialogs to complete MVP refactoring
bytedreamer Aug 21, 2025
f5c3f6f
Fix async void methods in ACUConsoleView to return Task
bytedreamer Aug 21, 2025
0005c4d
Remove unused fields and implement remember last directory for OSDP C…
bytedreamer Aug 21, 2025
6313938
Fix code inspection issues
bytedreamer Aug 21, 2025
5093053
Add test categorization with TestCategory attributes
bytedreamer Aug 21, 2025
1887a4e
Add API tracking system and enhanced documentation
bytedreamer Aug 24, 2025
65aafce
Remove version increments
bytedreamer Aug 25, 2025
b831dff
Use the updated GitTools package
bytedreamer Aug 25, 2025
00fb26d
Update Gitversion tasks names
bytedreamer Aug 25, 2025
e5840b2
Fix pipeline
bytedreamer Aug 25, 2025
86ccccb
Update GitVersion config version format
bytedreamer Aug 25, 2025
c1fb570
Fix GitVersion config
bytedreamer Aug 25, 2025
037b250
Fix GitVersion.yml
bytedreamer Aug 25, 2025
d8366aa
Fix GitVersion.yml
bytedreamer Aug 25, 2025
71896af
Fix GitVersion.yml
bytedreamer Aug 25, 2025
739e597
Fix GitVersion.yml
bytedreamer Aug 25, 2025
6fdd0d6
Fix GitVersion.yml
bytedreamer Aug 25, 2025
96ebd46
Use main instead of master in GitVersion.yml
bytedreamer Aug 25, 2025
350ebd1
Update build.yml
bytedreamer Aug 25, 2025
9ea08c5
Fix build version assignment
bytedreamer Aug 25, 2025
e4f2704
Merge remote-tracking branch 'origin/develop' into develop
bytedreamer Aug 25, 2025
2277b20
Fix GitVersion.yml
bytedreamer Aug 25, 2025
7cc51d9
Properly access the GitVersion variables in the build
bytedreamer Aug 25, 2025
f46c08d
Switch to osx-arm64
bytedreamer Aug 28, 2025
9ae9bb4
Update Directory.Build.props
bytedreamer Aug 28, 2025
320f228
Merge branch 'master' into develop
bytedreamer Aug 28, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,5 @@ _UpgradeReport_Files/
# For those who use p4diff/p4merge, ignore .orig files that
# those tools seem to leave behind
*.orig

.claude
42 changes: 42 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Build Commands
- Build project: `dotnet build`
- Build with specific configuration: `dotnet build --configuration Release`

## Test Commands
- Run all tests: `dotnet test`
- Run a specific test: `dotnet test --filter "FullyQualifiedName=OSDP.Net.Tests.{TestClass}.{TestMethod}"`
- Run tests with specific configuration: `dotnet test --configuration Release`

## Code Style Guidelines
- Follow default ReSharper C# coding style conventions
- Maintain abbreviations in uppercase (ACU, LED, OSDP, PIN, PIV, UID, SCBK)
- Follow async/await patterns for asynchronous operations
- Use dependency injection for testability
- Follow Arrange-Act-Assert pattern in tests
- Implement proper exception handling with descriptive messages
- Avoid blocking event threads
- Use interfaces for abstraction (e.g., IOsdpConnection)
- New commands should follow the existing command/reply model pattern
- Place commands in appropriate namespaces (Model/CommandData or Model/ReplyData)

## Project Structure
- Core library in `/src/OSDP.Net`
- Tests in `/src/OSDP.Net.Tests`
- Console application in `/src/Console`
- Sample applications in `/src/samples`

## OSDP Implementation
- **Command Implementation Status**: See `/docs/supported_commands.md` for current implementation status of OSDP v2.2 commands and replies
- **Device (PD) Implementation**: The `Device` class in `/src/OSDP.Net/Device.cs` provides the base implementation for OSDP Peripheral Devices
- **Command Handlers**: All command handlers are virtual methods in the Device class that can be overridden by specific device implementations
- **Connection Architecture**:
- Use `TcpConnectionListener` + `TcpOsdpConnection` for PDs accepting ACU connections
- Use `TcpServerOsdpConnection` for ACUs accepting device connections
- Use `SerialPortConnectionListener` for serial-based PD implementations

## Domain-Specific Terms
- Maintain consistent terminology for domain-specific terms like APDU, INCITS, OSDP, osdpcap, rmac, Wiegand
31 changes: 31 additions & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<Project>
<PropertyGroup>
<!-- Version properties will be set by GitVersion -->
<VersionPrefix>5.0.5</VersionPrefix>

<!-- Common properties for all projects -->
<Authors>Jonathan Horvath</Authors>
<Company>Z-bit Systems LLC</Company>
<Copyright>Copyright © $(Company) $([System.DateTime]::Now.Year)</Copyright>
<Product>OSDP.Net</Product>
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
<PackageProjectUrl>https://github.com/bytedreamer/OSDP.Net</PackageProjectUrl>
<PackageTags>OSDP;access-control;security;card-reader;biometric;ACU;PD;protocol;serial;tcp;door-access;physical-security</PackageTags>
<PackageReleaseNotes>See https://github.com/bytedreamer/OSDP.Net/releases for release notes.</PackageReleaseNotes>
<RepositoryUrl>https://github.com/bytedreamer/OSDP.Net.git</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<EmbedUntrackedSources>true</EmbedUntrackedSources>

<!-- Enable source link for debugging -->
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>

<!-- CI build settings -->
<ContinuousIntegrationBuild Condition="'$(TF_BUILD)' == 'true'">true</ContinuousIntegrationBuild>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" PrivateAssets="All" />
</ItemGroup>
</Project>
104 changes: 96 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
[![SWUbanner](https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/banner2-direct.svg)](https://github.com/vshymanskyy/StandWithUkraine/blob/main/docs/README.md)

# OSDP.Net

[![Build Status](https://dev.azure.com/jonathanhorvath/OSDP.Net/_apis/build/status/bytedreamer.OSDP.Net?branchName=develop)](https://dev.azure.com/jonathanhorvath/OSDP.Net/_build/latest?definitionId=1&branchName=develop)
[![NuGet](https://img.shields.io/nuget/v/OSDP.Net.svg?style=flat)](https://www.nuget.org/packages/OSDP.Net/)

OSDP.Net is a .NET framework implementation of the Open Supervised Device Protocol (OSDP).
OSDP.Net is a .NET implementation of the Open Supervised Device Protocol (OSDP).
This protocol has been adopted by the Security Industry Association (SIA) to standardize access control hardware communication.
Further information can be found at [SIA OSDP Homepage](https://www.securityindustry.org/industry-standards/open-supervised-device-protocol/).

## Prerequisites

OSDP.Net supports the following .NET implementations:
- .NET Framework 4.6.2 and later
- NET 5.0 and later

## Getting Started

The OSDP.Net library provides a Nuget package to quickly add OSDP capability to a .NET Framework or Core project.
The OSDP.Net library provides a Nuget package to quickly add OSDP capability to a .NET project.
You can install it using the NuGet Package Console window:

```shell
Expand Down Expand Up @@ -40,7 +44,7 @@ Once the connection has started, add Peripheral Devices (PD).
panel.AddDevice(connectionId, address, useCrc, useSecureChannel, secureChannelKey);
```

The following code will install a PD with an unique Secure Channel key. The OSDP standard requires that setting the secure key can only occur while communications are secure.
The following code will install a PD with a unique Secure Channel key. The OSDP standard requires that setting the secure key can only occur while communications are secure.

```c#
panel.AddDevice(connectionId, address, useCrc, useSecureChannel); // connect using default SC key
Expand All @@ -62,10 +66,94 @@ var returnReplyData = await panel.OutputControl(connectionId, address, new Outpu
The reader number parameter found in some commands is used for devices with multiple readers attached. If the device has a single reader, a value of zero should be used.
```c#
byte defaultReaderNumber = 0;
bool success = await ReaderBuzzerControl(connectionId, address,
bool success = await panel.ReaderBuzzerControl(connectionId, address,
new ReaderBuzzerControl(defaultReaderNumber, ToneCode.Default, 2, 2, repeatNumber))
```

## Common Usage Examples

### Reading Card Data
```c#
// Register for card read events
panel.CardRead += async (sender, eventArgs) =>
{
await Task.Run(() =>
{
Console.WriteLine($"Card read from device {eventArgs.Address}");
if (eventArgs.CardData is RawCardData rawData)
{
Console.WriteLine($"Raw card data: {BitConverter.ToString(rawData.Data)}");
}
else if (eventArgs.CardData is FormattedCardData formattedData)
{
Console.WriteLine($"Formatted card data: {formattedData.CardNumber}");
}
});
};
```

### Handling Device Events
```c#
// Monitor device status changes
panel.InputStatusReport += async (sender, eventArgs) =>
{
await Task.Run(() =>
{
Console.WriteLine($"Input status changed on device {eventArgs.Address}");
foreach (var input in eventArgs.InputStatuses)
{
Console.WriteLine($"Input {input.Number}: {(input.Active ? "Active" : "Inactive")}");
}
});
};

// Handle NAK responses
panel.NakReplyReceived += async (sender, eventArgs) =>
{
await Task.Run(() =>
{
Console.WriteLine($"NAK received from device {eventArgs.Address}: {eventArgs.Nak.ErrorCode}");
});
};
```

### Managing Multiple Devices
```c#
// Add multiple devices on the same connection
var devices = new[] { 0, 1, 2, 3 }; // Device addresses
foreach (var address in devices)
{
panel.AddDevice(connectionId, address, useCrc: true, useSecureChannel: true);
}

// Send commands to all devices
foreach (var address in devices)
{
await panel.ReaderLedControl(connectionId, address, new ReaderLedControls(new[]
{
new ReaderLedControl(0, 0, LedColor.Green, LedColor.Black,
30, 30, PermanentControlCode.SetPermanentState)
}));
}
```

### Error Handling
```c#
try
{
var deviceId = await panel.IdReport(connectionId, address);
Console.WriteLine($"Device ID: {deviceId.VendorCode:X}-{deviceId.ModelNumber}-{deviceId.Version}");
}
catch (TimeoutException)
{
Console.WriteLine("Device communication timeout");
}
catch (Exception ex)
{
Console.WriteLine($"Error communicating with device: {ex.Message}");
}
```

## Custom Communication Implementations

OSDP.Net is able to plugin different methods of communications beyond what is included with the default package.
Expand All @@ -79,7 +167,7 @@ It simply requires the installation a new NuGet package. The code needs to be up
## Test Console

There is compiled version of the test console application for all the major platforms available for download.
It has all the required assemblies included to run as a self containsed executable.
It has all the required assemblies included to run as a self-contained executable.
The latest version of the package can be found at [https://www.z-bitco.com/downloads/OSDPTestConsole.zip](https://www.z-bitco.com/downloads/OSDPTestConsole.zip)

NOTE: First determine the COM port identifier of the 485 bus connected to the computer.
Expand All @@ -93,4 +181,4 @@ Be sure to save configuration before exiting.
## Contributing

The current goal is to properly support all the commands and replies outlined the OSDP v2.2 standard.
The document that outlines the specific of the standard can be found on the [SIA website](https://mysia.securityindustry.org/ProductCatalog/Product.aspx?ID=16773). Contact me through my consulting company [Z-bit System, LLC](https://z-bitco.com), if interested in further collaboration with the OSDP.Net library.
The document that outlines the specific of the standard can be found on the [SIA website](https://mysia.securityindustry.org/ProductCatalog/Product.aspx?ID=16773). Contact me through my consulting company [Z-bit System, LLC](https://z-bitco.com) if you're interested in collaborating on the OSDP.Net library.
140 changes: 140 additions & 0 deletions api-baseline.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
# OSDP.Net Public API Baseline
# Generated: 2025-08-24 12:00:00
# Configuration: Release
#
# Format: [TYPE] FullTypeName
#

# Core Classes
[CLASS] OSDP.Net.ControlPanel
[CLASS] OSDP.Net.Device
[CLASS] OSDP.Net.DeviceConfiguration
[CLASS] OSDP.Net.DeviceComSetUpdatedEventArgs
[CLASS] OSDP.Net.Packet

# Interfaces
[INTERFACE] OSDP.Net.Connections.IOsdpConnection
[INTERFACE] OSDP.Net.Connections.IOsdpConnectionListener
[INTERFACE] OSDP.Net.Messages.SecureChannel.IMessageSecureChannel

# Connection Classes
[CLASS] OSDP.Net.Connections.OsdpConnection
[CLASS] OSDP.Net.Connections.OsdpConnectionListener
[CLASS] OSDP.Net.Connections.SerialPortOsdpConnection
[CLASS] OSDP.Net.Connections.SerialPortConnectionListener
[CLASS] OSDP.Net.Connections.TcpClientOsdpConnection
[CLASS] OSDP.Net.Connections.TcpServerOsdpConnection
[CLASS] OSDP.Net.Connections.TcpConnectionListener

# Exception Classes
[CLASS] OSDP.Net.OSDPNetException
[CLASS] OSDP.Net.NackReplyException
[CLASS] OSDP.Net.InvalidPayloadException
[CLASS] OSDP.Net.SecureChannelRequired

# Panel Commands and Discovery
[CLASS] OSDP.Net.PanelCommands.DeviceDiscover.DeviceDiscoveryException
[CLASS] OSDP.Net.PanelCommands.DeviceDiscover.ControlPanelInUseException
[CLASS] OSDP.Net.PanelCommands.DeviceDiscover.DiscoveryOptions
[CLASS] OSDP.Net.PanelCommands.DeviceDiscover.DiscoveryResult

# Event Args Classes
[CLASS] OSDP.Net.Bus.ConnectionStatusEventArgs
[CLASS] OSDP.Net.ControlPanel.NakReplyEventArgs
[CLASS] OSDP.Net.ControlPanel.ConnectionStatusEventArgs
[CLASS] OSDP.Net.ControlPanel.LocalStatusReportReplyEventArgs
[CLASS] OSDP.Net.ControlPanel.InputStatusReportReplyEventArgs
[CLASS] OSDP.Net.ControlPanel.OutputStatusReportReplyEventArgs
[CLASS] OSDP.Net.ControlPanel.ReaderStatusReportReplyEventArgs
[CLASS] OSDP.Net.ControlPanel.RawCardDataReplyEventArgs
[CLASS] OSDP.Net.ControlPanel.FormattedCardDataReplyEventArgs
[CLASS] OSDP.Net.ControlPanel.ManufacturerSpecificReplyEventArgs
[CLASS] OSDP.Net.ControlPanel.KeypadReplyEventArgs
[CLASS] OSDP.Net.ControlPanel.FileTransferStatus
[CLASS] OSDP.Net.ControlPanel.FileTransferException

# Messages and Secure Channel
[CLASS] OSDP.Net.Messages.Message
[CLASS] OSDP.Net.Messages.SecureChannel.MessageSecureChannel
[CLASS] OSDP.Net.Messages.SecureChannel.ACUMessageSecureChannel
[CLASS] OSDP.Net.Messages.SecureChannel.SecurityContext
[CLASS] OSDP.Net.Messages.SecureChannel.SecurityBlock

# Base Model Classes
[CLASS] OSDP.Net.Model.PayloadData
[CLASS] OSDP.Net.Model.CommandData.CommandData

# Command Data Classes
[CLASS] OSDP.Net.Model.CommandData.ACUReceiveSize
[CLASS] OSDP.Net.Model.CommandData.BiometricReadData
[CLASS] OSDP.Net.Model.CommandData.BiometricTemplateData
[CLASS] OSDP.Net.Model.CommandData.CommunicationConfiguration
[CLASS] OSDP.Net.Model.CommandData.EncryptionKeyConfiguration
[CLASS] OSDP.Net.Model.CommandData.GetPIVData
[CLASS] OSDP.Net.Model.CommandData.KeepReaderActive
[CLASS] OSDP.Net.Model.CommandData.ManufacturerSpecific
[CLASS] OSDP.Net.Model.CommandData.OutputControl
[CLASS] OSDP.Net.Model.CommandData.OutputControls
[CLASS] OSDP.Net.Model.CommandData.ReaderBuzzerControl
[CLASS] OSDP.Net.Model.CommandData.ReaderLedControl
[CLASS] OSDP.Net.Model.CommandData.ReaderLedControls
[CLASS] OSDP.Net.Model.CommandData.ReaderTextOutput

# Reply Data Classes
[CLASS] OSDP.Net.Model.ReplyData.Ack
[CLASS] OSDP.Net.Model.ReplyData.BiometricMatchResult
[CLASS] OSDP.Net.Model.ReplyData.BiometricReadResult
[CLASS] OSDP.Net.Model.ReplyData.CommunicationConfiguration
[CLASS] OSDP.Net.Model.ReplyData.DataFragmentResponse
[CLASS] OSDP.Net.Model.ReplyData.DeviceCapabilities
[CLASS] OSDP.Net.Model.ReplyData.DeviceCapability
[CLASS] OSDP.Net.Model.ReplyData.MsgSizeDeviceCap
[CLASS] OSDP.Net.Model.ReplyData.RcvBuffSizeDeviceCap
[CLASS] OSDP.Net.Model.ReplyData.LargestCombMsgSizeDeviceCap
[CLASS] OSDP.Net.Model.ReplyData.CommSecurityDeviceCap
[CLASS] OSDP.Net.Model.ReplyData.DeviceIdentification
[CLASS] OSDP.Net.Model.ReplyData.FileTransferStatus
[CLASS] OSDP.Net.Model.ReplyData.FormattedCardData
[CLASS] OSDP.Net.Model.ReplyData.InputStatus
[CLASS] OSDP.Net.Model.ReplyData.KeypadData
[CLASS] OSDP.Net.Model.ReplyData.LocalStatus
[CLASS] OSDP.Net.Model.ReplyData.ManufacturerSpecific
[CLASS] OSDP.Net.Model.ReplyData.Nak
[CLASS] OSDP.Net.Model.ReplyData.OutputStatus
[CLASS] OSDP.Net.Model.ReplyData.RawCardData
[CLASS] OSDP.Net.Model.ReplyData.ReaderStatus
[CLASS] OSDP.Net.Model.ReplyData.ReturnReplyData

# Utility Classes
[CLASS] OSDP.Net.Utilities.BinaryExtensions
[CLASS] OSDP.Net.Utilities.BinaryUtils
[CLASS] OSDP.Net.Utilities.Pollyfill

# Tracing Classes
[CLASS] OSDP.Net.Tracing.OSDPCapEntry
[CLASS] OSDP.Net.Tracing.PacketDecoding

# Enums
[ENUM] OSDP.Net.Messages.CommandType
[ENUM] OSDP.Net.Messages.ReplyType
[ENUM] OSDP.Net.Messages.MessageType
[ENUM] OSDP.Net.Messages.SecureChannel.SecurityBlockType
[ENUM] OSDP.Net.Model.CommandData.BiometricFormat
[ENUM] OSDP.Net.Model.CommandData.BiometricType
[ENUM] OSDP.Net.Model.CommandData.GetPIVData.ObjectId
[ENUM] OSDP.Net.Model.CommandData.OutputControlCode
[ENUM] OSDP.Net.Model.CommandData.ReaderBuzzerControl.ToneCode
[ENUM] OSDP.Net.Model.CommandData.ReaderLedControl.TemporaryReaderControlCode
[ENUM] OSDP.Net.Model.CommandData.ReaderLedControl.PermanentReaderControlCode
[ENUM] OSDP.Net.Model.CommandData.ReaderLedControl.LedColor
[ENUM] OSDP.Net.Model.CommandData.ReaderTextOutput.TextCommand
[ENUM] OSDP.Net.Model.CommandData.SecureChannelConfiguration.KeyType
[ENUM] OSDP.Net.Model.ReplyData.BiometricStatus
[ENUM] OSDP.Net.Model.ReplyData.CapabilityFunction
[ENUM] OSDP.Net.Model.ReplyData.FileTransferStatus.StatusDetail
[ENUM] OSDP.Net.Model.ReplyData.FormattedCardData.ReadDirection
[ENUM] OSDP.Net.Model.ReplyData.Nak.ErrorCode
[ENUM] OSDP.Net.Model.ReplyData.RawCardData.FormatCode
[ENUM] OSDP.Net.Model.ReplyData.ReaderTamperStatus
[ENUM] OSDP.Net.PanelCommands.DeviceDiscover.DiscoveryStatus
[ENUM] OSDP.Net.Tracing.TraceDirection
Loading