Skip to content

Latest commit

 

History

History
734 lines (589 loc) · 22.3 KB

README.md

File metadata and controls

734 lines (589 loc) · 22.3 KB

Linux platform library for .NET

Library NuGet
LinuxDotNet.Cups NuGet
LinuxDotNet.Disk NuGet
LinuxDotNet.GameInput NuGet
LinuxDotNet.InputEvent NuGet
LinuxDotNet.SystemInfo NuGet
LinuxDotNet.Video4Linux2 NuGet

Video2

🖨️LinuxDotNet.Cups

CUPS API wrapper.

Usage

List printers

foreach (var printer in CupsPrinter.GetPrinters())
{
    Console.Write(printer.Name);
    if (printer.IsDefault)
    {
        Console.Write(" (Default)");
    }
    Console.WriteLine();

    foreach (var (name, value) in printer.Options)
    {
        Console.WriteLine($"  {name}: {value}");
    }
}

Print file

var jobId = CupsPrinter.PrintFile(file, printer);

Print stream

using var image = SampleImage.Create();
var options = new PrintOptions
{
    Printer = printer,
    Copies = 1,
    MediaSize = "A4",
    ColorMode = true,
    Orientation = PrintOrientation.Portrait,
    Quality = PrintQuality.Normal
};

var jobId = CupsPrinter.PrintStream(image, options);

⚡LinuxDotNet.Disk

SMART information.

Usage

Disk information

var disks = DiskInfo.GetInformation();
foreach (var disk in disks)
{
    Console.WriteLine($"Disk #{disk.Index}: {disk.DeviceName}");
    Console.WriteLine($"  Model:          {disk.Model}");
    Console.WriteLine($"  Serial:         {disk.SerialNumber}");
    Console.WriteLine($"  Firmware:       {disk.FirmwareRevision}");
    Console.WriteLine($"  DiskType:       {disk.DiskType}");
    Console.WriteLine($"  SmartType:      {disk.SmartType}");
    Console.WriteLine($"  Size:           {FormatSize(disk.Size)}");
    Console.WriteLine($"  Removable:      {disk.Removable}");

    var partitions = disk.GetPartitions().ToList();
    if (partitions.Count > 0)
    {
        Console.WriteLine("  Partitions:");
        foreach (var partition in partitions)
        {
            var mountInfo = !String.IsNullOrEmpty(partition.MountPoint) ? $" -> {partition.MountPoint} ({partition.FileSystem})" : string.Empty;
            Console.WriteLine($"    {partition.Name}: {FormatSize(partition.Size)}{mountInfo}");
        }
    }

    if (disk.SmartType == SmartType.Nvme)
    {
        PrintNvmeSmart((ISmartNvme)disk.Smart);
    }
    else if (disk.SmartType == SmartType.Generic)
    {
        PrintGenericSmart((ISmartGeneric)disk.Smart);
    }
}

static void PrintNvmeSmart(ISmartNvme smart)
{
    Console.WriteLine($"  SMART (NVMe): Update=[{smart.LastUpdate}] Error=[{smart.LastError}]");
    Console.WriteLine($"    CriticalWarning:          {smart.CriticalWarning}");
    Console.WriteLine($"    Temperature:              {smart.Temperature}C");
    Console.WriteLine($"    AvailableSpare:           {smart.AvailableSpare}%");
    Console.WriteLine($"    PercentageUsed:           {smart.PercentageUsed}%");
    Console.WriteLine($"    DataUnitRead:             {smart.DataUnitRead} ({FormatDataUnits(smart.DataUnitRead)})");
    Console.WriteLine($"    DataUnitWritten:          {smart.DataUnitWritten} ({FormatDataUnits(smart.DataUnitWritten)})");
    Console.WriteLine($"    PowerCycles:              {smart.PowerCycles}");
    Console.WriteLine($"    PowerOnHours:             {smart.PowerOnHours}");
    Console.WriteLine($"    UnsafeShutdowns:          {smart.UnsafeShutdowns}");
    Console.WriteLine($"    MediaErrors:              {smart.MediaErrors}");
}

