Files
DP44/enriched-qwen3-coder-next/DataPRO/IService/Classes/CAN.md
2026-04-17 14:55:32 -04:00

155 lines
9.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
source_files:
- DataPRO/IService/Classes/CAN/CANConfig.cs
- DataPRO/IService/Classes/CAN/CANModuleConfig.cs
generated_at: "2026-04-16T03:56:57.762497+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "49767c75e3daaeaa"
---
# CAN
## Documentation: CAN Configuration Module (`DTS.DASLib.Service`)
---
### 1. Purpose
This module provides XML-based serialization and deserialization for CAN (Controller Area Network) hardware configuration data in the DAS (Data Acquisition System) service layer. It enables persistent storage and retrieval of system-wide CAN module configurations (`CANConfig`) and per-module settings (`CANModuleConfig`), including channel definitions, recording parameters, and firmware metadata. The classes implement `IXmlSerializable` to support custom XML formatting, allowing configuration files to be stored in a human-readable and version-tolerant manner under the `DASConfigs` subdirectory relative to the executing assembly.
---
### 2. Public Interface
#### `CANConfig` class
- **`public Dictionary<string, CANModuleConfig> Modules { get; }`**
Read-only dictionary mapping module serial numbers (string keys) to `CANModuleConfig` instances. Represents all configured CAN modules.
- **`public string FileName { get; }`**
Full path to the XML file from which this `CANConfig` instance was loaded (or to which it will be written). Set only during construction.
- **`public CANConfig()`**
Default constructor. Initializes an empty configuration with no modules or file association.
- **`public CANConfig(string fileName, bool deleteIfPresent)`**
Constructor that attempts to load configuration from `fileName` (relative to `DASConfigs/` subdirectory). If `deleteIfPresent` is `true`, the file is deleted before loading (resulting in an empty config). If `false`, the file is read via `ReadXml`. Exceptions during file I/O or XML parsing are logged via `APILogger`.
- **`public void SetModule(CANModuleConfig module)`**
Inserts or updates a module in the `_modules` dictionary using `module.SerialNumber` as the key. No validation beyond key existence.
- **`public CANModuleConfig GetModule(CANModuleConfig module)`**
Returns the module stored under `module.SerialNumber`. If not present, inserts the provided `module` instance into the dictionary and returns it. *Note: This mutates the config even when the module is not yet known.*
- **`public XmlSchema GetSchema()`**
Returns `null`. Required by `IXmlSerializable` but unused.
- **`public void ReadXml(XmlReader reader)`**
Deserializes XML starting at `<CANConfig>` root. Reads a `<Modules>` section containing multiple `<CANModule>` elements. Each `<CANModule>` is deserialized into a `CANModuleConfig` and added via `SetModule`.
- **`public void WriteXml(XmlWriter writer)`**
Serializes the configuration as `<CANConfig><Modules>...</Modules></CANConfig>`. Each `CANModuleConfig` is written via its own `WriteXml` method, with `writer.Flush()` called after writing the `<Modules>` start tag and after each module.
#### `CANModuleConfig` class
- **`public string SerialNumber { get; set; }`**
Unique identifier for the CAN module (used as dictionary key in `CANConfig.Modules`).
- **`public string TestId { get; set; }`**
Identifier for the test associated with this module.
- **`public string TestDescription { get; set; }`**
Human-readable description of the test.
- **`public DFConstantsAndEnums.RecordingMode RecordingMode { get; set; }`**
Recording mode enum (e.g., continuous, event-triggered). Defaults to `InvalidArmMode`.
- **`public float AAFilterRateHz { get; set; }`**
Anti-aliasing filter rate in Hz. Default `0`.
- **`public double PreTriggerSeconds { get; set; }`**
Duration (seconds) of data to capture *before* a trigger event. Default `0`.
- **`public double PostTriggerSeconds { get; set; }`**
Duration (seconds) of data to capture *after* a trigger event. Default `0`.
- **`public string FirmwareVersion { get; set; }`**
Firmware version string reported by the module.
- **`public UInt64? MaxEventStorageSpaceInBytes { get; set; }`**
Optional maximum storage space (in bytes) for event-triggered recordings. Nullable; defaults to `0`.
- **`public int ModuleArrayIndex { get; set; }`**
Index of the module in a logical array (e.g., for ordering). Default `0`.
- **`public string FileName { get; }`**
Full path to the XML file from which this module config was loaded. Set only during construction.
- **`public CANModuleConfig()`**
Default constructor. Initializes all properties to defaults.
- **`public CANModuleConfig(string fileName)`**
Constructor that loads configuration from `fileName` (relative to `DASConfigs/`). Logs errors on failure.
- **`public void SetChannel(CANInputDASChannel channel)`**
Inserts or updates a channel in the internal `_channels` dictionary using `channel.ModuleChannelNumber` as the key.
- **`public CANInputDASChannel GetChannel(CANInputDASChannel channel)`**
Returns the channel stored under `channel.ModuleChannelNumber`. If not present, inserts the provided `channel` and returns it. *Note: Mutates config on miss.*
- **`public XmlSchema GetSchema()`**
Returns `null`. Required by `IXmlSerializable` but unused.
- **`public void ReadXml(XmlReader reader)`**
Deserializes XML starting at `<CANModule>`. Reads scalar properties (`SerialNumber`, `TestId`, etc.) and the `<Channels>` section. For `RecordingMode`, `AAFilterRateHz`, `PreTriggerSeconds`, `PostTriggerSeconds`, and `MaxEventStorageSpaceInBytes`, parsing errors are logged and defaults retained. `ModuleArrayIndex` is read via `ReadModuleArray`, which silently ignores errors (for backward compatibility with older config files).
- **`public void WriteXml(XmlWriter writer)`**
Serializes the module as `<CANModule>...</CANModule>`. Writes all scalar properties and the `<Channels>` section. For each channel, calls `WriteElementStart`, `WriteXml`, and `WriteElementEnd` on the channel object.
- **`public virtual void WriteElementStart(XmlWriter writer)`**
Writes `<CANModule xsi:type="...">` where `...` is the runtime type name (e.g., `CANInputDASChannel`). Allows polymorphic deserialization.
- **`public virtual void WriteElementEnd(XmlWriter writer)`**
Writes `</CANModule>`.
---
### 3. Invariants
- **`SerialNumber` uniqueness**: Within a `CANConfig.Modules` dictionary, keys are `SerialNumber` strings. Duplicate keys are overwritten (not rejected).
- **`ModuleChannelNumber` uniqueness**: Within a `CANModuleConfig._channels` dictionary, keys are `ModuleChannelNumber` integers. Duplicate keys are overwritten.
- **XML structure**: `CANConfig` XML root is `<CANConfig>`, containing `<Modules>` with nested `<CANModule>` elements. `CANModuleConfig` XML root is `<CANModule>`.
- **Backward compatibility**: `ReadModuleArray` silently ignores missing or malformed `ModuleArrayIndex` elements, assuming older config files may lack them.
- **Default values**: All numeric/string properties have non-null defaults (e.g., `""` for strings, `0` for numerics, `InvalidArmMode` for `RecordingMode`). `MaxEventStorageSpaceInBytes` defaults to `0` (not `null`).
- **File paths**: All file paths are constructed relative to the executing assemblys directory, under `DASConfigs/<fileName>`.
---
### 4. Dependencies
- **Internal dependencies**:
- `DTS.Common.Utilities.Logging.APILogger` for error logging (used in constructors, `ReadXml`, `WriteXml`, and `ReadModuleArray`).
- `DTS.Common.Enums.DASFactory.DFConstantsAndEnums.RecordingMode` enum (used in `RecordingMode` property).
- `DASChannel` (base class) and `CANInputDASChannel` (concrete channel type) for channel storage and serialization. *Note: `DASChannel` is referenced but not defined in the provided sources.*
- **External dependencies**:
- `System.Xml`, `System.Xml.Serialization`, `System.IO`, `System.Reflection` (standard .NET libraries).
- File system access (for reading/writing XML files in `DASConfigs/`).
- **Depended upon by**:
Unknown from source alone. Likely consumed by higher-level DAS service components (e.g., configuration managers, CAN interface drivers) that initialize or update CAN module settings.
---
### 5. Gotchas
- **`GetModule`/`GetChannel` mutate on miss**: Both methods add the provided module/channel to the internal dictionary if not found, which may be unintended (e.g., during read-only queries). Consider renaming or clarifying intent.
- **No validation on `SerialNumber`/`ModuleChannelNumber`**: Duplicates are silently overwritten. No uniqueness enforcement beyond dictionary semantics.
- **`ReadModuleArray` swallows errors**: The `catch` block in `ReadModuleArray` ignores all exceptions, potentially masking real issues (e.g., malformed XML). This is intentional for backward compatibility but may complicate debugging.
- **`MaxEventStorageSpaceInBytes` range check is incomplete**: The condition `d >= 0 && d < ulong.MaxValue` allows `d == ulong.MaxValue`, but `Convert.ToUInt64(d)` will throw for `d == ulong.MaxValue` (since `double` may not represent it exactly). Should use `d <= ulong.MaxValue - 1` or similar.
- **No `WriteXml` override for base `DASChannel`**: The `WriteXml` method iterates over `_channels.Values` as `DASChannel`, but only `CANInputDASChannel` is instantiated in `ReadXml`. If other `DASChannel` subclasses exist, `WriteElementStart`/`WriteElementEnd` must be overridden appropriately.
- **Hardcoded path construction**: `Path.Combine(Path.GetDirectoryName(...), "DASConfigs", fileName)` assumes `DASConfigs` is a subdirectory of the assembly directory. May fail in non-standard deployment scenarios (e.g., single-file publish).
- **No XML validation schema**: `GetSchema()` returns `null`, so no schema validation occurs during deserialization. Malformed XML may cause runtime errors or silent data loss.
None identified beyond the above.