# Add New Hardware Support - DataPRO Prompt Template ## Context DataPRO supports various Data Acquisition System (DAS) hardware through the hardware abstraction layer in `Common/DTS.Common.DAS.Concepts/` and the `DataPRO/Modules/Hardware/` modules. Hardware support involves implementing interfaces for arm/disarm, data collection, real-time streaming, and trigger functionality. ## System Architecture ``` Common/DTS.Common.DAS.Concepts/ ├── DAS/ │ ├── Channel/ # Channel abstraction │ ├── DAS.Id.cs # Hardware identification │ └── DAS.Channel.cs # Channel definitions ├── Interfaces/ # Hardware interfaces ├── IArmable.cs # Arming capability ├── IDataCollectionEnabled.cs # Data collection ├── IDownloadEnabled.cs # Data download ├── IRealtimeable.cs # Real-time streaming ├── ITriggerable.cs # Trigger capability └── IGpioEnabled.cs # GPIO support DataPRO/Modules/Hardware/ ├── HardwareList/ # Hardware management UI │ ├── Model/ │ ├── View/ │ └── ViewModel/ └── AddEditHardware/ # Hardware configuration ``` ## Step-by-Step Instructions ### 1. Create Hardware Model **File:** `Common/DTS.Common.DAS.Concepts/DAS/{HardwareName}.cs` ```csharp using System; using System.Collections.Generic; namespace DTS.Common.DAS.Concepts { public class {HARDWARE_NAME} : IArmable, IDataCollectionEnabled, IRealtimeable, ITriggerable { public DASId Id { get; set; } public string SerialNumber { get; set; } public string FirmwareVersion { get; set; } public int ChannelCount { get; set; } public int SampleRate { get; set; } public ArmStatus ArmStatus { get; private set; } public bool IsDataCollectionEnabled { get; private set; } public bool IsRealtimeEnabled { get; private set; } public {HARDWARE_NAME}() { Id = new DASId(); ChannelCount = 8; SampleRate = 100000; ArmStatus = ArmStatus.Disarmed; } // IArmable implementation public void Arm() { ValidateArmConditions(); SendArmCommand(); ArmStatus = ArmStatus.Armed; } public void Disarm() { SendDisarmCommand(); ArmStatus = ArmStatus.Disarmed; } public AvailableArmModes GetAvailableArmModes() { return new AvailableArmModes { Modes = new List { ArmMode.Triggered, ArmMode.Immediate } }; } // IDataCollectionEnabled implementation public void EnableDataCollection() { ConfigureDataCollection(); IsDataCollectionEnabled = true; } public void DisableDataCollection() { StopDataCollection(); IsDataCollectionEnabled = false; } // IRealtimeable implementation public void StartRealtime() { ValidateRealtimeConditions(); StartRealtimeStreaming(); IsRealtimeEnabled = true; } public void StopRealtime() { StopRealtimeStreaming(); IsRealtimeEnabled = false; } // ITriggerable implementation public void ConfigureTrigger(TriggerConfiguration config) { ValidateTriggerConfiguration(config); ApplyTriggerSettings(config); } // Hardware-specific methods private void ValidateArmConditions() { if (string.IsNullOrEmpty(SerialNumber)) throw new InvalidOperationException("Serial number required"); } private void SendArmCommand() { // Hardware communication implementation } private void SendDisarmCommand() { // Hardware communication implementation } private void ConfigureDataCollection() { // Configure sample rate, duration, etc. } private void StopDataCollection() { // Stop collection } private void ValidateRealtimeConditions() { if (!IsDataCollectionEnabled) throw new InvalidOperationException("Enable data collection first"); } private void StartRealtimeStreaming() { // Start real-time data stream } private void StopRealtimeStreaming() { // Stop real-time data stream } private void ValidateTriggerConfiguration(TriggerConfiguration config) { if (config.Threshold < 0) throw new ArgumentException("Invalid threshold"); } private void ApplyTriggerSettings(TriggerConfiguration config) { // Apply trigger configuration to hardware } } public class TriggerConfiguration { public double Threshold { get; set; } public TriggerEdge Edge { get; set; } public int Channel { get; set; } } public enum TriggerEdge { Rising, Falling, Both } } ``` ### 2. Create Hardware Channel Definition **File:** `Common/DTS.Common.DAS.Concepts/DAS/{HardwareName}Channel.cs` ```csharp using System; using DTS.Common.DAS.Concepts.Channel; namespace DTS.Common.DAS.Concepts { public class {HARDWARE_NAME}Channel : DAS.Channel { public int PhysicalChannel { get; set; } public string Label { get; set; } public double FullScaleRange { get; set; } public double ExcitationVoltage { get; set; } public {HARDWARE_NAME}Channel(int index) { PhysicalChannel = index; FullScaleRange = 10.0; ExcitationVoltage = 0.0; } public void Configure(ChannelConfiguration config) { FullScaleRange = config.FullScaleRange; ExcitationVoltage = config.ExcitationVoltage; ApplyChannelSettings(); } private void ApplyChannelSettings() { // Apply channel configuration to hardware } } public class ChannelConfiguration { public double FullScaleRange { get; set; } public double ExcitationVoltage { get; set; } public CouplingMode Coupling { get; set; } } public enum CouplingMode { DC, AC } } ``` ### 3. Create Hardware Factory **File:** `Common/DTS.Common.DAS.Concepts/DAS/{HardwareName}Factory.cs` ```csharp using System; using DTS.Common.DAS.Concepts.Interfaces; namespace DTS.Common.DAS.Concepts { public class {HARDWARE_NAME}Factory : IDASFactory { public string HardwareType => "{HARDWARE_NAME}"; public DAS.Channel CreateChannel(int index) { return new {HARDWARE_NAME}Channel(index); } public {HARDWARE_NAME} CreateHardware(string serialNumber) { var hardware = new {HARDWARE_NAME} { SerialNumber = serialNumber }; InitializeHardware(hardware); return hardware; } private void InitializeHardware({HARDWARE_NAME} hardware) { // Hardware initialization // Connect, discover channels, read firmware version } public bool CanCreate(string hardwareIdentifier) { // Check if this factory supports the given hardware return hardwareIdentifier.StartsWith("{HARDWARE_PREFIX}"); } } } ``` ### 4. Update Hardware List Module **File:** `DataPRO/Modules/Hardware/HardwareList/Model/{HardwareName}Model.cs` ```csharp using System; using System.ComponentModel; using DTS.Common.DAS.Concepts; namespace HardwareList.Model { public class {HARDWARE_NAME}Model : INotifyPropertyChanged { private {HARDWARE_NAME} _hardware; public string SerialNumber { get => _hardware?.SerialNumber; set { if (_hardware != null) _hardware.SerialNumber = value; OnPropertyChanged(nameof(SerialNumber)); } } public string FirmwareVersion => _hardware?.FirmwareVersion; public int ChannelCount => _hardware?.ChannelCount ?? 0; public ArmStatus ArmStatus => _hardware?.ArmStatus ?? ArmStatus.Disarmed; public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } public void SetHardware({HARDWARE_NAME} hardware) { _hardware = hardware; OnPropertyChanged(nameof(SerialNumber)); OnPropertyChanged(nameof(FirmwareVersion)); OnPropertyChanged(nameof(ChannelCount)); OnPropertyChanged(nameof(ArmStatus)); } } } ``` ### 5. Create Hardware View **File:** `DataPRO/Modules/Hardware/HardwareList/View/{HardwareName}View.xaml` ```xml ``` ### 6. Register Factory in Bootstrapper **File:** Modify the bootstrapper or module initialization ```csharp private void RegisterDASFactories() { // Register existing factories _unityContainer.RegisterType("SLICE6"); _unityContainer.RegisterType("TDAS"); // Register new hardware factory _unityContainer.RegisterType("{HARDWARE_NAME}"); } ``` ### 7. Add Hardware Type to Enums **File:** `Common/DTS.Common/Enums/HardwareTypes.cs` ```csharp public enum HardwareType { Unknown, SLICE6, TDAS, {HARDWARE_NAME} // Add new type } ``` ## Interface Reference ### IArmable ```csharp public interface IArmable { ArmStatus ArmStatus { get; } void Arm(); void Disarm(); AvailableArmModes GetAvailableArmModes(); } ``` ### IDataCollectionEnabled ```csharp public interface IDataCollectionEnabled { bool IsDataCollectionEnabled { get; } void EnableDataCollection(); void DisableDataCollection(); } ``` ### IRealtimeable ```csharp public interface IRealtimeable { bool IsRealtimeEnabled { get; } void StartRealtime(); void StopRealtime(); } ``` ### ITriggerable ```csharp public interface ITriggerable { void ConfigureTrigger(TriggerConfiguration config); } ``` ## Files to Create/Modify Summary | File | Action | |------|--------| | `DTS.Common.DAS.Concepts/DAS/{HardwareName}.cs` | Create | | `DTS.Common.DAS.Concepts/DAS/{HardwareName}Channel.cs` | Create | | `DTS.Common.DAS.Concepts/DAS/{HardwareName}Factory.cs` | Create | | `HardwareList/Model/{HardwareName}Model.cs` | Create | | `HardwareList/View/{HardwareName}View.xaml` | Create | | `HardwareList/View/{HardwareName}View.xaml.cs` | Create | | `HardwareList/HardwareListModule.cs` | Modify (register) | | `DTS.Common/Enums/HardwareType.cs` | Modify (add enum) | ## Validation Checklist - [ ] Hardware class implements required interfaces (`IArmable`, etc.) - [ ] Channel class inherits from `DAS.Channel` - [ ] Factory implements `IDASFactory` - [ ] All interface methods properly implemented - [ ] Validation added for hardware commands - [ ] Error handling for communication failures - [ ] Factory registered in DI container - [ ] Hardware type added to enum - [ ] View properly data-bound to ViewModel - [ ] Localization strings added - [ ] Channel configuration supports hardware features ## Hardware Communication Patterns 1. **Synchronous Commands:** Use for arm/disarm operations 2. **Asynchronous Data:** Use for real-time streaming 3. **Status Polling:** Implement periodic status checks 4. **Error Recovery:** Handle disconnections gracefully 5. **Timeout Handling:** Set appropriate timeouts for operations ## Common Gotchas - Always check connection status before sending commands - Validate hardware state transitions (can't arm if already armed) - Handle firmware version differences - Consider backward compatibility with older firmware - Implement proper disposal of resources