static void PrintGenericSmart(ISmartGeneric smart)
{
    Console.WriteLine($"  SMART (Generic): Update=[{smart.LastUpdate}] Error=[{smart.LastError}] Assessment=[{smart.Assessment}]");
    Console.WriteLine("    ID   FLAG   CUR  WOR  THR  RAW");
    Console.WriteLine("    ---  ----   ---  ---  ---  --------");

    foreach (var id in smart.GetSupportedIds())
    {
        var attr = smart.GetAttribute(id);
        if (attr.HasValue)
        {
            Console.WriteLine($"    {(byte)id,3}  0x{attr.Value.Flags:X4} {attr.Value.CurrentValue,3}  {attr.Value.WorstValue,3}  {attr.Value.Threshold,3}  {attr.Value.RawValue}");
        }
    }
}

🎮LinuxDotNet.GameInput

/dev/input/js* device reader.

Usage

Use event

using var controller = new GameController();

controller.ConnectionChanged += static connected =>
{
    Console.WriteLine($"Connected: {connected}");
};
controller.ButtonChanged += static (address, value) =>
{
    Console.WriteLine($"Button {address} Changed: {value}");
};
controller.AxisChanged += static (address, value) =>
{
    Console.WriteLine($"Axis {address} Changed: {value}");
};

controller.Start();

Console.ReadLine();

controller.Stop();

Use loop

using var controller = new GameController();

controller.Start();

while (true)
{
    Console.SetCursorPosition(0, 0);
    Console.WriteLine($"Connected: {controller.IsConnected.ToString(),-5}");
    for (var i = (byte)0; i < 8; i++)
    {
        Console.WriteLine($"Button {i}: {controller.GetButtonPressed(i).ToString(),-5}");
    }
    for (var i = (byte)0; i < 8; i++)
    {
        Console.WriteLine($"Axis {i}: {controller.GetAxisValue(i),6}");
    }

    Thread.Sleep(50);
}

⌨️LinuxDotNet.InputEvent

/dev/input/event* device reader.

Usage

List devices

foreach (var device in EventDeviceInfo.GetDevices())
{
    Console.WriteLine($"{device.Device,-18}  {device.VendorId}:{device.ProductId}  {device.Name}");
}

Barcode reader

🖥️LinuxDotNet.SystemInfo

System information api.

Usage

Hardware

var hw = PlatformProvider.GetHardware();

Console.WriteLine("[DMI]");
Console.WriteLine($"Vendor:         {hw.Vendor}");
Console.WriteLine($"ProductName:    {hw.ProductName}");

Console.WriteLine("[CPU]");
Console.WriteLine($"Brand:          {hw.CpuBrandString}");
Console.WriteLine($"Vendor:         {hw.CpuVendor}");
Console.WriteLine($"Family:         {hw.CpuFamily}");
Console.WriteLine($"Model:          {hw.CpuModel}");
Console.WriteLine($"Stepping:       {hw.CpuStepping}");
Console.WriteLine($"Logical:        {hw.LogicalCpu}");
Console.WriteLine($"Physical:       {hw.PhysicalCpu}");
Console.WriteLine($"CoresPerSocket: {hw.CoresPerSocket}");
Console.WriteLine($"FrequencyMax:   {hw.CpuFrequencyMax / 1_000_000.0:F0} MHz");

Console.WriteLine("[Cache]");
Console.WriteLine($"L1D:            {hw.L1DCacheSize / 1024} KB");
Console.WriteLine($"L1I:            {hw.L1ICacheSize / 1024} KB");
Console.WriteLine($"L2:             {hw.L2CacheSize / 1024} KB");
Console.WriteLine($"L3:             {hw.L3CacheSize / 1024} KB");

Console.WriteLine("[Memory]");
Console.WriteLine($"MemoryTotal:    {hw.MemoryTotal / 1024 / 1024} MB");

Kernel

var kernel = PlatformProvider.GetKernel();
Console.WriteLine($"OsType:                 {kernel.OsType}");
Console.WriteLine($"OsRelease:              {kernel.OsRelease}");
Console.WriteLine($"KernelVersion:          {kernel.KernelVersion}");
Console.WriteLine($"OsProductVersion:       {kernel.OsProductVersion}");
Console.WriteLine($"OsName:                 {kernel.OsName}");
Console.WriteLine($"OsPrettyName:           {kernel.OsPrettyName}");
Console.WriteLine($"OsId:                   {kernel.OsId}");
Console.WriteLine($"BootTime:               {kernel.BootTime}");
Console.WriteLine($"MaxProcesses:           {kernel.MaxProcesses}");
Console.WriteLine($"MaxFiles:               {kernel.MaxFiles}");
Console.WriteLine($"MaxFilesPerProcess:     {kernel.MaxFilesPerProcess}");

