Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
98 changes: 92 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,19 @@

The DAQiFi Core Library is a .NET library designed to simplify interaction with DAQiFi devices. It provides a robust and intuitive API for discovering, connecting to, and communicating with DAQiFi hardware, making it an ideal choice for developers building applications that require data acquisition and device control.

## Roadmap Key Features
- **Device Discovery**: Easily find DAQiFi devices connected via USB, serial, or WiFi.
- **Connection Management**: Establish and manage connections with minimal effort.
- **Channel Configuration**: Support for both analog and digital channels, with easy configuration.
- **Data Streaming**: Stream data from devices in real-time.
- **Firmware Updates**: Manage firmware updates seamlessly.
## Features

### ✅ Available Now
- **Device Discovery**: Find DAQiFi devices connected via WiFi, USB/Serial, or HID bootloader mode
- **Transport Layer**: UDP and Serial communication support with async/await patterns
- **Protocol Buffers**: Efficient binary message serialization for device communication
- **Cross-Platform**: Compatible with .NET 8.0 and .NET 9.0

### 🚧 In Development
- **Connection Management**: Establish and manage connections with minimal effort
- **Channel Configuration**: Support for both analog and digital channels
- **Data Streaming**: Stream data from devices in real-time
- **Firmware Updates**: Manage firmware updates seamlessly

## Getting Started

Expand All @@ -17,6 +24,85 @@ The DAQiFi Core Library is a .NET library designed to simplify interaction with
dotnet add package Daqifi.Core
```

### Quick Start: Device Discovery

```csharp
using Daqifi.Core.Device.Discovery;

// Discover WiFi devices on your network
using var wifiFinder = new WiFiDeviceFinder();
wifiFinder.DeviceDiscovered += (sender, e) =>
{
var device = e.DeviceInfo;
Console.WriteLine($"Found: {device.Name} at {device.IPAddress}");
Console.WriteLine($" Serial: {device.SerialNumber}");
Console.WriteLine($" Firmware: {device.FirmwareVersion}");
};

var devices = await wifiFinder.DiscoverAsync(TimeSpan.FromSeconds(5));
Console.WriteLine($"Discovery complete. Found {devices.Count()} device(s)");

// Discover USB/Serial devices
using var serialFinder = new SerialDeviceFinder();
var serialDevices = await serialFinder.DiscoverAsync();

foreach (var device in serialDevices)
{
Console.WriteLine($"Serial Port: {device.PortName}");
}
```

### Advanced Discovery Options

```csharp
// Use cancellation tokens for fine-grained control
using var cts = new CancellationTokenSource();
cts.CancelAfter(TimeSpan.FromSeconds(10));

try
{
var devices = await wifiFinder.DiscoverAsync(cts.Token);
}
catch (OperationCanceledException)
{
Console.WriteLine("Discovery was cancelled");
}

