215 lines
15 KiB
Markdown
215 lines
15 KiB
Markdown
|
|
---
|
||
|
|
source_files:
|
||
|
|
- Common/DTS.CommonCore/Utils/XMLUtils.cs
|
||
|
|
- Common/DTS.CommonCore/Utils/EnumUtils.cs
|
||
|
|
- Common/DTS.CommonCore/Utils/ImageButton.cs
|
||
|
|
- Common/DTS.CommonCore/Utils/PNGImageUtil.cs
|
||
|
|
- Common/DTS.CommonCore/Utils/MouseUtils.cs
|
||
|
|
- Common/DTS.CommonCore/Utils/StopWatch.cs
|
||
|
|
- Common/DTS.CommonCore/Utils/SerializableDictionary.cs
|
||
|
|
- Common/DTS.CommonCore/Utils/TestUtils.cs
|
||
|
|
- Common/DTS.CommonCore/Utils/SecureQueue.cs
|
||
|
|
- Common/DTS.CommonCore/Utils/ByteConverter.cs
|
||
|
|
- Common/DTS.CommonCore/Utils/NetworkUtils.cs
|
||
|
|
- Common/DTS.CommonCore/Utils/BusyWaitAnimation.cs
|
||
|
|
generated_at: "2026-04-16T02:13:53.536236+00:00"
|
||
|
|
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||
|
|
schema_version: 1
|
||
|
|
sha256: "0a10ccd507cef203"
|
||
|
|
---
|
||
|
|
|
||
|
|
# DTS.Common.Utils Module Documentation
|
||
|
|
|
||
|
|
## 1. Purpose
|
||
|
|
|
||
|
|
This module provides a collection of utility classes and static helper methods for common operations across the DTS (Data Acquisition and Test System) codebase. It serves as a foundational layer supporting UI components (`ImageButton`, `BusyWaitAnimation`), data serialization (`SerializableDictionary`), low-level binary operations (`ByteConvertor`), network diagnostics (`NetworkUtils`), timing and profiling (`StopWatchQueue`), enumeration handling (`EnumUtil`), image rendering (`PNGImageUtil`), mouse coordinate translation (`MouseUtilities`), and test-specific utilities (`TestUtils`). The module consolidates cross-cutting concerns to avoid duplication and promote consistency across the system.
|
||
|
|
|
||
|
|
## 2. Public Interface
|
||
|
|
|
||
|
|
### `EnumUtil` (static class)
|
||
|
|
- **`GetValues<T>()`**
|
||
|
|
Returns an `IEnumerable<T>` of all enum values of type `T` using `Enum.GetValues`.
|
||
|
|
- **`GetValuesList<T>()`**
|
||
|
|
Returns an `ItemCollection` (from `Xceed.Wpf.Toolkit.PropertyGrid.Attributes`) containing key-value pairs of enum values and their names.
|
||
|
|
|
||
|
|
### `ImageButton` (class, inherits `Button`)
|
||
|
|
- **Constructor `ImageButton()`**
|
||
|
|
Initializes a `StackPanel`-based button with an `Image` and `TextBlock` arranged vertically.
|
||
|
|
- **`Source` (property, `ImageSource`)**
|
||
|
|
Gets/sets the image displayed in the button.
|
||
|
|
- **`ImageText` (property, `string`)**
|
||
|
|
Gets/sets the text displayed below the image.
|
||
|
|
|
||
|
|
### `PNGImageUtil` (static class)
|
||
|
|
- **`SaveImage(FrameworkElement view, string fileName)`**
|
||
|
|
Renders the given WPF `FrameworkElement` to a PNG file at `fileName` using `RenderTargetBitmap` and `PngBitmapEncoder`.
|
||
|
|
|
||
|
|
### `MouseUtilities` (class)
|
||
|
|
- **`GetMousePosition(Visual relativeTo)`**
|
||
|
|
Returns the current mouse cursor position as a `Point`, transformed to be relative to the specified `Visual`. Uses Win32 API (`GetCursorPos`, `ScreenToClient`) and WPF transform logic. Includes scaling correction based on `CompositionTarget.TransformToDevice`.
|
||
|
|
|
||
|
|
### `StopWatchQueue` (class)
|
||
|
|
- **Constructor `StopWatchQueue(string name)`**
|
||
|
|
Initializes a queue with a name and internal `Stopwatch` and `Queue<long>` (capacity 5000).
|
||
|
|
- **`Start()`**
|
||
|
|
Starts the internal `Stopwatch`.
|
||
|
|
- **`Stop()`**
|
||
|
|
Stops the `Stopwatch`, enqueues the elapsed ticks, and resets the `Stopwatch`.
|
||
|
|
- **`DumpData()`**
|
||
|
|
Writes timing statistics (count, max, min, average, standard deviation) and all recorded values (in milliseconds) to a timestamped CSV file named `<name><filetime>.csv`.
|
||
|
|
- **Finalizer `~StopWatchQueue()`**
|
||
|
|
Calls `DumpData()` on disposal (via finalization).
|
||
|
|
|
||
|
|
### `SerializableDictionary<TKey, TValue>` (class, implements `IXmlSerializable`)
|
||
|
|
- **Constructor**
|
||
|
|
Inherits from `Dictionary<TKey, TValue>` and implements `IXmlSerializable`.
|
||
|
|
- **`GetSchema()`**
|
||
|
|
Returns `null`.
|
||
|
|
- **`ReadXml(XmlReader reader)`**
|
||
|
|
Deserializes a dictionary from XML with `<items><item><key>...</key><value>...</value></item>...</items>` structure.
|
||
|
|
- **`WriteXml(XmlWriter writer)`**
|
||
|
|
Serializes the dictionary to the same XML structure.
|
||
|
|
|
||
|
|
### `TestModuleTimeStamp` (class)
|
||
|
|
- **`TriggerTimestampSec` (int)**
|
||
|
|
Seconds component of a timestamp.
|
||
|
|
- **`TriggerTimestampNanoSec` (int)**
|
||
|
|
Nanoseconds component of a timestamp.
|
||
|
|
|
||
|
|
### `TestUtils` (static class)
|
||
|
|
- **`MinUnixTime(IEnumerable<TestModuleTimeStamp> basemodules)`**
|
||
|
|
Returns a `Tuple<double, double>` of `(TriggerTimestampSec, TriggerTimestampNanoSec)` for the earliest timestamp that satisfies:
|
||
|
|
`moduleTime > utcAverage - utcStandardDeviation`,
|
||
|
|
where `moduleTime = sec + nano / NANOS_PER_SECOND`.
|
||
|
|
If no modules or invalid input, returns `null`.
|
||
|
|
*Note: Logic appears to select the earliest timestamp within one standard deviation below the mean.*
|
||
|
|
- **`ParseROISuffix(string test)`**
|
||
|
|
Extracts ROI suffix from a colon-separated test string. Tries two strategies:
|
||
|
|
1. If ≥4 segments, returns last segment.
|
||
|
|
2. If contains `EventNumber`, returns suffix after last underscore in that segment (prefixed with `_`).
|
||
|
|
Returns `string.Empty` if no match.
|
||
|
|
|
||
|
|
### `SecureQueue<T>` (class, implements `IDisposable`)
|
||
|
|
- **`NullPolicy` enum**
|
||
|
|
`DenyNull`, `SkipNull`, `AllowNull` — behavior when `Enqueue` receives null or zero-length array.
|
||
|
|
- **Constructor `SecureQueue(NullPolicy policy, string name)`**
|
||
|
|
Initializes queue with policy, name, and internal locking/event mechanisms.
|
||
|
|
- **`ResetEvent()`**
|
||
|
|
Resets the internal `ManualResetEvent`.
|
||
|
|
- **`Enqueue(T[] newData)`**
|
||
|
|
Thread-safe enqueue with null-checking per policy. Logs via `APILogger` if `ExtraCommunicationLogging` is enabled.
|
||
|
|
- **`WaitForData(int timeoutMillisec)`**
|
||
|
|
Blocks up to `timeoutMillisec` for data; returns `true` if data arrived, `false` on timeout.
|
||
|
|
- **`QueueWaitHandle` (property)**
|
||
|
|
Exposes the internal `ManualResetEvent` as a `WaitHandle`.
|
||
|
|
- **`Dequeue(bool resetEvent)`**
|
||
|
|
Thread-safe dequeue: concatenates all queued arrays into one large array. Resets internal event. Returns empty array if queue empty.
|
||
|
|
- **`Flush()`**
|
||
|
|
Clears the queue and resets the event.
|
||
|
|
- **`IsEmpty()`**
|
||
|
|
Returns `true` if queue count is zero.
|
||
|
|
- **`Dispose()`**
|
||
|
|
No-op (empty implementation).
|
||
|
|
|
||
|
|
### `ByteConvertor` (class)
|
||
|
|
- **`Convert(byte[] input, int offset, out T value)`**
|
||
|
|
Reads from `input` at `offset` and deserializes to `T` (supports `byte`, `ushort`, `short`, `uint`, `int`, `ulong`, `long`, `float`, `double`, `string`).
|
||
|
|
*Note:* Integer types are read in **big-endian (network) order** (e.g., `ushort` uses `input[offset+0] << 8 | input[offset+1]`).
|
||
|
|
`float`/`double` use `BitConverter` (host-endian).
|
||
|
|
`string` reads until null terminator.
|
||
|
|
- **`ToByteArray(T value)`**
|
||
|
|
Serializes `T` to a byte array in **big-endian (network) order** (e.g., `ToByteArray(ushort)` writes high byte first).
|
||
|
|
`float`/`double` use `BitConverter.GetBytes` (host-endian).
|
||
|
|
`string` writes characters + null terminator.
|
||
|
|
|
||
|
|
### `NetworkUtils` (static class)
|
||
|
|
- **`IsNetworkInterfaceUp(IPAddress ip)`**
|
||
|
|
Returns `true` if the given IP is assigned to an active, non-loopback, IPv4-enabled, multicast-capable network interface. Skips 169.254.x.x (link-local) addresses.
|
||
|
|
- **`GetAvailableNetworkInterfaces(long minimumSpeed = 10000000)`**
|
||
|
|
Returns list of `NetworkInterface`s that are non-loopback, non-virtual, non-Bluetooth, non-modem, and meet minimum speed. Excludes Npcap interfaces.
|
||
|
|
- **`GetAvailableHosts(bool supportMulticastOnly = false)`**
|
||
|
|
Returns `List<HostInfo>` (custom type, not shown) with IP, network ID, MAC, and start/end addresses for each valid unicast IPv4 interface. Skips 169.254.x.x and Npcap interfaces.
|
||
|
|
- **`GetStartAndEndAddress(IPAddress ip, IPAddress mask, out string startAddress, out string endAddress)`**
|
||
|
|
Computes network start (AND of IP and mask) and broadcast end (OR of IP and inverted mask) addresses. Returns empty strings on error.
|
||
|
|
- **`TryParseConnectionString(string connectionString, out string ipAddress)`**
|
||
|
|
Attempts to extract an IP address from a connection string (supports URI or colon-separated format). Returns `true` if successful and IP is valid.
|
||
|
|
|
||
|
|
### `BusyWaitAnimation` (class)
|
||
|
|
- **`StylePresets` enum**
|
||
|
|
`MacOsx`, `Firefox`, `Ie7`, `Custom`.
|
||
|
|
- **Properties**
|
||
|
|
`Color`, `BgColor`, `OuterCircleRadius`, `InnerCircleRadius`, `NumberSpoke`, `Active`, `SpokeThickness`, `RotationSpeed`, `StylePreset`.
|
||
|
|
- **Constructor `BusyWaitAnimation()`**
|
||
|
|
Initializes timer, appearance, and drawing resources.
|
||
|
|
- **`SetCircleAppearance(int numberSpoke, int spokeThickness, int innerCircleRadius, int outerCircleRadius)`**
|
||
|
|
Updates appearance parameters and invalidates.
|
||
|
|
- **`GDIGraphics` (property)**
|
||
|
|
Exposes internal `Graphics` object.
|
||
|
|
- **`hDC` (property)**
|
||
|
|
Gets/sets the device context handle and initializes `Graphics`.
|
||
|
|
- **`SetDrawArea(Rectangle rect)`**
|
||
|
|
Sets drawing bounds and initializes backing bitmap and graphics.
|
||
|
|
|
||
|
|
## 3. Invariants
|
||
|
|
|
||
|
|
- **`ByteConvertor.Convert` for integers**: Always interprets multi-byte values in **big-endian (network byte order)**, regardless of host architecture.
|
||
|
|
- **`ByteConvertor.ToByteArray` for integers**: Always outputs in **big-endian (network byte order)**.
|
||
|
|
- **`PNGImageUtil.SaveImage`**: Requires `view.ActualWidth` and `view.ActualHeight` to be positive and non-zero; otherwise, `RenderTargetBitmap` may fail or produce invalid output.
|
||
|
|
- **`StopWatchQueue`**: Records elapsed ticks in `Stop()`; values are converted to milliseconds using `Stopwatch.Frequency` during `DumpData()`.
|
||
|
|
- **`SecureQueue<T>`**:
|
||
|
|
- `Dequeue()` concatenates *all* queued arrays into a single array — not a FIFO of arrays.
|
||
|
|
- `Dequeue()` always resets the internal `ManualResetEvent`, even if the queue was empty.
|
||
|
|
- Thread-safety is ensured via `lock(ByteQueueLock)`.
|
||
|
|
- **`TestUtils.MinUnixTime`**:
|
||
|
|
- Uses `Common.Constants.NANOS_PER_SECOND` and `Common.Constants.TEN_MILLIS_IN_SEC` (not defined in this module).
|
||
|
|
- Selects the *first* module satisfying the condition in iteration order, not necessarily the globally earliest valid timestamp.
|
||
|
|
- **`TestUtils.ParseROISuffix`**:
|
||
|
|
- Relies on `DTS.Common.Constants.EventNumber` (not defined here).
|
||
|
|
- Returns `_` + last segment only if the last segment *does not* contain the event number string.
|
||
|
|
- **`NetworkUtils.IsNetworkInterfaceUp`**: Skips interfaces with no IPv4 properties or link-local (169.254.x.x) addresses.
|
||
|
|
|
||
|
|
## 4. Dependencies
|
||
|
|
|
||
|
|
### Internal Dependencies (from source)
|
||
|
|
- **`DTS.Common.Interface`** (via `TestUtils.cs`)
|
||
|
|
- **`DTS.Common.Utilities.Logging`** (via `SecureQueue.cs`, `NetworkUtils.cs`)
|
||
|
|
- **`DTS.DASLib.Utility`** (namespace for `SerializableDictionary` in `SerializableDictionary.cs`)
|
||
|
|
- **`DTS.Common.Constants`** (referenced but not defined in this module — used in `TestUtils.cs`)
|
||
|
|
- **`Xceed.Wpf.Toolkit.PropertyGrid.Attributes`** (for `ItemCollection` in `EnumUtil.cs`)
|
||
|
|
|
||
|
|
### External Dependencies (via `using`)
|
||
|
|
- **System**: `System.Collections.Generic`, `System.Diagnostics`, `System.IO`, `System.Linq`, `System.Text`, `System.Threading`, `System.Threading.Tasks`, `System.Windows`, `System.Windows.Media`, `System.Windows.Media.Imaging`, `System.Windows.Threading`, `System.Windows.Forms`, `System.Drawing`, `System.Drawing.Drawing2D`, `System.Runtime.InteropServices`, `System.Xml`, `System.Xml.Serialization`, `System.Net`, `System.Net.NetworkInformation`, `System.Net.Sockets`
|
||
|
|
- **Windows Presentation Foundation (WPF)**: `System.Windows.Controls`, `System.Windows.Interop`, `System.Windows.Media.Imaging`
|
||
|
|
- **Windows Forms**: `System.Windows.Forms`
|
||
|
|
- **GDI+**: `System.Drawing`, `System.Drawing.Drawing2D`
|
||
|
|
- **Win32 API**: `user32.dll` (for `GetCursorPos`, `GetPhysicalCursorPos`, `ScreenToClient`)
|
||
|
|
|
||
|
|
### Inferred Consumers
|
||
|
|
- UI components (`ImageButton`, `BusyWaitAnimation`) likely used in WPF/WinForms UI layers.
|
||
|
|
- `ByteConvertor`, `SecureQueue`, `StopWatchQueue` used in low-level data acquisition or networking modules.
|
||
|
|
- `NetworkUtils`, `PNGImageUtil`, `TestUtils` used in test automation, diagnostics, or reporting modules.
|
||
|
|
- `SerializableDictionary` used for XML persistence of dictionaries.
|
||
|
|
|
||
|
|
## 5. Gotchas
|
||
|
|
|
||
|
|
- **`ByteConvertor` integer conversions**: Despite the class summary claiming "network order", `float` and `double` use `BitConverter` (host-endian), which may cause inconsistencies if expecting consistent endianness across all types.
|
||
|
|
- **`StopWatchQueue.DumpData()`**: Writes CSV with header `"All values in milli seconds"` — but values are computed as `ticks / Frequency * 1000`, which is correct for milliseconds. Ensure `Stopwatch.Frequency` is consistent across platforms.
|
||
|
|
- **`SecureQueue.Dequeue()`**: Returns a *flattened* array of all queued arrays, not the first queued array. This is likely intentional for streaming but may be surprising.
|
||
|
|
- **`MouseUtilities.GetMousePosition()`**: Uses a non-standard scaling correction (`factor = 2D - M22`) and conditional Y-offset adjustment. This may be fragile under DPI scaling changes or high-DPI scenarios.
|
||
|
|
- **`TestUtils.MinUnixTime()`**:
|
||
|
|
- Uses `basemodules.First()` as initial `minUnixTime`, then compares *only* if `module.TriggerTimestampSec <= minUnixTime.Item1 && module.TriggerTimestampNanoSec < minUnixTime.Item2`. This logic may skip valid candidates if seconds are equal but nanoseconds are greater.
|
||
|
|
- The standard deviation cap (`TEN_MILLIS_IN_SEC`) is applied *after* computing deviation, but the comparison uses `>`, not `>=`.
|
||
|
|
- No validation that `basemodules` is non-null *before* calling `.Count()` (though `.Count()` on null throws).
|
||
|
|
- **`TestUtils.ParseROISuffix()`**:
|
||
|
|
- Uses `test.Split(":".ToCharArray(), ...)` — string split with char array is inefficient; `Split(':')` would be simpler.
|
||
|
|
- Relies on `DTS.Common.Constants.EventNumber` — if undefined or changed, behavior breaks silently.
|
||
|
|
- **`NetworkUtils.GetAvailableHosts()`**: Skips 169.254.x.x addresses but does not skip other link-local ranges (e.g., IPv6). Also filters Npcap interfaces by description — may miss other packet-capture tools.
|
||
|
|
- **`BusyWaitAnimation`**:
|
||
|
|
- Uses `Graphics.FromHdc` — requires valid `hDC` to be set before drawing; otherwise, `FromHdc` may throw.
|
||
|
|
- `Invalidate()` uses `_backgroundImage`, but `_backgroundImage` is only initialized in `SetDrawArea()` — calling `Invalidate()` before `SetDrawArea()` will cause `NullReferenceException`.
|
||
|
|
- Timer interval is set via `TimeSpan.FromMilliseconds(value)` where `value` is `Ticks` — this is incorrect; `Ticks` is not milliseconds. Should use `TimeSpan.FromMilliseconds(value)` with `value` in milliseconds, or `TimeSpan.FromTicks(value)` if `value` is ticks. The property `RotationSpeed` returns `_timer.Interval.Ticks`, but setting it expects milliseconds — this mismatch is a bug.
|
||
|
|
- **`SerializableDictionary`**:
|
||
|
|
- Uses `XmlSerializer` for keys and values — requires `TKey` and `TValue` to be serializable by `XmlSerializer`.
|
||
|
|
- Does not handle duplicate keys during deserialization (would throw `ArgumentException` from `Dictionary.Add`).
|
||
|
|
- `ReadXml` assumes XML structure `<items><item>...</item>...</items>` — any deviation (e.g., whitespace, attributes) may cause parsing errors.
|
||
|
|
- **`EnumUtil.GetValuesList<T>()`**: Uses `ItemCollection` from Xceed toolkit — may not be available in all environments or may require specific toolkit version.
|