Uptime

using var uptime = PlatformProvider.GetUptime();
Console.WriteLine($"Uptime: {uptime.Elapsed}");

Stat

using var stat = PlatformProvider.GetSystemStat();
Console.WriteLine($"Interrupt:      {stat.Interrupt}");
Console.WriteLine($"ContextSwitch:  {stat.ContextSwitch}");
Console.WriteLine($"SoftIrq:        {stat.SoftIrq}");
Console.WriteLine($"RunnableTasks:  {stat.RunnableTasks}");
Console.WriteLine($"BlockedTasks:   {stat.BlockedTasks}");

Console.WriteLine($"User:           {stat.CpuTotal.User}");
Console.WriteLine($"Nice:           {stat.CpuTotal.Nice}");
Console.WriteLine($"System:         {stat.CpuTotal.System}");
Console.WriteLine($"Idle:           {stat.CpuTotal.Idle}");
Console.WriteLine($"IoWait:         {stat.CpuTotal.IoWait}");
Console.WriteLine($"Irq:            {stat.CpuTotal.Irq}");
Console.WriteLine($"SoftIrq:        {stat.CpuTotal.SoftIrq}");
Console.WriteLine($"Steal:          {stat.CpuTotal.Steal}");
Console.WriteLine($"Guest:          {stat.CpuTotal.Guest}");
Console.WriteLine($"GuestNice:      {stat.CpuTotal.GuestNice}");

LoadAverage

using var load = PlatformProvider.GetLoadAverage();
Console.WriteLine($"Average1:  {load.Average1:F2}");
Console.WriteLine($"Average5:  {load.Average5:F2}");
Console.WriteLine($"Average15: {load.Average15:F2}");

Memory

using var memory = PlatformProvider.GetMemoryStat();
Console.WriteLine($"MemoryTotal:     {memory.MemoryTotal}");
Console.WriteLine($"MemoryAvailable: {memory.MemoryAvailable}");
Console.WriteLine($"Buffers:         {memory.Buffers}");
Console.WriteLine($"Cached:          {memory.Cached}");

VirtualMemory

using var vm = PlatformProvider.GetVirtualMemoryStat();
Console.WriteLine($"PageIn:            {vm.PageIn}");
Console.WriteLine($"PageOut:           {vm.PageOut}");
Console.WriteLine($"SwapIn:            {vm.SwapIn}");
Console.WriteLine($"SwapOut:           {vm.SwapOut}");
Console.WriteLine($"PageFaults:        {vm.PageFaults}");
Console.WriteLine($"MajorPageFaults:   {vm.MajorPageFaults}");
Console.WriteLine($"OutOfMemoryKiller: {vm.OutOfMemoryKiller}");

Partition

var partitions = PlatformProvider.GetPartitions();
foreach (var partition in partitions)
{
    Console.WriteLine($"Name:          {partition.Name}");
    Console.WriteLine($"DeviceClass:   {partition.DeviceClass} ({(int)partition.DeviceClass})");
    Console.WriteLine($"No:            {partition.No}");
    Console.WriteLine($"Blocks:        {partition.Blocks}");

    var mounts = partition.GetMounts();
    if (mounts.Count > 0)
    {
        Console.WriteLine($"MountPoint:    {String.Join(' ', mounts.Select(m => m.MountPoint))}");
    }
}

Mount

var mounts = PlatformProvider.GetMounts();
foreach (var mount in mounts)
{
    Console.WriteLine($"Device:        {mount.DeviceName}");
    Console.WriteLine($"MountPoint:    {mount.MountPoint}");
    Console.WriteLine($"FileSystem:    {mount.FileSystem}");
    Console.WriteLine($"Options:       {mount.Option}");
    Console.WriteLine($"IsLocal:       {mount.IsLocal}");

    using var usage = PlatformProvider.GetFileSystemUsage(mount.MountPoint);
    Console.WriteLine($"TotalSize:     {usage.TotalSize}");
    Console.WriteLine($"FreeSize:      {usage.FreeSize}");
    Console.WriteLine($"AvailableSize: {usage.AvailableSize}");
    Console.WriteLine($"TotalFiles:    {usage.TotalFiles}");
    Console.WriteLine($"FreeFiles:     {usage.FreeFiles}");
}

