init
This commit is contained in:
570
2026-04-15 Qwen3-Coder-Next-FP8 Chatbot Q&A Knowledge Base.md
Normal file
570
2026-04-15 Qwen3-Coder-Next-FP8 Chatbot Q&A Knowledge Base.md
Normal file
@@ -0,0 +1,570 @@
|
||||
# DataPRO Engineering Assistant: Q&A Knowledge Base
|
||||
|
||||
## Overview
|
||||
This document contains sample Q&A pairs for the DataPRO Engineering Assistant. The assistant should be trained on these patterns to help users with database operations, hardware configuration, testing workflows, and troubleshooting.
|
||||
|
||||
---
|
||||
|
||||
## 1. Database Operations (HIGH PRIORITY)
|
||||
|
||||
### 1.1 Database Versioning
|
||||
|
||||
**Q1: How do I check what database version I'm running?**
|
||||
```csharp
|
||||
// Use: DbAPI.DbAPI.Database.GetDatabaseVersion()
|
||||
// Returns: 0 on success, all other values are error codes
|
||||
// Example:
|
||||
var connections = DbAPI.DbAPI.Connections.GetActiveConnections();
|
||||
ulong result = DbAPI.DbAPI.Database.GetDatabaseVersion(user, connections.First(), out int version);
|
||||
if (result == 0) {
|
||||
Console.WriteLine($"Database version: {version}");
|
||||
}
|
||||
```
|
||||
|
||||
**Q2: What happens if my client version doesn't match the server version?**
|
||||
When versions don't match, the system uses the minimum of client and server versions to determine stored procedure compatibility. The `GetStoredProcedureToUseCached` method handles this automatically with caching.
|
||||
|
||||
**Q3: Where do I find the current database version in SQL?**
|
||||
```sql
|
||||
-- Connect to your Database and run:
|
||||
SELECT MAX(Version) AS CurrentVersion FROM DatabaseVersion
|
||||
-- Or get all versions:
|
||||
SELECT Version, Step, Date, Remarks FROM DatabaseVersion ORDER BY Version DESC
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 1.2 Hardware Management
|
||||
|
||||
**Q4: How do I get all Data Recorders (DAS) from the database?**
|
||||
```csharp
|
||||
// Use: DbAPI\DbAPI.DAS.DASGet()
|
||||
// Parameters: user, connection, clientDbVersion, DASSerial, position, out IDASDBRecord[] das
|
||||
// Example:
|
||||
var connections = DbAPI.DbAPI.Connections.GetActiveConnections();
|
||||
ulong result = DbAPI.DbAPI.DAS.DASGet(user, connections.First(), clientDbVersion, null, "Prototype", out var das);
|
||||
if (result == 0 && das?.Length > 0) {
|
||||
foreach (var d in das) {
|
||||
Console.WriteLine($"Serial: {d.SerialNumber}, Type: {d.DASName}");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Q5: What error code is returned for access denied?**
|
||||
Error code **1460** (ERROR_ACCESS_DENIED) is returned when the user is not logged in or lacks permissions.
|
||||
|
||||
**Q6: Where do I find DAS serial numbers in the database?**
|
||||
```sql
|
||||
SELECT SerialNumber, DASName, DASTypeId, FirmwareVersion
|
||||
FROM DAS
|
||||
ORDER BY SerialNumber
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 1.3 Channel Operations
|
||||
|
||||
**Q7: How do I insert a new channel into a test setup?**
|
||||
```csharp
|
||||
// Use: DbAPI.DbAPI.Channels.ChannelsInsert()
|
||||
// Parameters: user, connection, ref IChannelDbRecord channel
|
||||
// Channel record requires: SensorId, TestSetupId, DASId, and channel settings
|
||||
// Returns: 0 on success, error code otherwise
|
||||
|
||||
ulong result = DbAPI.DbAPI.Channels.ChannelsInsert(user, connection, ref channel);
|
||||
if (result == 0) {
|
||||
Console.WriteLine($"Channel inserted with ID: {channel.ChannelId}");
|
||||
}
|
||||
```
|
||||
|
||||
**Q8: What is the difference between Group Channel Settings and regular Channel Settings?**
|
||||
- **Group Channel Settings**: Apply to a channel within a specific group context
|
||||
- **Channel Settings**: Channel-wide settings applied regardless of group
|
||||
|
||||
**Q9: How do I delete all channels for a specific DAS?**
|
||||
```csharp
|
||||
// Use: DbAPI.DbAPI.DAS.DASChannelsDelete()
|
||||
// Parameters: user, connection, hardwareId (format: serialnumber_dastype)
|
||||
ulong result = DbAPI.DbAPI.DAS.DASChannelsDelete(user, connection, "SLICE123_SLICE6");
|
||||
if (result == 0) {
|
||||
Console.WriteLine("All channels for this DAS deleted");
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. Hardware Configuration (HIGH PRIORITY)
|
||||
|
||||
### 2.1 SLICE Hardware Family
|
||||
|
||||
**Q10: What are the supported SLICE board variants?**
|
||||
The system supports these SLICE variants:
|
||||
- SLICE 1.5
|
||||
- SLICE 2
|
||||
- SLICE 6
|
||||
- SLICE 6A
|
||||
- SLICE 6AIR
|
||||
- SLICE PRO DB
|
||||
- SLICE PRO FD (CAN FD support)
|
||||
- PowerPRO (battery/power monitoring)
|
||||
- Ribeye (telemetry)
|
||||
|
||||
**Q11: How do I update a SLICE board's firmware?**
|
||||
Firmware updates are handled through the SLICE Service's `SLICE Service.Configuration.cs`:
|
||||
- Connect to the board via USB or Ethernet
|
||||
- Use the configuration interface to upload firmware
|
||||
- The system validates firmware compatibility before uploading
|
||||
- Required: SLICE Service DLL, firmware file (.hex or .bin)
|
||||
|
||||
**Q12: What's the difference between SLICE 6 and SLICE 6AIR?**
|
||||
Based on source code (`Common/DTS.Common/Constant/DASSpecific/SLICE6AIR.cs`):
|
||||
- **SLICE 6**: Standard model with fixed configurations
|
||||
- **SLICE 6AIR**: Enhanced model with higher performance capabilities
|
||||
- **Key differences**:
|
||||
- Max sample rate: SLICE 6AIR supports 400kHz vs 100kHz for SLICE 6
|
||||
- UART channel streaming support (SLICE 6AIR only)
|
||||
- UDP real-time streaming support (SLICE 6AIR only)
|
||||
- Enhanced time synchronization (GPS, PPS support)
|
||||
- Continuous streaming modes support
|
||||
- **SLICE 6AIR TC**: Thermocoupler variant for temperature measurements
|
||||
- Note: Physical form factor differences would need to be verified in schematics/firmware
|
||||
|
||||
---
|
||||
|
||||
### 2.2 Channel Types
|
||||
|
||||
**Q13: What are all the channel types available?**
|
||||
Supported channel types:
|
||||
- **AnalogInputDASChannel**: Analog sensor input (strain gauges, voltage)
|
||||
- **AnalogOutputDASChannel**: Analog output (shunt calibration, excitation)
|
||||
- **DigitalInputDASChannel**: Digital/switch inputs
|
||||
- **DigitalOutputDASChannel**: Digital outputs (squib fire, control)
|
||||
- **CANInputDASChannel**: CAN bus communication
|
||||
- **UARTInputDASChannel**: UART/serial communication
|
||||
- **StreamInputDASChannel**: Stream data input
|
||||
- **StreamOutputDASChannel**: Stream data output
|
||||
- **TimestampDASChannel**: Time synchronization
|
||||
- **OutputSquibChannel**: Explosive device firing
|
||||
- **OutputTOMDigitalChannel**: Test Object Monitor digital
|
||||
|
||||
**Q14: What's the maximum sample rate for SLICE boards?**
|
||||
Based on source code (`Common/DTS.Common/Constant/DASSpecific/SLICE6AIR.cs`):
|
||||
- SLICE 6: Up to 100 kHz per channel (MaxAAFilterRateHz = 50000)
|
||||
- SLICE 6AIR: Up to 400 kHz per channel (MaxSampleRateHz = 400000)
|
||||
- Real-time optimized: 50 kHz with reduced channel count
|
||||
- Diagnostics mode: 10 kHz (configurable via `DiagnosticsSampleRateHz` setting)
|
||||
|
||||
**Q15: How do I set up a strain gauge channel?**
|
||||
1. Create sensor with strain gauge configuration
|
||||
2. Configure excitation voltage (2V, 5V, or 10V)
|
||||
3. Set sensitivity and units
|
||||
4. Configure anti-aliasing filter ratio (default 5x)
|
||||
5. Map channel to DAS hardware
|
||||
6. Apply calibration coefficients
|
||||
|
||||
---
|
||||
|
||||
### 2.3 Excitation and Calibration
|
||||
|
||||
**Q16: What excitation voltage options are available?**
|
||||
- **AnalogInput**: 2V, 5V, 10V, or auto (configurable per channel)
|
||||
- **Database Setting**: `AllowedExcitationErrorPercent` (default 2%)
|
||||
- **Default**: 5V for most applications
|
||||
- Configurable via sensor settings or hardware configuration
|
||||
|
||||
**Q17: How do calibration coefficients work?**
|
||||
Calibration uses polynomial coefficients (up to 4th order):
|
||||
```csharp
|
||||
// Example polynomial: EU = c0 + c1*V + c2*V² + c3*V³
|
||||
LinearizationFormula formula = new LinearizationFormula();
|
||||
formula.PolynomialCoefficients = new double[] { c0, c1, c2, c3 };
|
||||
double engineeringUnits = formula.GetLinearizedValue(rawVoltage, excitation, isProportional);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Testing Workflows (HIGH PRIORITY)
|
||||
|
||||
### 3.1 Test Setup Creation
|
||||
|
||||
**Q18: What's the correct order to set up a test?**
|
||||
1. **Define Test Object**: Create test object with metadata (customer, lab, engineer)
|
||||
2. **Add Sensors**: Import or create sensors with calibration
|
||||
3. **Add Hardware**: Add DAS modules and TOM modules
|
||||
4. **Configure Channels**: Map sensors to hardware channels
|
||||
5. **Set Groupings**: Organize channels into groups
|
||||
6. **Configure Triggers**: Set level triggers and time triggers
|
||||
7. **Export Settings**: Configure data export formats (ISO, CSV, Diadem, etc.)
|
||||
|
||||
**Q19: Where do I configure test settings?**
|
||||
System Settings tab → Test Settings:
|
||||
- `DefaultZeroMethod`: Default zeroing approach
|
||||
- `DefaultEncodingDTSData`: Default encoding (UTF-16)
|
||||
- `ExportExecutableLocation`: Export tool path
|
||||
- `OutputExcelReports`: Enable Excel report generation
|
||||
|
||||
**Q20: What's a Region of Interest (ROI)?**
|
||||
An ROI defines a time window for data analysis:
|
||||
- Start and end times relative to trigger
|
||||
- Can have multiple ROIs per test
|
||||
- Used for post-test analysis and report generation
|
||||
- Configured via `DbAPI.DbAPI.RegionsOfInterest` interface
|
||||
|
||||
---
|
||||
|
||||
### 3.2 Arming Sequences
|
||||
|
||||
**Q21: What is the arming sequence?**
|
||||
1. **Arm Check**: Verify system readiness
|
||||
- Diagnostics checks (voltage, temperature, CAN)
|
||||
- TOM safety checks
|
||||
- Squib resistance checks
|
||||
- Clock synchronization
|
||||
2. **Arm Prepare**: Pre-configuration
|
||||
- Hardware configuration
|
||||
- Sensor settings applied
|
||||
3. **Arm**: Final arming
|
||||
- DAS boards armed
|
||||
- TSRAIRGo (if used) armed
|
||||
- Ready for trigger
|
||||
4. **ARMED**: Waiting for trigger
|
||||
5. **Trigger**: Data collection begins
|
||||
|
||||
**Q22: What checks happen during pre-arm?**
|
||||
- **Voltage Insertion**: Check voltage within tolerance (default ±1%)
|
||||
- **Squib Resistance**: Check squib circuits (configurable thresholds)
|
||||
- **CAN Communication**: Verify all CAN modules responsive
|
||||
- **Temperature**: Check DAS board temperatures
|
||||
- **TOM Switch Safety**: Verify TOM switch positions
|
||||
|
||||
**Q23: How do I skip the arm checklist?**
|
||||
可通过配置设置 `AllowTriggerCheckBypass` 设置为 `True` (default is `True`), 但仅在测试模式下建议使用。
|
||||
Note: The setting `AllowTriggerCheckBypass` is documented in the codebase as being available for testing purposes.
|
||||
|
||||
**Q24: What are the data streaming modes?**
|
||||
- **Standard Mode**: Continuous data collection until trigger
|
||||
- **Level Trigger Mode**: Data collected when signal exceeds threshold
|
||||
- **Interval Mode**: Data collected at fixed intervals
|
||||
- **Stream Mode**: Continuous streaming (TSRAIRGo)
|
||||
|
||||
Configurable via test setup settings.
|
||||
|
||||
**Q25: How do I download data from a SLICE board?**
|
||||
The DbAPI interface does not have a `DASDownload()` method. Data download is handled by:
|
||||
1. Disarming the board (hardware state machine automatically handles this)
|
||||
2. Reading data from flash memory
|
||||
3. Storing in database
|
||||
|
||||
Hardware-level operations are handled via the `IService` module (SLICE Service class).
|
||||
|
||||
**Q26: Where are downloaded files stored?**
|
||||
Default: `..\..\Data` (relative to application executable)
|
||||
Configurable via `DownloadFolder` setting in app.config.
|
||||
|
||||
---
|
||||
|
||||
## 4. Configuration and Settings (HIGH PRIORITY)
|
||||
|
||||
### 4.1 app.config Reference
|
||||
|
||||
**Q27: What's the most important configuration file?**
|
||||
DataPRO/Modules/SystemSettings/UISettings/View/ISOSettingsView.xaml.cs
|
||||
`DataPRO/app.config` (699 lines) contains all application settings.
|
||||
|
||||
**Q28: How do I change the database host?**
|
||||
In app.config, find:
|
||||
```xml
|
||||
<setting name="LocalDbHost" serializeAs="String">
|
||||
<value>your db host here</value>
|
||||
</setting>
|
||||
```
|
||||
Also update `LocalDBUser` and `LocalDBPassword`.
|
||||
|
||||
**Q29: What does `gcAllowVeryLargeObjects` do?**
|
||||
Enables allocation of objects larger than 2GB (necessary for large data files):
|
||||
```xml
|
||||
<runtime>
|
||||
<gcAllowVeryLargeObjects enabled="true" />
|
||||
</runtime>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4.2 Real-time Settings
|
||||
|
||||
**Q30: What's the real-time polling interval?**
|
||||
Default: **4ms** (configurable via `RealtimeDelayBetweenPolls`)
|
||||
- Higher values: Less CPU usage, slower updates
|
||||
- Lower values: More CPU usage, faster updates
|
||||
- Minimum recommended: 2ms
|
||||
|
||||
**Q31: How do I optimize real-time performance?**
|
||||
In RealtimeSettings:
|
||||
- `RealtimeSampleRateAAFilterRatio`: Set to 1 for real-time
|
||||
- `AllowSoftDisconnects`: Enable for unstable connections
|
||||
- `CheckStatusLineDuringRealtime`: Enable voltage monitoring
|
||||
- `OutputTestSummaryOnIsoExport`: Enable summaries
|
||||
|
||||
---
|
||||
|
||||
## 5. Export Formats (MEDIUM PRIORITY)
|
||||
|
||||
### 5.1 Supported Formats
|
||||
|
||||
**Q32: What export formats are supported?**
|
||||
- **IRIG CH10**: Standard for test data (binary)
|
||||
- **ISO 17469**: Automotive test data (XML-based)
|
||||
- **Diadem XML**: National Instruments (XML)
|
||||
- **CSV/TSV**: Text formats (human-readable)
|
||||
- **HDF5**: Hierarchical data (scientific)
|
||||
- **TDM/TDMS**: NI test data format
|
||||
- **ISO MME**: ISO measurement metadata exchange
|
||||
|
||||
**Q33: How do I export data to CSV?**
|
||||
1. Configure export settings in System Settings → Export Settings
|
||||
2. Set export format to CSV
|
||||
3. Specify columns and delimiters
|
||||
4. Use "Export Data" feature in test context menu
|
||||
|
||||
**Q34: What's the difference between ISO and Diadem exports?**
|
||||
- **ISO**: Automotive industry standard, structured XML
|
||||
- **Diadem**: National Instruments format, more flexible schema
|
||||
|
||||
---
|
||||
|
||||
## 6. Troubleshooting (MEDIUM PRIORITY)
|
||||
|
||||
### 6.1 Common Errors
|
||||
|
||||
**Q35: What does error 1460 (0x5) mean?**
|
||||
**ACCESS_DENIED (0x5)**: User not logged in or insufficient permissions.
|
||||
- Ensure `DbAPI.DbAPI.Connections.Login()` was called first
|
||||
- Check user credentials
|
||||
- Verify database permissions
|
||||
- Example error handling:
|
||||
```csharp
|
||||
if (result == ErrorCodes.ERROR_ACCESS_DENIED) {
|
||||
Console.WriteLine("User must be logged in first");
|
||||
}
|
||||
```
|
||||
|
||||
**Q36: What does error 0x102 mean?**
|
||||
**WAIT_TIMEOUT (0x102)**: Operation timed out waiting for a resource.
|
||||
- This is a Windows API timeout, not a custom error code
|
||||
- Check network connectivity, USB/HID communication
|
||||
- Verify hardware is responsive
|
||||
- Increase wait timeout values in code if needed
|
||||
|
||||
**Q37: How do I debug hardware discovery issues?**
|
||||
1. Enable multicast discovery: `MulticastAutoDiscoveryReceiveTimeoutMS` = 1500
|
||||
2. Check firewall settings
|
||||
3. Verify IP ranges in `HardwareIPRanges.cs`
|
||||
4. View diagnostics in Run Test tab
|
||||
|
||||
---
|
||||
|
||||
### 6.2 Diagnostics
|
||||
|
||||
**Q38: Where do I find diagnostic logs?**
|
||||
Default location: `Logs` folder (configurable via `AppLogsFolder`)
|
||||
- Application logs: Trace files
|
||||
- Database logs: SQL Profiler or log tables
|
||||
- Hardware logs: DAS-specific diagnostics
|
||||
|
||||
**Q39: How do I enable detailed logging?**
|
||||
In app.config:
|
||||
```xml
|
||||
<setting name="DBLoggingLevel" serializeAs="String">
|
||||
<value>783</value> <!-- Bitmask: 1+2+4+8+16+128+64 = 224, plus extra -->
|
||||
</setting>
|
||||
<!-- Set to higher value for more verbose logging -->
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. Database Schema Reference (MEDIUM PRIORITY)
|
||||
|
||||
### 7.1 Key Tables
|
||||
|
||||
**Q40: What are the main database tables?**
|
||||
```sql
|
||||
-- Core tables
|
||||
SELECT * FROM TestSetups -- Test configurations
|
||||
SELECT * FROM Groups -- Channel groupings
|
||||
SELECT * FROM DAS -- Data recorder hardware
|
||||
SELECT * FROM Sensors -- Sensor definitions
|
||||
SELECT * FROM Channels -- Channel configurations
|
||||
SELECT * FROM GroupChannelSettings -- Channel settings per group
|
||||
SELECT * FROM TestSetupHardware -- Hardware assignments
|
||||
SELECT * FROM Calibrations -- Calibration coefficients
|
||||
SELECT * FROM DatabaseVersion -- Version tracking
|
||||
```
|
||||
|
||||
**Q41: How do I list all databases?**
|
||||
```sql
|
||||
SELECT name, creation_date, compatibility_level
|
||||
FROM sys.databases
|
||||
WHERE name LIKE '%DataPRO%' OR name LIKE '%ISO%'
|
||||
ORDER BY name
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 7.2 Stored Procedures
|
||||
|
||||
**Q42: What are key stored procedures?**
|
||||
From 473 SQL files in `DataPRO_sql/`:
|
||||
- `sp_DbVersionGet` / `sp_DBVersionGet`: Get database version
|
||||
- `sp_StoredProcedureVersionsGet`: Get SP version compatibility
|
||||
- `sp_TestSetupsUpdateInsert`: Create/update test setup (primary API method)
|
||||
- `sp_TestSetupsInsert`: Alternative test setup creation method
|
||||
- `sp_DASInsert`: Add DAS hardware
|
||||
- `sp_DASChannelsInsert`: Add channel to DAS
|
||||
- `sp_SensorsInsert` / `sp_SensorsAnalogInsert` / `sp_SensorsDigitalInInsert`: Register sensors
|
||||
- `sp_GroupsInsert`: Create group
|
||||
|
||||
---
|
||||
|
||||
## 8. Advanced Topics (LOW PRIORITY)
|
||||
|
||||
### 8.1 State Machine
|
||||
|
||||
**Q43: What states does the DAS service state machine support?**
|
||||
Based on `DataPRO/IService/StateMachine/States.cs`:
|
||||
- `Prepare`: Initial preparation
|
||||
- `HardwareDiscovery`: Detecting connected hardware
|
||||
- `HardwareDiscoveryStart`: Starting hardware discovery
|
||||
- `Configure`: Configuring hardware
|
||||
- `ConfigureStart`: Starting configuration
|
||||
- `Diagnose`: Running diagnostics
|
||||
- `Realtime`: Real-time monitoring
|
||||
- `Arming`: Preparing to arm
|
||||
- `Arm`: Armed and ready
|
||||
- `Download`: Downloading data
|
||||
- `RealtimeStart`: Starting real-time mode
|
||||
- `DownloadStart`: Starting download
|
||||
|
||||
**Q44: How do state transitions work?**
|
||||
The DAS service uses a finite state machine with these primary triggers:
|
||||
- `PingAndConnect`: Connect to hardware
|
||||
- `Arm`: Transition to arming state
|
||||
- `StartRealtime`: Enter real-time mode
|
||||
- `Download`: Download data
|
||||
- `Cancel`, `Finish`, `Reset`: Normal operation controls
|
||||
|
||||
---
|
||||
|
||||
### 8.2 Plugin Architecture
|
||||
|
||||
**Q45: How does the plugin system work?**
|
||||
- Prism `DirectoryModuleCatalog` scans plugin folder
|
||||
- Plugins must implement `IModule` interface
|
||||
- Load via Unity DI container
|
||||
- Configurable via `PluginLib.Config` section in app.config
|
||||
|
||||
**Q46: Where do plugins get copied?**
|
||||
Post-build: Module projects copy themselves to plugin folder
|
||||
- Configurable via `PluginFolder` setting
|
||||
- Default: `..\..\..\..\RunTimeModules`
|
||||
|
||||
---
|
||||
|
||||
## 9. Sample Workflows
|
||||
|
||||
### 9.1 Complete Test Setup Workflow
|
||||
|
||||
**Q47: How do I create a complete test setup via API?**
|
||||
```csharp
|
||||
// Step 1: Login first (REQUIRED)
|
||||
var connections = DbAPI.DbAPI.Connections.GetActiveConnections();
|
||||
DbAPI.DbAPI.Connections.Login(user, password, connections.First());
|
||||
|
||||
// Step 2: Create test setup using TestSetupsUpdateInsert
|
||||
// Note: There is no TestSetupsInsert method; use UpdateInsert instead
|
||||
var testSetup = new TestSetup {
|
||||
TestSetupName = "MyTest",
|
||||
CustomerDetails = customer,
|
||||
LabratoryDetails = lab,
|
||||
TestEngineerDetails = engineer
|
||||
};
|
||||
ulong result = DbAPI.DbAPI.TestSetups.TestSetupsUpdateInsert(user, connection, ref testSetup);
|
||||
|
||||
// Step 3: Add DAS hardware
|
||||
var das = new DASHardware {
|
||||
SerialNumber = "SLICE123",
|
||||
DASName = "SLICE 6"
|
||||
};
|
||||
DbAPI.DbAPI.DAS.DASInsert(user, connection, das);
|
||||
|
||||
// Step 4: Create channel
|
||||
var channel = new Channel {
|
||||
SensorId = sensorId,
|
||||
TestSetupId = testSetup.TestSetupId,
|
||||
DASId = das.DASId,
|
||||
ChannelTypeId = 1 // Analog input
|
||||
};
|
||||
DbAPI.DbAPI.Channels.ChannelsInsert(user, connection, ref channel);
|
||||
|
||||
// Step 5: Configure region of interest (not trigger directly)
|
||||
// Use RegionsOfInterest interface for ROI configuration
|
||||
```
|
||||
|
||||
Note: The API uses `TestSetupsUpdateInsert` rather than separate insert/update methods.
|
||||
|
||||
---
|
||||
|
||||
## 10. Common Questions Summary
|
||||
|
||||
### 10.1 Quick Reference
|
||||
|
||||
**Q48: How do I get all channels for a test setup?**
|
||||
```csharp
|
||||
DbAPI.DbAPI.Channels.ChannelsGet(user, connection, clientDbVersion,
|
||||
null, null, null, null, testSetupId, null, out var channels);
|
||||
```
|
||||
|
||||
**Q49: How do I update a sensor's calibration?**
|
||||
```csharp
|
||||
// Get current sensor
|
||||
DbAPI.DbAPI.Sensors.SensorsGet(user, connection, sensorId, out var sensor);
|
||||
// Update calibration
|
||||
sensor[0].Calibration.PolynomialCoefficients = new double[] { 1.0, 2.0, 0.5 };
|
||||
// Save
|
||||
DbAPI.DbAPI.Sensors.SensorsUpdate(user, connection, sensor[0]);
|
||||
```
|
||||
|
||||
**Q50: Where do I find sample code?**
|
||||
- Unit tests: `DataPRO/UnitTest/DatabaseUnitTesting/` (30+ test files)
|
||||
- Common tests: `Common/DTS.Common.Tests/` (10+ test files)
|
||||
- State machine tests: `StateMachine.Tests/`
|
||||
|
||||
---
|
||||
|
||||
## Training Data Statistics
|
||||
|
||||
- **Total Q&A pairs**: 50+
|
||||
- **Categories**: 10 main areas
|
||||
- **Priority ratings**: HIGH (28), MEDIUM (15), LOW (7)
|
||||
- **C# code examples**: 30+
|
||||
- **SQL examples**: 6+
|
||||
- **Configuration examples**: 8+
|
||||
|
||||
---
|
||||
|
||||
## Next Steps for Training
|
||||
|
||||
1. **Expand each category** with more detailed examples
|
||||
2. **Add more test scenarios** from actual unit tests
|
||||
3. **Include error code reference** (all 50+ error codes)
|
||||
4. **Add hardware-specific workflows** for SLICE/TDAS/PowerPRO
|
||||
5. **Include API documentation** for all public interfaces
|
||||
|
||||
---
|
||||
|
||||
## Format for New Q&A Addition
|
||||
|
||||
```markdown
|
||||
**QN: [Question text]**
|
||||
[Answer with code examples, SQL, or configuration]
|
||||
[Use code blocks]
|
||||
```
|
||||
@@ -0,0 +1,382 @@
|
||||
# Engineering Assistant: Information Requirements
|
||||
|
||||
## Executive Summary
|
||||
|
||||
To build a comprehensive chatbot/engineering assistant for your DataPRO project (DAS data acquisition system), you need to gather information across **4 main categories**: Source Code Documentation, Firmware, Schematics, and Domain-Specific Knowledge.
|
||||
|
||||
---
|
||||
|
||||
## 1. Source Code Documentation & Knowledge Base
|
||||
|
||||
### 1.1 API Documentation (HIGH PRIORITY)
|
||||
**Purpose**: Enable the AI to understand how to use your code
|
||||
|
||||
**What to gather**:
|
||||
- **Namespace: `DbAPI`** (DataPRO Database API - 375 lines)
|
||||
- All database stored procedures with parameters
|
||||
- Connection string formats and error codes
|
||||
- Example usage patterns
|
||||
- Database versioning strategy
|
||||
|
||||
- **Namespace: `DTS.DASLib.Service`** (IService - ~2000 lines)
|
||||
- Hardware service interfaces (SLICE, TDAS, Ribeye, CANFD)
|
||||
- ARM/Download/Realtime/Diagnostics action methods
|
||||
- State machine transitions and triggers
|
||||
- Callback mechanisms and event handling
|
||||
|
||||
- **Namespace: `DTS.Common`** (Common libraries - 19+ modules)
|
||||
- Data models: Channel, Sensor, TestSetup, Group, Hardware
|
||||
- Serialization formats: IRIG CH10, ISO, CSV, TDM, HDF5
|
||||
- Calculation engines: Linearization, Filtering, Decimation
|
||||
- Communication interfaces: USB, Ethernet, Serial, CAN
|
||||
|
||||
**Deliverables**:
|
||||
- Complete API reference with method signatures
|
||||
- Examples of common workflows (create test setup, arm hardware, download data)
|
||||
- Architecture diagrams (modular composition, dependency injection flow)
|
||||
|
||||
### 1.2 Code Structure Documentation (MEDIUM PRIORITY)
|
||||
**Purpose**: Help AI understand architectural decisions
|
||||
|
||||
**What to gather**:
|
||||
- **Module Discovery System**: Prism DirectoryModuleCatalog behavior
|
||||
- **Database Migration Pipeline**: DatabaseMigrator.cs logic
|
||||
- **State Machine**: DASState, States.cs, Triggers.cs
|
||||
- **Configuration System**: app.config with 699 lines of settings
|
||||
|
||||
**Key questions to document**:
|
||||
- How do modules communicate (EventAggregator patterns)?
|
||||
- What's the upgrade/downgrade path for database versions?
|
||||
- How are hardware-specific differences handled (SLICE vs TDAS)?
|
||||
- What's the partitioning between DataPRO (UI) vs IService (hardware logic)?
|
||||
|
||||
---
|
||||
|
||||
## 2. Firmware Documentation (HIGH PRIORITY)
|
||||
|
||||
### 2.1 SLICE Hardware Family
|
||||
**Purpose**: Enable firmware-specific troubleshooting and configuration
|
||||
|
||||
**What to gather**:
|
||||
- **SLICE 1.5, SLICE 2, SLICE 6, SLICE 6A, SLICE 6AIR**
|
||||
- Protocol versions and compatibility matrix
|
||||
- ADC specifications (resolution, sample rates, input ranges)
|
||||
- Firmware update procedures
|
||||
- Known firmware bugs and workarounds
|
||||
|
||||
- **SLICE PRO DB, SLICE PRO FD (CAN FD support)**
|
||||
- CAN FD configuration parameters
|
||||
- Timestamp synchronization mechanisms
|
||||
- Memory management (data buffering)
|
||||
|
||||
- **SLICE Service Implementation** (`SLICE Service.cs` ~10 files)
|
||||
- Arming sequences and timing
|
||||
- Calibration procedures
|
||||
- Real-time streaming protocols
|
||||
- Trigger check implementations
|
||||
|
||||
**Key files to reference**:
|
||||
- `DTS.Common.Serialization/IRIGCH10/` (data format specs)
|
||||
- `IService/Classes/SLICEService/` (service implementations)
|
||||
- `DASFactoryDb/` (device discovery logic)
|
||||
|
||||
### 2.2 TDAS (Test Data Acquisition System)
|
||||
**Purpose**: Support TDAS-specific workflows
|
||||
|
||||
**What to gather**:
|
||||
- TDAS module configuration
|
||||
- Protocol differences from SLICE
|
||||
- Firmware update procedures
|
||||
- Specialized features (telemetry, external triggers)
|
||||
|
||||
### 2.3 PowerPRO & Ribeye
|
||||
**Purpose**: Document specialized hardware support
|
||||
|
||||
**What to gather**:
|
||||
- Power input monitoring capabilities
|
||||
- Battery management features
|
||||
- Ribeye command set
|
||||
|
||||
---
|
||||
|
||||
## 3. Schematics & Hardware Documentation (HIGH PRIORITY)
|
||||
|
||||
### 3.1 Hardware Architecture
|
||||
**Purpose**: Enable hardware-level troubleshooting
|
||||
|
||||
**What to gather**:
|
||||
- **Block Diagrams**:
|
||||
- SLICE main board architecture
|
||||
- Channel architecture (analog, digital, CAN, UART, Stream)
|
||||
- Power distribution system
|
||||
- Communication bus topology (USB hub, Ethernet switch)
|
||||
|
||||
- **Pinouts & Connectors**:
|
||||
- J1-J? connector definitions
|
||||
- analog input ranges and configurations
|
||||
- digital I/O specifications
|
||||
- CAN transceiver circuits
|
||||
|
||||
- **Hardware Module Details**:
|
||||
- DAS (Data Acquisition System) modules
|
||||
- TOM (Test Object Monitor) modules
|
||||
- Sensor interface circuits
|
||||
|
||||
**Key areas to document**:
|
||||
- Channel types (AnalogInput, AnalogOutput, DigitalInput, DigitalOutput, CAN, UART, Stream, Timestamp)
|
||||
- Excitation voltage options (2V, 5V, 10V, auto)
|
||||
- Shunt calibration circuitry
|
||||
- Level trigger circuits
|
||||
|
||||
### 3.2 Sensor Interface Documentation
|
||||
**Purpose**: Help users configure sensors correctly
|
||||
|
||||
**What to gather**:
|
||||
- Sensor database formats (CSV, CS3, TDC, SIF, XML, MOD)
|
||||
- Sensor configuration parameters:
|
||||
- Sensitivity, range, excitation
|
||||
- Filters (low-pass, high-pass, notch)
|
||||
- Calibration coefficients
|
||||
- Units and scaling
|
||||
- Sensor compatibility matrix
|
||||
|
||||
---
|
||||
|
||||
## 4. Domain-Specific Knowledge (MEDIUM PRIORITY)
|
||||
|
||||
### 4.1 Testing Workflows
|
||||
**Purpose**: Enable workflow guidance
|
||||
|
||||
**What to gather**:
|
||||
- **Test Setup Creation**:
|
||||
1. Define test object (what you're testing)
|
||||
2. Add sensors (attach to test object)
|
||||
3. Add hardware (DAS modules, TOM modules)
|
||||
4. Configure channels (map sensors to hardware)
|
||||
5. Set triggers (level triggers, time triggers)
|
||||
6. Configure data export formats
|
||||
|
||||
- **Arming Sequences**:
|
||||
- Pre-arm checks (diagnostics, voltage, temperature)
|
||||
- TOM safety checks
|
||||
- Clock synchronization
|
||||
- Final arm confirmation
|
||||
|
||||
- **Data Collection**:
|
||||
- Real-time monitoring options
|
||||
- Data streaming modes
|
||||
- Event detection
|
||||
|
||||
- **Post-Test**:
|
||||
- Download procedures
|
||||
- Export formats (Diadem, CSV, HDF5, ISO, TDM)
|
||||
- Report generation
|
||||
|
||||
### 4.2 Configuration Settings (Critical - 699-line config file)
|
||||
**Purpose**: Explain obscure but critical settings
|
||||
|
||||
**Key categories to document**:
|
||||
- **Hardware Discovery**: Multicast auto-discovery, IP ranges
|
||||
- **Real-time**: Polling intervals, optimization settings
|
||||
- **Database**: Connection strings, logging levels
|
||||
- **Export**: ISO compliance, CSV delimiters, file naming
|
||||
- **Squib Fire**: Fire modes (CAP, CONSTANT), tolerance settings
|
||||
- **Diagnostics**: Sample rates, filtering options
|
||||
|
||||
**Notable settings**:
|
||||
- `LocalDbHost`: Database server location
|
||||
- `RealtimeDelayBetweenPolls`: 4ms default
|
||||
- `DiagnosticsSampleRateHz`: 10000 Hz
|
||||
- `SampleRateAAFilterRatio`: 5 (anti-aliasing)
|
||||
- `AllowedVoltageInsertionErrorPercent`: 1%
|
||||
- `PowerAndBattery`: Battery monitoring settings
|
||||
|
||||
---
|
||||
|
||||
## 5. Error Handling & Troubleshooting (MEDIUM PRIORITY)
|
||||
|
||||
### 5.1 Common Error Codes
|
||||
**What to gather**:
|
||||
- `ErrorCodes.cs` definitions
|
||||
- Database error codes (sp_ procedures)
|
||||
- Hardware-specific error messages
|
||||
- Connection timeout scenarios
|
||||
|
||||
### 5.2 Diagnostic Procedures
|
||||
**What to gather**:
|
||||
- Hardware discovery diagnostics
|
||||
- Digital input diagnostics
|
||||
- CAN diagnostics
|
||||
- TCDiagnosticResult handling
|
||||
- Squib resistance checks
|
||||
|
||||
---
|
||||
|
||||
## 6. Export & Integration Formats (LOW PRIORITY but important)
|
||||
|
||||
### 6.1 Supported Export Formats
|
||||
**What to gather**:
|
||||
- **IRIG CH10** (standard for test data)
|
||||
- **ISO 17469** (automotive test data)
|
||||
- **Diadem XML** (National Instruments)
|
||||
- **CSV/TSV** (text formats)
|
||||
- **HDF5** (hierarchical data)
|
||||
- **TDM/TDMS** (NI test data)
|
||||
|
||||
### 6.2 External System Integration
|
||||
**What to gather**:
|
||||
- CANFD API integration
|
||||
- Equipment exchange formats
|
||||
- Third-party sensor import (CS3, TDC, EQX, SIF, XML)
|
||||
|
||||
---
|
||||
|
||||
## 7. Testing & Validation Data (MEDIUM PRIORITY)
|
||||
|
||||
### 7.1 Unit Tests
|
||||
**What to gather**:
|
||||
- Existing NUnit test suite (DatabaseUnitTesting, StateMachine.Tests, SensorDB.Test)
|
||||
- Test data examples
|
||||
- Expected output formats
|
||||
- Regression test scenarios
|
||||
|
||||
### 7.2 Sample Test Setups
|
||||
**What to gather**:
|
||||
- Sample test configuration files
|
||||
- Test setup templates (.tts files)
|
||||
- Hardware configuration files
|
||||
- Sensor databases
|
||||
|
||||
---
|
||||
|
||||
## 8. Installation & Deployment (LOW PRIORITY)
|
||||
|
||||
### 8.1 Installer Documentation
|
||||
**What to gather**:
|
||||
- InstallShield custom actions
|
||||
- SQL LocalDB instance management
|
||||
- Driver installation (WINUSB, HID)
|
||||
- Licensing system (Portable.BouncyCastle, CoreCompat.Portable.Licensing)
|
||||
|
||||
### 8.2 Database Schema
|
||||
**What to gather**:
|
||||
- Database version table structure
|
||||
- Stored procedure versions
|
||||
- Migration scripts (473 SQL files in `DataPRO_sql/`)
|
||||
- Indexes and performance optimizations
|
||||
|
||||
---
|
||||
|
||||
## 9. Performance Considerations (MEDIUM PRIORITY)
|
||||
|
||||
### 9.1 Known Performance Bottlenecks
|
||||
**What to gather**:
|
||||
- Large file handling (gcAllowVeryLargeObjects enabled)
|
||||
- Database query optimization patterns
|
||||
- Memory allocation patterns
|
||||
- Real-time data buffering strategies
|
||||
|
||||
### 9.2 Configuration Optimization
|
||||
**What to gather**:
|
||||
- `MaxSamplesToFilter`: 100 million
|
||||
- `ReceiveBufferSizeBytes`: 65536
|
||||
- `SendBufferSizeBytes`: 65536
|
||||
- Concurrent download settings
|
||||
- Cache settings
|
||||
|
||||
---
|
||||
|
||||
## 10. Licensing & Compliance (LOW PRIORITY)
|
||||
|
||||
### 10.1 Licensing System
|
||||
**What to gather**:
|
||||
- License property structures
|
||||
- Licensing API endpoint (`http://dtslicensing/`)
|
||||
- Feature flags and entitlements
|
||||
- Trial vs full license differences
|
||||
|
||||
### 10.2 Compliance Standards
|
||||
**What to gather**:
|
||||
- ISO 9001 requirements for test data
|
||||
- Automotive industry standards (ASPICE, ISO 26262 if applicable)
|
||||
- Data retention requirements
|
||||
|
||||
---
|
||||
|
||||
## Priority-Based Gathering Plan
|
||||
|
||||
### Phase 1 (Week 1-2): Core API Documentation
|
||||
- [ ] Document DbAPI namespace
|
||||
- [ ] Document DTS.DASLib.Service namespace
|
||||
- [ ] Document DTS.Common core classes
|
||||
- [ ] Create database schema documentation
|
||||
|
||||
### Phase 2 (Week 3-4): Hardware Documentation
|
||||
- [ ] Document SLICE hardware family
|
||||
- [ ] Document TDAS hardware
|
||||
- [ ] Document PowerPRO & Ribeye
|
||||
- [ ] Document sensor interfaces
|
||||
|
||||
### Phase 3 (Week 5-6): Workflows & Configuration
|
||||
- [ ] Document testing workflows
|
||||
- [ ] Document configuration system
|
||||
- [ ] Document error handling
|
||||
- [ ] Create troubleshooting guide
|
||||
|
||||
### Phase 4 (Week 7-8): Advanced Topics
|
||||
- [ ] Document export formats
|
||||
- [ ] Document test data
|
||||
- [ ] Document performance tuning
|
||||
- [ ] Document licensing
|
||||
|
||||
---
|
||||
|
||||
## Recommended Data Formats for Chatbot Training
|
||||
|
||||
### 1. Structured Documentation
|
||||
- Markdown files with clear hierarchies
|
||||
- YAML/JSON for configuration schemas
|
||||
- CSV for lookup tables (error codes, hardware specifications)
|
||||
|
||||
### 2. Code Examples
|
||||
- C# code snippets with comments
|
||||
- SQL stored procedure examples
|
||||
- Configuration file examples
|
||||
|
||||
### 3. Dialogue Patterns
|
||||
- Common user questions
|
||||
- Troubleshooting dialogues
|
||||
- Configuration guidance conversations
|
||||
|
||||
### 4. Knowledge Graph
|
||||
- Class relationships
|
||||
- Hardware dependencies
|
||||
- Workflow sequences
|
||||
|
||||
---
|
||||
|
||||
## Quick Start: First 10 Files to Document
|
||||
|
||||
1. **DataPRO/DbAPI/DbAPI.cs** (375 lines) - Database API entry point
|
||||
2. **DataPRO/IService/Modules/SLICE Service/SLICE Service.cs** - Main hardware service
|
||||
3. **DataPRO/DbAPI/Database/IDatabase.cs** - Database interface
|
||||
4. **DataPRO/DbAPI/DAS/IDataRecorders.cs** - Hardware interface
|
||||
5. **DataPRO/DbAPI/Sensors/ISensors.cs** - Sensor interface
|
||||
6. **DataPRO/DbAPI/TestSetups/ITestSetups.cs** - Test setup interface
|
||||
7. **Common/DTS.Common.DataModel/Classes/Enums.cs** - All enums
|
||||
8. **Common/DTS.Common.DAS.Concepts/DAS/Channel/Channel.cs** - Channel model
|
||||
9. **Common/DTS.Common.Serialization/IRIGCH10/TMATS/TMATS.cs** - IRIG format
|
||||
10. **DataPRO/DataPRO/app.config** (699 lines) - Critical configuration
|
||||
|
||||
---
|
||||
|
||||
## Next Steps
|
||||
|
||||
Would you like me to:
|
||||
1. **Create detailed documentation stubs** for the top 10 priority files?
|
||||
2. **Generate SQL documentation** for the 473 database procedures?
|
||||
3. **Build a knowledge base schema** for the chatbot?
|
||||
4. **Extract and explain** a specific subsystem (e.g., SLICE arming sequence)?
|
||||
5. **Create sample Q&A pairs** for common user scenarios?
|
||||
|
||||
Let me know which direction you'd like to take first, and I'll help you build out the engineering assistant's knowledge base!
|
||||
190
2026-04-15 Qwen3-Coder-Next-FP8 First Report.md
Normal file
190
2026-04-15 Qwen3-Coder-Next-FP8 First Report.md
Normal file
@@ -0,0 +1,190 @@
|
||||
# Comprehensive Plan: DataPRO Project Enhancement & Modernization
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
### Current Technology Stack
|
||||
- **Primary Framework**: .NET Framework 4.5.2-4.8 (legacy, not cross-platform)
|
||||
- **UI Framework**: WPF with Prism 7.x + Unity DI container
|
||||
- **Database**: SQL Server LocalDB (User Instances)
|
||||
- **Architecture Pattern**: Modular composite application with MVVM pattern
|
||||
- **Languages**: C# (predominantly), some VB.NET interop
|
||||
|
||||
### Project Structure
|
||||
```
|
||||
├── Common/ (19+ libraries - reusable components)
|
||||
├── DataPRO/ (main application + modules)
|
||||
├── DTS Viewer/ (secondary viewer application)
|
||||
└── Installer/ (InstallShield-based deployment)
|
||||
```
|
||||
|
||||
### Key Components
|
||||
- **DataPRO**: Main application (WinForms/WPF hybrid, x86/x64 builds)
|
||||
- **DataPRO.Core**: Plugin architecture, settings management, service management
|
||||
- **IService**: Hardware service layer (~200 classes managing SLICE/TDAS/Ribeye hardware)
|
||||
- **DbAPI**: Database access layer (new SDK-style project)
|
||||
- **DatabaseMigrator**: Version migration tool for LocalDB user instances
|
||||
- **473 SQL files**: Database schema changes, stored procedures
|
||||
|
||||
---
|
||||
|
||||
## Improvement Plan
|
||||
|
||||
### Phase 1: Foundation Stabilization (Weeks 1-4)
|
||||
**Priority: HIGH**
|
||||
|
||||
#### 1.1 Test Infrastructure
|
||||
- **Current**: NUnit 3.12.0, limited test coverage
|
||||
- **Actions**:
|
||||
- Expand unit test coverage to ~70%+ (prioritize core logic: sensor math, channel processing)
|
||||
- Add integration tests for database operations
|
||||
- Implement CI/CD pipeline (Azure DevOps or GitHub Actions)
|
||||
- Add code quality tools: SonarQube/AltCover for coverage, StyleCop for consistency
|
||||
|
||||
#### 1.2 Dependency Management
|
||||
- **Current**: Mixed packages.config + project references
|
||||
- **Actions**:
|
||||
- Migrate all `packages.config` to `PackageReference` format
|
||||
- Consolidate duplicate libraries (Newtonsoft.Json versions, Prism libraries)
|
||||
- Audit third-party dependencies for security vulnerabilities
|
||||
|
||||
#### 1.3 Configuration Modernization
|
||||
- **Current**: 699-line app.config with hardcoded secrets
|
||||
- **Actions**:
|
||||
- Extract sensitive values (passwords) to encrypted configuration or secure vault
|
||||
- Implement configuration validation
|
||||
- Migrate from legacy `<applicationSettings>` to strongly-typed Options pattern
|
||||
|
||||
---
|
||||
|
||||
### Phase 2: Architecture Modernization (Weeks 5-12)
|
||||
**Priority: MEDIUM**
|
||||
|
||||
#### 2.1 .NET Target Framework Upgrade
|
||||
- **Current**: .NET Framework 4.5.2/4.8 (Windows-only)
|
||||
- **Target**: .NET 8.0 (LTS, cross-platform, performance gains)
|
||||
- **Approach**: Gradual migration strategy
|
||||
1. Upgrade to .NET 6.0 first (easier migration path)
|
||||
2. Update all projects to SDK-style `.csproj` format
|
||||
3. Refactor WinForms components to WPF or modern equivalent
|
||||
|
||||
**Challenges**:
|
||||
- ComponentOne WPF controls (need compatibility check)
|
||||
- InstallShield installer (may need replacement with MSIX or WiX)
|
||||
|
||||
#### 2.2 Dependency Injection Container
|
||||
- **Current**: Unity Container (deprecated, no active development)
|
||||
- **Target**: Microsoft.Extensions.DependencyInjection (standard .NET DI)
|
||||
- **Benefits**:
|
||||
- Active Microsoft support
|
||||
- Better integration with modern .NET
|
||||
- Cleaner API
|
||||
|
||||
#### 2.3 Database Access Layer
|
||||
- **Current**: Legacy DbAPI with 473 SQL scripts
|
||||
- **Actions**:
|
||||
- Introduce Entity Framework Core or Dapper for type-safe database access
|
||||
- Implement database version migrations with FluentMigrator or EF Core Migrations
|
||||
- Add database connection pooling optimization
|
||||
|
||||
#### 2.4 Module Architecture
|
||||
- **Current**: Prism DirectoryModuleCatalog (file-based discovery)
|
||||
- **Actions**:
|
||||
- Add assembly scanning with dependency constraints
|
||||
- Implement module versioning
|
||||
- Add module health checks and lifecycle management
|
||||
|
||||
---
|
||||
|
||||
### Phase 3: Performance Optimization (Weeks 13-16)
|
||||
**Priority: HIGH**
|
||||
|
||||
#### 3.1 Memory Management
|
||||
- **Current**: Applications can consume large memory (gcAllowVeryLargeObjects enabled)
|
||||
- **Actions**:
|
||||
- Profile memory usage (dotMemory or Visual Studio Diagnostic Tools)
|
||||
- Implement lazy loading for large data structures
|
||||
- Add object pooling for frequently created objects
|
||||
|
||||
#### 3.2 Database Query Optimization
|
||||
- **Actions**:
|
||||
- Add database query profiling
|
||||
- Implement caching layer for frequently accessed data
|
||||
- Optimize stored procedures (30+ queries have been cached)
|
||||
|
||||
#### 3.3 Real-time Processing
|
||||
- **Current**: polling-based real-time updates (4ms intervals)
|
||||
- **Actions**:
|
||||
- Evaluate reactive extensions (Rx) for event-driven updates
|
||||
- Consider background services with background workers
|
||||
- Optimize UDP multicast listening
|
||||
|
||||
---
|
||||
|
||||
### Phase 4: Developer Experience (Weeks 17-20)
|
||||
**Priority: MEDIUM**
|
||||
|
||||
#### 4.1 Build & Deployment
|
||||
- **Actions**:
|
||||
- Implement automated build pipeline
|
||||
- Create hotfix deployment strategy
|
||||
- Add application self-update mechanism
|
||||
|
||||
#### 4.2 Documentation
|
||||
- **Actions**:
|
||||
- Generate API documentation with DocFX
|
||||
- Create architecture decision records (ADRs)
|
||||
- Add code comments for public APIs
|
||||
|
||||
#### 4.3 Monitoring & Telemetry
|
||||
- **Actions**:
|
||||
- Implement structured logging (Serilog or Microsoft.Extensions.Logging)
|
||||
- Add application health monitoring
|
||||
- Set up error reporting (Sentry or Application Insights)
|
||||
|
||||
---
|
||||
|
||||
## Recommended Starting Points
|
||||
|
||||
### Immediate Action Items (Next 2 Weeks):
|
||||
|
||||
1. **Set up CI/CD pipeline**
|
||||
- GitHub Actions/Azure DevOps build
|
||||
- Automated test execution on pull requests
|
||||
|
||||
2. **Add code quality gates**
|
||||
- Configure SonarQube or similar
|
||||
- Enforce coding standards
|
||||
|
||||
3. **Create feature branch strategy**
|
||||
- trunk-based development or GitFlow
|
||||
- Define release cadence
|
||||
|
||||
4. **Start migration to SDK-style projects**
|
||||
- Convert one non-critical module first
|
||||
- Validate build process
|
||||
|
||||
5. **Performance baseline**
|
||||
- Measure startup time, memory usage, database query times
|
||||
- Document current metrics
|
||||
|
||||
---
|
||||
|
||||
## Risk Assessment
|
||||
|
||||
| Risk | Impact | Mitigation |
|
||||
|------|--------|------------|
|
||||
| .NET Framework → .NET 6+ breaking changes | HIGH | Phase-by-phase migration, extensive testing |
|
||||
| Database schema migration issues | HIGH | Backup strategies, rollback procedures |
|
||||
| Dependency conflicts | MEDIUM | Gradual package updates, dependency analysis |
|
||||
| Installer changes | MEDIUM | Test thoroughly with different OS versions |
|
||||
|
||||
---
|
||||
|
||||
## Next Steps
|
||||
|
||||
Before proceeding, please confirm:
|
||||
1. Database migration strategy (keep LocalDB, migrate to SQLite/SQL Server Express?)
|
||||
2. UI framework direction (modernize WPF, migrate to MAUI?)
|
||||
3. Deployment Targets (on-premises only, or cloud-hosted?)
|
||||
4. Third-party dependencies (bound to ComponentOne, open to alternatives?)
|
||||
5. Testing priorities (which modules need test coverage first?)
|
||||
55
AGENTS.md
Normal file
55
AGENTS.md
Normal file
@@ -0,0 +1,55 @@
|
||||
# opencode Configuration
|
||||
|
||||
This file configures opencode for working with the DataPRO codebase.
|
||||
|
||||
## Model Configuration
|
||||
|
||||
Configured to use vast.ai hosted GLM-5-FP8 model with 131k context window.
|
||||
|
||||
## MCP Servers
|
||||
|
||||
### vastai-ctl
|
||||
Control vast.ai GPU instances (start, stop, status).
|
||||
|
||||
### retrieval
|
||||
Semantic search over code and enrichment documentation.
|
||||
- `vector_search(query)` - Find relevant code by meaning
|
||||
- `get_module_summary(path)` - Get AI-generated module docs
|
||||
- `list_enriched_modules()` - List all enriched modules
|
||||
|
||||
## AI-Generated Artifacts
|
||||
|
||||
This codebase has pre-computed AI artifacts for efficient assistance:
|
||||
|
||||
| Location | Purpose |
|
||||
|----------|---------|
|
||||
| `GLM5Analysis/Architecture.md` | System architecture overview |
|
||||
| `GLM5Analysis/PatternLibrary/` | Reusable code patterns |
|
||||
| `GLM5Analysis/PromptTemplates/` | Task-specific guides |
|
||||
| `GLM5Analysis/TestScaffolds/` | Test templates |
|
||||
| `enriched-qwen3-coder-next/` | Module-level documentation |
|
||||
|
||||
**Always check `GLM5Analysis/` before starting a task.**
|
||||
|
||||
## Workflow
|
||||
|
||||
1. Check `GLM5Analysis/Architecture.md` for system context
|
||||
2. Check `GLM5Analysis/PromptTemplates/` for task-specific guidance
|
||||
3. Use `vector_search()` to find relevant code
|
||||
4. Use `get_module_summary()` for detailed module docs
|
||||
5. Follow patterns from `GLM5Analysis/PatternLibrary/`
|
||||
|
||||
## Build Commands
|
||||
|
||||
```bash
|
||||
# Build solution (requires Windows/Visual Studio)
|
||||
msbuild DataPRO/DataPRO.sln /p:Configuration=Debug
|
||||
|
||||
# Run tests
|
||||
# Tests are NUnit-based in DataPRO/UnitTest/
|
||||
```
|
||||
|
||||
## Important Files
|
||||
|
||||
- `GIT Migration.md` - Plan for SVN to Git migration
|
||||
- `AGENTS.md` - Instructions for AI assistants
|
||||
1
Common/DTS.Common.CPU/.svn/entries
Normal file
1
Common/DTS.Common.CPU/.svn/entries
Normal file
@@ -0,0 +1 @@
|
||||
12
|
||||
1
Common/DTS.Common.CPU/.svn/format
Normal file
1
Common/DTS.Common.CPU/.svn/format
Normal file
@@ -0,0 +1 @@
|
||||
12
|
||||
@@ -0,0 +1,134 @@
|
||||
using System;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.Windows.Media.Imaging;
|
||||
using DTS.Common.CPU;
|
||||
using DTS.Common.Interface;
|
||||
using Microsoft.Practices.Prism.Modularity;
|
||||
using Microsoft.Practices.Unity;
|
||||
|
||||
[assembly: CPUName()]
|
||||
[assembly: CUPImage()]
|
||||
namespace DTS.Common.CPU
|
||||
{
|
||||
[Export(typeof(IModule))]
|
||||
[Module(ModuleName = "CPU")]
|
||||
public class CPUModule : IModule
|
||||
{
|
||||
/// <summary>
|
||||
/// Injected unity container
|
||||
/// </summary>
|
||||
private readonly IUnityContainer _unityContainer;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CPUModule"/> class.
|
||||
/// </summary>
|
||||
/// <param name="unityContainer">Obtained reference of the unity container by using dependency injection.</param>
|
||||
public CPUModule(IUnityContainer unityContainer)
|
||||
{
|
||||
|
||||
_unityContainer = unityContainer;
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
// Register View & View-Model with Unity dependency injection container as a singleton.
|
||||
_unityContainer.RegisterType<ICPUEngine, CPUEngine>();
|
||||
//_unityContainer.RegisterType<IPropertyViewModel, PropertyViewModel>();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attribute class contains assembly name
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false)]
|
||||
public class CPUNameAttribute : TextAttribute
|
||||
{
|
||||
private readonly string _assemblyName;
|
||||
public CPUNameAttribute() : this(null) { }
|
||||
|
||||
public CPUNameAttribute(string s)
|
||||
{
|
||||
_assemblyName = "CPUAsssembly";
|
||||
}
|
||||
|
||||
public override string AssemblyName
|
||||
{
|
||||
get { return _assemblyName; }
|
||||
}
|
||||
|
||||
public override Type GetAttributeType()
|
||||
{
|
||||
return typeof(TextAttribute);
|
||||
}
|
||||
|
||||
public override string GetAssemblyName()
|
||||
{
|
||||
return AssemblyName;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attribute class contains assembly image and name - used on the Main screen to display available components
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false)]
|
||||
public class CUPImageAttribute : ImageAttribute
|
||||
{
|
||||
private BitmapImage _img;
|
||||
|
||||
public CUPImageAttribute() : this(null) { }
|
||||
public override BitmapImage AssemblyImage
|
||||
{
|
||||
get { _img = AssemblyInfo.GetImage(AssemblyNames.CPU.ToString()); return _img; }
|
||||
}
|
||||
public CUPImageAttribute(string s)
|
||||
{
|
||||
_img = AssemblyInfo.GetImage(AssemblyNames.CPU.ToString());
|
||||
}
|
||||
|
||||
public override Type GetAttributeType()
|
||||
{
|
||||
return typeof(ImageAttribute);
|
||||
}
|
||||
|
||||
public override BitmapImage GetAssemblyImage()
|
||||
{
|
||||
return AssemblyImage;
|
||||
}
|
||||
|
||||
public override string GetAssemblyName()
|
||||
{
|
||||
return AssemblyName;
|
||||
}
|
||||
|
||||
public override eAssemblyRegion GetAssemblyRegion()
|
||||
{
|
||||
return AssemblyRegion;
|
||||
}
|
||||
|
||||
public override string GetAssemblyGroup()
|
||||
{
|
||||
return AssemblyGroup;
|
||||
}
|
||||
|
||||
private string _name;
|
||||
public override string AssemblyName
|
||||
{
|
||||
get { _name = AssemblyNames.CPU.ToString(); return _name; }
|
||||
}
|
||||
|
||||
private string _group;
|
||||
public override string AssemblyGroup
|
||||
{
|
||||
get { _group = eAssemblyGroups.Viewer.ToString(); return _group; }
|
||||
}
|
||||
|
||||
|
||||
private eAssemblyRegion _region;
|
||||
public override eAssemblyRegion AssemblyRegion
|
||||
{
|
||||
get { _region = eAssemblyRegion.NotAssigned; return _region; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
using System.ComponentModel;
|
||||
using Microsoft.Practices.Prism.Events;
|
||||
using Microsoft.Practices.Prism.Interactivity.InteractionRequest;
|
||||
using Microsoft.Practices.Prism.Regions;
|
||||
using Microsoft.Practices.Unity;
|
||||
using Microsoft.Practices.ServiceLocation;
|
||||
using DTS.Common.Events;
|
||||
using DTS.Common.Interface;
|
||||
using DTS.Common.Base;
|
||||
using System;
|
||||
|
||||
namespace DTS.Common.CPU
|
||||
{
|
||||
public class CPUEngine : ICPUEngine
|
||||
{
|
||||
|
||||
private IEventAggregator _eventAggregator { get; set; }
|
||||
private new IRegionManager _regionManager;
|
||||
private IUnityContainer _unityContainer { get; set; }
|
||||
public IServiceLocator _serviceLocator { get; private set; }
|
||||
|
||||
public InteractionRequest<Notification> NotificationRequest { get; private set; }
|
||||
public new InteractionRequest<Confirmation> ConfirmationRequest { get; private set; }
|
||||
|
||||
public CPUEngine()
|
||||
{
|
||||
_unityContainer= ServiceLocator.Current.GetInstance<IUnityContainer>();
|
||||
_eventAggregator = _unityContainer.Resolve<IEventAggregator>();
|
||||
_serviceLocator = _unityContainer.Resolve<IServiceLocator>();
|
||||
|
||||
NotificationRequest = new InteractionRequest<Notification>();
|
||||
ConfirmationRequest = new InteractionRequest<Confirmation>();
|
||||
|
||||
_eventAggregator.GetEvent<RaiseNotification>().Subscribe(OnRaiseNotification);
|
||||
_eventAggregator.GetEvent<ShowStatus>().Subscribe(OnStatusChange);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Private Event handler for Status change event.
|
||||
/// </summary>
|
||||
private void OnStatusChange(StatusInfo content)
|
||||
{
|
||||
//IsBusy = content.IsBusy;
|
||||
//IsBusyMessage = content.Text;
|
||||
//NotificationRequest.Raise(new Notification { Content = content, Title = "DataPRO" });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Private Event handler for RaiseNotification event.
|
||||
/// </summary>
|
||||
private void OnRaiseNotification(NotificationContentEventArgs eventArgsWithTitle)
|
||||
{
|
||||
// Notification object expects a NotificationContentEventArgsWithoutTitle object and a Title string.
|
||||
var eventArgsWithoutTitle = new NotificationContentEventArgs(eventArgsWithTitle.Message, eventArgsWithTitle.MessageDetails, eventArgsWithTitle.Image);
|
||||
|
||||
NotificationRequest.Raise(new Notification
|
||||
{
|
||||
Content = eventArgsWithoutTitle,
|
||||
Title = eventArgsWithTitle.Title
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public new event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
public void OnPropertyChanged(string propertyName)
|
||||
{
|
||||
var eventHandler = PropertyChanged;
|
||||
if (eventHandler != null) { eventHandler(this, new PropertyChangedEventArgs(propertyName)); }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace DTS.Common.CPU
|
||||
{
|
||||
public class BREngine
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{761A8290-184D-4610-967C-25B08D27A1A9}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>DTS.Common.CPU</RootNamespace>
|
||||
<AssemblyName>DTS.Common.CPU</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<SccProjectName>
|
||||
</SccProjectName>
|
||||
<SccLocalPath>
|
||||
</SccLocalPath>
|
||||
<SccAuxPath>
|
||||
</SccAuxPath>
|
||||
<SccProvider>
|
||||
</SccProvider>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.Expression.Interactions, Version=4.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\DTS.Common\lib\PrismLibrary\Microsoft.Expression.Interactions.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Practices.Prism">
|
||||
<HintPath>..\DTS.Common\lib\PrismLibrary\Microsoft.Practices.Prism.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Practices.Prism.Interactivity">
|
||||
<HintPath>..\DTS.Common\lib\PrismLibrary\Microsoft.Practices.Prism.Interactivity.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Practices.Prism.UnityExtensions">
|
||||
<HintPath>..\DTS.Common\lib\PrismLibrary\Microsoft.Practices.Prism.UnityExtensions.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Practices.ServiceLocation">
|
||||
<HintPath>..\DTS.Common\lib\PrismLibrary\Microsoft.Practices.ServiceLocation.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Practices.Unity, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\DTS.Common\lib\PrismLibrary\Microsoft.Practices.Unity.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Practices.Unity.Interception">
|
||||
<HintPath>..\DTS.Common\lib\PrismLibrary\Microsoft.Practices.Unity.Interception.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="PresentationCore" />
|
||||
<Reference Include="PresentationFramework" />
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.ComponentModel.Composition" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Windows" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Windows.Interactivity, Version=4.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\DTS.Common\lib\System.Windows.Interactivity.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Xaml" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="WindowsBase" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Classes\BREngine.cs" />
|
||||
<Compile Include="Classes\CPUEngine.cs" />
|
||||
<Compile Include="CPUModule.cs" />
|
||||
<Compile Include="Properties\Annotations.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\DTS.Common.Core\DTS.Common.Core.csproj">
|
||||
<Project>{fab1f470-1574-4301-b56e-d3364aa93679}</Project>
|
||||
<Name>DTS.Common.Core</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\DTS.Common\DTS.Common.csproj">
|
||||
<Project>{114edc77-f3b5-4576-a91b-40818d503b55}</Project>
|
||||
<Name>DTS.Common</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent>copy "$(TargetPath)" "$(SolutionDir)..\RunTimeModules\$(TargetFileName)"</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("DTS.Common.CPU")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("DTS.Common.CPU")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2017")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("a68ef337-debf-4265-8dec-8acf01e76ee6")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
BIN
Common/DTS.Common.CPU/.svn/wc.db
Normal file
BIN
Common/DTS.Common.CPU/.svn/wc.db
Normal file
Binary file not shown.
0
Common/DTS.Common.CPU/.svn/wc.db-journal
Normal file
0
Common/DTS.Common.CPU/.svn/wc.db-journal
Normal file
134
Common/DTS.Common.CPU/CPUModule.cs
Normal file
134
Common/DTS.Common.CPU/CPUModule.cs
Normal file
@@ -0,0 +1,134 @@
|
||||
using System;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.Windows.Media.Imaging;
|
||||
using DTS.Common.CPU;
|
||||
using DTS.Common.Interface;
|
||||
using Microsoft.Practices.Prism.Modularity;
|
||||
using Microsoft.Practices.Unity;
|
||||
|
||||
[assembly: CPUName()]
|
||||
[assembly: CUPImage()]
|
||||
namespace DTS.Common.CPU
|
||||
{
|
||||
[Export(typeof(IModule))]
|
||||
[Module(ModuleName = "CPU")]
|
||||
public class CPUModule : IModule
|
||||
{
|
||||
/// <summary>
|
||||
/// Injected unity container
|
||||
/// </summary>
|
||||
private readonly IUnityContainer _unityContainer;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CPUModule"/> class.
|
||||
/// </summary>
|
||||
/// <param name="unityContainer">Obtained reference of the unity container by using dependency injection.</param>
|
||||
public CPUModule(IUnityContainer unityContainer)
|
||||
{
|
||||
|
||||
_unityContainer = unityContainer;
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
// Register View & View-Model with Unity dependency injection container as a singleton.
|
||||
_unityContainer.RegisterType<ICPUEngine, CPUEngine>();
|
||||
//_unityContainer.RegisterType<IPropertyViewModel, PropertyViewModel>();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attribute class contains assembly name
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false)]
|
||||
public class CPUNameAttribute : TextAttribute
|
||||
{
|
||||
private readonly string _assemblyName;
|
||||
public CPUNameAttribute() : this(null) { }
|
||||
|
||||
public CPUNameAttribute(string s)
|
||||
{
|
||||
_assemblyName = "CPUAsssembly";
|
||||
}
|
||||
|
||||
public override string AssemblyName
|
||||
{
|
||||
get { return _assemblyName; }
|
||||
}
|
||||
|
||||
public override Type GetAttributeType()
|
||||
{
|
||||
return typeof(TextAttribute);
|
||||
}
|
||||
|
||||
public override string GetAssemblyName()
|
||||
{
|
||||
return AssemblyName;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attribute class contains assembly image and name - used on the Main screen to display available components
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false)]
|
||||
public class CUPImageAttribute : ImageAttribute
|
||||
{
|
||||
private BitmapImage _img;
|
||||
|
||||
public CUPImageAttribute() : this(null) { }
|
||||
public override BitmapImage AssemblyImage
|
||||
{
|
||||
get { _img = AssemblyInfo.GetImage(AssemblyNames.CPU.ToString()); return _img; }
|
||||
}
|
||||
public CUPImageAttribute(string s)
|
||||
{
|
||||
_img = AssemblyInfo.GetImage(AssemblyNames.CPU.ToString());
|
||||
}
|
||||
|
||||
public override Type GetAttributeType()
|
||||
{
|
||||
return typeof(ImageAttribute);
|
||||
}
|
||||
|
||||
public override BitmapImage GetAssemblyImage()
|
||||
{
|
||||
return AssemblyImage;
|
||||
}
|
||||
|
||||
public override string GetAssemblyName()
|
||||
{
|
||||
return AssemblyName;
|
||||
}
|
||||
|
||||
public override eAssemblyRegion GetAssemblyRegion()
|
||||
{
|
||||
return AssemblyRegion;
|
||||
}
|
||||
|
||||
public override string GetAssemblyGroup()
|
||||
{
|
||||
return AssemblyGroup;
|
||||
}
|
||||
|
||||
private string _name;
|
||||
public override string AssemblyName
|
||||
{
|
||||
get { _name = AssemblyNames.CPU.ToString(); return _name; }
|
||||
}
|
||||
|
||||
private string _group;
|
||||
public override string AssemblyGroup
|
||||
{
|
||||
get { _group = eAssemblyGroups.Viewer.ToString(); return _group; }
|
||||
}
|
||||
|
||||
|
||||
private eAssemblyRegion _region;
|
||||
public override eAssemblyRegion AssemblyRegion
|
||||
{
|
||||
get { _region = eAssemblyRegion.NotAssigned; return _region; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
7
Common/DTS.Common.CPU/Classes/BREngine.cs
Normal file
7
Common/DTS.Common.CPU/Classes/BREngine.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
namespace DTS.Common.CPU
|
||||
{
|
||||
public class BREngine
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
72
Common/DTS.Common.CPU/Classes/CPUEngine.cs
Normal file
72
Common/DTS.Common.CPU/Classes/CPUEngine.cs
Normal file
@@ -0,0 +1,72 @@
|
||||
using System.ComponentModel;
|
||||
using Microsoft.Practices.Prism.Events;
|
||||
using Microsoft.Practices.Prism.Interactivity.InteractionRequest;
|
||||
using Microsoft.Practices.Prism.Regions;
|
||||
using Microsoft.Practices.Unity;
|
||||
using Microsoft.Practices.ServiceLocation;
|
||||
using DTS.Common.Events;
|
||||
using DTS.Common.Interface;
|
||||
using DTS.Common.Base;
|
||||
using System;
|
||||
|
||||
namespace DTS.Common.CPU
|
||||
{
|
||||
public class CPUEngine : ICPUEngine
|
||||
{
|
||||
|
||||
private IEventAggregator _eventAggregator { get; set; }
|
||||
private new IRegionManager _regionManager;
|
||||
private IUnityContainer _unityContainer { get; set; }
|
||||
public IServiceLocator _serviceLocator { get; private set; }
|
||||
|
||||
public InteractionRequest<Notification> NotificationRequest { get; private set; }
|
||||
public new InteractionRequest<Confirmation> ConfirmationRequest { get; private set; }
|
||||
|
||||
public CPUEngine()
|
||||
{
|
||||
_unityContainer= ServiceLocator.Current.GetInstance<IUnityContainer>();
|
||||
_eventAggregator = _unityContainer.Resolve<IEventAggregator>();
|
||||
_serviceLocator = _unityContainer.Resolve<IServiceLocator>();
|
||||
|
||||
NotificationRequest = new InteractionRequest<Notification>();
|
||||
ConfirmationRequest = new InteractionRequest<Confirmation>();
|
||||
|
||||
_eventAggregator.GetEvent<RaiseNotification>().Subscribe(OnRaiseNotification);
|
||||
_eventAggregator.GetEvent<ShowStatus>().Subscribe(OnStatusChange);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Private Event handler for Status change event.
|
||||
/// </summary>
|
||||
private void OnStatusChange(StatusInfo content)
|
||||
{
|
||||
//IsBusy = content.IsBusy;
|
||||
//IsBusyMessage = content.Text;
|
||||
//NotificationRequest.Raise(new Notification { Content = content, Title = "DataPRO" });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Private Event handler for RaiseNotification event.
|
||||
/// </summary>
|
||||
private void OnRaiseNotification(NotificationContentEventArgs eventArgsWithTitle)
|
||||
{
|
||||
// Notification object expects a NotificationContentEventArgsWithoutTitle object and a Title string.
|
||||
var eventArgsWithoutTitle = new NotificationContentEventArgs(eventArgsWithTitle.Message, eventArgsWithTitle.MessageDetails, eventArgsWithTitle.Image);
|
||||
|
||||
NotificationRequest.Raise(new Notification
|
||||
{
|
||||
Content = eventArgsWithoutTitle,
|
||||
Title = eventArgsWithTitle.Title
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public new event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
public void OnPropertyChanged(string propertyName)
|
||||
{
|
||||
var eventHandler = PropertyChanged;
|
||||
if (eventHandler != null) { eventHandler(this, new PropertyChangedEventArgs(propertyName)); }
|
||||
}
|
||||
}
|
||||
}
|
||||
96
Common/DTS.Common.CPU/DTS.Common.CPU.csproj
Normal file
96
Common/DTS.Common.CPU/DTS.Common.CPU.csproj
Normal file
@@ -0,0 +1,96 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{761A8290-184D-4610-967C-25B08D27A1A9}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>DTS.Common.CPU</RootNamespace>
|
||||
<AssemblyName>DTS.Common.CPU</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<SccProjectName>
|
||||
</SccProjectName>
|
||||
<SccLocalPath>
|
||||
</SccLocalPath>
|
||||
<SccAuxPath>
|
||||
</SccAuxPath>
|
||||
<SccProvider>
|
||||
</SccProvider>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.Expression.Interactions, Version=4.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\DTS.Common\lib\PrismLibrary\Microsoft.Expression.Interactions.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Practices.Prism">
|
||||
<HintPath>..\DTS.Common\lib\PrismLibrary\Microsoft.Practices.Prism.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Practices.Prism.Interactivity">
|
||||
<HintPath>..\DTS.Common\lib\PrismLibrary\Microsoft.Practices.Prism.Interactivity.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Practices.Prism.UnityExtensions">
|
||||
<HintPath>..\DTS.Common\lib\PrismLibrary\Microsoft.Practices.Prism.UnityExtensions.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Practices.ServiceLocation">
|
||||
<HintPath>..\DTS.Common\lib\PrismLibrary\Microsoft.Practices.ServiceLocation.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Practices.Unity, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\DTS.Common\lib\PrismLibrary\Microsoft.Practices.Unity.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Practices.Unity.Interception">
|
||||
<HintPath>..\DTS.Common\lib\PrismLibrary\Microsoft.Practices.Unity.Interception.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="PresentationCore" />
|
||||
<Reference Include="PresentationFramework" />
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.ComponentModel.Composition" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Windows" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Windows.Interactivity, Version=4.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\DTS.Common\lib\System.Windows.Interactivity.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Xaml" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="WindowsBase" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Classes\BREngine.cs" />
|
||||
<Compile Include="Classes\CPUEngine.cs" />
|
||||
<Compile Include="CPUModule.cs" />
|
||||
<Compile Include="Properties\Annotations.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\DTS.Common.Core\DTS.Common.Core.csproj">
|
||||
<Project>{fab1f470-1574-4301-b56e-d3364aa93679}</Project>
|
||||
<Name>DTS.Common.Core</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\DTS.Common\DTS.Common.csproj">
|
||||
<Project>{114edc77-f3b5-4576-a91b-40818d503b55}</Project>
|
||||
<Name>DTS.Common</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent>copy "$(TargetPath)" "$(SolutionDir)..\RunTimeModules\$(TargetFileName)"</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
1039
Common/DTS.Common.CPU/Properties/Annotations.cs
Normal file
1039
Common/DTS.Common.CPU/Properties/Annotations.cs
Normal file
File diff suppressed because it is too large
Load Diff
36
Common/DTS.Common.CPU/Properties/AssemblyInfo.cs
Normal file
36
Common/DTS.Common.CPU/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("DTS.Common.CPU")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("DTS.Common.CPU")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2017")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("a68ef337-debf-4265-8dec-8acf01e76ee6")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
1
Common/DTS.Common.Calculations/.svn/entries
Normal file
1
Common/DTS.Common.Calculations/.svn/entries
Normal file
@@ -0,0 +1 @@
|
||||
12
|
||||
1
Common/DTS.Common.Calculations/.svn/format
Normal file
1
Common/DTS.Common.Calculations/.svn/format
Normal file
@@ -0,0 +1 @@
|
||||
12
|
||||
@@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace DTS.Common.Calculations
|
||||
{
|
||||
/// <summary>
|
||||
/// Filtered Channel Data
|
||||
/// simple class for holding generic data for calculations
|
||||
/// in the future I'd like to be able to accept channels with different units and convert them
|
||||
/// to a common unit, so I add support for that now
|
||||
/// </summary>
|
||||
public class ChannelData
|
||||
{
|
||||
/// <summary>
|
||||
/// Engineering units of Data
|
||||
/// </summary>
|
||||
public string Units { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Pre-Filtered EU data
|
||||
/// </summary>
|
||||
public double[] FilteredEU { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a ChannelData object
|
||||
/// </summary>
|
||||
/// <param name="units">Engineering units of data</param>
|
||||
public ChannelData(string units)
|
||||
{
|
||||
Units = units;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
using System;
|
||||
|
||||
namespace DTS.Common.Calculations
|
||||
{
|
||||
public class HeadInjuryCriterion
|
||||
{
|
||||
/// <summary>
|
||||
/// Calculates the head injury criterion given a resultant channel, and a desired clip length
|
||||
/// </summary>
|
||||
/// <param name="resultant">Acceleration vector (x,y,z resultant)</param>
|
||||
/// <param name="SPS">Actual sample rate</param>
|
||||
/// <param name="clipLengthMS">Length in ms </param>
|
||||
/// <returns>MAX Head Injury Criterion over the data input for the clip requested</returns>
|
||||
public static HICResult GetHeadInjuryCriterion(ChannelData resultant, double SPS, int clipLengthMS)
|
||||
{
|
||||
System.Diagnostics.Trace.Assert(SPS > 0, "Actual sample rate must be positive");
|
||||
System.Diagnostics.Trace.Assert(clipLengthMS > 0, "Clip length must be positive");
|
||||
|
||||
int maxHICPoint = int.MinValue;
|
||||
double maxHIC = int.MinValue;
|
||||
int maxHICEndPoint = int.MinValue;
|
||||
|
||||
int maxclip = Convert.ToInt32(Math.Ceiling(clipLengthMS * SPS / 1000D));
|
||||
|
||||
for (int clip = 1; clip <= maxclip; clip++)
|
||||
{
|
||||
System.Diagnostics.Trace.Assert(clip < resultant.FilteredEU.Length, string.Format("data must be atleast {0} ms", clipLengthMS));
|
||||
double clipInSeconds = clip / SPS;
|
||||
for (int i = 0; i < resultant.FilteredEU.Length - clip; i++)
|
||||
{
|
||||
//note we are exhaustively recalculating sums, we can do this much better without a doubt, but lets get the
|
||||
//first method done (brute force)
|
||||
//also note, definite integral doesn't include last point, so we have to add one point back in
|
||||
double integral = Integral.DefiniteIntegral(resultant.FilteredEU, i, i + clip, SPS);
|
||||
double hic = clipInSeconds * Math.Pow(integral / clipInSeconds, 2.5D);
|
||||
if (hic > maxHIC) { maxHIC = hic; maxHICPoint = i; maxHICEndPoint = i + clip; }
|
||||
}
|
||||
}
|
||||
return new HICResult(maxHIC, clipLengthMS, maxHICPoint, maxHICEndPoint);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// helper class for storing/handling hic results
|
||||
/// </summary>
|
||||
public class HICResult
|
||||
{
|
||||
public int StartSample { get; }
|
||||
public int EndSample { get; }
|
||||
public int HicLengthMS { get; }
|
||||
public double HIC { get; }
|
||||
/// <summary>
|
||||
/// constructs a new HIC result
|
||||
/// </summary>
|
||||
/// <param name="hic">HIC value</param>
|
||||
/// <param name="hicLength">length of HIC in ms</param>
|
||||
/// <param name="endSample">start sample of HIC</param>
|
||||
/// <param name="startSample">end sample of HIC</param>
|
||||
public HICResult(double hic, int hicLength, int startSample, int endSample)
|
||||
{
|
||||
StartSample = startSample;
|
||||
EndSample = endSample;
|
||||
HicLengthMS = hicLength;
|
||||
HIC = hic;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace DTS.Common.Calculations
|
||||
{
|
||||
public static class Resultant
|
||||
{
|
||||
/// <summary>
|
||||
/// generates a resultant channel given input vectors
|
||||
/// Will throw an assertion if lengths of data don't match, or if
|
||||
/// units don't match
|
||||
/// </summary>
|
||||
/// <param name="channels">List of channels to combine via
|
||||
/// sum of squares
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// resultant vector from sum of squares of inputs
|
||||
/// </returns>
|
||||
public static ChannelData GenerateResultantChannel(List<ChannelData> channels)
|
||||
{
|
||||
int length = (from ch in channels select ch.FilteredEU.Length).Max();
|
||||
foreach (var ch in channels) { System.Diagnostics.Trace.Assert(ch.FilteredEU.Length == length); }
|
||||
//make sure the channels are all the same units and lengths,
|
||||
//we assert here since the higher level should be expected to provide clean inputs
|
||||
var units = (from ch in channels select ch.Units).Distinct();
|
||||
System.Diagnostics.Trace.Assert(units.Count() == 1);
|
||||
|
||||
var values = new List<double>();
|
||||
|
||||
//in a future version we can parallize this for efficiency
|
||||
//values.Add will need to be replaced by an indexer when we do
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
double d = 0D;
|
||||
foreach (var ch in channels)
|
||||
{
|
||||
d += ch.FilteredEU[i] * ch.FilteredEU[i];
|
||||
}
|
||||
values.Add(System.Math.Sqrt(d));
|
||||
}
|
||||
|
||||
var cd = new ChannelData(units.First());
|
||||
cd.FilteredEU = values.ToArray();
|
||||
return cd;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
namespace DTS.Common.Calculations
|
||||
{
|
||||
public static class Integral
|
||||
{
|
||||
/// <summary>
|
||||
/// integrates a channel over an interval
|
||||
/// </summary>
|
||||
/// <param name="input">data to integrate</param>
|
||||
/// <param name="start">index to start integration at (inclusive)</param>
|
||||
/// <param name="end">index to end integration at (inclusive)</param>
|
||||
/// <returns></returns>
|
||||
public static double DefiniteIntegral(double[] input, int start, int end, double SPS)
|
||||
{
|
||||
//we use trapezoidal summation to get integral, there is an assumption that the input data is
|
||||
//tightly time aligned (otherwise we'd have to divide each interval by the actual distance, and not 1/2)
|
||||
//=(SUMPRODUCT(H25:H56,A26:A57)-SUMPRODUCT(A25:A56,H26:H57)+A57*H57-A25*H25)/2
|
||||
double d = 0;
|
||||
for (int i = start + 1; i < end; i++)
|
||||
{
|
||||
d += 2D * input[i];
|
||||
}
|
||||
d += input[start];
|
||||
d += input[end];
|
||||
|
||||
return .5D * d / SPS;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>9.0.21022</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{5CE6F27B-1C5B-4101-88DE-58A30B1E5F37}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>DTS.Common.Calculations</RootNamespace>
|
||||
<AssemblyName>Calculations</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<FileUpgradeFlags>
|
||||
</FileUpgradeFlags>
|
||||
<UpgradeBackupLocation>
|
||||
</UpgradeBackupLocation>
|
||||
<OldToolsVersion>3.5</OldToolsVersion>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\x86\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
||||
<OutputPath>bin\x86\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\x64\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
||||
<OutputPath>bin\x64\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml.Linq">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="System.Data.DataSetExtensions">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ChannelData.cs" />
|
||||
<Compile Include="HeadInjuryCriterion.cs" />
|
||||
<Compile Include="Integral.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Resultant.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
@@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("HeadInjuryCriterion")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("HeadInjuryCriterion")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2013")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("a83e3800-290f-4513-9756-d37168152099")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
BIN
Common/DTS.Common.Calculations/.svn/wc.db
Normal file
BIN
Common/DTS.Common.Calculations/.svn/wc.db
Normal file
Binary file not shown.
0
Common/DTS.Common.Calculations/.svn/wc.db-journal
Normal file
0
Common/DTS.Common.Calculations/.svn/wc.db-journal
Normal file
35
Common/DTS.Common.Calculations/ChannelData.cs
Normal file
35
Common/DTS.Common.Calculations/ChannelData.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace DTS.Common.Calculations
|
||||
{
|
||||
/// <summary>
|
||||
/// Filtered Channel Data
|
||||
/// simple class for holding generic data for calculations
|
||||
/// in the future I'd like to be able to accept channels with different units and convert them
|
||||
/// to a common unit, so I add support for that now
|
||||
/// </summary>
|
||||
public class ChannelData
|
||||
{
|
||||
/// <summary>
|
||||
/// Engineering units of Data
|
||||
/// </summary>
|
||||
public string Units { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Pre-Filtered EU data
|
||||
/// </summary>
|
||||
public double[] FilteredEU { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a ChannelData object
|
||||
/// </summary>
|
||||
/// <param name="units">Engineering units of data</param>
|
||||
public ChannelData(string units)
|
||||
{
|
||||
Units = units;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>9.0.21022</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{5CE6F27B-1C5B-4101-88DE-58A30B1E5F37}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>DTS.Common.Calculations</RootNamespace>
|
||||
<AssemblyName>Calculations</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<FileUpgradeFlags>
|
||||
</FileUpgradeFlags>
|
||||
<UpgradeBackupLocation>
|
||||
</UpgradeBackupLocation>
|
||||
<OldToolsVersion>3.5</OldToolsVersion>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\x86\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
||||
<OutputPath>bin\x86\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\x64\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
||||
<OutputPath>bin\x64\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml.Linq">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="System.Data.DataSetExtensions">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ChannelData.cs" />
|
||||
<Compile Include="HeadInjuryCriterion.cs" />
|
||||
<Compile Include="Integral.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Resultant.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
69
Common/DTS.Common.Calculations/HeadInjuryCriterion.cs
Normal file
69
Common/DTS.Common.Calculations/HeadInjuryCriterion.cs
Normal file
@@ -0,0 +1,69 @@
|
||||
using System;
|
||||
|
||||
namespace DTS.Common.Calculations
|
||||
{
|
||||
public class HeadInjuryCriterion
|
||||
{
|
||||
/// <summary>
|
||||
/// Calculates the head injury criterion given a resultant channel, and a desired clip length
|
||||
/// </summary>
|
||||
/// <param name="resultant">Acceleration vector (x,y,z resultant)</param>
|
||||
/// <param name="SPS">Actual sample rate</param>
|
||||
/// <param name="clipLengthMS">Length in ms </param>
|
||||
/// <returns>MAX Head Injury Criterion over the data input for the clip requested</returns>
|
||||
public static HICResult GetHeadInjuryCriterion(ChannelData resultant, double SPS, int clipLengthMS)
|
||||
{
|
||||
System.Diagnostics.Trace.Assert(SPS > 0, "Actual sample rate must be positive");
|
||||
System.Diagnostics.Trace.Assert(clipLengthMS > 0, "Clip length must be positive");
|
||||
|
||||
int maxHICPoint = int.MinValue;
|
||||
double maxHIC = int.MinValue;
|
||||
int maxHICEndPoint = int.MinValue;
|
||||
|
||||
int maxclip = Convert.ToInt32(Math.Ceiling(clipLengthMS * SPS / 1000D));
|
||||
|
||||
for (int clip = 1; clip <= maxclip; clip++)
|
||||
{
|
||||
System.Diagnostics.Trace.Assert(clip < resultant.FilteredEU.Length, string.Format("data must be atleast {0} ms", clipLengthMS));
|
||||
double clipInSeconds = clip / SPS;
|
||||
for (int i = 0; i < resultant.FilteredEU.Length - clip; i++)
|
||||
{
|
||||
//note we are exhaustively recalculating sums, we can do this much better without a doubt, but lets get the
|
||||
//first method done (brute force)
|
||||
//also note, definite integral doesn't include last point, so we have to add one point back in
|
||||
double integral = Integral.DefiniteIntegral(resultant.FilteredEU, i, i + clip, SPS);
|
||||
double hic = clipInSeconds * Math.Pow(integral / clipInSeconds, 2.5D);
|
||||
if (hic > maxHIC) { maxHIC = hic; maxHICPoint = i; maxHICEndPoint = i + clip; }
|
||||
}
|
||||
}
|
||||
return new HICResult(maxHIC, clipLengthMS, maxHICPoint, maxHICEndPoint);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// helper class for storing/handling hic results
|
||||
/// </summary>
|
||||
public class HICResult
|
||||
{
|
||||
public int StartSample { get; }
|
||||
public int EndSample { get; }
|
||||
public int HicLengthMS { get; }
|
||||
public double HIC { get; }
|
||||
/// <summary>
|
||||
/// constructs a new HIC result
|
||||
/// </summary>
|
||||
/// <param name="hic">HIC value</param>
|
||||
/// <param name="hicLength">length of HIC in ms</param>
|
||||
/// <param name="endSample">start sample of HIC</param>
|
||||
/// <param name="startSample">end sample of HIC</param>
|
||||
public HICResult(double hic, int hicLength, int startSample, int endSample)
|
||||
{
|
||||
StartSample = startSample;
|
||||
EndSample = endSample;
|
||||
HicLengthMS = hicLength;
|
||||
HIC = hic;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
28
Common/DTS.Common.Calculations/Integral.cs
Normal file
28
Common/DTS.Common.Calculations/Integral.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
namespace DTS.Common.Calculations
|
||||
{
|
||||
public static class Integral
|
||||
{
|
||||
/// <summary>
|
||||
/// integrates a channel over an interval
|
||||
/// </summary>
|
||||
/// <param name="input">data to integrate</param>
|
||||
/// <param name="start">index to start integration at (inclusive)</param>
|
||||
/// <param name="end">index to end integration at (inclusive)</param>
|
||||
/// <returns></returns>
|
||||
public static double DefiniteIntegral(double[] input, int start, int end, double SPS)
|
||||
{
|
||||
//we use trapezoidal summation to get integral, there is an assumption that the input data is
|
||||
//tightly time aligned (otherwise we'd have to divide each interval by the actual distance, and not 1/2)
|
||||
//=(SUMPRODUCT(H25:H56,A26:A57)-SUMPRODUCT(A25:A56,H26:H57)+A57*H57-A25*H25)/2
|
||||
double d = 0;
|
||||
for (int i = start + 1; i < end; i++)
|
||||
{
|
||||
d += 2D * input[i];
|
||||
}
|
||||
d += input[start];
|
||||
d += input[end];
|
||||
|
||||
return .5D * d / SPS;
|
||||
}
|
||||
}
|
||||
}
|
||||
36
Common/DTS.Common.Calculations/Properties/AssemblyInfo.cs
Normal file
36
Common/DTS.Common.Calculations/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("HeadInjuryCriterion")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("HeadInjuryCriterion")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2013")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("a83e3800-290f-4513-9756-d37168152099")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
47
Common/DTS.Common.Calculations/Resultant.cs
Normal file
47
Common/DTS.Common.Calculations/Resultant.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace DTS.Common.Calculations
|
||||
{
|
||||
public static class Resultant
|
||||
{
|
||||
/// <summary>
|
||||
/// generates a resultant channel given input vectors
|
||||
/// Will throw an assertion if lengths of data don't match, or if
|
||||
/// units don't match
|
||||
/// </summary>
|
||||
/// <param name="channels">List of channels to combine via
|
||||
/// sum of squares
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// resultant vector from sum of squares of inputs
|
||||
/// </returns>
|
||||
public static ChannelData GenerateResultantChannel(List<ChannelData> channels)
|
||||
{
|
||||
int length = (from ch in channels select ch.FilteredEU.Length).Max();
|
||||
foreach (var ch in channels) { System.Diagnostics.Trace.Assert(ch.FilteredEU.Length == length); }
|
||||
//make sure the channels are all the same units and lengths,
|
||||
//we assert here since the higher level should be expected to provide clean inputs
|
||||
var units = (from ch in channels select ch.Units).Distinct();
|
||||
System.Diagnostics.Trace.Assert(units.Count() == 1);
|
||||
|
||||
var values = new List<double>();
|
||||
|
||||
//in a future version we can parallize this for efficiency
|
||||
//values.Add will need to be replaced by an indexer when we do
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
double d = 0D;
|
||||
foreach (var ch in channels)
|
||||
{
|
||||
d += ch.FilteredEU[i] * ch.FilteredEU[i];
|
||||
}
|
||||
values.Add(System.Math.Sqrt(d));
|
||||
}
|
||||
|
||||
var cd = new ChannelData(units.First());
|
||||
cd.FilteredEU = values.ToArray();
|
||||
return cd;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
// <autogenerated />
|
||||
using System;
|
||||
using System.Reflection;
|
||||
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.8", FrameworkDisplayName = "")]
|
||||
@@ -0,0 +1,4 @@
|
||||
// <autogenerated />
|
||||
using System;
|
||||
using System.Reflection;
|
||||
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
|
||||
Binary file not shown.
Binary file not shown.
1
Common/DTS.Common.Core/.svn/entries
Normal file
1
Common/DTS.Common.Core/.svn/entries
Normal file
@@ -0,0 +1 @@
|
||||
12
|
||||
1
Common/DTS.Common.Core/.svn/format
Normal file
1
Common/DTS.Common.Core/.svn/format
Normal file
@@ -0,0 +1 @@
|
||||
12
|
||||
@@ -0,0 +1,139 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ClassDiagram MajorVersion="1" MinorVersion="1">
|
||||
<Class Name="DTS.Common.Core.Config.DTSConfig" Collapsed="true">
|
||||
<Position X="0.5" Y="0.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AIAQAAAEAACAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAIA=</HashCode>
|
||||
<FileName>Config\DTSConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="DTS.Common.Core.DTSConstants" Collapsed="true">
|
||||
<Position X="2.25" Y="0.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAgAAAAA=</HashCode>
|
||||
<FileName>DTSConstants.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="DTS.Common.Core.EventManager.EventManager" Collapsed="true">
|
||||
<Position X="4" Y="0.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAIIAAACAAGAEAACAAAAAACAAAAQAAAAABAAAA=</HashCode>
|
||||
<FileName>EventManager\EventManager.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="DTS.Common.Core.EventManager.EventMetaData<T>" Collapsed="true">
|
||||
<Position X="5.75" Y="0.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA=</HashCode>
|
||||
<FileName>EventManager\EventManager.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="DTS.Common.Core.PluginLib.PluginConfig" Collapsed="true">
|
||||
<Position X="4" Y="1.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAgAAAIAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>PluginLib\PluginConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="DTS.Common.Core.PluginLib.PluginConfigData" Collapsed="true">
|
||||
<Position X="5.75" Y="1.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAA=</HashCode>
|
||||
<FileName>PluginLib\PluginConfigData.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="DTS.Common.Core.PluginLib.PluginConfigSectionHandler" Collapsed="true">
|
||||
<Position X="0.5" Y="2.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>PluginLib\PluginConfigSectionHandler.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="DTS.Common.Core.PluginLib.FilterHashKeyCollection" Collapsed="true">
|
||||
<Position X="2.25" Y="1.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAACAAAAAAAAAAAACAAAAAAAAAABAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>PluginLib\PluginConfigSectionHandler.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="DTS.Common.Core.PluginLib.FilterHashElement" Collapsed="true">
|
||||
<Position X="0.5" Y="1.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAgAAAAAAA=</HashCode>
|
||||
<FileName>PluginLib\PluginConfigSectionHandler.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="DTS.Common.Core.PluginLib.PluginManager" Collapsed="true">
|
||||
<Position X="2.25" Y="2.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AEAABAAAAAAEAACAAAMAAAAAAAAAAAAAAgAAAAAAAAA=</HashCode>
|
||||
<FileName>PluginLib\PluginManager.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="DTS.Common.Core.ServiceManager.ServiceManager" Collapsed="true">
|
||||
<Position X="4" Y="2.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>gAAAAAAAAAAAAABAAEAAAAABAAAAAAAAAAAAAAFAAAA=</HashCode>
|
||||
<FileName>ServiceManager\ServiceManager.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="DTS.Common.Core.ServiceManager.ServicePublishedEvent" Collapsed="true" BaseTypeListCollapsed="true">
|
||||
<Position X="5.75" Y="2.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAA=</HashCode>
|
||||
<FileName>ServiceManager\ServicePublishedEvent.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<Lollipop Position="0.2" Collapsed="true" />
|
||||
</Class>
|
||||
<Class Name="DTS.Common.Core.Settings.SettingsChangedEventArgs<TKey, TItem>" Collapsed="true">
|
||||
<Position X="0.5" Y="3.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAQAAAEAAAAEAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Settings\SettingsChangedEventArgs.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="DTS.Common.Core.Settings.SettingsCollection<TKey, TItem>" Collapsed="true" BaseTypeListCollapsed="true">
|
||||
<Position X="2.25" Y="3.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>CAIAAAAAAAAEABAQCAAABAQAABAAAAAEAAAgAABwKAA=</HashCode>
|
||||
<FileName>Settings\SettingsCollection.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<Lollipop Position="0.2" Collapsed="true" />
|
||||
</Class>
|
||||
<Interface Name="DTS.Common.Core.ServiceManager.IServicePublishedEvent" Collapsed="true">
|
||||
<Position X="0.5" Y="4.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAA=</HashCode>
|
||||
<FileName>ServiceManager\IServicePublishedEvent.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Enum Name="DTS.Common.Core.EventManager.EventDiagnosticType" Collapsed="true">
|
||||
<Position X="2.25" Y="5.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAABAAAAAAAAAAAAAEIACAAAAAAABAAAA=</HashCode>
|
||||
<FileName>EventManager\EventManager.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Enum>
|
||||
<Enum Name="DTS.Common.Core.Settings.ChangeSettingType" Collapsed="true">
|
||||
<Position X="0.5" Y="5.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAIAAAAAAAAAAABAABAABAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Settings\SettingsChangedEventArgs.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Enum>
|
||||
<Delegate Name="DTS.Common.Core.EventManager.SubscriberCallbackDelegate<T>" Collapsed="true">
|
||||
<Position X="2.25" Y="6.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>EventManager\EventManager.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Delegate>
|
||||
<Delegate Name="DTS.Common.Core.EventManager.DiagnosticCallbackDelegate" Collapsed="true">
|
||||
<Position X="0.5" Y="6.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAACAAEAAAAAAAAAEAAAABAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>EventManager\EventManager.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Delegate>
|
||||
<Font Name="Segoe UI" Size="9" />
|
||||
</ClassDiagram>
|
||||
@@ -0,0 +1,46 @@
|
||||
using System.Configuration;
|
||||
|
||||
namespace DTS.Common.Core.PluginLib
|
||||
{
|
||||
/// <summary>
|
||||
/// Support class that parses data from DTS.Common.Core.PluginLib.Config configuration section
|
||||
/// </summary>
|
||||
public class PluginConfigSectionHandler : ConfigurationSection
|
||||
{
|
||||
[ConfigurationProperty("PluginFolders")]
|
||||
public FilterHashKeyCollection HashKeys => (FilterHashKeyCollection)base["PluginFolders"];
|
||||
}
|
||||
|
||||
[ConfigurationCollection(typeof(FilterHashElement))]
|
||||
public class FilterHashKeyCollection : ConfigurationElementCollection
|
||||
{
|
||||
protected override ConfigurationElement CreateNewElement()
|
||||
{
|
||||
return new FilterHashElement();
|
||||
}
|
||||
|
||||
protected override object GetElementKey(ConfigurationElement element)
|
||||
{
|
||||
return ((FilterHashElement)element).Key;
|
||||
}
|
||||
|
||||
public FilterHashElement this[int idx] => (FilterHashElement)BaseGet(idx);
|
||||
}
|
||||
|
||||
public class FilterHashElement : ConfigurationElement
|
||||
{
|
||||
[ConfigurationProperty("key", DefaultValue = "", IsKey = true, IsRequired = true)]
|
||||
public string Key
|
||||
{
|
||||
get => (string)base["key"];
|
||||
set => base["key"] = value;
|
||||
}
|
||||
|
||||
[ConfigurationProperty("value", DefaultValue = "", IsKey = false, IsRequired = false)]
|
||||
public string Value
|
||||
{
|
||||
get => (string)base["value"];
|
||||
set => base["value"] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
using DTS.Common.Utilities.Logging;
|
||||
using System;
|
||||
using System.Configuration;
|
||||
using System.Linq;
|
||||
// ReSharper disable InconsistentNaming
|
||||
// ReSharper disable EmptyConstructor
|
||||
|
||||
namespace DTS.Common.Core.Config
|
||||
{
|
||||
public static class DTSConfig
|
||||
{
|
||||
private static string AltConfigPath;
|
||||
public static string AltConfigPathGet()
|
||||
{
|
||||
lock (MyLock)
|
||||
{
|
||||
return AltConfigPath;
|
||||
}
|
||||
}
|
||||
public static void AltConfigPathSet(string path)
|
||||
{
|
||||
lock (MyLock)
|
||||
{
|
||||
AltConfigPath = path;
|
||||
}
|
||||
}
|
||||
// static constructor
|
||||
static DTSConfig()
|
||||
{
|
||||
}
|
||||
|
||||
public static void DTSConfigInit(string path)
|
||||
{
|
||||
SetAltConfigPath(path);
|
||||
}
|
||||
private static object MyLock = new object();
|
||||
/// <summary>
|
||||
/// Static variable to hold alternate configuration file
|
||||
/// </summary>
|
||||
private static Configuration AltConfig;
|
||||
|
||||
public static Configuration GetAltConfig()
|
||||
{
|
||||
lock (MyLock)
|
||||
{
|
||||
return AltConfig;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Static variable to hold alternate configuration file
|
||||
/// </summary>
|
||||
/// <history>
|
||||
///
|
||||
/// </history>
|
||||
public static void SetAltConfigPath(string path)
|
||||
{
|
||||
lock (MyLock)
|
||||
{
|
||||
AltConfigPath = path;
|
||||
var dtsConfig = new ExeConfigurationFileMap
|
||||
{
|
||||
ExeConfigFilename = string.IsNullOrEmpty(AltConfigPath) ? DTSConstants.CustomConfigPath : AltConfigPath
|
||||
};
|
||||
|
||||
AltConfig = ConfigurationManager.OpenMappedExeConfiguration(dtsConfig, ConfigurationUserLevel.None, true);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Static method to retrieve a setting from config file
|
||||
/// </summary>
|
||||
/// <param name="key">string</param>
|
||||
/// <returns>string</returns>
|
||||
public static string GetAppSetting(string key)
|
||||
{
|
||||
var appSetting = AltConfig.AppSettings.Settings.Cast<KeyValueConfigurationElement>().FirstOrDefault(setting => setting.Key == key);
|
||||
if (appSetting == null)
|
||||
{
|
||||
APILogger.Log(
|
||||
$"## AltConfig.AppSettings.Settings.Cast<KeyValueConfigurationElement>().FirstOrDefault(setting => setting.Key == key) is null for key={key}");
|
||||
}
|
||||
return appSetting == null ? string.Empty : appSetting.Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Static method to get a section from config file. Used by plugin code to get plugin library section.
|
||||
/// </summary>
|
||||
/// <param name="sectionName">string</param>
|
||||
/// <returns>object</returns>
|
||||
public static object GetSection(string sectionName)
|
||||
{
|
||||
var section = AltConfig.GetSection(sectionName);
|
||||
if (section == null)
|
||||
{
|
||||
APILogger.Log($"## AltConfig.GetSection(sectionName) is null for sectionName={sectionName}");
|
||||
}
|
||||
return section;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
using System;
|
||||
|
||||
namespace DTS.Common.Core.Settings
|
||||
{
|
||||
/// <summary>
|
||||
/// Event arguments describing change to settings collection
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey">key type used in collection</typeparam>
|
||||
/// <typeparam name="TItem">value type used in collection</typeparam>
|
||||
public class SettingsChangedEventArgs<TKey, TItem> : EventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="changeType">type of scenario change</param>
|
||||
public SettingsChangedEventArgs(ChangeSettingType changeType)
|
||||
{
|
||||
ChangeType = changeType;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="changeType">change type</param>
|
||||
/// <param name="key">key type used in collection</param>
|
||||
public SettingsChangedEventArgs(ChangeSettingType changeType, TKey key)
|
||||
{
|
||||
ChangeType = changeType;
|
||||
Key = key;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="changeType">change type</param>
|
||||
/// <param name="key">key type used in collection</param>
|
||||
/// <param name="item">value type used in collection</param>
|
||||
public SettingsChangedEventArgs(ChangeSettingType changeType, TKey key, TItem item)
|
||||
{
|
||||
ChangeType = changeType;
|
||||
Key = key;
|
||||
Item = item;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns type of scenario change
|
||||
/// </summary>
|
||||
public ChangeSettingType ChangeType
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// key associated with changed setting
|
||||
/// </summary>
|
||||
public TKey Key
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Value associated with changed settting
|
||||
/// </summary>
|
||||
public TItem Item
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Type of settings changed
|
||||
/// </summary>
|
||||
public enum ChangeSettingType
|
||||
{
|
||||
Add = 0,
|
||||
Remove = 1,
|
||||
Modified = 3,
|
||||
ClearAll = 4
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
// ReSharper disable InconsistentNaming
|
||||
namespace DTS.Common.Core
|
||||
{
|
||||
public static class DTSConstants
|
||||
{
|
||||
public const string CustomConfigPath = @"C:\dev\DTS.Viewer\bin\Debug\DTS.Viewer.exe.config";
|
||||
public const string ViewerConfigPath = @"C:\dev\DTS.Viewer\bin\Debug\DTS.Viewer.exe.config";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,193 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
|
||||
namespace DTS.Common.Core.EventManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Delegate used by event listeners
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="item"></param>
|
||||
public delegate void SubscriberCallbackDelegate<in T>(T item) where T : class;
|
||||
|
||||
public delegate void DiagnosticCallbackDelegate(EventDiagnosticType eventType, Type t, object eventData, string listener);
|
||||
|
||||
/// <summary>
|
||||
/// Allows components to publish events without knowing who is listening
|
||||
/// </summary>
|
||||
public static class EventManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Tracks listeners
|
||||
/// </summary>
|
||||
private static readonly Dictionary<Type, List<object>> SubscriberList = new Dictionary<Type, List<object>>();
|
||||
|
||||
/// <summary>
|
||||
/// Tracks diagnostic listeners
|
||||
/// </summary>
|
||||
private static readonly List<DiagnosticCallbackDelegate> DiagnosticList = new List<DiagnosticCallbackDelegate>();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Publish an event
|
||||
/// </summary>
|
||||
/// <typeparam name="T">type of event</typeparam>
|
||||
/// <param name="eventData">event listener</param>
|
||||
public static void Publish<T>(T eventData) where T : class
|
||||
{
|
||||
if (!SubscriberList.ContainsKey(typeof(T))) return;
|
||||
|
||||
var listeners = SubscriberList[typeof(T)];
|
||||
|
||||
foreach (var listener in listeners)
|
||||
{
|
||||
var metaData = listener as EventMetaData<T>;
|
||||
if (metaData == null) continue;
|
||||
|
||||
var triggerCallback = true;
|
||||
|
||||
if (metaData.EventFilter != null)
|
||||
{
|
||||
triggerCallback = metaData.EventFilter(eventData);
|
||||
}
|
||||
|
||||
if (triggerCallback)
|
||||
{
|
||||
metaData.Callback(eventData);
|
||||
}
|
||||
|
||||
SendDiagnosticEvent(EventDiagnosticType.PublishEvent, typeof(T), eventData, metaData.EventFilter?.Method);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subscribe to an event
|
||||
/// </summary>
|
||||
/// <typeparam name="T">type of event</typeparam>
|
||||
/// <param name="listener">event listener</param>
|
||||
public static void Subscribe<T>(SubscriberCallbackDelegate<T> listener) where T : class
|
||||
{
|
||||
Subscribe(listener, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subscribe to an event
|
||||
/// </summary>
|
||||
/// <typeparam name="T">type of event</typeparam>
|
||||
/// <param name="listener">event listener</param>
|
||||
/// <param name="eventFilter">predicate to filter events sent to event listener</param>
|
||||
public static void Subscribe<T>(SubscriberCallbackDelegate<T> listener, Predicate<T> eventFilter) where T : class
|
||||
{
|
||||
if (!SubscriberList.ContainsKey(typeof(T)))
|
||||
{
|
||||
SubscriberList.Add(typeof(T), new List<object>());
|
||||
}
|
||||
|
||||
var listeners = SubscriberList[typeof(T)];
|
||||
|
||||
var metaData = new EventMetaData<T> { Callback = listener, EventFilter = eventFilter };
|
||||
|
||||
listeners.Add(metaData);
|
||||
|
||||
SendDiagnosticEvent(EventDiagnosticType.AddListener, typeof(T), null, listener.Method);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allows a subscriber to unsubscribe
|
||||
/// </summary>
|
||||
/// <typeparam name="T">type of event</typeparam>
|
||||
/// <param name="listener">event listener</param>
|
||||
public static void UnSubscribe<T>(SubscriberCallbackDelegate<T> listener) where T : class
|
||||
{
|
||||
if (!SubscriberList.ContainsKey(typeof(T))) return;
|
||||
|
||||
var listeners = SubscriberList[typeof(T)];
|
||||
|
||||
listeners.RemoveAll(p =>
|
||||
{
|
||||
return p is EventMetaData<T> eventMetaData && eventMetaData.Callback == listener;
|
||||
});
|
||||
|
||||
SendDiagnosticEvent(EventDiagnosticType.RemoveListener, typeof(T), null, listener.Method);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears all listeners
|
||||
/// </summary>
|
||||
public static void Clear()
|
||||
{
|
||||
SubscriberList.Clear();
|
||||
SendDiagnosticEvent(EventDiagnosticType.RemoveListener, null, null, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add diagnostic listener
|
||||
/// </summary>
|
||||
/// <param name="listener">event listener</param>
|
||||
public static void SubscribeToDiagnosticEvents(DiagnosticCallbackDelegate listener)
|
||||
{
|
||||
DiagnosticList.Add(listener);
|
||||
SendDiagnosticEvent(EventDiagnosticType.AddListenerDiagnostic, null, null, listener.Method);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clear diagnostic event
|
||||
/// </summary>
|
||||
/// <param name="listener">listener to unsubscribe</param>
|
||||
public static void UnSubscribeToDiagnosticEvents(DiagnosticCallbackDelegate listener)
|
||||
{
|
||||
DiagnosticList.RemoveAll(p => p == listener);
|
||||
SendDiagnosticEvent(EventDiagnosticType.RemoveListenerDiagnostic, null, null, listener.Method);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clear all diagnostic events
|
||||
/// </summary>
|
||||
public static void ClearDiagnosticEvents()
|
||||
{
|
||||
DiagnosticList.Clear();
|
||||
SendDiagnosticEvent(EventDiagnosticType.RemoveListenerDiagnostic, null, null, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a diagnostic event
|
||||
/// </summary>
|
||||
/// <param name="diagnosticEventType"></param>
|
||||
/// <param name="eventType"></param>
|
||||
/// <param name="eventData"></param>
|
||||
/// <param name="listenerMethod"></param>
|
||||
private static void SendDiagnosticEvent(EventDiagnosticType diagnosticEventType, Type eventType, object eventData, MemberInfo listenerMethod)
|
||||
{
|
||||
foreach (var diagnosticEvent in DiagnosticList)
|
||||
{
|
||||
string listener = null;
|
||||
|
||||
if (listenerMethod != null && listenerMethod.DeclaringType != null)
|
||||
{
|
||||
listener = $"{listenerMethod.DeclaringType.FullName}.{listenerMethod.Name} , {listenerMethod.DeclaringType.Assembly.FullName}";
|
||||
}
|
||||
|
||||
diagnosticEvent(diagnosticEventType, eventType, eventData, listener);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public enum EventDiagnosticType
|
||||
{
|
||||
AddListener = 0,
|
||||
AddListenerDiagnostic = 1,
|
||||
PublishEvent = 2,
|
||||
RemoveListenerDiagnostic = 3,
|
||||
RemoveListener = 4
|
||||
}
|
||||
|
||||
internal class EventMetaData<T> where T : class
|
||||
{
|
||||
public Predicate<T> EventFilter { get; set; }
|
||||
public SubscriberCallbackDelegate<T> Callback { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
|
||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/></startup></configuration>
|
||||
@@ -0,0 +1,20 @@
|
||||
using System;
|
||||
|
||||
namespace DTS.Common.Core.ServiceManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Event fired when a service interface is published\unpublished
|
||||
/// </summary>
|
||||
public interface IServicePublishedEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns type of service being published\unpublished
|
||||
/// </summary>
|
||||
Type ServiceType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if Service is being published, false if being unpublished
|
||||
/// </summary>
|
||||
bool IsPublished { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace DTS.Common.Core.PluginLib
|
||||
{
|
||||
/// <summary>
|
||||
/// Support class that stores data de-serialized from DatPro.Core.PluginLib.Config in App.Config configuration section
|
||||
/// </summary>
|
||||
[XmlRoot(ElementName = "DatPro.Core.PluginLib.Config")]
|
||||
public class PluginConfigData
|
||||
{
|
||||
[XmlArrayItem("Folder")]
|
||||
public string[] PluginFolders;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using DTS.Common.Core.Config;
|
||||
// ReSharper disable InconsistentNaming
|
||||
|
||||
namespace DTS.Common.Core.PluginLib
|
||||
{
|
||||
/// <summary>
|
||||
/// Static class used to store plugin configuration info
|
||||
/// </summary>
|
||||
public static class PluginConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// name of setting to look in config for equipment database
|
||||
/// </summary>
|
||||
public const string DTSPlugins = "DTSPlugins";
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// concatenate plugin name from app setting with class exporter name for DTS plugins
|
||||
/// </summary>
|
||||
/// <param name="setting"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetDTSPluginsSetting(string setting)
|
||||
{
|
||||
return DTSConfig.GetAppSetting(DTSPlugins) + "." + setting;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using System;
|
||||
|
||||
namespace DTS.Common.Core.ServiceManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Event fired when a service interface is published\unpublished
|
||||
/// </summary>
|
||||
public class ServicePublishedEvent : IServicePublishedEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns type of service being published\unpublished
|
||||
/// </summary>
|
||||
public Type ServiceType
|
||||
{
|
||||
get;
|
||||
internal set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if Service is being published, false if being unpublished
|
||||
/// </summary>
|
||||
public bool IsPublished
|
||||
{
|
||||
get;
|
||||
internal set;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
// ReSharper disable InconsistentNaming
|
||||
|
||||
namespace DTS.Common.Core.ServiceManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Service manager allows a component to publish an implementation of a singleton interface (service) that
|
||||
/// other components can retrieve reference to without knowing who published it
|
||||
/// </summary>
|
||||
public static class ServiceManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Stores all published interfaces
|
||||
/// </summary>
|
||||
private static readonly Dictionary<Type, object> Services = new Dictionary<Type, object>();
|
||||
|
||||
/// <summary>
|
||||
/// Publishes a service
|
||||
/// </summary>
|
||||
/// <typeparam name="T">interface type of service</typeparam>
|
||||
/// <param name="item">implementation of service</param>
|
||||
public static void Publish<T>(T item) where T : class
|
||||
{
|
||||
if (Services.ContainsKey(typeof(T)))
|
||||
{
|
||||
throw new ArgumentException($"{typeof(T).Name}: has already been published");
|
||||
}
|
||||
|
||||
Services.Add(typeof(T), item);
|
||||
SendServicePublishedEvent(typeof(T), true);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Publishes a list of services
|
||||
/// </summary>
|
||||
/// <param name="item">class that will implement all the listed interfaces</param>
|
||||
/// <param name="interfaceList">list of interfaces</param>
|
||||
/// <param name="skipPublishedInterfaces">true to avoid errors on already published interfaces</param>
|
||||
public static void Publish(object item, IEnumerable<Type> interfaceList, bool skipPublishedInterfaces)
|
||||
{
|
||||
foreach (var t in interfaceList)
|
||||
{
|
||||
if (Exists(t))
|
||||
{
|
||||
if (!skipPublishedInterfaces)
|
||||
{
|
||||
// service already published and caller indicated we should error out
|
||||
throw new ArgumentException($"{t.Name}: has already been published");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// service doesn't exist so publish it
|
||||
Services.Add(t, item);
|
||||
SendServicePublishedEvent(t, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if specifed interface has been published, false if not
|
||||
/// </summary>
|
||||
/// <typeparam name="T">type of interface to check</typeparam>
|
||||
/// <returns>true if interface has been published; false if not published</returns>
|
||||
public static bool Exists<T>() where T : class
|
||||
{
|
||||
return Services.ContainsKey(typeof(T));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if specifed interface has been published, false if not
|
||||
/// </summary>
|
||||
/// <param name="t">type of interface to check</param>
|
||||
/// <returns>true if interface has been published; false if not published</returns>
|
||||
public static bool Exists(Type t)
|
||||
{
|
||||
return Services.ContainsKey(t);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns published service
|
||||
/// </summary>
|
||||
/// <typeparam name="T">interface type of service</typeparam>
|
||||
/// <returns>published service or exception if not currently published</returns>
|
||||
public static T Get<T>() where T : class
|
||||
{
|
||||
if (!Services.ContainsKey(typeof(T)))
|
||||
{
|
||||
throw new ArgumentException($"{typeof(T).Name}: has not been published");
|
||||
}
|
||||
|
||||
return Services[typeof(T)] as T;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears specified service
|
||||
/// </summary>
|
||||
/// <typeparam name="T">interface type of service to clear</typeparam>
|
||||
public static void Clear<T>() where T : class
|
||||
{
|
||||
if (Services.ContainsKey(typeof(T)))
|
||||
{
|
||||
SendServicePublishedEvent(typeof(T), false);
|
||||
Services.Remove(typeof(T));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears list of published interfaces
|
||||
/// </summary>
|
||||
/// <param name="interfaceList">list of interfaces to unpublish</param>
|
||||
public static void Clear(IEnumerable<Type> interfaceList)
|
||||
{
|
||||
foreach (var t in interfaceList)
|
||||
{
|
||||
if (!Services.ContainsKey(t)) continue;
|
||||
|
||||
SendServicePublishedEvent(t, false);
|
||||
Services.Remove(t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Sends a IServicePublishedEvent through the Event Manger to let subscribers know when
|
||||
/// a service is published or unpublished
|
||||
/// </summary>
|
||||
/// <param name="type">type of interface</param>
|
||||
/// <param name="published">true if being published, false if being unpublished</param>
|
||||
private static void SendServicePublishedEvent(Type type, bool published)
|
||||
{
|
||||
EventManager.EventManager.Publish<IServicePublishedEvent>(new ServicePublishedEvent
|
||||
{
|
||||
IsPublished = published,
|
||||
ServiceType = type
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,213 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
namespace DTS.Common.Core.Settings
|
||||
{
|
||||
/// <summary>
|
||||
/// Implements a dictionary with events when an item is changed
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey">key type</typeparam>
|
||||
/// <typeparam name="TItem">value type</typeparam>
|
||||
public class SettingsCollection<TKey, TItem> : IDictionary<TKey, TItem>
|
||||
{
|
||||
/// <summary>
|
||||
/// Event fired when an item changes in dictionary
|
||||
/// </summary>
|
||||
public event EventHandler<SettingsChangedEventArgs<TKey, TItem>> CollectionItemPropertyChanged;
|
||||
|
||||
/// <summary>
|
||||
/// List of stored items
|
||||
/// </summary>
|
||||
private readonly Dictionary<TKey, TItem> _items = new Dictionary<TKey, TItem>();
|
||||
|
||||
|
||||
#region IDictionary
|
||||
|
||||
/// <summary>
|
||||
/// Add item
|
||||
/// </summary>
|
||||
/// <param name="key">key</param>
|
||||
/// <param name="value">value</param>
|
||||
public void Add(TKey key, TItem value)
|
||||
{
|
||||
_items.Add(key, value);
|
||||
FireItemChangedEvent(ChangeSettingType.Add, key, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if item contains key
|
||||
/// </summary>
|
||||
/// <param name="key">key</param>
|
||||
/// <returns>true if key exists</returns>
|
||||
public bool ContainsKey(TKey key)
|
||||
{
|
||||
return _items.ContainsKey(key);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Returns all keys in collection
|
||||
/// </summary>
|
||||
public ICollection<TKey> Keys => _items.Keys;
|
||||
|
||||
/// <summary>
|
||||
/// Removes key
|
||||
/// </summary>
|
||||
/// <param name="key">key</param>
|
||||
/// <returns>true if key removed</returns>
|
||||
public bool Remove(TKey key)
|
||||
{
|
||||
var res = _items.Remove(key);
|
||||
if (res) FireItemChangedEvent(ChangeSettingType.Remove, key);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Trys to get specified value
|
||||
/// </summary>
|
||||
/// <param name="key">key</param>
|
||||
/// <param name="value">value if key exists</param>
|
||||
/// <returns>true if key exists; false if it doesn't exist</returns>
|
||||
public bool TryGetValue(TKey key, out TItem value)
|
||||
{
|
||||
return _items.TryGetValue(key, out value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// List of values in collection
|
||||
/// </summary>
|
||||
public ICollection<TItem> Values => _items.Values;
|
||||
|
||||
/// <summary>
|
||||
/// Gets/sets item in collection (overloads [] operator)
|
||||
/// </summary>
|
||||
/// <param name="key">key</param>
|
||||
/// <returns>item in collection</returns>
|
||||
public TItem this[TKey key]
|
||||
{
|
||||
get => _items[key];
|
||||
set
|
||||
{
|
||||
_items[key] = value;
|
||||
FireItemChangedEvent(ChangeSettingType.Add, key, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds new item
|
||||
/// </summary>
|
||||
/// <param name="item">new item to add</param>
|
||||
public void Add(KeyValuePair<TKey, TItem> item)
|
||||
{
|
||||
_items.Add(item.Key, item.Value);
|
||||
FireItemChangedEvent(ChangeSettingType.Add, item.Key, item.Value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears entire collection
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
_items.Clear();
|
||||
FireItemChangedEvent(ChangeSettingType.ClearAll);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if item is in collection
|
||||
/// </summary>
|
||||
/// <param name="item">item to check</param>
|
||||
/// <returns>true if item exists</returns>
|
||||
public bool Contains(KeyValuePair<TKey, TItem> item)
|
||||
{
|
||||
return _items.ContainsKey(item.Key) && _items.ContainsValue(item.Value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copys items to array
|
||||
/// </summary>
|
||||
/// <param name="array"></param>
|
||||
/// <param name="arrayIndex"></param>
|
||||
public void CopyTo(KeyValuePair<TKey, TItem>[] array, int arrayIndex)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns count of items
|
||||
/// </summary>
|
||||
public int Count => _items.Count;
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if readonly collection
|
||||
/// </summary>
|
||||
public bool IsReadOnly => false;
|
||||
|
||||
/// <summary>
|
||||
/// Removes specified item
|
||||
/// </summary>
|
||||
/// <param name="item">item to remove</param>
|
||||
/// <returns>true if item removed</returns>
|
||||
public bool Remove(KeyValuePair<TKey, TItem> item)
|
||||
{
|
||||
var res = _items.Remove(item.Key);
|
||||
if (res) FireItemChangedEvent(ChangeSettingType.Remove, item.Key);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return enumerator for collection
|
||||
/// </summary>
|
||||
/// <returns>enumerator</returns>
|
||||
public IEnumerator<KeyValuePair<TKey, TItem>> GetEnumerator()
|
||||
{
|
||||
return _items.GetEnumerator();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return enumerator for collection
|
||||
/// </summary>
|
||||
/// <returns>enumerator</returns>
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return _items.GetEnumerator();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private methods
|
||||
|
||||
/// <summary>
|
||||
/// Fires collection change event
|
||||
/// </summary>
|
||||
/// <param name="changeType">type of change</param>
|
||||
private void FireItemChangedEvent(ChangeSettingType changeType)
|
||||
{
|
||||
CollectionItemPropertyChanged?.Invoke(this, new SettingsChangedEventArgs<TKey, TItem>(changeType));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fires collection change event
|
||||
/// </summary>
|
||||
/// <param name="changeType">type of change</param>
|
||||
/// <param name="key">key</param>
|
||||
private void FireItemChangedEvent(ChangeSettingType changeType, TKey key)
|
||||
{
|
||||
CollectionItemPropertyChanged?.Invoke(this, new SettingsChangedEventArgs<TKey, TItem>(changeType, key));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fires collection change event
|
||||
/// </summary>
|
||||
/// <param name="changeType">type of change</param>
|
||||
/// <param name="key">key</param>
|
||||
/// <param name="item">item</param>
|
||||
private void FireItemChangedEvent(ChangeSettingType changeType, TKey key, TItem item)
|
||||
{
|
||||
CollectionItemPropertyChanged?.Invoke(this, new SettingsChangedEventArgs<TKey, TItem>(changeType, key, item));
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{FAB1F470-1574-4301-B56E-D3364AA93679}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>DTS.Common.Core</RootNamespace>
|
||||
<AssemblyName>DTS.Common.Core</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<SccProjectName>
|
||||
</SccProjectName>
|
||||
<SccLocalPath>
|
||||
</SccLocalPath>
|
||||
<SccAuxPath>
|
||||
</SccAuxPath>
|
||||
<SccProvider>
|
||||
</SccProvider>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\x64\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
||||
<OutputPath>bin\x64\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\x86\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
||||
<OutputPath>bin\x86\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.ComponentModel.Composition" />
|
||||
<Reference Include="System.Configuration" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Config\DTSConfig.cs" />
|
||||
<Compile Include="DTSConstants.cs" />
|
||||
<Compile Include="EventManager\EventManager.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="ServiceManager\IServicePublishedEvent.cs" />
|
||||
<Compile Include="ServiceManager\ServiceManager.cs" />
|
||||
<Compile Include="ServiceManager\ServicePublishedEvent.cs" />
|
||||
<Compile Include="Settings\SettingsChangedEventArgs.cs" />
|
||||
<Compile Include="Settings\SettingsCollection.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
<None Include="Design\DTS.Common.CoreClassDiagram.cd" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\DTS.Common.Utilities\DTS.Common.Utilities.csproj">
|
||||
<Project>{03EACE47-EA59-44AC-B49D-956E4DC4D618}</Project>
|
||||
<Name>DTS.Common.Utilities</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent>
|
||||
</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<PreBuildEvent>
|
||||
</PreBuildEvent>
|
||||
</PropertyGroup>
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
@@ -0,0 +1,272 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.IO;
|
||||
using System.ComponentModel.Composition.Hosting;
|
||||
using System.ComponentModel.Composition.ReflectionModel;
|
||||
using System.Linq;
|
||||
using DTS.Common.Core.Config;
|
||||
using DTS.Common.Utilities.Logging;
|
||||
|
||||
// ReSharper disable RedundantJumpStatement
|
||||
// ReSharper disable UnusedTypeParameter
|
||||
// ReSharper disable UnusedMember.Local
|
||||
// ReSharper disable UnusedParameter.Local
|
||||
|
||||
namespace DTS.Common.Core.PluginLib
|
||||
{
|
||||
/// <summary>
|
||||
/// PluginManager class to manage MEF plugins
|
||||
/// NOTE: This class has to be thread safe
|
||||
/// </summary>
|
||||
public class PluginManager
|
||||
{
|
||||
// reference to singleton plugin manager
|
||||
private static PluginManager _pluginManager;
|
||||
|
||||
/// <summary>
|
||||
/// MEF catalog
|
||||
/// </summary>
|
||||
public AggregateCatalog PluginCatalog { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// MEF container
|
||||
/// </summary>
|
||||
private CompositionContainer PluginContainer { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Thread lock
|
||||
/// </summary>
|
||||
private static readonly object THREAD_LOCK = new object();
|
||||
|
||||
/// <summary>
|
||||
/// Constructor that intializes catalog and container
|
||||
/// </summary>
|
||||
private PluginManager(string appPath)
|
||||
{
|
||||
// Create MEF catalog
|
||||
PluginCatalog = new AggregateCatalog();
|
||||
DTSConfig.DTSConfigInit(appPath);
|
||||
// Get plugin folder from App.Config;
|
||||
var pcsh = (PluginConfigSectionHandler)DTSConfig.GetSection("DTS.Common.Core.PluginLib.Config"); //DTS.Common.Core.PluginLib.Config
|
||||
if (pcsh == null)
|
||||
{
|
||||
APILogger.Log("## Unable to retrieve plugin config data from DTS.Config (DTS.Common.Core.PluginLib.Config)");
|
||||
throw new Exception("Unable to retrieve plugin config data from DTS.config (DTS.Common.Core.PluginLib.Config)");
|
||||
}
|
||||
|
||||
|
||||
foreach (FilterHashElement element in pcsh.HashKeys)
|
||||
{
|
||||
try
|
||||
{
|
||||
var info = new DirectoryInfo(element.Value);
|
||||
if (!info.Exists)
|
||||
{
|
||||
APILogger.Log($"## Plugin directory does not exist: {element.Value}");
|
||||
throw new IOException($"Plugin directory does not exist: {element.Value}");
|
||||
}
|
||||
|
||||
PluginCatalog.Catalogs.Add(new DirectoryCatalog(element.Value));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log(ex);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
// Create MEF container
|
||||
PluginContainer = new CompositionContainer(PluginCatalog);
|
||||
|
||||
foreach (var catalog in PluginCatalog.Catalogs)
|
||||
{
|
||||
var directoryCatalog = catalog as DirectoryCatalog;
|
||||
|
||||
if (directoryCatalog == null)
|
||||
{
|
||||
APILogger.Log("## directory catalog is null");
|
||||
continue;
|
||||
}
|
||||
var pluginDir = directoryCatalog.FullPath;
|
||||
|
||||
var files = new DirectoryInfo(pluginDir).GetFiles("*.dll");
|
||||
|
||||
foreach (var assembly in files.Where(f => !f.Name.StartsWith("DTS.Common") && !f.Name.StartsWith("C1") && !f.Name.StartsWith("Xceed")))
|
||||
{
|
||||
var assemblyName = pluginDir + @"\" + assembly.Name;
|
||||
//var assemblyName = $"{pluginDir}{assembly.Name}";
|
||||
// verift assembly exists and matches requested paramaters
|
||||
if (!File.Exists(assemblyName))
|
||||
{
|
||||
APILogger.Log($"## File Not Found!: {assemblyName}");
|
||||
continue;
|
||||
}
|
||||
|
||||
//var info = AssemblyName.GetAssemblyName(assemblyName);
|
||||
|
||||
// NOTE: sometimes args.Name only has short assembly name, sometimes full name with public key and version
|
||||
//if (info == null || (info.FullName != args.Name && (info.Name != args.Name)))
|
||||
//{
|
||||
// continue;
|
||||
//}
|
||||
|
||||
// Load assembly
|
||||
try
|
||||
{
|
||||
var asm = Assembly.LoadFrom(assemblyName);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log("## Failed to load assembly:", ex);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
public List<Assembly> GetPluginList<T>() where T : class
|
||||
{
|
||||
var assemblyList = new List<Assembly>();
|
||||
var manager = GetPluginManager(string.Empty);
|
||||
foreach (var catalog in manager.PluginCatalog.Catalogs)
|
||||
{
|
||||
var directoryCatalog = catalog as DirectoryCatalog;
|
||||
if (directoryCatalog == null) continue;
|
||||
assemblyList.AddRange(directoryCatalog.Parts.Select(part => ReflectionModelServices.GetPartType(part).Value.Assembly).Distinct().ToList());
|
||||
|
||||
}
|
||||
return assemblyList;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns MEF plugin of type t
|
||||
/// Throws error if no type exported by plugin or more than one plugin has exported type
|
||||
/// </summary>
|
||||
/// <typeparam name="T">type to get</typeparam>
|
||||
/// <returns>reference to type t from MEF plugin</returns>
|
||||
public static T GetPlugin<T>() where T : class
|
||||
{
|
||||
var export = GetPluginManager(string.Empty).PluginContainer.GetExport<T>();
|
||||
return export?.Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns MEF plugin of type T from a collection of plugins that export the same type
|
||||
/// </summary>
|
||||
/// <typeparam name="T">exported type implemented by potentially multiple plugins</typeparam>
|
||||
/// <param name="configPluginSetting">string that tells us which specific plugin we want</param>
|
||||
/// <returns>type T</returns>
|
||||
public static T GetPlugin<T>(string configPluginSetting) where T : class
|
||||
{
|
||||
var result = new Lazy<T>();
|
||||
var manager = GetPluginManager(configPluginSetting);
|
||||
var plugins = manager.PluginContainer.GetExports<T>();
|
||||
|
||||
//loop through plugins returned and get the specific one we're looking for
|
||||
foreach (var item in plugins)
|
||||
{
|
||||
if (item.Value.ToString() != configPluginSetting) continue;
|
||||
result = item;
|
||||
break;
|
||||
}
|
||||
return result.Value;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns list of MEF plugins that export type t
|
||||
/// </summary>
|
||||
/// <typeparam name="T">type to get</typeparam>
|
||||
/// <returns>list of references to type t from MEF plugins</returns>
|
||||
public static IEnumerable<Lazy<T>> GetPlugins<T>() where T : class
|
||||
{
|
||||
var manager = GetPluginManager(string.Empty);
|
||||
return manager.PluginContainer.GetExports<T>();
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns static singleton reference to plugin manager class
|
||||
/// </summary>
|
||||
/// <returns>plugin class</returns>
|
||||
public static PluginManager GetPluginManager(string appPath)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(appPath))
|
||||
{
|
||||
var directoryInfo = new DirectoryInfo(appPath);
|
||||
}
|
||||
lock (THREAD_LOCK)
|
||||
{
|
||||
if (_pluginManager != null)
|
||||
{
|
||||
foreach (var catalog in _pluginManager.PluginCatalog.Catalogs)
|
||||
{
|
||||
var directoryCatalog = catalog as DirectoryCatalog;
|
||||
if (directoryCatalog == null) continue;
|
||||
}
|
||||
}
|
||||
return _pluginManager ?? (_pluginManager = new PluginManager(appPath));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This event triggered if system can't find plugin dependancies
|
||||
/// CurrentDomain_AssemblyResolve can search through list of directories instead of just one
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="args"></param>
|
||||
/// <returns></returns>
|
||||
private Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
|
||||
{
|
||||
foreach (var catalog in PluginCatalog.Catalogs)
|
||||
{
|
||||
var directoryCatalog = catalog as DirectoryCatalog;
|
||||
if (directoryCatalog == null)
|
||||
{
|
||||
APILogger.Log("## null directoryCatalog");
|
||||
continue;
|
||||
}
|
||||
var pluginDir = directoryCatalog.FullPath;
|
||||
|
||||
// get name of assembly
|
||||
var baseName = args.Name.Split(new[] { ',' })[0];
|
||||
var assemblyName = $"{pluginDir}\\{baseName}.dll";
|
||||
|
||||
// verift assembly exists and matches requested paramaters
|
||||
if (!File.Exists(assemblyName))
|
||||
{
|
||||
APILogger.Log($"## assembly does not exist: {assemblyName}");
|
||||
continue;
|
||||
}
|
||||
var info = AssemblyName.GetAssemblyName(assemblyName);
|
||||
|
||||
// NOTE: sometimes args.Name only has short assembly name, sometimes full name with public key and version
|
||||
if (info == null || info.FullName != args.Name && info.Name != args.Name)
|
||||
{
|
||||
APILogger.Log("## assembly info is incomplete");
|
||||
continue;
|
||||
}
|
||||
|
||||
// Load assembly
|
||||
try
|
||||
{
|
||||
var asm = Assembly.LoadFrom(assemblyName);
|
||||
return asm;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log("## failed to load", ex);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("DTS.Common.Core")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("DTS.Common.Core")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2016")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("bdf5ad7a-51db-4ad0-8186-d1ead7405848")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
BIN
Common/DTS.Common.Core/.svn/wc.db
Normal file
BIN
Common/DTS.Common.Core/.svn/wc.db
Normal file
Binary file not shown.
0
Common/DTS.Common.Core/.svn/wc.db-journal
Normal file
0
Common/DTS.Common.Core/.svn/wc.db-journal
Normal file
4
Common/DTS.Common.Core/App.config
Normal file
4
Common/DTS.Common.Core/App.config
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
|
||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/></startup></configuration>
|
||||
100
Common/DTS.Common.Core/Config/DTSConfig.cs
Normal file
100
Common/DTS.Common.Core/Config/DTSConfig.cs
Normal file
@@ -0,0 +1,100 @@
|
||||
using DTS.Common.Utilities.Logging;
|
||||
using System;
|
||||
using System.Configuration;
|
||||
using System.Linq;
|
||||
// ReSharper disable InconsistentNaming
|
||||
// ReSharper disable EmptyConstructor
|
||||
|
||||
namespace DTS.Common.Core.Config
|
||||
{
|
||||
public static class DTSConfig
|
||||
{
|
||||
private static string AltConfigPath;
|
||||
public static string AltConfigPathGet()
|
||||
{
|
||||
lock (MyLock)
|
||||
{
|
||||
return AltConfigPath;
|
||||
}
|
||||
}
|
||||
public static void AltConfigPathSet(string path)
|
||||
{
|
||||
lock (MyLock)
|
||||
{
|
||||
AltConfigPath = path;
|
||||
}
|
||||
}
|
||||
// static constructor
|
||||
static DTSConfig()
|
||||
{
|
||||
}
|
||||
|
||||
public static void DTSConfigInit(string path)
|
||||
{
|
||||
SetAltConfigPath(path);
|
||||
}
|
||||
private static object MyLock = new object();
|
||||
/// <summary>
|
||||
/// Static variable to hold alternate configuration file
|
||||
/// </summary>
|
||||
private static Configuration AltConfig;
|
||||
|
||||
public static Configuration GetAltConfig()
|
||||
{
|
||||
lock (MyLock)
|
||||
{
|
||||
return AltConfig;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Static variable to hold alternate configuration file
|
||||
/// </summary>
|
||||
/// <history>
|
||||
///
|
||||
/// </history>
|
||||
public static void SetAltConfigPath(string path)
|
||||
{
|
||||
lock (MyLock)
|
||||
{
|
||||
AltConfigPath = path;
|
||||
var dtsConfig = new ExeConfigurationFileMap
|
||||
{
|
||||
ExeConfigFilename = string.IsNullOrEmpty(AltConfigPath) ? DTSConstants.CustomConfigPath : AltConfigPath
|
||||
};
|
||||
|
||||
AltConfig = ConfigurationManager.OpenMappedExeConfiguration(dtsConfig, ConfigurationUserLevel.None, true);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Static method to retrieve a setting from config file
|
||||
/// </summary>
|
||||
/// <param name="key">string</param>
|
||||
/// <returns>string</returns>
|
||||
public static string GetAppSetting(string key)
|
||||
{
|
||||
var appSetting = AltConfig.AppSettings.Settings.Cast<KeyValueConfigurationElement>().FirstOrDefault(setting => setting.Key == key);
|
||||
if (appSetting == null)
|
||||
{
|
||||
APILogger.Log(
|
||||
$"## AltConfig.AppSettings.Settings.Cast<KeyValueConfigurationElement>().FirstOrDefault(setting => setting.Key == key) is null for key={key}");
|
||||
}
|
||||
return appSetting == null ? string.Empty : appSetting.Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Static method to get a section from config file. Used by plugin code to get plugin library section.
|
||||
/// </summary>
|
||||
/// <param name="sectionName">string</param>
|
||||
/// <returns>object</returns>
|
||||
public static object GetSection(string sectionName)
|
||||
{
|
||||
var section = AltConfig.GetSection(sectionName);
|
||||
if (section == null)
|
||||
{
|
||||
APILogger.Log($"## AltConfig.GetSection(sectionName) is null for sectionName={sectionName}");
|
||||
}
|
||||
return section;
|
||||
}
|
||||
}
|
||||
}
|
||||
108
Common/DTS.Common.Core/DTS.Common.Core.csproj
Normal file
108
Common/DTS.Common.Core/DTS.Common.Core.csproj
Normal file
@@ -0,0 +1,108 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{FAB1F470-1574-4301-B56E-D3364AA93679}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>DTS.Common.Core</RootNamespace>
|
||||
<AssemblyName>DTS.Common.Core</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<SccProjectName>
|
||||
</SccProjectName>
|
||||
<SccLocalPath>
|
||||
</SccLocalPath>
|
||||
<SccAuxPath>
|
||||
</SccAuxPath>
|
||||
<SccProvider>
|
||||
</SccProvider>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\x64\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
||||
<OutputPath>bin\x64\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\x86\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
||||
<OutputPath>bin\x86\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.ComponentModel.Composition" />
|
||||
<Reference Include="System.Configuration" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Config\DTSConfig.cs" />
|
||||
<Compile Include="DTSConstants.cs" />
|
||||
<Compile Include="EventManager\EventManager.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="ServiceManager\IServicePublishedEvent.cs" />
|
||||
<Compile Include="ServiceManager\ServiceManager.cs" />
|
||||
<Compile Include="ServiceManager\ServicePublishedEvent.cs" />
|
||||
<Compile Include="Settings\SettingsChangedEventArgs.cs" />
|
||||
<Compile Include="Settings\SettingsCollection.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
<None Include="Design\DTS.Common.CoreClassDiagram.cd" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\DTS.Common.Utilities\DTS.Common.Utilities.csproj">
|
||||
<Project>{03EACE47-EA59-44AC-B49D-956E4DC4D618}</Project>
|
||||
<Name>DTS.Common.Utilities</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent>
|
||||
</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<PreBuildEvent>
|
||||
</PreBuildEvent>
|
||||
</PropertyGroup>
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
9
Common/DTS.Common.Core/DTSConstants.cs
Normal file
9
Common/DTS.Common.Core/DTSConstants.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
// ReSharper disable InconsistentNaming
|
||||
namespace DTS.Common.Core
|
||||
{
|
||||
public static class DTSConstants
|
||||
{
|
||||
public const string CustomConfigPath = @"C:\dev\DTS.Viewer\bin\Debug\DTS.Viewer.exe.config";
|
||||
public const string ViewerConfigPath = @"C:\dev\DTS.Viewer\bin\Debug\DTS.Viewer.exe.config";
|
||||
}
|
||||
}
|
||||
139
Common/DTS.Common.Core/Design/DTS.Common.CoreClassDiagram.cd
Normal file
139
Common/DTS.Common.Core/Design/DTS.Common.CoreClassDiagram.cd
Normal file
@@ -0,0 +1,139 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ClassDiagram MajorVersion="1" MinorVersion="1">
|
||||
<Class Name="DTS.Common.Core.Config.DTSConfig" Collapsed="true">
|
||||
<Position X="0.5" Y="0.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AIAQAAAEAACAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAIA=</HashCode>
|
||||
<FileName>Config\DTSConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="DTS.Common.Core.DTSConstants" Collapsed="true">
|
||||
<Position X="2.25" Y="0.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAgAAAAA=</HashCode>
|
||||
<FileName>DTSConstants.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="DTS.Common.Core.EventManager.EventManager" Collapsed="true">
|
||||
<Position X="4" Y="0.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAIIAAACAAGAEAACAAAAAACAAAAQAAAAABAAAA=</HashCode>
|
||||
<FileName>EventManager\EventManager.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="DTS.Common.Core.EventManager.EventMetaData<T>" Collapsed="true">
|
||||
<Position X="5.75" Y="0.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA=</HashCode>
|
||||
<FileName>EventManager\EventManager.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="DTS.Common.Core.PluginLib.PluginConfig" Collapsed="true">
|
||||
<Position X="4" Y="1.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAgAAAIAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>PluginLib\PluginConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="DTS.Common.Core.PluginLib.PluginConfigData" Collapsed="true">
|
||||
<Position X="5.75" Y="1.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAA=</HashCode>
|
||||
<FileName>PluginLib\PluginConfigData.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="DTS.Common.Core.PluginLib.PluginConfigSectionHandler" Collapsed="true">
|
||||
<Position X="0.5" Y="2.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>PluginLib\PluginConfigSectionHandler.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="DTS.Common.Core.PluginLib.FilterHashKeyCollection" Collapsed="true">
|
||||
<Position X="2.25" Y="1.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAACAAAAAAAAAAAACAAAAAAAAAABAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>PluginLib\PluginConfigSectionHandler.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="DTS.Common.Core.PluginLib.FilterHashElement" Collapsed="true">
|
||||
<Position X="0.5" Y="1.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAgAAAAAAA=</HashCode>
|
||||
<FileName>PluginLib\PluginConfigSectionHandler.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="DTS.Common.Core.PluginLib.PluginManager" Collapsed="true">
|
||||
<Position X="2.25" Y="2.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AEAABAAAAAAEAACAAAMAAAAAAAAAAAAAAgAAAAAAAAA=</HashCode>
|
||||
<FileName>PluginLib\PluginManager.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="DTS.Common.Core.ServiceManager.ServiceManager" Collapsed="true">
|
||||
<Position X="4" Y="2.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>gAAAAAAAAAAAAABAAEAAAAABAAAAAAAAAAAAAAFAAAA=</HashCode>
|
||||
<FileName>ServiceManager\ServiceManager.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="DTS.Common.Core.ServiceManager.ServicePublishedEvent" Collapsed="true" BaseTypeListCollapsed="true">
|
||||
<Position X="5.75" Y="2.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAA=</HashCode>
|
||||
<FileName>ServiceManager\ServicePublishedEvent.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<Lollipop Position="0.2" Collapsed="true" />
|
||||
</Class>
|
||||
<Class Name="DTS.Common.Core.Settings.SettingsChangedEventArgs<TKey, TItem>" Collapsed="true">
|
||||
<Position X="0.5" Y="3.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAQAAAEAAAAEAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Settings\SettingsChangedEventArgs.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="DTS.Common.Core.Settings.SettingsCollection<TKey, TItem>" Collapsed="true" BaseTypeListCollapsed="true">
|
||||
<Position X="2.25" Y="3.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>CAIAAAAAAAAEABAQCAAABAQAABAAAAAEAAAgAABwKAA=</HashCode>
|
||||
<FileName>Settings\SettingsCollection.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<Lollipop Position="0.2" Collapsed="true" />
|
||||
</Class>
|
||||
<Interface Name="DTS.Common.Core.ServiceManager.IServicePublishedEvent" Collapsed="true">
|
||||
<Position X="0.5" Y="4.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAA=</HashCode>
|
||||
<FileName>ServiceManager\IServicePublishedEvent.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Enum Name="DTS.Common.Core.EventManager.EventDiagnosticType" Collapsed="true">
|
||||
<Position X="2.25" Y="5.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAABAAAAAAAAAAAAAEIACAAAAAAABAAAA=</HashCode>
|
||||
<FileName>EventManager\EventManager.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Enum>
|
||||
<Enum Name="DTS.Common.Core.Settings.ChangeSettingType" Collapsed="true">
|
||||
<Position X="0.5" Y="5.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAIAAAAAAAAAAABAABAABAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Settings\SettingsChangedEventArgs.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Enum>
|
||||
<Delegate Name="DTS.Common.Core.EventManager.SubscriberCallbackDelegate<T>" Collapsed="true">
|
||||
<Position X="2.25" Y="6.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>EventManager\EventManager.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Delegate>
|
||||
<Delegate Name="DTS.Common.Core.EventManager.DiagnosticCallbackDelegate" Collapsed="true">
|
||||
<Position X="0.5" Y="6.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAACAAEAAAAAAAAAEAAAABAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>EventManager\EventManager.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Delegate>
|
||||
<Font Name="Segoe UI" Size="9" />
|
||||
</ClassDiagram>
|
||||
193
Common/DTS.Common.Core/EventManager/EventManager.cs
Normal file
193
Common/DTS.Common.Core/EventManager/EventManager.cs
Normal file
@@ -0,0 +1,193 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
|
||||
namespace DTS.Common.Core.EventManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Delegate used by event listeners
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="item"></param>
|
||||
public delegate void SubscriberCallbackDelegate<in T>(T item) where T : class;
|
||||
|
||||
public delegate void DiagnosticCallbackDelegate(EventDiagnosticType eventType, Type t, object eventData, string listener);
|
||||
|
||||
/// <summary>
|
||||
/// Allows components to publish events without knowing who is listening
|
||||
/// </summary>
|
||||
public static class EventManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Tracks listeners
|
||||
/// </summary>
|
||||
private static readonly Dictionary<Type, List<object>> SubscriberList = new Dictionary<Type, List<object>>();
|
||||
|
||||
/// <summary>
|
||||
/// Tracks diagnostic listeners
|
||||
/// </summary>
|
||||
private static readonly List<DiagnosticCallbackDelegate> DiagnosticList = new List<DiagnosticCallbackDelegate>();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Publish an event
|
||||
/// </summary>
|
||||
/// <typeparam name="T">type of event</typeparam>
|
||||
/// <param name="eventData">event listener</param>
|
||||
public static void Publish<T>(T eventData) where T : class
|
||||
{
|
||||
if (!SubscriberList.ContainsKey(typeof(T))) return;
|
||||
|
||||
var listeners = SubscriberList[typeof(T)];
|
||||
|
||||
foreach (var listener in listeners)
|
||||
{
|
||||
var metaData = listener as EventMetaData<T>;
|
||||
if (metaData == null) continue;
|
||||
|
||||
var triggerCallback = true;
|
||||
|
||||
if (metaData.EventFilter != null)
|
||||
{
|
||||
triggerCallback = metaData.EventFilter(eventData);
|
||||
}
|
||||
|
||||
if (triggerCallback)
|
||||
{
|
||||
metaData.Callback(eventData);
|
||||
}
|
||||
|
||||
SendDiagnosticEvent(EventDiagnosticType.PublishEvent, typeof(T), eventData, metaData.EventFilter?.Method);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subscribe to an event
|
||||
/// </summary>
|
||||
/// <typeparam name="T">type of event</typeparam>
|
||||
/// <param name="listener">event listener</param>
|
||||
public static void Subscribe<T>(SubscriberCallbackDelegate<T> listener) where T : class
|
||||
{
|
||||
Subscribe(listener, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subscribe to an event
|
||||
/// </summary>
|
||||
/// <typeparam name="T">type of event</typeparam>
|
||||
/// <param name="listener">event listener</param>
|
||||
/// <param name="eventFilter">predicate to filter events sent to event listener</param>
|
||||
public static void Subscribe<T>(SubscriberCallbackDelegate<T> listener, Predicate<T> eventFilter) where T : class
|
||||
{
|
||||
if (!SubscriberList.ContainsKey(typeof(T)))
|
||||
{
|
||||
SubscriberList.Add(typeof(T), new List<object>());
|
||||
}
|
||||
|
||||
var listeners = SubscriberList[typeof(T)];
|
||||
|
||||
var metaData = new EventMetaData<T> { Callback = listener, EventFilter = eventFilter };
|
||||
|
||||
listeners.Add(metaData);
|
||||
|
||||
SendDiagnosticEvent(EventDiagnosticType.AddListener, typeof(T), null, listener.Method);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allows a subscriber to unsubscribe
|
||||
/// </summary>
|
||||
/// <typeparam name="T">type of event</typeparam>
|
||||
/// <param name="listener">event listener</param>
|
||||
public static void UnSubscribe<T>(SubscriberCallbackDelegate<T> listener) where T : class
|
||||
{
|
||||
if (!SubscriberList.ContainsKey(typeof(T))) return;
|
||||
|
||||
var listeners = SubscriberList[typeof(T)];
|
||||
|
||||
listeners.RemoveAll(p =>
|
||||
{
|
||||
return p is EventMetaData<T> eventMetaData && eventMetaData.Callback == listener;
|
||||
});
|
||||
|
||||
SendDiagnosticEvent(EventDiagnosticType.RemoveListener, typeof(T), null, listener.Method);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears all listeners
|
||||
/// </summary>
|
||||
public static void Clear()
|
||||
{
|
||||
SubscriberList.Clear();
|
||||
SendDiagnosticEvent(EventDiagnosticType.RemoveListener, null, null, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add diagnostic listener
|
||||
/// </summary>
|
||||
/// <param name="listener">event listener</param>
|
||||
public static void SubscribeToDiagnosticEvents(DiagnosticCallbackDelegate listener)
|
||||
{
|
||||
DiagnosticList.Add(listener);
|
||||
SendDiagnosticEvent(EventDiagnosticType.AddListenerDiagnostic, null, null, listener.Method);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clear diagnostic event
|
||||
/// </summary>
|
||||
/// <param name="listener">listener to unsubscribe</param>
|
||||
public static void UnSubscribeToDiagnosticEvents(DiagnosticCallbackDelegate listener)
|
||||
{
|
||||
DiagnosticList.RemoveAll(p => p == listener);
|
||||
SendDiagnosticEvent(EventDiagnosticType.RemoveListenerDiagnostic, null, null, listener.Method);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clear all diagnostic events
|
||||
/// </summary>
|
||||
public static void ClearDiagnosticEvents()
|
||||
{
|
||||
DiagnosticList.Clear();
|
||||
SendDiagnosticEvent(EventDiagnosticType.RemoveListenerDiagnostic, null, null, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a diagnostic event
|
||||
/// </summary>
|
||||
/// <param name="diagnosticEventType"></param>
|
||||
/// <param name="eventType"></param>
|
||||
/// <param name="eventData"></param>
|
||||
/// <param name="listenerMethod"></param>
|
||||
private static void SendDiagnosticEvent(EventDiagnosticType diagnosticEventType, Type eventType, object eventData, MemberInfo listenerMethod)
|
||||
{
|
||||
foreach (var diagnosticEvent in DiagnosticList)
|
||||
{
|
||||
string listener = null;
|
||||
|
||||
if (listenerMethod != null && listenerMethod.DeclaringType != null)
|
||||
{
|
||||
listener = $"{listenerMethod.DeclaringType.FullName}.{listenerMethod.Name} , {listenerMethod.DeclaringType.Assembly.FullName}";
|
||||
}
|
||||
|
||||
diagnosticEvent(diagnosticEventType, eventType, eventData, listener);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public enum EventDiagnosticType
|
||||
{
|
||||
AddListener = 0,
|
||||
AddListenerDiagnostic = 1,
|
||||
PublishEvent = 2,
|
||||
RemoveListenerDiagnostic = 3,
|
||||
RemoveListener = 4
|
||||
}
|
||||
|
||||
internal class EventMetaData<T> where T : class
|
||||
{
|
||||
public Predicate<T> EventFilter { get; set; }
|
||||
public SubscriberCallbackDelegate<T> Callback { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
27
Common/DTS.Common.Core/PluginLib/PluginConfig.cs
Normal file
27
Common/DTS.Common.Core/PluginLib/PluginConfig.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using DTS.Common.Core.Config;
|
||||
// ReSharper disable InconsistentNaming
|
||||
|
||||
namespace DTS.Common.Core.PluginLib
|
||||
{
|
||||
/// <summary>
|
||||
/// Static class used to store plugin configuration info
|
||||
/// </summary>
|
||||
public static class PluginConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// name of setting to look in config for equipment database
|
||||
/// </summary>
|
||||
public const string DTSPlugins = "DTSPlugins";
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// concatenate plugin name from app setting with class exporter name for DTS plugins
|
||||
/// </summary>
|
||||
/// <param name="setting"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetDTSPluginsSetting(string setting)
|
||||
{
|
||||
return DTSConfig.GetAppSetting(DTSPlugins) + "." + setting;
|
||||
}
|
||||
}
|
||||
}
|
||||
14
Common/DTS.Common.Core/PluginLib/PluginConfigData.cs
Normal file
14
Common/DTS.Common.Core/PluginLib/PluginConfigData.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace DTS.Common.Core.PluginLib
|
||||
{
|
||||
/// <summary>
|
||||
/// Support class that stores data de-serialized from DatPro.Core.PluginLib.Config in App.Config configuration section
|
||||
/// </summary>
|
||||
[XmlRoot(ElementName = "DatPro.Core.PluginLib.Config")]
|
||||
public class PluginConfigData
|
||||
{
|
||||
[XmlArrayItem("Folder")]
|
||||
public string[] PluginFolders;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
using System.Configuration;
|
||||
|
||||
namespace DTS.Common.Core.PluginLib
|
||||
{
|
||||
/// <summary>
|
||||
/// Support class that parses data from DTS.Common.Core.PluginLib.Config configuration section
|
||||
/// </summary>
|
||||
public class PluginConfigSectionHandler : ConfigurationSection
|
||||
{
|
||||
[ConfigurationProperty("PluginFolders")]
|
||||
public FilterHashKeyCollection HashKeys => (FilterHashKeyCollection)base["PluginFolders"];
|
||||
}
|
||||
|
||||
[ConfigurationCollection(typeof(FilterHashElement))]
|
||||
public class FilterHashKeyCollection : ConfigurationElementCollection
|
||||
{
|
||||
protected override ConfigurationElement CreateNewElement()
|
||||
{
|
||||
return new FilterHashElement();
|
||||
}
|
||||
|
||||
protected override object GetElementKey(ConfigurationElement element)
|
||||
{
|
||||
return ((FilterHashElement)element).Key;
|
||||
}
|
||||
|
||||
public FilterHashElement this[int idx] => (FilterHashElement)BaseGet(idx);
|
||||
}
|
||||
|
||||
public class FilterHashElement : ConfigurationElement
|
||||
{
|
||||
[ConfigurationProperty("key", DefaultValue = "", IsKey = true, IsRequired = true)]
|
||||
public string Key
|
||||
{
|
||||
get => (string)base["key"];
|
||||
set => base["key"] = value;
|
||||
}
|
||||
|
||||
[ConfigurationProperty("value", DefaultValue = "", IsKey = false, IsRequired = false)]
|
||||
public string Value
|
||||
{
|
||||
get => (string)base["value"];
|
||||
set => base["value"] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
272
Common/DTS.Common.Core/PluginLib/PluginManager.cs
Normal file
272
Common/DTS.Common.Core/PluginLib/PluginManager.cs
Normal file
@@ -0,0 +1,272 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.IO;
|
||||
using System.ComponentModel.Composition.Hosting;
|
||||
using System.ComponentModel.Composition.ReflectionModel;
|
||||
using System.Linq;
|
||||
using DTS.Common.Core.Config;
|
||||
using DTS.Common.Utilities.Logging;
|
||||
|
||||
// ReSharper disable RedundantJumpStatement
|
||||
// ReSharper disable UnusedTypeParameter
|
||||
// ReSharper disable UnusedMember.Local
|
||||
// ReSharper disable UnusedParameter.Local
|
||||
|
||||
namespace DTS.Common.Core.PluginLib
|
||||
{
|
||||
/// <summary>
|
||||
/// PluginManager class to manage MEF plugins
|
||||
/// NOTE: This class has to be thread safe
|
||||
/// </summary>
|
||||
public class PluginManager
|
||||
{
|
||||
// reference to singleton plugin manager
|
||||
private static PluginManager _pluginManager;
|
||||
|
||||
/// <summary>
|
||||
/// MEF catalog
|
||||
/// </summary>
|
||||
public AggregateCatalog PluginCatalog { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// MEF container
|
||||
/// </summary>
|
||||
private CompositionContainer PluginContainer { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Thread lock
|
||||
/// </summary>
|
||||
private static readonly object THREAD_LOCK = new object();
|
||||
|
||||
/// <summary>
|
||||
/// Constructor that intializes catalog and container
|
||||
/// </summary>
|
||||
private PluginManager(string appPath)
|
||||
{
|
||||
// Create MEF catalog
|
||||
PluginCatalog = new AggregateCatalog();
|
||||
DTSConfig.DTSConfigInit(appPath);
|
||||
// Get plugin folder from App.Config;
|
||||
var pcsh = (PluginConfigSectionHandler)DTSConfig.GetSection("DTS.Common.Core.PluginLib.Config"); //DTS.Common.Core.PluginLib.Config
|
||||
if (pcsh == null)
|
||||
{
|
||||
APILogger.Log("## Unable to retrieve plugin config data from DTS.Config (DTS.Common.Core.PluginLib.Config)");
|
||||
throw new Exception("Unable to retrieve plugin config data from DTS.config (DTS.Common.Core.PluginLib.Config)");
|
||||
}
|
||||
|
||||
|
||||
foreach (FilterHashElement element in pcsh.HashKeys)
|
||||
{
|
||||
try
|
||||
{
|
||||
var info = new DirectoryInfo(element.Value);
|
||||
if (!info.Exists)
|
||||
{
|
||||
APILogger.Log($"## Plugin directory does not exist: {element.Value}");
|
||||
throw new IOException($"Plugin directory does not exist: {element.Value}");
|
||||
}
|
||||
|
||||
PluginCatalog.Catalogs.Add(new DirectoryCatalog(element.Value));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log(ex);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
// Create MEF container
|
||||
PluginContainer = new CompositionContainer(PluginCatalog);
|
||||
|
||||
foreach (var catalog in PluginCatalog.Catalogs)
|
||||
{
|
||||
var directoryCatalog = catalog as DirectoryCatalog;
|
||||
|
||||
if (directoryCatalog == null)
|
||||
{
|
||||
APILogger.Log("## directory catalog is null");
|
||||
continue;
|
||||
}
|
||||
var pluginDir = directoryCatalog.FullPath;
|
||||
|
||||
var files = new DirectoryInfo(pluginDir).GetFiles("*.dll");
|
||||
|
||||
foreach (var assembly in files.Where(f => !f.Name.StartsWith("DTS.Common") && !f.Name.StartsWith("C1") && !f.Name.StartsWith("Xceed")))
|
||||
{
|
||||
var assemblyName = pluginDir + @"\" + assembly.Name;
|
||||
//var assemblyName = $"{pluginDir}{assembly.Name}";
|
||||
// verift assembly exists and matches requested paramaters
|
||||
if (!File.Exists(assemblyName))
|
||||
{
|
||||
APILogger.Log($"## File Not Found!: {assemblyName}");
|
||||
continue;
|
||||
}
|
||||
|
||||
//var info = AssemblyName.GetAssemblyName(assemblyName);
|
||||
|
||||
// NOTE: sometimes args.Name only has short assembly name, sometimes full name with public key and version
|
||||
//if (info == null || (info.FullName != args.Name && (info.Name != args.Name)))
|
||||
//{
|
||||
// continue;
|
||||
//}
|
||||
|
||||
// Load assembly
|
||||
try
|
||||
{
|
||||
var asm = Assembly.LoadFrom(assemblyName);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log("## Failed to load assembly:", ex);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
public List<Assembly> GetPluginList<T>() where T : class
|
||||
{
|
||||
var assemblyList = new List<Assembly>();
|
||||
var manager = GetPluginManager(string.Empty);
|
||||
foreach (var catalog in manager.PluginCatalog.Catalogs)
|
||||
{
|
||||
var directoryCatalog = catalog as DirectoryCatalog;
|
||||
if (directoryCatalog == null) continue;
|
||||
assemblyList.AddRange(directoryCatalog.Parts.Select(part => ReflectionModelServices.GetPartType(part).Value.Assembly).Distinct().ToList());
|
||||
|
||||
}
|
||||
return assemblyList;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns MEF plugin of type t
|
||||
/// Throws error if no type exported by plugin or more than one plugin has exported type
|
||||
/// </summary>
|
||||
/// <typeparam name="T">type to get</typeparam>
|
||||
/// <returns>reference to type t from MEF plugin</returns>
|
||||
public static T GetPlugin<T>() where T : class
|
||||
{
|
||||
var export = GetPluginManager(string.Empty).PluginContainer.GetExport<T>();
|
||||
return export?.Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns MEF plugin of type T from a collection of plugins that export the same type
|
||||
/// </summary>
|
||||
/// <typeparam name="T">exported type implemented by potentially multiple plugins</typeparam>
|
||||
/// <param name="configPluginSetting">string that tells us which specific plugin we want</param>
|
||||
/// <returns>type T</returns>
|
||||
public static T GetPlugin<T>(string configPluginSetting) where T : class
|
||||
{
|
||||
var result = new Lazy<T>();
|
||||
var manager = GetPluginManager(configPluginSetting);
|
||||
var plugins = manager.PluginContainer.GetExports<T>();
|
||||
|
||||
//loop through plugins returned and get the specific one we're looking for
|
||||
foreach (var item in plugins)
|
||||
{
|
||||
if (item.Value.ToString() != configPluginSetting) continue;
|
||||
result = item;
|
||||
break;
|
||||
}
|
||||
return result.Value;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns list of MEF plugins that export type t
|
||||
/// </summary>
|
||||
/// <typeparam name="T">type to get</typeparam>
|
||||
/// <returns>list of references to type t from MEF plugins</returns>
|
||||
public static IEnumerable<Lazy<T>> GetPlugins<T>() where T : class
|
||||
{
|
||||
var manager = GetPluginManager(string.Empty);
|
||||
return manager.PluginContainer.GetExports<T>();
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns static singleton reference to plugin manager class
|
||||
/// </summary>
|
||||
/// <returns>plugin class</returns>
|
||||
public static PluginManager GetPluginManager(string appPath)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(appPath))
|
||||
{
|
||||
var directoryInfo = new DirectoryInfo(appPath);
|
||||
}
|
||||
lock (THREAD_LOCK)
|
||||
{
|
||||
if (_pluginManager != null)
|
||||
{
|
||||
foreach (var catalog in _pluginManager.PluginCatalog.Catalogs)
|
||||
{
|
||||
var directoryCatalog = catalog as DirectoryCatalog;
|
||||
if (directoryCatalog == null) continue;
|
||||
}
|
||||
}
|
||||
return _pluginManager ?? (_pluginManager = new PluginManager(appPath));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This event triggered if system can't find plugin dependancies
|
||||
/// CurrentDomain_AssemblyResolve can search through list of directories instead of just one
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="args"></param>
|
||||
/// <returns></returns>
|
||||
private Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
|
||||
{
|
||||
foreach (var catalog in PluginCatalog.Catalogs)
|
||||
{
|
||||
var directoryCatalog = catalog as DirectoryCatalog;
|
||||
if (directoryCatalog == null)
|
||||
{
|
||||
APILogger.Log("## null directoryCatalog");
|
||||
continue;
|
||||
}
|
||||
var pluginDir = directoryCatalog.FullPath;
|
||||
|
||||
// get name of assembly
|
||||
var baseName = args.Name.Split(new[] { ',' })[0];
|
||||
var assemblyName = $"{pluginDir}\\{baseName}.dll";
|
||||
|
||||
// verift assembly exists and matches requested paramaters
|
||||
if (!File.Exists(assemblyName))
|
||||
{
|
||||
APILogger.Log($"## assembly does not exist: {assemblyName}");
|
||||
continue;
|
||||
}
|
||||
var info = AssemblyName.GetAssemblyName(assemblyName);
|
||||
|
||||
// NOTE: sometimes args.Name only has short assembly name, sometimes full name with public key and version
|
||||
if (info == null || info.FullName != args.Name && info.Name != args.Name)
|
||||
{
|
||||
APILogger.Log("## assembly info is incomplete");
|
||||
continue;
|
||||
}
|
||||
|
||||
// Load assembly
|
||||
try
|
||||
{
|
||||
var asm = Assembly.LoadFrom(assemblyName);
|
||||
return asm;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log("## failed to load", ex);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
36
Common/DTS.Common.Core/Properties/AssemblyInfo.cs
Normal file
36
Common/DTS.Common.Core/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("DTS.Common.Core")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("DTS.Common.Core")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2016")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("bdf5ad7a-51db-4ad0-8186-d1ead7405848")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
@@ -0,0 +1,20 @@
|
||||
using System;
|
||||
|
||||
namespace DTS.Common.Core.ServiceManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Event fired when a service interface is published\unpublished
|
||||
/// </summary>
|
||||
public interface IServicePublishedEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns type of service being published\unpublished
|
||||
/// </summary>
|
||||
Type ServiceType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if Service is being published, false if being unpublished
|
||||
/// </summary>
|
||||
bool IsPublished { get; }
|
||||
}
|
||||
}
|
||||
141
Common/DTS.Common.Core/ServiceManager/ServiceManager.cs
Normal file
141
Common/DTS.Common.Core/ServiceManager/ServiceManager.cs
Normal file
@@ -0,0 +1,141 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
// ReSharper disable InconsistentNaming
|
||||
|
||||
namespace DTS.Common.Core.ServiceManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Service manager allows a component to publish an implementation of a singleton interface (service) that
|
||||
/// other components can retrieve reference to without knowing who published it
|
||||
/// </summary>
|
||||
public static class ServiceManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Stores all published interfaces
|
||||
/// </summary>
|
||||
private static readonly Dictionary<Type, object> Services = new Dictionary<Type, object>();
|
||||
|
||||
/// <summary>
|
||||
/// Publishes a service
|
||||
/// </summary>
|
||||
/// <typeparam name="T">interface type of service</typeparam>
|
||||
/// <param name="item">implementation of service</param>
|
||||
public static void Publish<T>(T item) where T : class
|
||||
{
|
||||
if (Services.ContainsKey(typeof(T)))
|
||||
{
|
||||
throw new ArgumentException($"{typeof(T).Name}: has already been published");
|
||||
}
|
||||
|
||||
Services.Add(typeof(T), item);
|
||||
SendServicePublishedEvent(typeof(T), true);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Publishes a list of services
|
||||
/// </summary>
|
||||
/// <param name="item">class that will implement all the listed interfaces</param>
|
||||
/// <param name="interfaceList">list of interfaces</param>
|
||||
/// <param name="skipPublishedInterfaces">true to avoid errors on already published interfaces</param>
|
||||
public static void Publish(object item, IEnumerable<Type> interfaceList, bool skipPublishedInterfaces)
|
||||
{
|
||||
foreach (var t in interfaceList)
|
||||
{
|
||||
if (Exists(t))
|
||||
{
|
||||
if (!skipPublishedInterfaces)
|
||||
{
|
||||
// service already published and caller indicated we should error out
|
||||
throw new ArgumentException($"{t.Name}: has already been published");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// service doesn't exist so publish it
|
||||
Services.Add(t, item);
|
||||
SendServicePublishedEvent(t, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if specifed interface has been published, false if not
|
||||
/// </summary>
|
||||
/// <typeparam name="T">type of interface to check</typeparam>
|
||||
/// <returns>true if interface has been published; false if not published</returns>
|
||||
public static bool Exists<T>() where T : class
|
||||
{
|
||||
return Services.ContainsKey(typeof(T));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if specifed interface has been published, false if not
|
||||
/// </summary>
|
||||
/// <param name="t">type of interface to check</param>
|
||||
/// <returns>true if interface has been published; false if not published</returns>
|
||||
public static bool Exists(Type t)
|
||||
{
|
||||
return Services.ContainsKey(t);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns published service
|
||||
/// </summary>
|
||||
/// <typeparam name="T">interface type of service</typeparam>
|
||||
/// <returns>published service or exception if not currently published</returns>
|
||||
public static T Get<T>() where T : class
|
||||
{
|
||||
if (!Services.ContainsKey(typeof(T)))
|
||||
{
|
||||
throw new ArgumentException($"{typeof(T).Name}: has not been published");
|
||||
}
|
||||
|
||||
return Services[typeof(T)] as T;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears specified service
|
||||
/// </summary>
|
||||
/// <typeparam name="T">interface type of service to clear</typeparam>
|
||||
public static void Clear<T>() where T : class
|
||||
{
|
||||
if (Services.ContainsKey(typeof(T)))
|
||||
{
|
||||
SendServicePublishedEvent(typeof(T), false);
|
||||
Services.Remove(typeof(T));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears list of published interfaces
|
||||
/// </summary>
|
||||
/// <param name="interfaceList">list of interfaces to unpublish</param>
|
||||
public static void Clear(IEnumerable<Type> interfaceList)
|
||||
{
|
||||
foreach (var t in interfaceList)
|
||||
{
|
||||
if (!Services.ContainsKey(t)) continue;
|
||||
|
||||
SendServicePublishedEvent(t, false);
|
||||
Services.Remove(t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Sends a IServicePublishedEvent through the Event Manger to let subscribers know when
|
||||
/// a service is published or unpublished
|
||||
/// </summary>
|
||||
/// <param name="type">type of interface</param>
|
||||
/// <param name="published">true if being published, false if being unpublished</param>
|
||||
private static void SendServicePublishedEvent(Type type, bool published)
|
||||
{
|
||||
EventManager.EventManager.Publish<IServicePublishedEvent>(new ServicePublishedEvent
|
||||
{
|
||||
IsPublished = published,
|
||||
ServiceType = type
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using System;
|
||||
|
||||
namespace DTS.Common.Core.ServiceManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Event fired when a service interface is published\unpublished
|
||||
/// </summary>
|
||||
public class ServicePublishedEvent : IServicePublishedEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns type of service being published\unpublished
|
||||
/// </summary>
|
||||
public Type ServiceType
|
||||
{
|
||||
get;
|
||||
internal set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if Service is being published, false if being unpublished
|
||||
/// </summary>
|
||||
public bool IsPublished
|
||||
{
|
||||
get;
|
||||
internal set;
|
||||
}
|
||||
}
|
||||
}
|
||||
84
Common/DTS.Common.Core/Settings/SettingsChangedEventArgs.cs
Normal file
84
Common/DTS.Common.Core/Settings/SettingsChangedEventArgs.cs
Normal file
@@ -0,0 +1,84 @@
|
||||
using System;
|
||||
|
||||
namespace DTS.Common.Core.Settings
|
||||
{
|
||||
/// <summary>
|
||||
/// Event arguments describing change to settings collection
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey">key type used in collection</typeparam>
|
||||
/// <typeparam name="TItem">value type used in collection</typeparam>
|
||||
public class SettingsChangedEventArgs<TKey, TItem> : EventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="changeType">type of scenario change</param>
|
||||
public SettingsChangedEventArgs(ChangeSettingType changeType)
|
||||
{
|
||||
ChangeType = changeType;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="changeType">change type</param>
|
||||
/// <param name="key">key type used in collection</param>
|
||||
public SettingsChangedEventArgs(ChangeSettingType changeType, TKey key)
|
||||
{
|
||||
ChangeType = changeType;
|
||||
Key = key;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="changeType">change type</param>
|
||||
/// <param name="key">key type used in collection</param>
|
||||
/// <param name="item">value type used in collection</param>
|
||||
public SettingsChangedEventArgs(ChangeSettingType changeType, TKey key, TItem item)
|
||||
{
|
||||
ChangeType = changeType;
|
||||
Key = key;
|
||||
Item = item;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns type of scenario change
|
||||
/// </summary>
|
||||
public ChangeSettingType ChangeType
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// key associated with changed setting
|
||||
/// </summary>
|
||||
public TKey Key
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Value associated with changed settting
|
||||
/// </summary>
|
||||
public TItem Item
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Type of settings changed
|
||||
/// </summary>
|
||||
public enum ChangeSettingType
|
||||
{
|
||||
Add = 0,
|
||||
Remove = 1,
|
||||
Modified = 3,
|
||||
ClearAll = 4
|
||||
}
|
||||
|
||||
}
|
||||
213
Common/DTS.Common.Core/Settings/SettingsCollection.cs
Normal file
213
Common/DTS.Common.Core/Settings/SettingsCollection.cs
Normal file
@@ -0,0 +1,213 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
namespace DTS.Common.Core.Settings
|
||||
{
|
||||
/// <summary>
|
||||
/// Implements a dictionary with events when an item is changed
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey">key type</typeparam>
|
||||
/// <typeparam name="TItem">value type</typeparam>
|
||||
public class SettingsCollection<TKey, TItem> : IDictionary<TKey, TItem>
|
||||
{
|
||||
/// <summary>
|
||||
/// Event fired when an item changes in dictionary
|
||||
/// </summary>
|
||||
public event EventHandler<SettingsChangedEventArgs<TKey, TItem>> CollectionItemPropertyChanged;
|
||||
|
||||
/// <summary>
|
||||
/// List of stored items
|
||||
/// </summary>
|
||||
private readonly Dictionary<TKey, TItem> _items = new Dictionary<TKey, TItem>();
|
||||
|
||||
|
||||
#region IDictionary
|
||||
|
||||
/// <summary>
|
||||
/// Add item
|
||||
/// </summary>
|
||||
/// <param name="key">key</param>
|
||||
/// <param name="value">value</param>
|
||||
public void Add(TKey key, TItem value)
|
||||
{
|
||||
_items.Add(key, value);
|
||||
FireItemChangedEvent(ChangeSettingType.Add, key, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if item contains key
|
||||
/// </summary>
|
||||
/// <param name="key">key</param>
|
||||
/// <returns>true if key exists</returns>
|
||||
public bool ContainsKey(TKey key)
|
||||
{
|
||||
return _items.ContainsKey(key);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Returns all keys in collection
|
||||
/// </summary>
|
||||
public ICollection<TKey> Keys => _items.Keys;
|
||||
|
||||
/// <summary>
|
||||
/// Removes key
|
||||
/// </summary>
|
||||
/// <param name="key">key</param>
|
||||
/// <returns>true if key removed</returns>
|
||||
public bool Remove(TKey key)
|
||||
{
|
||||
var res = _items.Remove(key);
|
||||
if (res) FireItemChangedEvent(ChangeSettingType.Remove, key);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Trys to get specified value
|
||||
/// </summary>
|
||||
/// <param name="key">key</param>
|
||||
/// <param name="value">value if key exists</param>
|
||||
/// <returns>true if key exists; false if it doesn't exist</returns>
|
||||
public bool TryGetValue(TKey key, out TItem value)
|
||||
{
|
||||
return _items.TryGetValue(key, out value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// List of values in collection
|
||||
/// </summary>
|
||||
public ICollection<TItem> Values => _items.Values;
|
||||
|
||||
/// <summary>
|
||||
/// Gets/sets item in collection (overloads [] operator)
|
||||
/// </summary>
|
||||
/// <param name="key">key</param>
|
||||
/// <returns>item in collection</returns>
|
||||
public TItem this[TKey key]
|
||||
{
|
||||
get => _items[key];
|
||||
set
|
||||
{
|
||||
_items[key] = value;
|
||||
FireItemChangedEvent(ChangeSettingType.Add, key, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds new item
|
||||
/// </summary>
|
||||
/// <param name="item">new item to add</param>
|
||||
public void Add(KeyValuePair<TKey, TItem> item)
|
||||
{
|
||||
_items.Add(item.Key, item.Value);
|
||||
FireItemChangedEvent(ChangeSettingType.Add, item.Key, item.Value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears entire collection
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
_items.Clear();
|
||||
FireItemChangedEvent(ChangeSettingType.ClearAll);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if item is in collection
|
||||
/// </summary>
|
||||
/// <param name="item">item to check</param>
|
||||
/// <returns>true if item exists</returns>
|
||||
public bool Contains(KeyValuePair<TKey, TItem> item)
|
||||
{
|
||||
return _items.ContainsKey(item.Key) && _items.ContainsValue(item.Value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copys items to array
|
||||
/// </summary>
|
||||
/// <param name="array"></param>
|
||||
/// <param name="arrayIndex"></param>
|
||||
public void CopyTo(KeyValuePair<TKey, TItem>[] array, int arrayIndex)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns count of items
|
||||
/// </summary>
|
||||
public int Count => _items.Count;
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if readonly collection
|
||||
/// </summary>
|
||||
public bool IsReadOnly => false;
|
||||
|
||||
/// <summary>
|
||||
/// Removes specified item
|
||||
/// </summary>
|
||||
/// <param name="item">item to remove</param>
|
||||
/// <returns>true if item removed</returns>
|
||||
public bool Remove(KeyValuePair<TKey, TItem> item)
|
||||
{
|
||||
var res = _items.Remove(item.Key);
|
||||
if (res) FireItemChangedEvent(ChangeSettingType.Remove, item.Key);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return enumerator for collection
|
||||
/// </summary>
|
||||
/// <returns>enumerator</returns>
|
||||
public IEnumerator<KeyValuePair<TKey, TItem>> GetEnumerator()
|
||||
{
|
||||
return _items.GetEnumerator();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return enumerator for collection
|
||||
/// </summary>
|
||||
/// <returns>enumerator</returns>
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return _items.GetEnumerator();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private methods
|
||||
|
||||
/// <summary>
|
||||
/// Fires collection change event
|
||||
/// </summary>
|
||||
/// <param name="changeType">type of change</param>
|
||||
private void FireItemChangedEvent(ChangeSettingType changeType)
|
||||
{
|
||||
CollectionItemPropertyChanged?.Invoke(this, new SettingsChangedEventArgs<TKey, TItem>(changeType));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fires collection change event
|
||||
/// </summary>
|
||||
/// <param name="changeType">type of change</param>
|
||||
/// <param name="key">key</param>
|
||||
private void FireItemChangedEvent(ChangeSettingType changeType, TKey key)
|
||||
{
|
||||
CollectionItemPropertyChanged?.Invoke(this, new SettingsChangedEventArgs<TKey, TItem>(changeType, key));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fires collection change event
|
||||
/// </summary>
|
||||
/// <param name="changeType">type of change</param>
|
||||
/// <param name="key">key</param>
|
||||
/// <param name="item">item</param>
|
||||
private void FireItemChangedEvent(ChangeSettingType changeType, TKey key, TItem item)
|
||||
{
|
||||
CollectionItemPropertyChanged?.Invoke(this, new SettingsChangedEventArgs<TKey, TItem>(changeType, key, item));
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
// <autogenerated />
|
||||
using System;
|
||||
using System.Reflection;
|
||||
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.8", FrameworkDisplayName = "")]
|
||||
@@ -0,0 +1,4 @@
|
||||
// <autogenerated />
|
||||
using System;
|
||||
using System.Reflection;
|
||||
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
|
||||
Binary file not shown.
Binary file not shown.
1
Common/DTS.Common.DAS.Concepts/.svn/entries
Normal file
1
Common/DTS.Common.DAS.Concepts/.svn/entries
Normal file
@@ -0,0 +1 @@
|
||||
12
|
||||
1
Common/DTS.Common.DAS.Concepts/.svn/format
Normal file
1
Common/DTS.Common.DAS.Concepts/.svn/format
Normal file
@@ -0,0 +1 @@
|
||||
12
|
||||
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* IArmable.cs
|
||||
*
|
||||
* Copyright © 2010
|
||||
* Diversified Technical Systems, Inc.
|
||||
* All Rights Reserved.
|
||||
*/
|
||||
|
||||
namespace DTS.DAS.Concepts
|
||||
{
|
||||
/// <summary>
|
||||
/// different possible arm modes
|
||||
/// </summary>
|
||||
public enum AvailableArmModes
|
||||
{
|
||||
LowPower,
|
||||
CircularBuffer,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// different possible armstatus
|
||||
/// </summary>
|
||||
public enum ArmStatus
|
||||
{
|
||||
Disarming,
|
||||
Disarmed,
|
||||
Arming,
|
||||
Armed,
|
||||
Recording, // Extra statuses (chuck's mail)
|
||||
}
|
||||
|
||||
///
|
||||
/// <summary>
|
||||
/// Formal description of the ability to "arm".
|
||||
/// </summary>
|
||||
///
|
||||
public interface IArmable
|
||||
{
|
||||
void Arm();
|
||||
void Disarm();
|
||||
ArmStatus ArmStatus { get; }
|
||||
AvailableArmModes ArmMode { get; }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Like Rollin said, NGI will (for now) be orphaned. NASCAR is in for sure. TSR6DX is really TSRPRO, I think. RateTestTSR==BlastTestTSR and needs to be flattened. TSR==TSRBasic. The missing one in that list is HEADSII.
|
||||
|
||||
//NASCAR is 3 16-bit channels using a 216 daughterboard.
|
||||
//TSRPRO is 6 channels, 3 16-bit on a 216 daughterboard, 3 12-bit on the 215 motherboard
|
||||
//BlastTestTSR is 7 channels, 4 12-bit on the 215 motherboard, 3 16-bit on a hacked daughterboard
|
||||
//TSRBasic is 3 12-bit channels on the 215 motherboard
|
||||
//HEADSII is 7 12-bit channels on the 221 board
|
||||
|
||||
//The other missing component to some of what you sent earlier is that some of these systems have multiple sample rates. BlastTestTSR will have the 4 12-bit channels @ 40ksps and the 3 16-bit channels @ 1ksps. NGI had 2 24-bit channels @ 1ksps and 2 16-bit (?? can't remember for sure) channels @ 1sps. As it stands now we have the lower level download code just interpolate slow data to fast data and then everything has the "same" sample rate at the upper level, but it might be nice to deal with it more formally since that creates some funny edge cases we have to deal with by limiting the download to occur in sample number chunks that are a multiple of the fast rate divided by the slow rate.
|
||||
|
||||
//On 8/12/2010 11:12 AM, Paul Hrissikopoulos wrote:
|
||||
//> By the way, the types that the switches currently in the TSR2 code seem to think important are:
|
||||
//>
|
||||
//> TSRModel.NASCARIDR:
|
||||
//> TSRModel.TSR6DX:
|
||||
//> TSRModel.RateTestTSR:
|
||||
//> TSRModel.BlastTSR:
|
||||
//> TSRModel.TSR:
|
||||
//> TSRModel.NGIPrototype:
|
||||
//>
|
||||
//> Are we going to want all of those? Some of those? Those and then some?
|
||||
//>
|
||||
//> On 8/12/2010 11:07 AM, Paul Hrissikopoulos wrote:
|
||||
//>> I guess in theory the software should be able to deal with the multiplicity of device types as it sees fit -- some code, definitely including parts of the UI, will need to be able to actively discriminate between types before doing something type-specific, but I think the hope is that the bulk should be able to use it in a more generic sense (arm the same, download the same, realtime the same, etc.). But still maybe that's a valid point -- do we foresee a ton of cases where we'll be doing interface is/as and/or typefield checks before doing something?
|
||||
//>>
|
||||
//>> On 8/12/2010 10:50 AM, Tadd Seiff wrote:
|
||||
//>>> I like this.
|
||||
//>>>
|
||||
//>>> My approach at the moment is immediately how to use this as a HEADS device. My understanding is that the device will surface through the factory which will populate things such as TSR.Channel[] Channels which can then be accessed safely only with RunTime checks like if (HEADS == unit.TSRModel) {...}. Does this put us in the same position being at the mercy of switch statements at a higher level? This is just my knee-jerk reaction.
|
||||
//>>>
|
||||
//>>> On 8/12/2010 10:08 AM, Paul Hrissikopoulos wrote:
|
||||
//>>>> My reordering is attached. Search it for "?" for some open questions. Please let me know if you think I'm missing anything major (or minor) or am entirely on the wrong track.
|
||||
//>>>>
|
||||
//>>>> On 8/9/2010 10:26 PM, Rollin White wrote:
|
||||
//>>>>> Here's an update with a channel class.
|
||||
//>>>>>
|
||||
//>>>>> Please voice concerns, opinions, etc. This is just my simple view of the task.
|
||||
//>>>>>
|
||||
//>>>>> On 8/9/2010 3:02 PM, Rollin White wrote:
|
||||
//>>>>>> Here's my first cut at the interface description for the next generation TSR class. The interface is meant to describe the features common to all models.
|
||||
//>>>>>>
|
||||
//>>>>>> In addition to what's here, there needs to be significant definition of the channel class. Finally, there are probably a few interfaces that need to be defined that class implementers would optionally implement. For example, ISupportsDynamicEventLength.
|
||||
//>>>>>>
|
||||
//>>>>>> This is simply a starting point. Comments welcome.
|
||||
//>>>>
|
||||
//>>>
|
||||
//>>
|
||||
//>
|
||||
//>
|
||||
|
||||
//--
|
||||
//Chuck Gillen-O'Neel
|
||||
//Diversified Technical Systems, Inc.
|
||||
//909 Electric Avenue, Suite 206
|
||||
//Seal Beach, CA 90740
|
||||
//Telephone: (562) 493-0158
|
||||
//Email: chuck.go@dtsweb.com
|
||||
|
||||
// My comments:
|
||||
|
||||
// * For sensitivity we should either have mv/count and eu/mv for each channel OR have eu/count for each channel. Obviously the former is more flexible, but also a little more complicated and maybe unneeded for 95-99% of TSR/HEADS applications.
|
||||
// * OffsetCounts in IChannel should be signed. We nearly always need to make offsets signed. I'm speaking from my own mistakes here ... !!! :)
|
||||
// * We need to think about the arm states a bit more. There have been a couple of cases where having a Disarming state, in addition to Disarmed, has been nice.
|
||||
// * For GPIOs we might as well surface (and extend the firmware a bit to support this) the fact that IOs can be inputs as well as high/low outputs. So, rather than just returning a bool we might want to return a state enum. It's already there in the interface for SetGPIO since the GPIOPin.Direction enum has input and output and if it's set to input the State parameter is effectively a no-op.
|
||||
// * The question of a good interface for Calibration is still unanswered. The interface as shown is obviously fine for doing those three readings, but I'm not sure how truly useful that is in a generic sense. I have a feeling that this is a place where we'll be hooking in model checks, etc. etc. Maybe that's okay and can be limited to the cal software.
|
||||
|
||||
|
||||
//On 8/12/2010 10:50 AM, Tadd Seiff wrote:
|
||||
//> I like this.
|
||||
//>
|
||||
//> My approach at the moment is immediately how to use this as a HEADS device. My understanding is that the device will surface through the factory which will populate things such as TSR.Channel[] Channels which can then be accessed safely only with RunTime checks like if (HEADS == unit.TSRModel) {...}. Does this put us in the same position being at the mercy of switch statements at a higher level? This is just my knee-jerk reaction.
|
||||
//>
|
||||
//> On 8/12/2010 10:08 AM, Paul Hrissikopoulos wrote:
|
||||
//>> My reordering is attached. Search it for "?" for some open questions. Please let me know if you think I'm missing anything major (or minor) or am entirely on the wrong track.
|
||||
//>>
|
||||
//>> On 8/9/2010 10:26 PM, Rollin White wrote:
|
||||
//>>> Here's an update with a channel class.
|
||||
//>>>
|
||||
//>>> Please voice concerns, opinions, etc. This is just my simple view of the task.
|
||||
//>>>
|
||||
//>>> On 8/9/2010 3:02 PM, Rollin White wrote:
|
||||
//>>>> Here's my first cut at the interface description for the next generation TSR class. The interface is meant to describe the features common to all models.
|
||||
//>>>>
|
||||
//>>>> In addition to what's here, there needs to be significant definition of the channel class. Finally, there are probably a few interfaces that need to be defined that class implementers would optionally implement. For example, ISupportsDynamicEventLength.
|
||||
//>>>>
|
||||
//>>>> This is simply a starting point. Comments welcome.
|
||||
//>>
|
||||
//>
|
||||
|
||||
//--
|
||||
//Chuck Gillen-O'Neel
|
||||
//Diversified Technical Systems, Inc.
|
||||
//909 Electric Avenue, Suite 206
|
||||
//Seal Beach, CA 90740
|
||||
//Telephone: (562) 493-0158
|
||||
//Email: chuck.go@dtsweb.com
|
||||
@@ -0,0 +1,682 @@
|
||||
using DTS.Common.Enums.Sensors;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace DTS.Common.DAS.Concepts
|
||||
{
|
||||
public class LinearizationFormula
|
||||
{
|
||||
private bool _bIsValid;
|
||||
public bool IsValid() { return _bIsValid; }
|
||||
public void MarkValid(bool bValid)
|
||||
{
|
||||
_bIsValid = bValid;
|
||||
}
|
||||
|
||||
|
||||
// Translation
|
||||
public NonLinearSLICEWareStyles NonLinearSliceWareStyle
|
||||
{
|
||||
get => (NonLinearSLICEWareStyles)NonLinearStyle;
|
||||
set => NonLinearStyle = (NonLinearStyles)value;
|
||||
}
|
||||
|
||||
public NonLinearStyles NonLinearStyle { get; set; } = NonLinearStyles.Polynomial; // Dont make the default style one that locks a specific zero-method FB 10323
|
||||
|
||||
public double PolynomialSensitivity { get; set; } = 1D;
|
||||
|
||||
public double LinearizationExponent { get; set; } = 1D;
|
||||
|
||||
/// <summary>
|
||||
/// THIS IS MM/V, (UI has already been updated, we need to update the variable name)
|
||||
/// </summary>
|
||||
private double _mmPerMV;
|
||||
public double MMPerV
|
||||
{
|
||||
get => _mmPerMV;
|
||||
set => _mmPerMV = value;
|
||||
}
|
||||
|
||||
public double MVAt0MM { get; set; }
|
||||
|
||||
public double Slope { get; set; }
|
||||
|
||||
public double Intercept { get; set; }
|
||||
|
||||
public double CalibrationFactor { get; set; }
|
||||
|
||||
public double ZeroPositionIntercept { get; set; }
|
||||
|
||||
public LinearizationFormula()
|
||||
{
|
||||
ZeroPositionIntercept = 0D;
|
||||
CalibrationFactor = 0D;
|
||||
Intercept = 0D;
|
||||
_coefficients = new List<double>(new double[] { 0, 0, 0, 0 });
|
||||
_exponents = new List<double>(new double[] { 0, 1, 2, 3 });
|
||||
}
|
||||
|
||||
public LinearizationFormula(LinearizationFormula copy)
|
||||
{
|
||||
UsemVOverVForPolys = copy.UsemVOverVForPolys;
|
||||
_bIsValid = copy._bIsValid;
|
||||
_coefficients = new List<double>(copy._coefficients.ToArray());
|
||||
_exponents = new List<double>(copy._exponents.ToArray());
|
||||
Intercept = copy.Intercept;
|
||||
LinearizationExponent = copy.LinearizationExponent;
|
||||
_mmPerMV = copy._mmPerMV;
|
||||
MVAt0MM = copy.MVAt0MM;
|
||||
Slope = copy.Slope;
|
||||
NonLinearStyle = copy.NonLinearStyle;
|
||||
_coefficients = new List<double>(copy._coefficients);
|
||||
_exponents = new List<double>(copy._exponents);
|
||||
PolynomialSensitivity = copy.PolynomialSensitivity;
|
||||
ZeroPositionIntercept = copy.ZeroPositionIntercept;
|
||||
CalibrationFactor = copy.CalibrationFactor;
|
||||
}
|
||||
public double GetCoefficient(double exponent)
|
||||
{
|
||||
for (var i = 0; i < _exponents.Count && i < _coefficients.Count; i++)
|
||||
{
|
||||
if (_exponents[i] == exponent) { return _coefficients[i]; }
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
public void SetCoefficient(double exponent, double coefficient)
|
||||
{
|
||||
for (var i = 0; i < _exponents.Count && i < _coefficients.Count; i++)
|
||||
{
|
||||
if (_exponents[i] == exponent) { _coefficients[i] = coefficient; return; }
|
||||
}
|
||||
}
|
||||
public double GetLinearizedValue(double input, double excitation)
|
||||
{
|
||||
if (NonLinearStyle != NonLinearStyles.Polynomial && input <= 0)
|
||||
{
|
||||
//ir-tracc should never be < 0, however we may get readings less than zero due to
|
||||
//noise and other factors, treat these as positive near to zero
|
||||
input = .001;
|
||||
}
|
||||
//first linearize
|
||||
input /= 1000D;//assume input is in mV and we want it in Volts
|
||||
input = Math.Pow(input, LinearizationExponent);
|
||||
|
||||
switch (NonLinearStyle)
|
||||
{
|
||||
case NonLinearStyles.IRTraccDiagnosticsZero:
|
||||
return GetEUDiagnosticsZero(input);
|
||||
case NonLinearStyles.IRTraccManual:
|
||||
return GetEUIRTraccManual(input);
|
||||
case NonLinearStyles.IRTraccZeroMMmV:
|
||||
return GetEUZeroMMmV(input);
|
||||
case NonLinearStyles.IRTraccAverageOverTime:
|
||||
return GetEUAverageOverTime(input);
|
||||
case NonLinearStyles.Polynomial:
|
||||
return GetEUPolynomial(input, excitation);
|
||||
case NonLinearStyles.IRTraccCalFactor:
|
||||
return GetEUIRTraccCalFactor(input);
|
||||
default:
|
||||
throw new NotSupportedException("unknown format: " + NonLinearStyle);
|
||||
}
|
||||
}
|
||||
private double GetEUIRTraccCalFactor(double volts)
|
||||
{
|
||||
return volts * CalibrationFactor + ZeroPositionIntercept;
|
||||
}
|
||||
private double GetEUIRTraccManual(double volts)
|
||||
{
|
||||
return (volts - Intercept) / Slope;
|
||||
}
|
||||
|
||||
public bool UsemVOverVForPolys { get; set; }
|
||||
|
||||
private double GetEUZeroMMmV(double volts)
|
||||
{
|
||||
var input = MVAt0MM / 1000D;
|
||||
input = Math.Pow(input, LinearizationExponent);
|
||||
if (double.IsNaN(input) || double.IsNegativeInfinity(input) || double.IsPositiveInfinity(input))
|
||||
{
|
||||
return volts * MMPerV;
|
||||
}
|
||||
return (volts * MMPerV - MMPerV * input);
|
||||
}
|
||||
private List<double> _coefficients = new List<double>();
|
||||
private List<double> _exponents = new List<double>();
|
||||
private double GetEUPolynomial(double volts, double excitation)
|
||||
{
|
||||
//per J2517
|
||||
//3.4 Use of the Calibration Coefficients
|
||||
//The potentiometer assembly should be re-installed in the dummy without any mechanical adjustment of the
|
||||
//potentiometer. Prior to a crash test, the original zero offset level must be preserved by either not zeroing the
|
||||
//potentiometer (by signal conditioning or post-processing) or the amount that was zeroed must be added during postprocessing.
|
||||
//During the test the absolute voltage output time history should be recorded. This voltage signal is then
|
||||
//converted to engineering units by:
|
||||
//1. Convert voltage signal to mV/V at the sensor. This is the sensor reading S.
|
||||
//2. Convert the sensor reading S to displacement D by using the equation:
|
||||
//D = A*S^3 + B*S^2 + C*S + M (Eq. 2)
|
||||
//where:
|
||||
//D is the displacement relative to the thorax design position in mm
|
||||
//S is the sensor output reading in mV/V
|
||||
//A, B, C, and M are the calibration coefficients
|
||||
//NOTE: Make sure to use sufficient significant digits on all coefficients to assure accuracy of the conversion to
|
||||
//engineering units. It is recommended to use 5 significant digits (example 0.000012345).
|
||||
|
||||
//double mV = volts * 1000D;
|
||||
//double gain = 1D;
|
||||
//mV = mV / (gain * excitation);
|
||||
|
||||
//if (0 != PolynomialSensitivity && 1!= PolynomialSensitivity) { mV /= PolynomialSensitivity; }
|
||||
//double eu = 0D;
|
||||
//for (int i = 0; i < _coefficients.Count && i < _exponents.Count; i++)
|
||||
//{
|
||||
// eu += _coefficients[i] * Math.Pow(mV, _exponents[i]);
|
||||
//}
|
||||
//return eu;
|
||||
|
||||
//CHANGED FOR GM TESTING
|
||||
|
||||
if (0 != PolynomialSensitivity && 1 != PolynomialSensitivity)
|
||||
{
|
||||
volts /= PolynomialSensitivity;
|
||||
}
|
||||
|
||||
var voltsOverV = 0D;
|
||||
if (UsemVOverVForPolys)
|
||||
{
|
||||
//convert to mV first
|
||||
voltsOverV = (volts * 1000D) / excitation;
|
||||
}
|
||||
else
|
||||
{
|
||||
//used by GM
|
||||
voltsOverV = volts / excitation;
|
||||
}
|
||||
double eu = 0;
|
||||
|
||||
for (var i = 0; i < _coefficients.Count && i < _exponents.Count; i++)
|
||||
{
|
||||
if (_exponents[i] != 0)
|
||||
{
|
||||
eu += _coefficients[i] * Math.Pow(voltsOverV, _exponents[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
eu += _coefficients[i];
|
||||
}
|
||||
}
|
||||
return eu;
|
||||
}
|
||||
/// <summary>
|
||||
/// MvAt0MM set at diagnostics
|
||||
/// </summary>
|
||||
/// <param name="volts"></param>
|
||||
/// <returns></returns>
|
||||
private double GetEUDiagnosticsZero(double volts)
|
||||
{
|
||||
//double input = MVAt0MM/1000D;
|
||||
//input = System.Math.Pow(input,LinearizationExponent);
|
||||
var input = double.NaN;
|
||||
if (double.IsNaN(input) || double.IsPositiveInfinity(input) || double.IsNegativeInfinity(input))
|
||||
{
|
||||
return volts * MMPerV;
|
||||
}
|
||||
return volts * MMPerV - MMPerV * input;
|
||||
}
|
||||
/// <summary>
|
||||
/// MVAt0MM set by diagnostics and then later on at
|
||||
/// Average Over Time
|
||||
/// </summary>
|
||||
/// <param name="volts"></param>
|
||||
/// <returns></returns>
|
||||
private double GetEUAverageOverTime(double volts)
|
||||
{
|
||||
//double input = MVAt0MM / 1000D;
|
||||
//input = System.Math.Pow(input, LinearizationExponent);
|
||||
var input = double.NaN;
|
||||
if (double.IsNaN(input) || double.IsNegativeInfinity(input) || double.IsPositiveInfinity(input))
|
||||
{
|
||||
return volts * MMPerV;
|
||||
}
|
||||
return volts * MMPerV - MMPerV * input;
|
||||
}
|
||||
|
||||
|
||||
public string ToSLICEWareSerializeString()
|
||||
{
|
||||
if (!_bIsValid) { return ""; }
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendFormat("{0}_", NonLinearStyle);
|
||||
|
||||
switch (NonLinearStyle)
|
||||
{
|
||||
case NonLinearStyles.IRTraccDiagnosticsZero:
|
||||
sb.Append(ToIRTraccDiagnosticZeroString());
|
||||
break;
|
||||
case NonLinearStyles.IRTraccManual:
|
||||
sb.Append(ToIRTraccManualString());
|
||||
break;
|
||||
case NonLinearStyles.IRTraccZeroMMmV:
|
||||
sb.Append(ToIRTraccZeroMMmVString());
|
||||
break;
|
||||
case NonLinearStyles.IRTraccAverageOverTime:
|
||||
sb.Append(ToIRTraccAverageOverTimeString());
|
||||
break;
|
||||
case NonLinearStyles.Polynomial:
|
||||
sb.Append(ToSLICEWarePolynomialString());
|
||||
break;
|
||||
case NonLinearStyles.IRTraccCalFactor:
|
||||
throw new NotSupportedException("CalFactor not supported in SLICEWare");
|
||||
default:
|
||||
throw new NotSupportedException("unknown type: " + NonLinearStyle);
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// serializes to a string of the format "c0xe0 c1xe1...cnxen"
|
||||
/// this will allow us arbitrary length polynomials and fractional exponents.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public string ToSerializeString()
|
||||
{
|
||||
if (!_bIsValid) { return ""; }
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendFormat("{0}_", NonLinearStyle);
|
||||
|
||||
switch (NonLinearStyle)
|
||||
{
|
||||
case NonLinearStyles.IRTraccDiagnosticsZero:
|
||||
sb.Append(ToIRTraccDiagnosticZeroString());
|
||||
break;
|
||||
case NonLinearStyles.IRTraccManual:
|
||||
sb.Append(ToIRTraccManualString());
|
||||
break;
|
||||
case NonLinearStyles.IRTraccZeroMMmV:
|
||||
sb.Append(ToIRTraccZeroMMmVString());
|
||||
break;
|
||||
case NonLinearStyles.IRTraccAverageOverTime:
|
||||
sb.Append(ToIRTraccAverageOverTimeString());
|
||||
break;
|
||||
case NonLinearStyles.Polynomial:
|
||||
sb.Append(ToPolynomialString());
|
||||
break;
|
||||
case NonLinearStyles.IRTraccCalFactor:
|
||||
sb.Append(ToIRTraccCalFactorString());
|
||||
break;
|
||||
default:
|
||||
throw new NotSupportedException("unknown type: " + NonLinearStyle);
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
public string ToIRTraccDiagnosticZeroString()
|
||||
{
|
||||
return $"{MMPerV.ToString(System.Globalization.CultureInfo.InvariantCulture)}x{LinearizationExponent.ToString(System.Globalization.CultureInfo.InvariantCulture)}";
|
||||
}
|
||||
public string ToIRTraccCalFactorString()
|
||||
{
|
||||
return $"{CalibrationFactor.ToString(System.Globalization.CultureInfo.InvariantCulture)}x{LinearizationExponent.ToString(System.Globalization.CultureInfo.InvariantCulture)}x{ZeroPositionIntercept.ToString(System.Globalization.CultureInfo.InvariantCulture)}";
|
||||
}
|
||||
public void FromIRTraccCalFactorString(string s, System.Globalization.CultureInfo culture)
|
||||
{
|
||||
var tokens = s.Split('x');
|
||||
if (tokens.Length < 3) { throw new NotSupportedException("Invalid CalFactor format: " + s); }
|
||||
|
||||
CalibrationFactor = double.Parse(tokens[0], culture);
|
||||
LinearizationExponent = double.Parse(tokens[1], culture);
|
||||
ZeroPositionIntercept = double.Parse(tokens[2], culture);
|
||||
}
|
||||
public void FromIRTraccDiagnosticZeroString(string s, System.Globalization.CultureInfo culture)
|
||||
{
|
||||
var tokens = s.Split('x');
|
||||
if (tokens.Length < 2) { throw new NotSupportedException("Invalid DiagnosticsZero format: " + s); }
|
||||
MMPerV = double.Parse(tokens[0], culture);
|
||||
LinearizationExponent = double.Parse(tokens[1], culture);
|
||||
}
|
||||
public string ToIRTraccManualString()
|
||||
{
|
||||
return $"{Slope.ToString(System.Globalization.CultureInfo.InvariantCulture)}x{Intercept.ToString(System.Globalization.CultureInfo.InvariantCulture)}x{LinearizationExponent.ToString(System.Globalization.CultureInfo.InvariantCulture)}";
|
||||
}
|
||||
public void FromIRTraccManualString(string s, System.Globalization.CultureInfo culture)
|
||||
{
|
||||
var tokens = s.Split('x');
|
||||
if (tokens.Length < 3) { throw new NotSupportedException("Invalid IRTraccManual format: " + s); }
|
||||
Slope = double.Parse(tokens[0], culture);
|
||||
Intercept = double.Parse(tokens[1], culture);
|
||||
LinearizationExponent = double.Parse(tokens[2], culture);
|
||||
}
|
||||
public string ToIRTraccZeroMMmVString()
|
||||
{
|
||||
return $"{MMPerV.ToString(System.Globalization.CultureInfo.InvariantCulture)}x{MVAt0MM.ToString(System.Globalization.CultureInfo.InvariantCulture)}x{LinearizationExponent.ToString(System.Globalization.CultureInfo.InvariantCulture)}";
|
||||
}
|
||||
public string ToSLICEWarePolynomialString()
|
||||
{
|
||||
//SLICEWare is the reverse order of our DataPRO Database
|
||||
var sb = new StringBuilder();
|
||||
for (var i = _exponents.Count - 1; i >= 0; i--)
|
||||
{
|
||||
if (i != _exponents.Count - 1) { sb.Append(","); }
|
||||
sb.AppendFormat("{0}x{1}", _coefficients[i].ToString(System.Globalization.CultureInfo.InvariantCulture),
|
||||
_exponents[i].ToString(System.Globalization.CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
sb.AppendFormat(",S={0}", PolynomialSensitivity.ToString(System.Globalization.CultureInfo.InvariantCulture));
|
||||
return sb.ToString();
|
||||
}
|
||||
public string ToPolynomialString()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
for (var i = 0; i < _coefficients.Count && i < _exponents.Count; i++)
|
||||
{
|
||||
if (i > 0) { sb.Append(","); }
|
||||
sb.AppendFormat("{0}x{1}", _coefficients[i].ToString(System.Globalization.CultureInfo.InvariantCulture),
|
||||
_exponents[i].ToString(System.Globalization.CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
sb.AppendFormat(",S={0},mV={1}",
|
||||
PolynomialSensitivity.ToString(System.Globalization.CultureInfo.InvariantCulture),
|
||||
UsemVOverVForPolys.ToString(System.Globalization.CultureInfo.InvariantCulture));
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
public double[] PolynomialCoefficients
|
||||
{
|
||||
get => _coefficients.ToArray();
|
||||
set => _coefficients = new List<double>(value);
|
||||
}
|
||||
public double[] PolynomialExponents
|
||||
{
|
||||
get => _exponents.ToArray();
|
||||
set => _exponents = new List<double>(value);
|
||||
}
|
||||
public string ToIRTraccAverageOverTimeString()
|
||||
{
|
||||
return $"{MMPerV.ToString(System.Globalization.CultureInfo.InvariantCulture)}x{LinearizationExponent.ToString(System.Globalization.CultureInfo.InvariantCulture)}";
|
||||
}
|
||||
public void FromIRTraccAverageOverTimeString(string s, System.Globalization.CultureInfo culture)
|
||||
{
|
||||
var tokens = s.Split('x');
|
||||
if (tokens.Length < 2) { throw new NotSupportedException("Invalid IRTRaccAverageOverTime format: " + s); }
|
||||
MMPerV = double.Parse(tokens[0], culture);
|
||||
LinearizationExponent = double.Parse(tokens[1], culture);
|
||||
}
|
||||
public void FromIRTraccZeroMMmVString(string s, System.Globalization.CultureInfo culture)
|
||||
{
|
||||
var tokens = s.Split('x');
|
||||
if (tokens.Length < 3) { throw new NotSupportedException("Invalid IRTraccZeroMMmV format: " + s); }
|
||||
MMPerV = double.Parse(tokens[0], culture);
|
||||
MVAt0MM = double.Parse(tokens[1], culture);
|
||||
LinearizationExponent = double.Parse(tokens[2], culture);
|
||||
}
|
||||
public void FromPolynomialString(string s, System.Globalization.CultureInfo culture)
|
||||
{
|
||||
_coefficients.Clear();
|
||||
_exponents.Clear();
|
||||
|
||||
var tokens = s.Split(',');
|
||||
foreach (var t in tokens)
|
||||
{
|
||||
var subtokens = t.Split('x');
|
||||
if (2 == subtokens.Length)
|
||||
{
|
||||
if (double.TryParse(subtokens[0], System.Globalization.NumberStyles.Float, culture, out var d))
|
||||
{
|
||||
_coefficients.Add(d);
|
||||
_exponents.Add(double.Parse(subtokens[1], culture));
|
||||
}
|
||||
else
|
||||
{
|
||||
PolynomialSensitivity = double.Parse(subtokens[1], culture);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
subtokens = t.Split('=');
|
||||
if (subtokens.Length == 2)
|
||||
{
|
||||
switch (subtokens[0])
|
||||
{
|
||||
case "S":
|
||||
PolynomialSensitivity = double.Parse(subtokens[1], culture);
|
||||
break;
|
||||
case "mV":
|
||||
UsemVOverVForPolys = Convert.ToBoolean(subtokens[1], culture);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public void FromSerializeString(string s, System.Globalization.CultureInfo culture)
|
||||
{
|
||||
if (string.IsNullOrEmpty(s)) { _bIsValid = false; return; }
|
||||
if (s.Equals("1") || s.Equals("0") || s.Equals("1 ")) { _bIsValid = false; return; }
|
||||
|
||||
var tokens = s.Split('_');
|
||||
if (tokens.Length < 2) { throw new NotSupportedException("unsupported Linearization Formula Format"); }
|
||||
var style = (NonLinearStyles)Enum.Parse(typeof(NonLinearStyles), tokens[0], true);
|
||||
NonLinearStyle = style;
|
||||
switch (NonLinearStyle)
|
||||
{
|
||||
case NonLinearStyles.IRTraccDiagnosticsZero:
|
||||
FromIRTraccDiagnosticZeroString(tokens[1], culture);
|
||||
_bIsValid = true;
|
||||
break;
|
||||
case NonLinearStyles.IRTraccManual:
|
||||
FromIRTraccManualString(tokens[1], culture);
|
||||
_bIsValid = true;
|
||||
break;
|
||||
case NonLinearStyles.IRTraccZeroMMmV:
|
||||
FromIRTraccZeroMMmVString(tokens[1], culture);
|
||||
_bIsValid = true;
|
||||
break;
|
||||
case NonLinearStyles.Polynomial:
|
||||
FromPolynomialString(tokens[1], culture);
|
||||
_bIsValid = true;
|
||||
break;
|
||||
case NonLinearStyles.IRTraccAverageOverTime:
|
||||
FromIRTraccAverageOverTimeString(tokens[1], culture);
|
||||
_bIsValid = true;
|
||||
break;
|
||||
case NonLinearStyles.IRTraccCalFactor:
|
||||
FromIRTraccCalFactorString(tokens[1], culture);
|
||||
_bIsValid = true;
|
||||
break;
|
||||
default:
|
||||
throw new NotSupportedException("Unknown format: " + NonLinearStyle);
|
||||
}
|
||||
}
|
||||
public void FromSerializeString(string s)
|
||||
{
|
||||
FromSerializeString(s, System.Globalization.CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
public void FromTDCSerializeString()
|
||||
{
|
||||
_bIsValid = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Will return a display string for a nonlinear calibration based on N4 formating
|
||||
/// </summary>
|
||||
public string ToDisplayString()
|
||||
{
|
||||
return ToDisplayString("N4");
|
||||
}
|
||||
/// <summary>
|
||||
/// Will return a display string for a nonlinear calibration based on 1st paramater formating string
|
||||
/// </summary>
|
||||
/// <param name="nonlinearFormat"></param>
|
||||
/// <returns></returns>
|
||||
public string ToDisplayString(string nonlinearFormat)
|
||||
{
|
||||
if (string.IsNullOrEmpty(nonlinearFormat)) { nonlinearFormat = "N4"; }
|
||||
switch (NonLinearStyle)
|
||||
{
|
||||
case NonLinearStyles.Polynomial:
|
||||
{
|
||||
return ToPolynomial(nonlinearFormat);
|
||||
}
|
||||
case NonLinearStyles.IRTraccZeroMMmV:
|
||||
{
|
||||
return $"mV = {MVAt0MM:n4}, {MMPerV:n4}*(V^{ToSuperScript(LinearizationExponent.ToString(nonlinearFormat))})";
|
||||
}
|
||||
case NonLinearStyles.IRTraccManual:
|
||||
{
|
||||
return $"((V^{ToSuperScript(LinearizationExponent.ToString(nonlinearFormat))})-{Intercept:n4})/{Slope:n4}";
|
||||
}
|
||||
case NonLinearStyles.IRTraccDiagnosticsZero:
|
||||
{
|
||||
return $"{MMPerV:n4}*(V^{ToSuperScript(LinearizationExponent.ToString(nonlinearFormat))})";
|
||||
}
|
||||
case NonLinearStyles.IRTraccAverageOverTime:
|
||||
{
|
||||
return $"{MMPerV:n4}*(V^{ToSuperScript(LinearizationExponent.ToString(nonlinearFormat))})";
|
||||
}
|
||||
case NonLinearStyles.IRTraccCalFactor:
|
||||
{
|
||||
return $"{ZeroPositionIntercept:n4}+{CalibrationFactor:n4}*(V^{ToSuperScript(LinearizationExponent.ToString(nonlinearFormat))})";
|
||||
}
|
||||
default:
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
private string ToPolynomial(string nonlinearFormat)
|
||||
{
|
||||
if (string.IsNullOrEmpty(nonlinearFormat)) { nonlinearFormat = "N4"; }
|
||||
|
||||
var sb = new StringBuilder();
|
||||
|
||||
var termNumber = PolynomialCoefficients.Length - 1;
|
||||
foreach (var x in PolynomialCoefficients)
|
||||
{
|
||||
if (PolynomialCoefficients[termNumber] != 0)
|
||||
{
|
||||
var coeff = PolynomialCoefficients[termNumber];
|
||||
|
||||
// Let the appended math symbol handle sign unless we're the first term.
|
||||
if (termNumber != PolynomialCoefficients.Length - 1)
|
||||
{
|
||||
coeff = Math.Abs(coeff);
|
||||
}
|
||||
sb.Append(coeff.ToString(nonlinearFormat));
|
||||
if (PolynomialExponents[termNumber] != 0)
|
||||
{
|
||||
sb.Append("x");
|
||||
if (PolynomialExponents[termNumber] != 1)
|
||||
{
|
||||
sb.Append(ToSuperScript(PolynomialExponents[termNumber].ToString("N0")));
|
||||
}
|
||||
}
|
||||
if (termNumber > 0)
|
||||
{
|
||||
// Coerricients are Displayed in absolute value. We need to combine the sign with the addition symbol
|
||||
sb.Append(PolynomialCoefficients[termNumber - 1] > 0 ? " + " : " - ");
|
||||
}
|
||||
}
|
||||
termNumber--;
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
private string ToSuperScript(string source)
|
||||
{
|
||||
var superScript = new StringBuilder();
|
||||
|
||||
foreach (var c in source)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '-':
|
||||
superScript.Append('\u207B');
|
||||
break;
|
||||
case '.':
|
||||
superScript.Append('\u00B7');
|
||||
break;
|
||||
case '1':
|
||||
superScript.Append('\u00B9');
|
||||
break;
|
||||
case '2':
|
||||
superScript.Append('\u00B2');
|
||||
break;
|
||||
case '3':
|
||||
superScript.Append('\u00B3');
|
||||
break;
|
||||
case '4':
|
||||
superScript.Append('\u2074');
|
||||
break;
|
||||
case '5':
|
||||
superScript.Append('\u2075');
|
||||
break;
|
||||
case '6':
|
||||
superScript.Append('\u2076');
|
||||
break;
|
||||
case '7':
|
||||
superScript.Append('\u2077');
|
||||
break;
|
||||
case '8':
|
||||
superScript.Append('\u2078');
|
||||
break;
|
||||
case '9':
|
||||
superScript.Append('\u2079');
|
||||
break;
|
||||
case '0':
|
||||
superScript.Append('\u2070');
|
||||
break;
|
||||
case '\'':
|
||||
superScript.Append('\u02C8');
|
||||
break;
|
||||
case ',':
|
||||
superScript.Append('\u22C5'); // there is no unicode superscript comma. this comes close
|
||||
break;
|
||||
case '\u00A0':
|
||||
superScript.Append('\u2009'); // unicode 'thin' space
|
||||
break;
|
||||
default:
|
||||
superScript.Append('\u207F');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return superScript.ToString();
|
||||
}
|
||||
/*
|
||||
* we are given an equation in the form of y = ax^1 + b, except x and y are backwards for us (y=V where we'd prefer X was voltage, so we switch it)
|
||||
* y/a - b/a = x, and then switch y and x, (1/a)x^1 -(b/a)x^0 = y
|
||||
* now we want to get the coefficient of the first equation, which is "a", we get this by taking the inverse
|
||||
* we get b on the other hand by taking -1 * (b/a)*a. if we have the "coefficient", we have a
|
||||
*/
|
||||
/*
|
||||
public double GetIRTraccCoefficient()
|
||||
{
|
||||
foreach (Factor f in Factors)
|
||||
{
|
||||
if (f.Exponent == 1D) { return System.Math.Pow(f.Coefficient, -1); }
|
||||
}
|
||||
return 1D; //0 doesn't make sense for ir
|
||||
}
|
||||
public double GetIRTraccConstant()
|
||||
{
|
||||
foreach (Factor f in Factors)
|
||||
{
|
||||
if (f.Exponent == 0D) { return -1D * GetIRTraccCoefficient() * f.Coefficient; }
|
||||
}
|
||||
return 0D;
|
||||
}
|
||||
public void SetIRTraccFactor(double coefficient, double constant)
|
||||
{
|
||||
if (0 == coefficient)
|
||||
{
|
||||
//well this doesn't make any sense ...
|
||||
coefficient = 1;
|
||||
}
|
||||
Factors = new Factor[]
|
||||
{
|
||||
new Factor(1/coefficient,1),
|
||||
new Factor(-constant/coefficient,0),
|
||||
};
|
||||
}*/
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
Test.Module.Channel.Sensor.ExcitationVoltage.cs
|
||||
|
||||
Copyright © 2008
|
||||
Diversified Technical Systems, Inc.
|
||||
All Rights Reserved
|
||||
*/
|
||||
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace DTS.DAS.Concepts
|
||||
{
|
||||
// *** see Test.cs ***
|
||||
public partial class Test
|
||||
{
|
||||
/// <summary>
|
||||
/// A container for DTS generic module concepts.
|
||||
/// </summary>
|
||||
public sealed partial class Module
|
||||
{
|
||||
// *** see Test.Module.Channel.cs ***
|
||||
public partial class Channel
|
||||
{
|
||||
//*** see Test.Module.Channel.Sensor.cs ***
|
||||
public partial class Sensor
|
||||
{
|
||||
/// <summary>
|
||||
/// All available Sensitivity Unit types.
|
||||
/// </summary>
|
||||
public enum SensUnits
|
||||
{
|
||||
/// <summary>
|
||||
/// No Sensitivity Units (Polynomial Sensor)
|
||||
/// </summary>
|
||||
[Description("NONE")]
|
||||
NONE = 0,
|
||||
/// <summary>
|
||||
/// Sensitivity expressed in mV with output at Capacity EU
|
||||
/// </summary>
|
||||
[Description("mV")]
|
||||
mV = 1,
|
||||
/// <summary>
|
||||
/// Excitation proportional sensitivity expressed in mV/V with output at Capacity EU
|
||||
/// </summary>
|
||||
[Description("mV/V")]
|
||||
mVperV = 2,
|
||||
/// <summary>
|
||||
/// Excitation proportional sensitivity expressed in mV/V/EU
|
||||
/// </summary>
|
||||
[Description("mV/V/EU")]
|
||||
mVperVperEU = 3,
|
||||
/// <summary>
|
||||
/// Sensitivity expressed in mV/EU
|
||||
/// </summary>
|
||||
[Description("mV/EU")]
|
||||
mVperEU = 4
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
Test.Module.Channel.Sensor.ShuntModeType.cs
|
||||
|
||||
Copyright © 2010
|
||||
Diversified Technical Systems, Inc.
|
||||
All Rights Reserved
|
||||
*/
|
||||
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace DTS.Common.DAS.Concepts
|
||||
{
|
||||
// *** see Test.cs ***
|
||||
public partial class Test
|
||||
{
|
||||
/// <summary>
|
||||
/// A container for DTS generic module concepts.
|
||||
/// </summary>
|
||||
public sealed partial class Module
|
||||
{
|
||||
// *** see Test.Module.Channel.cs ***
|
||||
public partial class Channel
|
||||
{
|
||||
//*** see DTS.Common.DAS.Concepts.Test.Module.Channel.Sensor.cs ***
|
||||
public partial class Sensor
|
||||
{
|
||||
public enum ShuntModeType
|
||||
{
|
||||
[Description("Internal")]
|
||||
Internal,
|
||||
[Description("External")]
|
||||
External,
|
||||
[Description("Emulation")]
|
||||
Emulation,
|
||||
[Description("None")]
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* DAS.Id.cs
|
||||
* DTM - why does this class exist? it's only encapsulating a string
|
||||
* Copyright © 2009
|
||||
* Diversified Technical Systems, Inc.
|
||||
* All Rights Reserved
|
||||
*/
|
||||
|
||||
using System;
|
||||
using DTS.Common.Utilities;
|
||||
|
||||
namespace DTS.Common.DAS.Concepts.DAS
|
||||
{
|
||||
/// <summary>
|
||||
/// Representation of the DTS.Common.DAS.Concepts.DAS.Id type.
|
||||
/// why does this class even exist?
|
||||
/// </summary>
|
||||
public sealed class Id : Exceptional, IComparable<Id>, IEquatable<Id>
|
||||
{
|
||||
/// <summary>
|
||||
/// The Thing In Itself.
|
||||
/// </summary>
|
||||
private readonly string value;
|
||||
|
||||
/// <summary>
|
||||
/// Initialize an instance of the DTS.Common.DAS.Concepts.DAS.Id class.
|
||||
/// </summary>
|
||||
public Id(string value)
|
||||
{
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allow DTS.Common.DAS.Concepts.DAS.Ids to be implicitly converted to strings.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="id">
|
||||
/// The <see cref="Id"/> id to be stringified.
|
||||
/// </param>
|
||||
///
|
||||
/// <returns>
|
||||
/// The <see cref="string"/> value of this DTS.Common.DAS.Concepts.DAS.Id.
|
||||
/// </returns>
|
||||
///
|
||||
public static implicit operator string(Id id)
|
||||
{
|
||||
return id.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allow strings to be implicitly converted to DTS.Slice.Control.DAS.Ids.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="id">
|
||||
/// The <see cref="string"/> value to be DTS.Slice.Control.DAS.Id-ified.
|
||||
/// </param>
|
||||
///
|
||||
/// <returns>
|
||||
/// The <see cref="Id"/> equivalent to the specified string.
|
||||
/// </returns>
|
||||
///
|
||||
public static implicit operator Id(string id)
|
||||
{
|
||||
return new Id(id);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (obj is Id that) { return Equals(that); }
|
||||
return string.Compare(ToString(), obj.ToString(), StringComparison.OrdinalIgnoreCase) == 0;
|
||||
}
|
||||
/// <summary>
|
||||
/// Determine whether this object instance and the specified object instance are equal.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="that">
|
||||
/// The <see cref="Id"/> to be compared to this object instance.
|
||||
/// </param>
|
||||
///
|
||||
/// <returns>
|
||||
/// <see cref="bool"/> true if this object is equal to the specified object; false otherwise.
|
||||
/// </returns>
|
||||
///
|
||||
public bool Equals(Id that)
|
||||
{
|
||||
if (value == that.value) { return true; }
|
||||
if (null == value) { return false; }
|
||||
if (null == that.value) { return false; }
|
||||
return value.Equals(that.value, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate a comparison value between this object and another of it's type.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="that">
|
||||
/// The <see cref="Id"/> to which this one is to be compared.
|
||||
/// </param>
|
||||
///
|
||||
/// <returns>
|
||||
/// An <see cref="int"/> value expressing the "similarity" between this object
|
||||
/// and the one specified.
|
||||
/// </returns>
|
||||
///
|
||||
public int CompareTo(Id that)
|
||||
{
|
||||
return Compare(this, that);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate a string representation of this class.
|
||||
/// </summary>
|
||||
///
|
||||
/// <returns>
|
||||
/// The <see cref="string"/> representation of this object.
|
||||
/// </returns>
|
||||
///
|
||||
public override string ToString()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate a hash code for this instance.
|
||||
/// </summary>
|
||||
///
|
||||
/// <returns>
|
||||
/// The <see cref="int"/> hash code for this instance.
|
||||
/// </returns>
|
||||
///
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return value?.GetHashCode() ?? 0;
|
||||
}
|
||||
public static bool operator ==(Id left, Id right)
|
||||
{
|
||||
if (ReferenceEquals(left, null))
|
||||
{
|
||||
return ReferenceEquals(right, null);
|
||||
}
|
||||
return left.Equals(right);
|
||||
}
|
||||
public static int Compare(Id left, Id right)
|
||||
{
|
||||
if (left == right) { return 0; }
|
||||
if (null == right) { return 1; }
|
||||
if (null == left) { return -1; }
|
||||
return string.Compare(left.ToString(), right.ToString(), StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
public static bool operator >= (Id left, Id right)
|
||||
{
|
||||
return Compare(left, right) >= 0;
|
||||
}
|
||||
public static bool operator >(Id left, Id right)
|
||||
{
|
||||
return Compare(left, right) > 0;
|
||||
}
|
||||
public static bool operator <= (Id left, Id right)
|
||||
{
|
||||
return Compare(left, right) <= 0;
|
||||
}
|
||||
public static bool operator <(Id left, Id right)
|
||||
{
|
||||
return Compare(left, right) < 0;
|
||||
}
|
||||
public static bool operator !=(Id left, Id right)
|
||||
{
|
||||
return !(left == right);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,230 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ClassDiagram MajorVersion="1" MinorVersion="1">
|
||||
<Class Name="DTS.Common.DAS.Concepts.DataScaler" Collapsed="true">
|
||||
<Position X="11.75" Y="0.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>yIIHsKRGAwEJpVQIBARAJBBuA1EgIBouDUBAUIBBABY=</HashCode>
|
||||
<FileName>DataScaler.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="DTS.Common.DAS.Concepts.DigitalInputScaleMultiplier" Collapsed="true">
|
||||
<Position X="13.5" Y="0.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAgAAIAAAgAAAAAAAAAhAAIAAAAQEAEEAAAA=</HashCode>
|
||||
<FileName>DigitalInputScaleMultiplier.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="DTS.Common.DAS.Concepts.RealtimeSample" Collapsed="true">
|
||||
<Position X="11.75" Y="1.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAgAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Interfaces\IRealtimeable.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="DTS.Common.DAS.Concepts.LinearizationFormula" Collapsed="true">
|
||||
<Position X="10" Y="1.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>EBABiQDJAEEswAAoCAgAAQJCAYBXAKGgAABAAgKEMUA=</HashCode>
|
||||
<FileName>LinearizationFormula.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="DTS.Common.DAS.Concepts.Test" Collapsed="true">
|
||||
<Position X="13.5" Y="1.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>ShuntModeType.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="DTS.Common.DAS.Concepts.TsrEvent" Collapsed="true" BaseTypeListCollapsed="true">
|
||||
<Position X="8.25" Y="2.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAABCwAAAAAAAAAAAAAAAAAAEoAAAAAAAAAAAEABA=</HashCode>
|
||||
<FileName>TsrEvent.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<Lollipop Position="0.2" Collapsed="true" />
|
||||
</Class>
|
||||
<Class Name="DTS.Common.DAS.Concepts.DAS.Channel<TDataType>" Collapsed="true">
|
||||
<Position X="8.25" Y="0.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>DAS\Channel\Channel.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="DTS.Common.DAS.Concepts.DAS.Id" Collapsed="true" BaseTypeListCollapsed="true">
|
||||
<Position X="8.25" Y="1.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAQIAAAAAAAAAQEgAAAAAAAAAAAAKAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>DAS\DAS.Id.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<Lollipop Position="0.2" Collapsed="true" />
|
||||
</Class>
|
||||
<Class Name="DTS.Common.DAS.Concepts.DAS.Channel.Data<TDatumType>" Collapsed="true">
|
||||
<Position X="10" Y="0.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>DAS\Channel\Data.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Interface Name="DTS.Common.DAS.Concepts.IArmable" Collapsed="true">
|
||||
<Position X="0.5" Y="0.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAEAAAAAAAAAAAgIAAAABAAAAAAAA=</HashCode>
|
||||
<FileName>Interfaces\IArmable.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Interface Name="DTS.Common.DAS.Concepts.ICalibratable" Collapsed="true">
|
||||
<Position X="8.25" Y="3.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAQAAAAAAADAAAAAAAAAAIAAEAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Interfaces\ICalibratable.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Interface Name="DTS.Common.DAS.Concepts.IDataCollectionEnabled" Collapsed="true">
|
||||
<Position X="0.5" Y="1.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>BAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Interfaces\IDataCollectionEnabled.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Interface Name="DTS.Common.DAS.Concepts.IDownloadEnabled" Collapsed="true">
|
||||
<Position X="3.5" Y="0.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAACAAAAABAQAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Interfaces\IDownloadEnabled.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Interface Name="DTS.Common.DAS.Concepts.IGpioEnabled" Collapsed="true">
|
||||
<Position X="8.25" Y="4.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABABAAAA=</HashCode>
|
||||
<FileName>Interfaces\IGpioEnabled.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Interface Name="DTS.Common.DAS.Concepts.IRealtimeable" Collapsed="true">
|
||||
<Position X="11.75" Y="5.25" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AIAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Interfaces\IRealtimeable.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Interface Name="DTS.Common.DAS.Concepts.ITriggerable" Collapsed="true">
|
||||
<Position X="5.75" Y="0.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Interfaces\ITriggerable.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Interface Name="DTS.Common.DAS.Concepts.DAS.Channel.ICalSignalAware" Collapsed="true">
|
||||
<Position X="10" Y="3.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAACAAAAAA=</HashCode>
|
||||
<FileName>Interfaces\DAS\Channel\ICalSignalAware.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Interface Name="DTS.Common.DAS.Concepts.DAS.Channel.IDecimatable<T>" Collapsed="true">
|
||||
<Position X="11.75" Y="3.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAACAgAAAAAAAAAAAgAAAAAAAAAIAA=</HashCode>
|
||||
<FileName>Interfaces\DAS\Channel\IDecimatable.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Interface Name="DTS.Common.DAS.Concepts.DAS.Channel.IEngineeringUnitAware" Collapsed="true">
|
||||
<Position X="13.5" Y="3.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Interfaces\DAS\Channel\IEngineeringUnitAware.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Interface Name="DTS.Common.DAS.Concepts.DAS.Channel.IInversionAware" Collapsed="true">
|
||||
<Position X="10" Y="4.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Interfaces\DAS\Channel\IInversionAware.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Interface Name="DTS.Common.DAS.Concepts.DAS.Channel.IIsoCodeAware" Collapsed="true">
|
||||
<Position X="11.75" Y="4.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Interfaces\DAS\Channel\IIsoCodeAware.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Interface Name="DTS.Common.DAS.Concepts.DAS.Channel.ILevelTriggerable" Collapsed="true">
|
||||
<Position X="8.25" Y="5.25" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAIAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAg=</HashCode>
|
||||
<FileName>Interfaces\DAS\Channel\ILevelTriggerable.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Interface Name="DTS.Common.DAS.Concepts.DAS.Channel.ILinearized" Collapsed="true">
|
||||
<Position X="10" Y="5.25" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Interfaces\DAS\Channel\ILinearized.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Interface Name="DTS.Common.DAS.Concepts.DAS.Channel.ISerialNumberAware" Collapsed="true">
|
||||
<Position X="13.5" Y="5.25" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Interfaces\DAS\Channel\ISerialNumberAware.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Interface Name="DTS.Common.DAS.Concepts.DAS.Channel.IShuntAware" Collapsed="true">
|
||||
<Position X="8.25" Y="6" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>ABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAA=</HashCode>
|
||||
<FileName>Interfaces\DAS\Channel\IShuntAware.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Interface Name="DTS.Common.DAS.Concepts.DAS.Channel.IVoltageInsertionAware" Collapsed="true">
|
||||
<Position X="10" Y="6" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAEAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Interfaces\DAS\Channel\IVoltageInsertAware.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Interface Name="DTS.Common.DAS.Concepts.DAS.Channel.ILargeDataAware" Collapsed="true">
|
||||
<Position X="13.5" Y="4.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Interfaces\ILargeDataAware.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Enum Name="DTS.Common.DAS.Concepts.ArmStatus" Collapsed="true">
|
||||
<Position X="8.25" Y="7" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAIBAAAAAAAAAAAAAAAIBAAAAAAAAgAAAAA=</HashCode>
|
||||
<FileName>ArmStatus.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Enum>
|
||||
<Enum Name="DTS.Common.DAS.Concepts.AvailableArmModes" Collapsed="true">
|
||||
<Position X="10" Y="7" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>AvailableArmModes.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Enum>
|
||||
<Enum Name="DTS.Common.DAS.Concepts.DAS.DecimationMethod" Collapsed="true">
|
||||
<Position X="11.75" Y="7" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>ACAAAAAAAAAAhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>DAS\DecimationMethod.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Enum>
|
||||
<Enum Name="DTS.Common.DAS.Concepts.DAS.Channel.LevelTriggerTypes" Collapsed="true">
|
||||
<Position X="8.25" Y="7.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>ACAAAAACACAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAACA=</HashCode>
|
||||
<FileName>DAS\Channel\LevelTriggerTypes.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Enum>
|
||||
<Enum Name="DTS.Common.Common.DAS.Concepts.GPIOPin.Directions" Collapsed="true">
|
||||
<Position X="13.5" Y="7" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAYAAAAEAQAAAAAAAAAgAAAAAA=</HashCode>
|
||||
<FileName>Interfaces\IGpioEnabled.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Enum>
|
||||
<Font Name="Segoe UI" Size="9" />
|
||||
</ClassDiagram>
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
Test.Module.RecordingMode.cs
|
||||
|
||||
Copyright © 2008
|
||||
Diversified Technical Systems, Inc.
|
||||
All Rights Reserved
|
||||
*/
|
||||
|
||||
using DTS.Common.Enums.DASFactory;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace DTS.Common.DAS.Concepts
|
||||
{
|
||||
// *** see Test.cs ***
|
||||
public partial class Test
|
||||
{
|
||||
/// <summary>
|
||||
/// A container for DTS generic module concepts.
|
||||
/// </summary>
|
||||
public sealed partial class Module
|
||||
{
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Convert a string representation of a recording mode enumeration into its corresponding
|
||||
/// enumeration value.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="recordingMode">
|
||||
/// The <see cref="string"/> representation to be converted.
|
||||
/// </param>
|
||||
///
|
||||
/// <returns>
|
||||
/// The <see cref="Test.Module.RecordingMode"/> value corresponding to the
|
||||
/// specified string, if any. If not, an exception will be thrown.
|
||||
/// </returns>
|
||||
///
|
||||
public static DFConstantsAndEnums.RecordingMode GetRecordingModeFromString(string recordingMode)
|
||||
{
|
||||
try
|
||||
{
|
||||
return (DFConstantsAndEnums.RecordingMode)Enum.Parse(typeof(DFConstantsAndEnums.RecordingMode), recordingMode);
|
||||
}
|
||||
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception("encountered problem getting recording mode from string representation " + (null != recordingMode ? "\"" + recordingMode + "\"" : "<<NULL>>"), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
namespace DTS.Common.DAS.Concepts.DAS
|
||||
{
|
||||
/// <summary>
|
||||
/// Methods for determining the value of the representative point for decimated sets.
|
||||
/// </summary>
|
||||
public enum DecimationMethod
|
||||
{
|
||||
/// <summary>
|
||||
/// Use that value of the PointsPerPoint-th point as the representative value.
|
||||
/// </summary>
|
||||
Point,
|
||||
|
||||
/// <summary>
|
||||
/// Use the average of the PointsPerPoint values as the representative value.
|
||||
/// </summary>
|
||||
Average,
|
||||
|
||||
/// <summary>
|
||||
/// Use the peak magnitude value of the PointsPerPoint values as the representative value.
|
||||
/// </summary>
|
||||
PeakMagnitude,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
Test.Module.Channel.Sensor.ExcitationVoltage.cs
|
||||
|
||||
Copyright © 2008
|
||||
Diversified Technical Systems, Inc.
|
||||
All Rights Reserved
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using DTS.Utilities;
|
||||
|
||||
namespace DTS.DAS.Concepts
|
||||
{
|
||||
// *** see Test.cs ***
|
||||
public partial class Test
|
||||
{
|
||||
/// <summary>
|
||||
/// A container for DTS generic module concepts.
|
||||
/// </summary>
|
||||
public sealed partial class Module
|
||||
{
|
||||
// *** see Test.Module.Channel.cs ***
|
||||
public partial class Channel
|
||||
{
|
||||
//*** see Test.Module.Channel.Sensor.cs ***
|
||||
public partial class Sensor
|
||||
{
|
||||
/// <summary>
|
||||
/// All available excitation voltages.
|
||||
/// </summary>
|
||||
public enum ExcitationVoltageOption
|
||||
{
|
||||
/// <summary>
|
||||
/// undefined excitation voltage
|
||||
/// </summary>
|
||||
[VoltageMagnitude(0.0)]
|
||||
[Description("Undefined")]
|
||||
Undefined=1,
|
||||
/// <summary>
|
||||
/// 2V
|
||||
/// </summary>
|
||||
[VoltageMagnitude(2.0)]
|
||||
[Description("2.0")]
|
||||
Volt2=2,
|
||||
/// <summary>
|
||||
/// 2.5V
|
||||
/// </summary>
|
||||
[VoltageMagnitude(2.5)]
|
||||
[Description("2.5")]
|
||||
Volt2_5=4,
|
||||
/// <summary>
|
||||
/// 3.0V
|
||||
/// </summary>
|
||||
[VoltageMagnitude(3.0)]
|
||||
[Description("3.0")]
|
||||
Volt3=8,
|
||||
/// <summary>
|
||||
/// 5V
|
||||
/// </summary>
|
||||
[VoltageMagnitude( 5.0 )]
|
||||
[Description("5.0")]
|
||||
Volt5=16,
|
||||
/// <summary>
|
||||
/// 10V
|
||||
/// </summary>
|
||||
[VoltageMagnitude( 10.0 )]
|
||||
[Description("10.0")]
|
||||
Volt10=32,
|
||||
/// <summary>
|
||||
/// 1V
|
||||
/// </summary>
|
||||
[VoltageMagnitude(1.0)]
|
||||
[Description("1.0")]
|
||||
Volt1 = 64
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a specified excitation voltage option into its associated numeric value.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="target">
|
||||
/// The <see cref="DTS.DAS.Concepts.Test.Module.Channel.Sensor.ExcitationVoltageOption"/> value
|
||||
/// to be converted.
|
||||
/// </param>
|
||||
///
|
||||
/// <returns>
|
||||
/// The <see cref="double"/> magnitude associated with the specified voltage option.
|
||||
/// </returns>
|
||||
///
|
||||
public static double GetExcitationVoltageMagnitudeFromEnum( ExcitationVoltageOption target )
|
||||
{
|
||||
try
|
||||
{
|
||||
return new VoltageMagnitudeAttributeCoder( ).DecodeAttributeValue( target );
|
||||
}
|
||||
|
||||
catch ( Exception ex )
|
||||
{
|
||||
throw new Exception( "encountered problem attempting to get excitation voltage magnitude from enum", ex );
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a specified voltage magnitude to the associated numeric value (if it exists;
|
||||
/// otherwise an exception is thrown).
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="magnitude">
|
||||
/// The <see cref="double"/> magnitude to be converted.
|
||||
/// </param>
|
||||
///
|
||||
/// <returns>
|
||||
/// The <see cref="DTS.DAS.Concepts.Test.Module.Channel.Sensor.ExcitationVoltageOption"/> value
|
||||
/// associated with the specified magnitude (if it exists).
|
||||
/// </returns>
|
||||
///
|
||||
public static ExcitationVoltageOption GetExcitationVoltageEnumFromMagnitude( double magnitude )
|
||||
{
|
||||
try
|
||||
{
|
||||
return new VoltageMagnitudeAttributeCoder( ).EncodeAttributeValue( magnitude );
|
||||
}
|
||||
|
||||
catch ( System.Exception ex )
|
||||
{
|
||||
throw new NotSupportedException( "encountered problem attempting to get excitation voltage enum from magnitude", ex );
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attribute for specifying the numerical magnitude of the attached field's
|
||||
/// "representation". Intended to be used with enumerations whose members represent
|
||||
/// voltage magnitude options so that the enum item can have a corresponding numerical
|
||||
/// value that can be extracted and used in calculations.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Field)]
|
||||
public class VoltageMagnitudeAttribute: System.Attribute
|
||||
{
|
||||
private readonly double _Value;
|
||||
/// <summary>
|
||||
/// returns voltage magnitude
|
||||
/// </summary>
|
||||
public double Value { get { return _Value; } }
|
||||
/// <summary>
|
||||
/// constructs a <see cref="DTS.DAS.Concepts.Test.Module.Channel.Sensor.VoltageMagnitudeAttribute" />
|
||||
/// with a given value
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
public VoltageMagnitudeAttribute(double value) { _Value = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Object for manipulating voltage option enumeration-attached
|
||||
/// <see cref="double"/> magnitude values.
|
||||
/// </summary>
|
||||
public class VoltageMagnitudeAttributeCoder
|
||||
: AttributeCoder<ExcitationVoltageOption, VoltageMagnitudeAttribute, double>
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a <see cref="DTS.DAS.Concepts.Test.Module.Channel.Sensor.VoltageMagnitudeAttributeCoder"/> object.
|
||||
/// </summary>
|
||||
public VoltageMagnitudeAttributeCoder()
|
||||
: base(attribute => attribute.Value, null)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* IGpioEnabled.cs
|
||||
*
|
||||
* Copyright © 2010
|
||||
* Diversified Technical Systems, Inc.
|
||||
* All Rights Reserved.
|
||||
*/
|
||||
|
||||
using DTS.Common.Common.DAS.Concepts.GPIOPin;
|
||||
|
||||
namespace DTS.Common.Common.DAS.Concepts.GPIOPin
|
||||
{
|
||||
public enum Directions
|
||||
{
|
||||
Output = 0x00, Peripheral = 0x01, Input = 0x02,
|
||||
InputPulledUp = 0x03, InputPulledDown = 0x04
|
||||
};
|
||||
}
|
||||
|
||||
namespace DTS.Common.DAS.Concepts
|
||||
{ ///
|
||||
/// <summary>
|
||||
/// Representation of GPIO functionality.
|
||||
/// </summary>
|
||||
///
|
||||
public interface IGpioEnabled
|
||||
{
|
||||
// TODO: Well have to bring these in as soon as we figure out where to get that enum from.
|
||||
|
||||
void SetGpio(uint Port, uint Pin, Directions Direction, bool State);
|
||||
bool GetGpio(uint Port, uint Pin);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* DTS.Common.DAS.Concepts.DAS.Channel.IVoltageInsertionAware.cs
|
||||
*
|
||||
* Copyright © 2012
|
||||
* Diversified Technical Systems, Inc.
|
||||
* All Rights Reserved
|
||||
*/
|
||||
|
||||
namespace DTS.Common.DAS.Concepts.DAS.Channel
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Definition of the concept of shunt-check awareness.
|
||||
/// </summary>
|
||||
public interface IVoltageInsertionAware
|
||||
{
|
||||
/// <summary>
|
||||
/// Get/set this object's <see cref="double"/> measured shunt deflection value.
|
||||
/// </summary>
|
||||
double ExpectedGain
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get/set this object's <see cref="double"/> target shunt deflection value.
|
||||
/// </summary>
|
||||
double MeasuredGain
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* DTS.Common.DAS.Concepts.DAS.Channel.IIsoCodeAware.cs
|
||||
*
|
||||
* Copyright © 2009
|
||||
* Diversified Technical Systems, Inc.
|
||||
* All Rights Reserved
|
||||
*/
|
||||
|
||||
namespace DTS.Common.DAS.Concepts.DAS.Channel
|
||||
{
|
||||
/// <summary>
|
||||
/// Definition of the concept of ISO code awareness.
|
||||
/// </summary>
|
||||
public interface IIsoCodeAware
|
||||
{
|
||||
/// <summary>
|
||||
/// Get/set this object's IsoCode <see cref="string"/>.
|
||||
/// </summary>
|
||||
string IsoCode
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
Test.Module.cs
|
||||
|
||||
Copyright © 2008
|
||||
Diversified Technical Systems, Inc.
|
||||
All Rights Reserved
|
||||
*/
|
||||
|
||||
namespace DTS.DAS.Concepts
|
||||
{
|
||||
// *** see Test.cs ***
|
||||
public partial class Test
|
||||
{
|
||||
/// <summary>
|
||||
/// A container for DTS generic module concepts.
|
||||
/// </summary>
|
||||
public sealed partial class Module
|
||||
{
|
||||
/// <summary>
|
||||
/// Class is not intended for instantiation.
|
||||
/// </summary>
|
||||
private Module( ) { }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* DAS.Channel.IInversionAware.cs
|
||||
*
|
||||
* Copyright © 2009
|
||||
* Diversified Technical Systems, Inc.
|
||||
* All Rights Reserved
|
||||
*/
|
||||
|
||||
namespace DTS.DAS.Concepts.DAS.Channel
|
||||
{
|
||||
/// <summary>
|
||||
/// Definition of the concept of inversion awareness.
|
||||
/// </summary>
|
||||
public interface IInversionAware
|
||||
{ ///
|
||||
/// <summary>
|
||||
/// Get/set this object's inversion state <see cref="bool"/>.
|
||||
/// </summary>
|
||||
///
|
||||
bool IsInverted
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
}
|
||||
public interface ILinearized
|
||||
{
|
||||
LinearizationFormula LinearizationFormula
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* DTS.Common.DAS.Concepts.DAS.Channel.cs
|
||||
*
|
||||
* Copyright © 2009
|
||||
* Diversified Technical Systems, Inc.
|
||||
* All Rights Reserved
|
||||
*/
|
||||
|
||||
using DTS.Common.Utilities;
|
||||
|
||||
namespace DTS.Common.DAS.Concepts.DAS
|
||||
{
|
||||
/// <summary>
|
||||
/// Slice control app's internal abstract representation of a DAS channel.
|
||||
/// </summary>
|
||||
///
|
||||
/// <typeparam name="TDataType">
|
||||
/// The "type" of the data contained by channels of this DAS.
|
||||
/// </typeparam>
|
||||
///
|
||||
public abstract class Channel<TDataType> : Exceptional
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
Test.Module.Channel.Sensor.ExcitationVoltage.cs
|
||||
|
||||
Copyright © 2008
|
||||
Diversified Technical Systems, Inc.
|
||||
All Rights Reserved
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using DTS.Common.Enums;
|
||||
using DTS.Common.Utilities;
|
||||
using DTS.Common.Utilities.Logging;
|
||||
|
||||
namespace DTS.Common.DAS.Concepts
|
||||
{
|
||||
// *** see Test.cs ***
|
||||
public partial class Test
|
||||
{
|
||||
/// <summary>
|
||||
/// A container for DTS generic module concepts.
|
||||
/// </summary>
|
||||
public sealed partial class Module
|
||||
{
|
||||
// *** see Test.Module.Channel.cs ***
|
||||
public partial class Channel
|
||||
{
|
||||
//*** see DTS.Common.DAS.Concepts.Test.Module.Channel.Sensor.cs ***
|
||||
public partial class Sensor
|
||||
{
|
||||
///// <summary>
|
||||
///// All available excitation voltages.
|
||||
///// </summary>
|
||||
//public enum ExcitationVoltageOption
|
||||
//{
|
||||
// /// <summary>
|
||||
// /// undefined excitation voltage
|
||||
// /// </summary>
|
||||
// [VoltageMagnitude(0.0)]
|
||||
// [Description("Undefined")]
|
||||
// Undefined=1,
|
||||
// /// <summary>
|
||||
// /// 2V
|
||||
// /// </summary>
|
||||
// [VoltageMagnitude(2.0)]
|
||||
// [Description("2.0")]
|
||||
// Volt2=2,
|
||||
// /// <summary>
|
||||
// /// 2.5V
|
||||
// /// </summary>
|
||||
// [VoltageMagnitude(2.5)]
|
||||
// [Description("2.5")]
|
||||
// Volt2_5=4,
|
||||
// /// <summary>
|
||||
// /// 3.0V
|
||||
// /// </summary>
|
||||
// [VoltageMagnitude(3.0)]
|
||||
// [Description("3.0")]
|
||||
// Volt3=8,
|
||||
// /// <summary>
|
||||
// /// 5V
|
||||
// /// </summary>
|
||||
// [VoltageMagnitude( 5.0 )]
|
||||
// [Description("5.0")]
|
||||
// Volt5=16,
|
||||
// /// <summary>
|
||||
// /// 10V
|
||||
// /// </summary>
|
||||
// [VoltageMagnitude( 10.0 )]
|
||||
// [Description("10.0")]
|
||||
// Volt10=32,
|
||||
// /// <summary>
|
||||
// /// 1V
|
||||
// /// </summary>
|
||||
// [VoltageMagnitude(1.0)]
|
||||
// [Description("1.0")]
|
||||
// Volt1 = 64
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a specified excitation voltage option into its associated numeric value.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="target">
|
||||
/// The <see cref="ExcitationVoltageOptions.ExcitationVoltageOption"/> value
|
||||
/// to be converted.
|
||||
/// </param>
|
||||
///
|
||||
/// <returns>
|
||||
/// The <see cref="double"/> magnitude associated with the specified voltage option.
|
||||
/// </returns>
|
||||
///
|
||||
public static double GetExcitationVoltageMagnitudeFromEnum(ExcitationVoltageOptions.ExcitationVoltageOption target)
|
||||
{
|
||||
try
|
||||
{
|
||||
return new ExcitationVoltageOptions.VoltageMagnitudeAttributeCoder().DecodeAttributeValue(target);
|
||||
}
|
||||
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new ArgumentException("encountered problem attempting to get excitation voltage magnitude from enum", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a specified voltage magnitude to the associated numeric value (if it exists;
|
||||
/// otherwise an exception is thrown).
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="magnitude">
|
||||
/// The <see cref="double"/> magnitude to be converted.
|
||||
/// </param>
|
||||
///
|
||||
/// <returns>
|
||||
/// The <see cref="ExcitationVoltageOptions.ExcitationVoltageOption"/> value
|
||||
/// associated with the specified magnitude (if it exists).
|
||||
/// </returns>
|
||||
///
|
||||
public static ExcitationVoltageOptions.ExcitationVoltageOption GetExcitationVoltageEnumFromMagnitude(double magnitude)
|
||||
{
|
||||
try
|
||||
{
|
||||
return new ExcitationVoltageOptions.VoltageMagnitudeAttributeCoder().EncodeAttributeValue(magnitude);
|
||||
}
|
||||
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log("encountered problem attempting to get excitation voltage enum from magnitude", ex);
|
||||
return ExcitationVoltageOptions.ExcitationVoltageOption.Undefined;
|
||||
}
|
||||
}
|
||||
|
||||
///// <summary>
|
||||
///// Attribute for specifying the numerical magnitude of the attached field's
|
||||
///// "representation". Intended to be used with enumerations whose members represent
|
||||
///// voltage magnitude options so that the enum item can have a corresponding numerical
|
||||
///// value that can be extracted and used in calculations.
|
||||
///// </summary>
|
||||
//[AttributeUsage(AttributeTargets.Field)]
|
||||
//public class VoltageMagnitudeAttribute: Attribute
|
||||
//{
|
||||
// /// <summary>
|
||||
// /// returns voltage magnitude
|
||||
// /// </summary>
|
||||
// public double Value { get; }
|
||||
|
||||
// /// <summary>
|
||||
// /// constructs a <see cref="Test.Module.Channel.Sensor.VoltageMagnitudeAttribute" />
|
||||
// /// with a given value
|
||||
// /// </summary>
|
||||
// /// <param name="value"></param>
|
||||
// public VoltageMagnitudeAttribute(double value) { Value = value; }
|
||||
//}
|
||||
|
||||
///// <summary>
|
||||
///// Object for manipulating voltage option enumeration-attached
|
||||
///// <see cref="double"/> magnitude values.
|
||||
///// </summary>
|
||||
//public class VoltageMagnitudeAttributeCoder
|
||||
// : AttributeCoder<ExcitationVoltageOptions.ExcitationVoltageOption, VoltageMagnitudeAttribute, double>
|
||||
//{
|
||||
// /// <summary>
|
||||
// /// Initializes a <see cref="Test.Module.Channel.Sensor.VoltageMagnitudeAttributeCoder"/> object.
|
||||
// /// </summary>
|
||||
// public VoltageMagnitudeAttributeCoder()
|
||||
// : base(attribute => attribute.Value, null)
|
||||
// {
|
||||
// }
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
Test.Module.Channel.cs
|
||||
|
||||
Copyright © 2008
|
||||
Diversified Technical Systems, Inc.
|
||||
All Rights Reserved
|
||||
*/
|
||||
|
||||
namespace DTS.DAS.Concepts
|
||||
{
|
||||
// *** see Test.cs ***
|
||||
public partial class Test
|
||||
{
|
||||
/// <summary>
|
||||
/// A container for DTS generic module concepts.
|
||||
/// </summary>
|
||||
public sealed partial class Module
|
||||
{
|
||||
/// <summary>
|
||||
/// A container for DTS generic channel concepts.
|
||||
/// </summary>
|
||||
public sealed partial class Channel
|
||||
{
|
||||
/// <summary>
|
||||
/// Class is not intended for instantiation.
|
||||
/// </summary>
|
||||
private Channel( ) { }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* DAS.Channel.cs
|
||||
*
|
||||
* Copyright © 2009
|
||||
* Diversified Technical Systems, Inc.
|
||||
* All Rights Reserved
|
||||
*/
|
||||
|
||||
using DTS.Utilities;
|
||||
|
||||
namespace DTS.DAS.Concepts.DAS
|
||||
{
|
||||
/// <summary>
|
||||
/// Slice control app's internal abstract representation of a DAS channel.
|
||||
/// </summary>
|
||||
///
|
||||
/// <typeparam name="DataType">
|
||||
/// The "type" of the data contained by channels of this DAS.
|
||||
/// </typeparam>
|
||||
///
|
||||
public abstract class Channel<DataType> : Exceptional
|
||||
{
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user