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

9.7 KiB
Raw Blame History

source_files, generated_at, model, schema_version, sha256
source_files generated_at model schema_version sha256
DataPRO/IService/Classes/CAN/CANConfig.cs
DataPRO/IService/Classes/CAN/CANModuleConfig.cs
2026-04-16T03:56:57.762497+00:00 Qwen/Qwen3-Coder-Next-FP8 1 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.