DiskStat

using var disk = PlatformProvider.GetDiskStat();
foreach (var device in disk.Devices)
{
    Console.WriteLine($"Name:           {device.Name}");
    Console.WriteLine($"ReadCompleted:  {device.ReadCompleted}");
    Console.WriteLine($"ReadMerged:     {device.ReadMerged}");
    Console.WriteLine($"ReadSectors:    {device.ReadSectors}");
    Console.WriteLine($"ReadTime:       {device.ReadTime}");
    Console.WriteLine($"WriteCompleted: {device.WriteCompleted}");
    Console.WriteLine($"WriteMerged:    {device.WriteMerged}");
    Console.WriteLine($"WriteSectors:   {device.WriteSectors}");
    Console.WriteLine($"WriteTime:      {device.WriteTime}");
    Console.WriteLine($"IosInProgress:  {device.IosInProgress}");
    Console.WriteLine($"IoTime:         {device.IoTime}");
    Console.WriteLine($"WeightIoTime:   {device.WeightIoTime}");
}

NetworkStat

using var network = PlatformProvider.GetNetworkStat();
foreach (var nif in network.Interfaces)
{
    Console.WriteLine($"Interface:    {nif.Interface}");
    Console.WriteLine($"RxBytes:      {nif.RxBytes}");
    Console.WriteLine($"RxPackets:    {nif.RxPackets}");
    Console.WriteLine($"RxErrors:     {nif.RxErrors}");
    Console.WriteLine($"RxDropped:    {nif.RxDropped}");
    Console.WriteLine($"RxFifo:       {nif.RxFifo}");
    Console.WriteLine($"RxFrame:      {nif.RxFrame}");
    Console.WriteLine($"RxCompressed: {nif.RxCompressed}");
    Console.WriteLine($"RxMulticast:  {nif.RxMulticast}");
    Console.WriteLine($"TxBytes:      {nif.TxBytes}");
    Console.WriteLine($"TxPackets:    {nif.TxPackets}");
    Console.WriteLine($"TxErrors:     {nif.TxErrors}");
    Console.WriteLine($"TxDropped:    {nif.TxDropped}");
    Console.WriteLine($"TxFifo:       {nif.TxFifo}");
    Console.WriteLine($"TxCollisions: {nif.TxCollisions}");
    Console.WriteLine($"TxCarrier:    {nif.TxCarrier}");
    Console.WriteLine($"TxCompressed: {nif.TxCompressed}");
}

Tcp/Tcp6

using var tcp = PlatformProvider.GetTcpStat();
using var tcp6 = PlatformProvider.GetTcp6Stat();
Console.WriteLine($"Established: {tcp.Established}");
Console.WriteLine($"SynSent:     {tcp.SynSent}");
Console.WriteLine($"SynRecv:     {tcp.SynRecv}");
Console.WriteLine($"FinWait1:    {tcp.FinWait1}");
Console.WriteLine($"FinWait2:    {tcp.FinWait2}");
Console.WriteLine($"TimeWait:    {tcp.TimeWait}");
Console.WriteLine($"Close:       {tcp.Close}");
Console.WriteLine($"CloseWait:   {tcp.CloseWait}");
Console.WriteLine($"LastAck:     {tcp.LastAck}");
Console.WriteLine($"Listen:      {tcp.Listen}");
Console.WriteLine($"Closing:     {tcp.Closing}");
Console.WriteLine($"Total:       {tcp.Total}");

ProcessSummary

using var process = PlatformProvider.GetProcessSummary();
Console.WriteLine($"ProcessCount: {process.ProcessCount}");
Console.WriteLine($"ThreadCount:  {process.ThreadCount}");

Processes

var processes = PlatformProvider.GetProcesses();