// Discover on custom UDP port (default is 30303)
using var customFinder = new WiFiDeviceFinder(port: 12345);
var customDevices = await customFinder.DiscoverAsync();
```

### Supported Devices

The library automatically detects DAQiFi hardware:
- **Nyquist 1**: DAQiFi's data acquisition device
- **Nyquist 3**: DAQiFi's advanced data acquisition device

Both devices are identified by their part number in the discovery response.

### Connection Types

- **WiFi**: Network-connected devices discovered via UDP broadcast
- **Serial**: USB-connected devices enumerated via serial ports
- **HID**: Devices in bootloader mode (requires platform-specific HID library)

## Real-World Usage

This library powers the [DAQiFi Desktop](https://github.com/daqifi/daqifi-desktop) application and is designed for:
- Custom data acquisition applications
- Automated testing systems
- Industrial monitoring solutions
- Research and development tools
- Any application requiring DAQiFi device integration

## Requirements

- .NET 8.0 or .NET 9.0
- For WiFi discovery: UDP port 30303 must be accessible (firewall configuration may be required)
- For Serial discovery: Appropriate USB drivers for your platform
- Admin privileges may be required for firewall configuration on Windows

## Publishing

This library follows semantic versioning (MAJOR.MINOR.PATCH):
Expand Down
86 changes: 86 additions & 0 deletions src/Daqifi.Core.Tests/Device/Discovery/DeviceInfoTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
using System.Net;
using Daqifi.Core.Device.Discovery;

namespace Daqifi.Core.Tests.Device.Discovery;

public class DeviceInfoTests
{
[Fact]
public void DeviceInfo_WiFiDevice_FormatsToStringCorrectly()
{
// Arrange
var deviceInfo = new DeviceInfo
{
Name = "NYQUIST",
SerialNumber = "12345",
IPAddress = IPAddress.Parse("192.168.1.100"),
Port = 9760,
ConnectionType = ConnectionType.WiFi
};

// Act
var result = deviceInfo.ToString();

// Assert
Assert.Contains("NYQUIST", result);
Assert.Contains("192.168.1.100", result);
Assert.Contains("9760", result);
Assert.Contains("12345", result);
}

[Fact]
public void DeviceInfo_SerialDevice_FormatsToStringCorrectly()
{
// Arrange
var deviceInfo = new DeviceInfo
{
Name = "DAQiFi",
SerialNumber = "67890",
PortName = "COM3",
ConnectionType = ConnectionType.Serial
};

// Act
var result = deviceInfo.ToString();

// Assert
Assert.Contains("DAQiFi", result);
Assert.Contains("COM3", result);
Assert.Contains("67890", result);
}

[Fact]
public void DeviceInfo_HidDevice_FormatsToStringCorrectly()
{
// Arrange
var deviceInfo = new DeviceInfo
{
Name = "DAQiFi Bootloader",
SerialNumber = "11111",
ConnectionType = ConnectionType.Hid
};

// Act
var result = deviceInfo.ToString();

// Assert
Assert.Contains("DAQiFi Bootloader", result);
Assert.Contains("HID", result);
Assert.Contains("11111", result);
}

[Fact]
public void DeviceInfo_DefaultValues_AreSetCorrectly()
{
// Arrange & Act
var deviceInfo = new DeviceInfo();

// Assert
Assert.Equal(string.Empty, deviceInfo.Name);
Assert.Equal(string.Empty, deviceInfo.SerialNumber);
Assert.Equal(string.Empty, deviceInfo.FirmwareVersion);
Assert.Equal(DeviceType.Unknown, deviceInfo.Type);
Assert.Equal(ConnectionType.Unknown, deviceInfo.ConnectionType);
Assert.True(deviceInfo.IsPowerOn); // Default should be true
}
}
80 changes: 80 additions & 0 deletions src/Daqifi.Core.Tests/Device/Discovery/HidDeviceFinderTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Daqifi.Core.Device.Discovery;

namespace Daqifi.Core.Tests.Device.Discovery;

public class HidDeviceFinderTests
{
[Fact]
public async Task DiscoverAsync_WithCancellationToken_ReturnsEmptyList()
{
// Arrange
using var finder = new HidDeviceFinder();
using var cts = new CancellationTokenSource();

// Act
var devices = await finder.DiscoverAsync(cts.Token);

// Assert
Assert.NotNull(devices);
// Currently returns empty as HID library is not yet implemented
Assert.Equal(0, devices.Count());
}

[Fact]
public async Task DiscoverAsync_WithTimeout_CompletesQuickly()
{
// Arrange
using var finder = new HidDeviceFinder();
var timeout = TimeSpan.FromSeconds(1);

// Act
var startTime = DateTime.UtcNow;
var devices = await finder.DiscoverAsync(timeout);
var elapsed = DateTime.UtcNow - startTime;

// Assert
Assert.NotNull(devices);
// Should complete very quickly since HID enumeration is not yet implemented
Assert.True(elapsed.TotalSeconds < timeout.TotalSeconds);
}

[Fact]
public async Task DiscoverAsync_RaisesDiscoveryCompletedEvent()
{
// Arrange
using var finder = new HidDeviceFinder();
var eventRaised = false;
finder.DiscoveryCompleted += (sender, args) => eventRaised = true;

// Act
await finder.DiscoverAsync(TimeSpan.FromMilliseconds(100));

// Assert
Assert.True(eventRaised);
}

[Fact]
public void HidDeviceFinder_Dispose_DoesNotThrow()
{
// Arrange
var finder = new HidDeviceFinder();

// Act & Assert
finder.Dispose();
}

[Fact]
public async Task HidDeviceFinder_AfterDispose_ThrowsObjectDisposedException()
{
// Arrange
var finder = new HidDeviceFinder();
finder.Dispose();

// Act & Assert
await Assert.ThrowsAsync<ObjectDisposedException>(() => finder.DiscoverAsync());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Daqifi.Core.Device.Discovery;

namespace Daqifi.Core.Tests.Device.Discovery;

public class SerialDeviceFinderTests
{
[Fact]
public async Task DiscoverAsync_WithCancellationToken_ReturnsDevices()
{
// Arrange
using var finder = new SerialDeviceFinder();
using var cts = new CancellationTokenSource();

// Act
var devices = await finder.DiscoverAsync(cts.Token);

// Assert
Assert.NotNull(devices);
// May or may not find devices depending on system, but should not throw
}

[Fact]
public async Task DiscoverAsync_WithTimeout_CompletesWithinTimeout()
{
// Arrange
using var finder = new SerialDeviceFinder();
var timeout = TimeSpan.FromSeconds(5);

// Act
var startTime = DateTime.UtcNow;
var devices = await finder.DiscoverAsync(timeout);
var elapsed = DateTime.UtcNow - startTime;

// Assert
Assert.NotNull(devices);
Assert.True(elapsed.TotalSeconds <= timeout.TotalSeconds + 1);
}

[Fact]
public async Task DiscoverAsync_RaisesDiscoveryCompletedEvent()
{
// Arrange
using var finder = new SerialDeviceFinder();
var eventRaised = false;
finder.DiscoveryCompleted += (sender, args) => eventRaised = true;

// Act
await finder.DiscoverAsync(TimeSpan.FromMilliseconds(100));

// Assert
Assert.True(eventRaised);
}

[Fact]
public void SerialDeviceFinder_Dispose_DoesNotThrow()
{
// Arrange
var finder = new SerialDeviceFinder();

// Act & Assert
finder.Dispose();
}

[Fact]
public async Task DiscoverAsync_AfterDispose_ThrowsObjectDisposedException()
{
// Arrange
var finder = new SerialDeviceFinder();
finder.Dispose();

// Act & Assert
await Assert.ThrowsAsync<ObjectDisposedException>(() => finder.DiscoverAsync());
}

[Fact]
public void SerialDeviceFinder_DefaultConstructor_Uses115200Baud()
{
// Arrange & Act
using var finder = new SerialDeviceFinder();

// Assert
Assert.NotNull(finder);
}

[Fact]
public void SerialDeviceFinder_CustomBaudRate_AcceptsCustomBaudRate()
{
// Arrange & Act
using var finder = new SerialDeviceFinder(9600);

// Assert
Assert.NotNull(finder);
}
}
Loading
Loading