Console.WriteLine($"{"PID",-6} {"Name",-20} {"State",-12} {"User",-5} {"Threads",7} {"RSS (MB)",10} {"CPU Time",10}");
Console.WriteLine(new string('-', 76));

foreach (var p in processes)
{
    var rss = (double)p.ResidentMemorySize / 1024 / 1024;
    var cpuTime = (p.UserTime + p.SystemTime).TotalSeconds;

    Console.WriteLine($"{p.ProcessId,-6} {TruncateName(p.Name, 20),-20} {p.State,-12} {p.UserId,-5} {p.ThreadCount,7} {rss,10:F2} {cpuTime,10:F2}");
}

static string TruncateName(string name, int maxLength) => name.Length <= maxLength ? name : name[..(maxLength - 3)] + "...";

FileDescriptor

using var fd = PlatformProvider.GetFileHandleStat();

Console.WriteLine($"Allocated: {fd.Allocated}");
Console.WriteLine($"Used:      {fd.Used}");
Console.WriteLine($"Max:       {fd.Max}");

Cpu

using var cpu = PlatformProvider.GetCpuDevice();

Console.WriteLine("Frequency");
foreach (var core in cpu.Cores)
{
    Console.WriteLine($"{core.Name}: {core.Frequency}");
}

if (cpu.Powers.Count > 0)
{
    Console.WriteLine("Power");
    foreach (var power in cpu.Powers)
    {
        Console.WriteLine($"{power.Name}: {power.Energy / 1000.0}");
    }
}

Mains

using var adapter = PlatformProvider.GetMainsDevice();
if (adapter.Supported)
{
    Console.WriteLine($"Online: {adapter.Online}");
}
else
{
    Console.WriteLine("No adapter found");
}

Battery

using var battery = PlatformProvider.GetBatteryDevice();
if (battery.Supported)
{
    Console.WriteLine($"Capacity:   {battery.Capacity}");
    Console.WriteLine($"Status:     {battery.Status}");
    Console.WriteLine($"Voltage:    {battery.Voltage / 1000.0:F2}");
    Console.WriteLine($"Current:    {battery.Current / 1000.0:F2}");
    Console.WriteLine($"Charge:     {battery.Charge / 1000.0:F2}");
    Console.WriteLine($"ChargeFull: {battery.ChargeFull / 1000.0:F2}");
}
else
{
    Console.WriteLine("No battery found");
}

HardwareMonitor

var monitors = PlatformProvider.GetHardwareMonitors();
foreach (var monitor in monitors)
{
    Console.WriteLine($"Monitor: {monitor.Type}");
    Console.WriteLine($"Name:    {monitor.Name}");
    foreach (var sensor in monitor.Sensors)
    {
        Console.WriteLine($"Sensor:  {sensor.Type}");
        Console.WriteLine($"Label:   {sensor.Label}");
        Console.WriteLine($"Value:   {sensor.Value}");
    }
}

// Each monitor must be disposed
foreach (var monitor in monitors)
{
    monitor.Dispose();
}

USB

foreach (var device in PlatformProvider.GetUsbDevices())
{
    Console.WriteLine($"{device.Name} {device.VendorId:x4}:{device.ProductId:x4} {device.Manufacturer} {device.Product}");
    Console.WriteLine($"  Class: {device.DeviceClass}, Speed: {device.Speed} Mbps, Path: {device.DevicePath}, Parent: {device.ParentName}");
    foreach (var usbInterface in device.Interfaces)
    {
        Console.WriteLine($"  #{usbInterface.Number} {usbInterface.InterfaceClass} {usbInterface.Driver} {String.Join(' ', usbInterface.DeviceFiles)}");
    }
}

DeviceFiles lists the device nodes created for each interface (/dev/videoN, /dev/input/eventN, /dev/input/jsN, /dev/hidrawN, /dev/ttyUSBN, /dev/ttyACMN, /dev/usb/lpN, block devices) and the names of network interfaces and sound cards.

Link

🎞️LinuxDotNet.Video4Linux2

Video for Linux API wrapper.

Usage

Video device information

foreach (var device in VideoInfo.GetAllVideo())
{
    Console.WriteLine($"Device: {device.Device}");
    Console.WriteLine($"Available: {device.IsAvailable}");
    Console.WriteLine($"Name: {device.Name}");
    Console.WriteLine($"Driver: {device.Driver}");
    Console.WriteLine($"Bus: {device.BusInfo}");
    Console.WriteLine($"USB: {device.UsbPort} {device.UsbVendorId:x4}:{device.UsbProductId:x4}");
    Console.WriteLine($"ById: {device.ById}");
    Console.WriteLine($"ByPath: {device.ByPath}");

    Console.WriteLine($"Capabilities: 0x{device.RawCapabilities:X8}");
    Console.WriteLine($"  Capture: {device.IsVideoCapture}");
    Console.WriteLine($"  Output: {device.IsVideoOutput}");
    Console.WriteLine($"  Metadata: {device.IsMetadata}");
    Console.WriteLine($"  Streaming: {device.IsStreaming}");

    Console.WriteLine($"Formats: {device.SupportedFormats.Count}");
    foreach (var format in device.SupportedFormats)
    {
        Console.WriteLine($"  Format: {format.PixelFormat}");
        Console.WriteLine($"    Description: {format.Description}");
        foreach (var resolution in format.SupportedResolutions)
        {
            Console.WriteLine($"    {resolution}: {String.Join(", ", format.GetFrameIntervals(resolution))} fps");
        }
    }

    Console.WriteLine($"Controls: {device.Controls.Count}");
    foreach (var control in device.Controls)
    {
        Console.WriteLine($"  {control.Name}: {control.Value} ({control.Minimum}..{control.Maximum})");
    }
}

Snapshot

using var capture = new VideoCapture(device);

var ret = capture.Open(width, height);
if (!ret)
{
    return;
}

width = capture.Width;
height = capture.Height;

// Snapshot
using var writer = new PooledBufferWriter<byte>(width * height * 2);
if (!capture.Snapshot(writer))
{
    Console.WriteLine("Snapshot failed.");
    return;
}

// Convert to RGBA
var buffer = new byte[width * height * 4];
ImageHelper.ConvertYUYV2RGBA(writer.WrittenSpan, buffer);

// Save
var info = new SKImageInfo(width, height, SKColorType.Rgba8888, SKAlphaType.Opaque);
using var image = SKImage.FromPixelCopy(info, buffer, width * 4);
using var data = image.Encode(SKEncodedImageFormat.Jpeg, 90);
using var stream = File.OpenWrite(output);
data.SaveTo(stream);

Capture

using var capture = new VideoCapture(device);

var ret = capture.Open(width, height);
if (!ret)
{
    return;
}

capture.FrameCaptured += frame =>
{
    // Use frame data
};

capture.StartCapture();

Capture MJPEG

using var capture = new VideoCapture(device);

if (!capture.Open(1920, 1080, PixelFormat.MJPG))
{
    return;
}

capture.FrameCaptured += frame =>
{
    // frame.Span is a JPEG image
};

capture.StartCapture();

Some UVC cameras send MJPEG frames without the Huffman table (DHT).
Use a decoder that supplies the standard table for such frames.

Frame information

Console.WriteLine($"Format: {capture.PixelFormat} Stride: {capture.BytesPerLine} Size: {capture.ImageSize} FrameRate: {capture.FrameRate}");

capture.FrameCaptured += frame =>
{
    // Sequence number, monotonic clock timestamp and error flag of the frame
    Console.WriteLine($"{frame.Sequence} {frame.Timestamp} {frame.IsError} {frame.Length}");
};

Frame rate

if (capture.SetFrameRate(15))
{
    Console.WriteLine($"FrameRate: {capture.FrameRate}");
}

capture.StartCapture();

FrameRate holds the rate the driver accepted, which can differ from the requested one.
FrameCaptured receives every frame the device sends; skip frames in the handler to process at a lower rate.

Controls

foreach (var control in capture.GetControls())
{
    Console.WriteLine($"{control.Name}: {control.Value} ({control.Minimum}..{control.Maximum}, default {control.DefaultValue})");
    foreach (var item in control.MenuItems)
    {
        Console.WriteLine($"  {item.Index}: {item}");
    }
}

capture.SetControl(VideoControlId.Brightness, 100);
var brightness = capture.GetControl(VideoControlId.Brightness);

Image

Video

🌐Link