Compare commits

..
Author SHA1 Message Date
michal b8f6af7112 Fix point 4. - take % validation from procedure to Q3 Calib factor CH1-3 verification
Implement error limit configuration for Q3 calibration factors.

- Add default and configurable error limits for Q3 calibration validation.
- Introduce `CalculateQ3CalibrationWithErrorLimits` for flexible validation handling.
- Overhaul Q3 workflow to respect configured limits, with fallback to defaults.
- Extend tests for calibration, including boundary and invalid inputs.
2026-09-16 10:23:04 +02:00
michal 684513ee59 Fix Genesis scheduling and synchronization for up to 10 workers 2026-09-10 22:09:30 +02:00
michal 52bd0d01ce Restore Genesis communication and Q3 calibration from special branches
A – Registration and execution
- Register GenesisCommunication Factory in the component list.
- Separate the Genesis form and sequence from iPerl communication.

B – Communication activities
- Restore initialization, connection, PCB reading, password and login.
- Include grouped login, mode switching and disconnection.
- Support processing up to 10 slots.

C1 – Input calibration factors
- Read three factors from Water meters / Text1–Text3.
- Validate integer values in the range 1–65535.
- Preserve the default of 15625 when all three fields are empty.

D – Q3 calibration
- Connect the Prepare Q3 → measurement → Write Q3 workflow.
- Add channel processing to FlyingStart and FlyingStartMassCollection.
- Reset previous measurement data and validate calculated factors.
- Mark factors as stored only after StoreCalibration succeeds.

E – Results and database
- Store calibration factors separately for each meter and channel.
- Add result entities, mappings and Q3 data.
- Extend DB.cs / EnsureSchema to create and update the schema.
- Preserve compatibility with the existing binary format.

Validation:
- Debug build and 18 tests passed.
- Simulated communication runs follow the same activity sequence.
- The complete Q3 workflow has not yet been verified on hardware.

Known limitation:
- An inherited mismatch in simulated responses and error propagation
  can produce an incorrect OK result; this change does not fix it.
2026-09-09 15:04:49 +02:00
michal 88b8bc5534 fix precision correct factor (Mexico), added diff, correction in percentage in Result Configuration 2026-09-07 14:07:07 +02:00
marekf d3c8813012 <Fix>: Correct test-dependent result evaluation in ResultsWriter, increase revision to 3.9.3145.101
Cause:

- ResultsWriter evaluated selected test-dependent items without the actual TestID.
- This caused values such as Test passed(), timestamps, flow, pressure, temperature, conductivity and error data to be empty or incorrect.

Solution:

1. Fixed test-aware result evaluation
   - Uses published regular meter test results.
   - Passes mtr.Name() as TestID to item.Print(wm, testId).

2. Restored correct test result mapping
   - Test-dependent values are now resolved from the correct TestRslt / MeterTestRslt.

3. Increased revision
   - Updated revision to 3.9.3145.101.
2026-09-03 10:00:40 +02:00
marekf 054075a341 <Feat>: Add XML result generation with file and MSSQL output support, increase revision to 3.9.3145.100
Cause:

- ResultsWriter required a generic way to generate customer-specific XML result data from TBF measurement results.
- The customer reference XML contains example runtime values and repeated result structures, so it cannot be used directly as the generated output.
- TBF result variables must be explicitly mapped to destinations in the customer XML structure.
- The generated XML result data must support two output targets:
  - direct creation of an XML file,
  - delivery of the XML payload to a Microsoft SQL stored procedure.
- Preview generation must allow the XML structure and configured mappings to be verified without executing the production database write.
- Increase revision to 3.9.3145.100.

Solution:

1. Added XML reference analysis
   - Creates a clean base XML structure.
   - Extracts the repeating result prototype.
   - Prevents sample runtime values from the customer reference XML from leaking into generated results.
2. Added configurable TBF-to-XML result mapping
   - Allows explicit mapping of TBF result variables to customer XML destinations.
   - Supports one-time and repeating XML destinations.
   - Keeps the mapping independent of the semantic meaning of customer XML attribute names.
3. Added XML destination viewer and configurator
   - Shows the current mapping.
   - Highlights repeating destinations.
   - Identifies already used one-time destinations.
4. Added runtime XML result generation
   - Uses the configured TBF-to-XML mappings.
   - Uses measurement procedure result data.
   - Builds the output from the clean base XML and repeating XML prototype.
   - Generates repeated result records according to the executed measurement procedure.
5. Added simulation-based Preview request
   - Generates a complete XML payload using simulation values.
   - Allows XML structure and mapping verification before production execution.
   - Does not execute the production stored procedure.
6. Added direct XML file output support to UniDataStorageWriter
   - Supports File / .xml as a physical output target.
   - Creates the generated XML result file in the configured output directory.
7. Added Microsoft SQL stored-procedure XML output
   - Supports Microsoft SQL / StoredProcedure as a physical output target.
   - Passes the generated XML payload through the configured stored procedure parameter.
8. Added optional XML payload archiving
   - Allows generated XML payloads to be stored in the configured Payload archive.
   - Can be used together with the Microsoft SQL stored-procedure output.
9. Kept ResultsWriter independent of the physical output target
   - ResultsWriter generates the result payload.
   - UniDataStorageWriter decides how and where the payload is physically written.
   - The same ResultsWriter XML generation mechanism is therefore used for both XML file and MSSQL outputs.
10. Increased revision
   - Updated revision to 3.9.3145.100.
2026-09-02 12:05:10 +02:00
marekf a0d53f9ec9 <Fix>: RefPulses carry-over by restoring testInProgress behavior in StandingStart, increase revision to 3.9.3145
Cause:
1. Background: Restore/ensure testInProgress behavior before the DataEntry sequence and explicitly prevent to reset the pulse.
2. Increase revision to 3.9.3145

Solution:
1. Deleted .AddOperation(testInProgress) calling
2. Increased revision to 3.9.3145
2026-08-25 13:49:49 +02:00
michal dfa8693be9 Added table columns TestRslt -> ConductMean, .... 2026-08-25 10:38:08 +02:00
marekf 1e45f48c75 <Update>: Version to 3.9.3144.0 in AssemblyInfo files 2026-08-25 08:23:27 +02:00
marekf d833eca584 <Merge_Fix>: System.Data.SQLite, System.Data.SQLite.Core, Stub.System.Data.SQLite.Core.NetFramework 2026-08-24 15:36:50 +02:00
marekf c966a7034c <Merge-Fix>: Solve merge conflicts 2026-08-24 15:04:11 +02:00
marekf f051d51ae0 <Fix>: Incorrect cycle resume behavior after Stop and Start, increase revision to 3.9.3134.114
Cause:
1. When the Cycle was stopped during the second or a later test and then resumed using the Start Test button, the resume confirmation was handled incorrectly. After selecting to continue, the sequence restarted from the first test instead of continuing from the interrupted test.
2. Increase revision to 3.9.3134.114

Solution:
1. Corrected the Cycle resume logic so that, after confirming continuation, the sequence resumes from the interrupted test instead of restarting from the first test.
2. Increased revision to 3.9.3134.114
2026-08-24 14:25:19 +02:00
marekf 267159e0a9 <Fix>: RefPulses carry-over by restoring testInProgress behavior in StandingStart, increase revision to 3.9.3134.113
Cause:
1. Background: there was a suspicion that the Bukoven board left RefPulses active across operations; this was investigated and ruled out. The pulse counter is reset by testInProgress when an operation is reused. During the third DataEntry window testInProgress had been temporarily disabled (SLM vs Karlsruhe difference), which allowed RefPulses to appear to persist.
2. Increase revision to 3.9.3134.113

Solution:
1. Restore/ensure testInProgress behavior during the DataEntry sequence and explicitly reset the pulse counter when starting a new operation.
2. Increased revision to 3.9.3134.113
2026-08-24 12:54:15 +02:00
michal 26db172153 Camera WM Purchase Order - crop disabled 2026-08-24 12:21:49 +02:00
michal 2e75f65b4a Update version to 3.9.3142.0 in AssemblyInfo files 2026-08-20 00:27:39 +02:00
michal 432cb91e5a Update Flip Mode handling and introduce SetTestModeOpto7Str alias
Refactor Flip Mode parameter type in `WMeterRsltItemSpec` to `Quantity.String` for consistency. Add `SetTestModeOpto7Str` alias to improve readability and replace legacy A0 test mode reference in `iPerlCommunicationParams`.
2026-08-20 00:27:06 +02:00
michal b0083afa10 DataEntry.UNI - timeout, autoclose improve
Introduce configurable timeouts for data entry volume reads in `IRegReaderSmart` and its implementations: added optional timeout parameters and updated default values across associated forms and methods. Updated `EntryFormCfg` to support customizable timeout settings.
2026-08-19 23:47:50 +02:00
michal 955b59a195 Improve UNI Data Entry auto close
Add tooltip functionality for parameter names in `ComponentCfgCtrl` and auto-close countdown improvements in UNI Data Entry forms
2026-08-19 22:32:14 +02:00
michal b904d0ca41 Fix Flip Mode - ver. 3.9.3141.0
Add robust handling for form closure in UNI Data Entry: prevent operations on disposed/closing forms, enhance logging, and update logic in serial number and volume updates. Increment version to 3.9.3141.0.
2026-08-19 19:13:41 +02:00
michal f34046df2a Update version to 3.9.3140.0 in AssemblyInfo files - FIX DataEntry.UNI 2026-08-19 14:49:24 +02:00
michal 889782068e Added counter to OK button, 5 sec default now
Add auto-close countdown timer for UNI data entry forms: implement timer logic, UI updates, and early exit handling
2026-08-19 14:47:34 +02:00
michal d12ee008db FIX UNI Data Entry - Smart Reader + missing files
Implement smart meter interface enhancements for AllyReader: Add `ISmartMeterReader` interface, update `RegisterReaderSelection` logic, integrate smart-meter position selection, and expand unit test coverage.
2026-08-19 14:33:06 +02:00
michal 6c3c6cd0ef FIX UNI Data Entry - corrensponded with iPerlCommunicationForm.cs
Add debug logging and UI enhancements for data entry processes: Improve register reader handling in sequences and forms, add detailed data entry debug logs, integrate serial number and volume watermarking, and update localized strings in multiple languages.
2026-08-19 13:18:34 +02:00
michal 5803f06bdb Flip mode related to test result - DB column in MeterTestRslt, support back compability
Add Flip Mode support across iPerl-related test methods and database schema: implement FlipMode property, update MeterTestRslt mappings, integrate schema migration logic, and refine test result handling.
2026-08-19 11:52:46 +02:00
michal a4acf30771 Refactor FlipMode enum and update references: rename DisabledConstant to Constant and EnabledRandomized to Randomized across codebase, including unit tests and integration tests, for improved readability and consistency. 2026-08-19 10:47:45 +02:00
michal a4ef208233 Fix ver. 3.9.3139 iPerlCommunicationForm.cs problems + exceptions if another regreadrer has mistakely same ports
Enhance iPerl dialog layout and error handling: improve `ShuffleTextBoxes` with positional mapping, refine checkbox state tracking, add detailed logging for labels and checkboxes, and handle serial port exceptions. Increment version to 3.9.3139.0.
2026-08-18 16:09:21 +02:00
michal be6b40b5cd Fix Optical heads ASIC iPerl dialog manual test communication 2026-08-18 14:05:33 +02:00
michal 8738edd0c5 Added FLIP MODE Constant, Randomised
Add support for Flip Mode configuration in iPerl: Implement `SetFlipMode` functionality in `OptoHeadTest` and `RadioService`, integrate constants, enhance UI, and add unit and integration tests for constant/randomized flip mode settings.
2026-08-18 13:59:59 +02:00
michal c71fe75446 Ally iPerl initial - reader,test method, unit test
Add AllyReader and AllyCalibration support with tests: Introduce new register readers, calibration methods, and comprehensive unit tests for integration and functionality validation. Update project files accordingly.
2026-08-18 10:01:02 +02:00
michal c619c7d3b8 Merge remote-tracking branch 'private-origin/develop/SLM-PT50_genesisDirectDecode' into develop/SLM-PT50_genesisDirectDecode 2026-08-17 10:27:57 +02:00
michal f3e5527145 ver. 3.9.3138.0 - OPTHO FORMATING improve (ASIC,genesis) 2026-08-17 10:27:10 +02:00
michal 39941842d4 OPTHO FORMATING improve (ASIC,genesis)
Enhance iPerlHat protocol logging and error handling: add optical HEX formatting, improve diagnostic messages, and extend test command descriptions.
2026-08-17 10:25:35 +02:00
michal 3488939995 FIX iPerl ASIC meter - mexico
Update MultiplyFactor constant to 1 and increment version to 3.9.3137.0
2026-08-14 14:14:33 +02:00
michal 0f2ef5a5bf bugfix IPERL_ASIC conductivity
update mappings , version 3.9.3136.0
2026-08-13 15:16:58 +02:00
michal 55d2381e8a Mexico - read additional parameters and store to DB, ver. 3.9.3135.0
Add support for reading and handling additional common parameters in OptoHeadTest. Extend RadioService and related classes with enhanced parsing and validation logic. Update UI and constants for functionality integration.
2026-08-12 16:20:16 +02:00
michal 126322584f Merge remote-tracking branch 'private-origin/develop/SLM-PT50_genesisDirectDecode' into develop/SLM-PT50_genesisDirectDecode 2026-08-05 12:48:48 +02:00
michal 4d9ddef3ca IperlASIC - added aditional parameters
Add support for reading additional common parameters in OptoHeadTest. Enhance `RadioService` and `VersionTypeResult` with new parsing logic. Update related constants and UI elements for functionality integration.
2026-08-05 10:57:34 +02:00
marekf 7139cdbe80 Merge branch 'develop/SLM-PT50-7-2026-merged-smart-cam-slm-mex' into develop/SLM-PT50_genesisDirectDecode 2026-08-04 16:31:57 +02:00
marekf 93d7456ccd <Fix>: RefPulses carry-over by restoring testInProgress behavior in StandingStartMassCollection, increase revision to 3.9.3134.112
Cause:
1. Background: there was a suspicion that the Bukoven board left RefPulses active across operations; this was investigated and ruled out. The pulse counter is reset by testInProgress when an operation is reused. During the third DataEntry window testInProgress had been temporarily disabled (SLM vs Karlsruhe difference), which allowed RefPulses to appear to persist.
2. Increase revision to 3.9.3134.112

Solution:
1. Restore/ensure testInProgress behavior during the DataEntry sequence and explicitly reset the pulse counter when starting a new operation.
2. Increased revision to 3.9.3134.112
2026-08-04 16:21:33 +02:00
michal 7a8ce7b6ab IperlASIC - Improved and added tests, hardware integtration tests works
Improve `VersionTypeResult` parsing and handling: Add compact/legacy payload support. Extend `ReadingUnits`. Update `IperlHatIntegrationTests` and `RadioService` with new tests and functionality integration.
2026-08-04 11:53:47 +02:00
michal 865528e344 iPerlASIC - additional parameters.
Add protocolCommons classes and enhance RadioService with support for CalibrationFactor, VersionType, ReadingUnits, and FlipMode operations. Add corresponding unit tests for validation. Update project files.
2026-08-03 15:42:16 +02:00
michal 02bb9ee9fa Update RadioService: Replace IsLoggedOn with IsConnected condition checks 2026-07-31 14:09:10 +02:00
marekf 79de40515a Upgrade: Deleted LANG_PL compilation condition, disabled legalizator before test, and version to 3.9.3134.111
Cause:
1. Unnecessary and mandatory user verification before the test, in addition, a bug appears: the "Approval by legalizer" window is displayed behind the main application window. The window was only needed for the Polish project.
2. `LANG_PL` constant in `TBF.csproj` was no longer needed.
3. Assembly version and file version in `AssemblyInfo.cs` needed to be incremented to `3.9.3134.111`.

Solution:
1. Made `altProcNameLabel` and `altProcNameTextBox` always visible and disabled specific UI controls in `ProcedureDlg.cs`.
2. Removed `LANG_PL` from `DefineConstants` in `TBF.csproj`.
3. Updated assembly version and file version in `AssemblyInfo.cs` to `3.9.3134.111`.
2026-07-28 11:49:37 +02:00
marekf e38c6c1199 Upgrade: Add remaining time display for tests, version 3.9.3134.110
Cause:
1. Missing functionality to display remaining time during tests in `StandingStartMassCollectionSeq.cs` and `StandingStartMassCollectionAdvanceSeq.cs`.
2. Assembly version and file version required an update to reflect changes.

Solution:
1. Implemented remaining time display in `StandingStartMassCollectionSeq.cs` and `StandingStartMassCollectionAdvanceSeq.cs` using `Bridge.OnActivity` to show time in minutes and seconds or seconds only.
2. Updated assembly version and file version in `AssemblyInfo.cs` to `3.9.3134.110`.
2026-07-28 11:32:53 +02:00
marekf dbb35a203e Update: Adjust input unit constants in DataEntry form and increment version to 3.9.3134.109
Cause:
1. Updated `unit` constant in `TestStartEndForm` class within `TBF.Rig.DataEntry.StandardCamera` namespace from `Unit.m3` to `Unit.l`.
2. Updated `unit` constant in `TestStartEndForm` class within `TBF.Rig.DataEntry.StandartCameraPurchaseOrder` namespace from `Unit.m3` to `Unit.l`.
3. Incremented assembly version and file version in `AssemblyInfo.cs` to `3.9.3134.109`.

Solution:
1. Changed `unit` constant in `TestStartEndForm` class within `TBF.Rig.DataEntry.StandardCamera` namespace to `Unit.l`.
2. Changed `unit` constant in `TestStartEndForm` class within `TBF.Rig.DataEntry.StandartCameraPurchaseOrder` namespace to `Unit.l`.
3. Updated assembly version and file version in `AssemblyInfo.cs` to `3.9.3134.109`.
2026-07-28 07:38:30 +02:00
marekf a88a094e86 Release SLM-PT50 3.9.3134.108, increase revision after merge 2026-07-23 13:08:52 +02:00
marekf ffaebbdf07 Merge branch 'develop/SLM-PT50_genesisDirectDecode' of http://87.197.120.129:33300/michal/tbf into develop/SLM-PT50 2026-07-23 12:57:20 +02:00
michal e7d04b55b3 Live Stream Operations: Add StartLiveStream to CJMS11 camera 2026-07-22 10:02:22 +02:00
michal 8301971906 Fix StartEndForm in StandartCameraPurchaseOrder layout and positioning, remove Scroll Bar 2026-07-21 16:03:43 +02:00
michal 693cf7e4e2 Refactor TestStartEndForm - Remove unused methods and comments, simplify image grouping logic. 2026-07-21 15:22:50 +02:00
michal 2fa212e6ff FIX CAMERA - Improve error handling, modularize image processing functions for CJMS11 cameras, and enhance multi-image support in TestStartEndForm. 2026-07-21 14:50:59 +02:00
marekf a210a0d1f2 Upgrade (UniDataStorageWriter): improve writer configuration UX and CSV handling
- added technology-specific default configuration for new writers
- auto-fill default SQL/XLSX write templates
- disabled write templates for CSV technology
- added technology-specific data source hints
- changed test parameter format to Column=Value and Where=Value;Set=Value
- improved parameter validation to prevent invalid input crashes
- added automatic CSV header creation and header validation
- aligned CSV writer behaviour with XLSX writer
- Increase revision number
2026-07-21 11:18:11 +02:00
marekf 4cd191fcb2 Merge branch 'develop/SLM-PT50-7-2026-merged-smart-cam-slm-mex' into develop/Mexico-6-2026 2026-07-20 15:54:01 +02:00
marekf e21833fb5f Release Mexico 3.9.3069.1 2026-07-20 15:47:06 +02:00
marekf b746ceb34a Upgrade - Replace PulsesTypeByQuantity with MultiFunctionalVariables unit filtering based on RegisterReader quantity type - remove PulsesTypeByQuantity-based parameter values
- generate available units using Units.IsQuantity(...)
- use Quantity.MultiFunctionalVariables to populate supported units
- centralize unit selection through Units.GetQuantity()
2026-07-20 14:09:29 +02:00
marekf 83c1f0e817 Update - Actualized revision nr. 2026-07-17 14:15:22 +02:00
marekf a88a5a8db2 Fix - 1. StandingStartMassCollection and StandingStartMassCollectionAdvance - changed all delayed Activity strings, 2. Added UI/Bridge onDelayedActivity() method for universal using 2026-07-17 14:15:04 +02:00
marekf 271200a8da Upgrade - StandingStartMassCollectionAdvance method - 1. changed structure and residual flow delays by changes in StandingStartMassCollection method, 2. added variables, counting and evaluation for volume/mass type of RegisterReader 2026-07-17 12:42:07 +02:00
marekf b703297f5e Fix - 1. repaired StandingStartMassCollection MassEN evaluation, the problem was caused by the end scale measuring only after recalculating the basic values - 2. removed fixed delay for the first diverter switching and first diverter switching was moved after a configurable delay - 3. hidden unitComboBox in the StartEnd dialog of the DataEntry.Standard24 component, because units are now defined using the RegisterReader component 2026-07-17 09:55:03 +02:00
marekf 637d1d021d Fix - StandingMassCollection method - add end mass measurement 2026-07-16 15:19:28 +02:00
marekf dbe424b17a Add - StandingStart method - Store and log default PumpPower for dynamic test repetitions - Read PumpPower from the current pump before starting dynamic tests.
- Store the value as the default PumpPower for subsequent test instances in the cycle.
- Add logging when PumpPower is initialized from the pump.
- Add logging at test start including test name, repetition number,
  last repetition flag, and PumpPower to improve diagnostics.
2026-07-16 14:21:00 +02:00
marekf be0525a319 Upgrade - improved StandingStart method by SLM requirements, added fixed delays for meters stabilization 2026-07-16 13:29:42 +02:00
marekf 0ce130f0ef Fix - repaired merging compatibility problem of GCI return type GciConnectResult - IsLoggedOn and IsConnected, increased VisualStudio version from 17.8 to 18.5 2026-07-16 12:37:59 +02:00
michal c1ee29cd06 Merge remote-tracking branch 'private-origin/develop/SLM-PT50_genesisDirectDecode' into develop/SLM-PT50_genesisDirectDecode 2026-07-16 12:28:36 +02:00
michal 28607e2729 fix Strings - Camera CJMS11 - support dialog multi pictures 2026-07-16 12:28:28 +02:00
michal f1bc71fb92 Camera CJMS11 - support dialog multi pictures 2026-07-16 12:19:27 +02:00
michal 69b607f963 Merge remote-tracking branch 'private-origin/develop/SLM-PT50_genesisDirectDecode' into develop/SLM-PT50_genesisDirectDecode
# Conflicts:
#	TBF/TBF.csproj
2026-07-16 10:28:15 +02:00
marekf 6ac3ea87ef Upgrade - improved StandingStartMassCollection method by SLM requirements, added fixed delays, added residual flow delays 2026-07-16 09:30:59 +02:00
marekf 38973e0030 Add - Store and log default PumpPower for dynamic test repetitions - Read PumpPower from the current pump before starting dynamic tests.
- Store the value as the default PumpPower for subsequent test instances in the cycle.
- Add logging when PumpPower is initialized from the pump.
- Add logging at test start including test name, repetition number,
  last repetition flag, and PumpPower to improve diagnostics.
2026-07-15 11:35:32 +02:00
marekf 37c89a4c9c Fix - missing safe shutdown when PerformSteps returns UiCmdStop
- When STOP is pressed during PerformSteps() in the BeforeTest transition,
Transition() returned immediately and skipped the common shutdown logic.
This caused FM pumps and valves to remain in their previous state.
- Perform the required safe shutdown (FM pump off and default valve setup)
before returning UiCmdStop or Error.
2026-07-14 14:41:53 +02:00
marekf 0075362f92 Fix - Handle scale underload condition
- Added Underload measurement state
- Detect underload responses from Mettler Toledo scales
- Automatically zero the scale after underload detection
- Restart mass measurement after successful zeroing
- Prevent zeroing response from being used as a valid measurement
- Preserve measurement stability by clearing buffered readings after underload
2026-07-13 14:01:57 +02:00
marekf 38d28599ad Merge branch 'develop/SLM-PT50_genesisDirectDecode' of http://87.197.120.129:33300/michal/tbf into develop/SLM-PT50 2026-07-03 13:37:26 +02:00
marekf c9a4b0f3ce Add (develop) - component ResultsWriter - added diag + english comments 2026-07-03 13:35:39 +02:00
marekf b74f1fd644 Add (develop) - first succesfull test - new component ResultsWriter - note: IResultsProcessor type componet, store result variables to database by using of component UniDataStorageWriter to the user-configured storage. The selection of variables is done using the standard UI for selecting the display of measurement results . In other words: The measurement results selected by the user are saved to a user-defined storage. 2026-07-03 12:46:56 +02:00
michal 26b7aa7e8b correction atempt MultiplyFactor for timestamp, volume calculation, 2026-07-02 23:53:15 +02:00
michal 92f63e744d fix INIT - Overload time fix for OptoTelegramRawTest 2026-07-02 23:24:00 +02:00
michal b0581d81ef Extend measurement window for low-flow tests 2026-07-02 23:08:28 +02:00
michal 540b9af871 Overload time fix for OptoTelegramRawTest 2026-07-02 22:32:19 +02:00
michal d11f7107fe fix time calculation from raw data 2026-07-02 21:49:01 +02:00
michal 3c5a28f69d changed LED state from 4 to 7 in 2026-07-02 21:47:14 +02:00
marekf 110b880304 Add (release) new component Modbus.WaterAnalyzerUni derived from original component Modbus.WaterAnalyzer. New component is expanded by the possibility to choose conductivity reading directly from the sensor (Modbus protocol) (original solution) or using a 4-20mA converter to serial line (RS232/485) (Modbus protocol). 2026-07-02 09:01:00 +02:00
marekf 7867044c0a Add (develop) new component ConductivityMeter, because we have papouch AD4RS converter (4-20mA to modbus) - first correct version for testing 2026-07-01 15:58:36 +02:00
marekf 88903f3dac Merge branch 'feature/task/Cordonel-preadjustmentUI-GenesisMeter-ZeroFlowGenesisMeter' into develop/UnionTown 2026-06-12 10:44:51 +02:00
marekf 4e223549ee Develop - GciBridge -> GCI -> PreadjustmentUI functions 7 - successful processes - testbench is exported to UnionTown - without CalibParams DB writer 2026-06-12 10:43:34 +02:00
marekf 2ea0df8faf Develop - GciBridge -> GCI -> create database core in GCI - SkeletoKey - CalibParams - first ok 2026-06-09 19:55:36 +02:00
marekf 061e85ca6b Develop - GciBridge -> GCI -> PreadjustmentUI functions 6 - first successful processes - without CalibParams DB reader and CalibParams DB writer 2026-06-09 08:53:54 +02:00
marekf 269e650b38 Merge branch 'feature/task/SWDocumentation-DocFX' into develop/UnionTown 2026-06-08 10:29:04 +02:00
marekf c2ff40d816 Develop - GCI - create documentation model 2, using DocFX tool - using .md files - output as html page 2026-06-02 07:26:36 +02:00
marekf eb09ae2eca Develop - GCI - create documentation model, using DocFX tool - using .md files - output as html page 2026-05-29 09:49:28 +02:00
960 changed files with 293880 additions and 10658 deletions
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Root Type="DevExpress.CodeRush.Foundation.CodePlaces.Options.FavoritesListContainer">
<Options Language="Neutral">
<Groups />
</Options>
</Root>
+2 -2
View File
@@ -8,7 +8,7 @@
<OutputType>WinExe</OutputType>
<RootNamespace>AppDiagnostic</RootNamespace>
<AssemblyName>AppDiagnostic</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
@@ -102,4 +102,4 @@
<None Include="Resources\TBF_icon.ico" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
</Project>
+3 -3
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.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>
@@ -9,7 +9,7 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Common</RootNamespace>
<AssemblyName>Common</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
@@ -114,4 +114,4 @@
<Target Name="AfterBuild">
</Target>
-->
</Project>
</Project>
+1 -1
View File
@@ -56,7 +56,7 @@ namespace Common.Iperl
public double Flow(double scalingFactor) { return 0.225 * scalingFactor * (double)FlowRaw; }
public double Volume(double scalingFactor) { return 0.0000625 * scalingFactor * (double)VolumeRawExt; }
public Int32 FlipTime() { return Impedance; }
public decimal TimestampDec() { return (decimal)TimestampExt / (decimal)8192; }
public decimal TimestampDec() { return (decimal)TimestampExt; }
public double VolumeDelta(double scalingFactor, OptoTelegramRaw previous) { return (previous == null) ? 0 : Volume(scalingFactor) - previous.Volume(scalingFactor); }
public decimal TimeDelta() { return TimestampDec() - TestStartTimestampDec; }
public string Label()
+55 -54
View File
@@ -2,6 +2,7 @@
/// Copyright (c) 2016-2021 Sensus Slovensko a.s.
///
using System;
using System.Linq;
namespace Common
{
@@ -286,97 +287,97 @@ namespace Common
public static bool IsQuantity(Unit unit, Quantity quantity)
{
return (quantity == GetQuantity(unit));
return GetQuantity(unit).Contains(quantity);
}
public static Quantity GetQuantity(Unit unit)
public static Quantity[] GetQuantity(Unit unit)
{
switch (unit)
{
case Unit.pulse:
case Unit.degree:
return Quantity.Pulses;
return new[] { Quantity.Pulses };
case Unit.ml:
return Quantity.Volume;
return new[] { Quantity.Volume, Quantity.MultiFunctionalVariables };
case Unit.l:
return Quantity.Volume;
return new[] { Quantity.Volume, Quantity.MultiFunctionalVariables };
case Unit.dm3:
return Quantity.Volume;
return new[] { Quantity.Volume, Quantity.MultiFunctionalVariables };
case Unit.USgal:
return Quantity.Volume;
return new[] { Quantity.Volume, Quantity.MultiFunctionalVariables };
case Unit.UKgal:
return Quantity.Volume;
return new[] { Quantity.Volume, Quantity.MultiFunctionalVariables };
case Unit.cf:
return Quantity.Volume;
return new[] { Quantity.Volume, Quantity.MultiFunctionalVariables };
case Unit.m3:
return Quantity.Volume;
return new[] { Quantity.Volume, Quantity.MultiFunctionalVariables };
case Unit.lph:
return Quantity.Flow;
return new[] { Quantity.Flow };
case Unit.cfph:
return Quantity.Flow;
return new[] { Quantity.Flow };
case Unit.lpm:
return Quantity.Flow;
return new[] { Quantity.Flow };
case Unit.USgalpm:
return Quantity.Flow;
return new[] { Quantity.Flow };
case Unit.m3ph:
return Quantity.Flow;
return new[] { Quantity.Flow };
case Unit.lps:
return Quantity.Flow;
return new[] { Quantity.Flow };
case Unit.USgalps:
return Quantity.Flow;
return new[] { Quantity.Flow };
case Unit.m3pm:
return Quantity.Flow;
return new[] { Quantity.Flow };
case Unit.cfs:
return Quantity.Flow;
return new[] { Quantity.Flow };
case Unit.gps:
return Quantity.MassFlow;
return new[] { Quantity.MassFlow};
case Unit.gpm:
return Quantity.MassFlow;
return new[] { Quantity.MassFlow};
case Unit.gph:
return Quantity.MassFlow;
return new[] { Quantity.MassFlow};
case Unit.kgps:
return Quantity.MassFlow;
return new[] { Quantity.MassFlow};
case Unit.kgpm:
return Quantity.MassFlow;
return new[] { Quantity.MassFlow};
case Unit.kgph:
return Quantity.MassFlow;
return new[] { Quantity.MassFlow};
case Unit.tps:
return Quantity.MassFlow;
return new[] { Quantity.MassFlow};
case Unit.tpm:
return Quantity.MassFlow;
return new[] { Quantity.MassFlow};
case Unit.tph:
return Quantity.MassFlow;
return new[] { Quantity.MassFlow};
case Unit.lbps:
return Quantity.MassFlow;
return new[] { Quantity.MassFlow};
case Unit.lbpm:
return Quantity.MassFlow;
return new[] { Quantity.MassFlow};
case Unit.lbph:
return Quantity.MassFlow;
return new[] { Quantity.MassFlow};
case Unit.g:
return Quantity.Mass;
return new[] { Quantity.Mass, Quantity.MultiFunctionalVariables };
case Unit.oz:
return Quantity.Mass;
return new[] { Quantity.Mass, Quantity.MultiFunctionalVariables };
case Unit.lb:
return Quantity.Mass;
return new[] { Quantity.Mass, Quantity.MultiFunctionalVariables };
case Unit.kg:
return Quantity.Mass;
return new[] { Quantity.Mass, Quantity.MultiFunctionalVariables };
case Unit.t:
return Quantity.Mass;
return new[] { Quantity.Mass, Quantity.MultiFunctionalVariables };
case Unit.ms:
case Unit.s:
case Unit.min:
case Unit.hour:
return Quantity.Time;
return new[] { Quantity.Time };
case Unit.C:
case Unit.F:
case Unit.K:
return Quantity.Temperature;
return new[] { Quantity.Temperature };
case Unit.Pa:
case Unit.hPa:
@@ -386,14 +387,14 @@ namespace Common
case Unit.psi:
case Unit.bar:
case Unit.MPa:
return Quantity.Pressure;
return new[] { Quantity.Pressure };
case Unit.RPct:
return Quantity.Humidity;
return new[] { Quantity.Humidity };
case Unit.Promile:
case Unit.Pct:
return Quantity.Error;
return new[] { Quantity.Error };
case Unit.mm:
case Unit.cm:
@@ -402,23 +403,23 @@ namespace Common
case Unit.foot:
case Unit.yard:
case Unit.m:
return Quantity.Length;
return new[] { Quantity.Length };
case Unit.kgpm3:
case Unit.kgpm3:
case Unit.kgpl:
return Quantity.Density;
return new[] { Quantity.Density };
case Unit.J:
case Unit.J:
case Unit.kJ:
case Unit.MJ:
case Unit.Wh:
case Unit.kWh:
case Unit.MWh:
return Quantity.Energy;
return new[] { Quantity.Energy };
case Unit.uSpcm:
case Unit.mSpm:
return Quantity.Conductivity;
return new[] { Quantity.Conductivity };
case Unit.ppl:
case Unit.ppdm3:
@@ -428,22 +429,22 @@ namespace Common
case Unit.dm3pp:
case Unit.lpdeg:
case Unit.dm3pdeg:
return Quantity.PulsePerLtr;
return new[] { Quantity.PulsePerLtr };
case Unit.ppkWh:
case Unit.kWhpp:
return Quantity.PulsePerKWh;
return new[] { Quantity.PulsePerKWh };
case Unit.A:
case Unit.mA:
return Quantity.Current;
return new[] { Quantity.Current };
case Unit.V:
case Unit.mV:
return Quantity.Voltage;
return new[] { Quantity.Voltage };
default:
return Quantity.Number;
return new[] { Quantity.Number };
}
}
+3 -3
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -10,7 +10,7 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Config</RootNamespace>
<AssemblyName>Config</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
@@ -150,4 +150,4 @@
<Target Name="AfterBuild">
</Target>
-->
</Project>
</Project>
+3 -3
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.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>
@@ -9,7 +9,7 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>DataMatrix4Net</RootNamespace>
<AssemblyName>DataMatrix4Net</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
@@ -58,4 +58,4 @@
<Target Name="AfterBuild">
</Target>
-->
</Project>
</Project>
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.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>
@@ -9,7 +9,7 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>DataStreamInterface</RootNamespace>
<AssemblyName>DataStreamInterface</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
@@ -61,4 +61,4 @@
<Target Name="AfterBuild">
</Target>
-->
</Project>
</Project>
+3 -3
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -10,7 +10,7 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Decrypt</RootNamespace>
<AssemblyName>Decrypt</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<TargetFrameworkProfile>
</TargetFrameworkProfile>
<FileAlignment>512</FileAlignment>
@@ -63,4 +63,4 @@
<Target Name="AfterBuild">
</Target>
-->
</Project>
</Project>
+3 -3
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -10,7 +10,7 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>DeviceTest</RootNamespace>
<AssemblyName>DeviceTest</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<TargetFrameworkProfile>
</TargetFrameworkProfile>
<FileAlignment>512</FileAlignment>
@@ -114,4 +114,4 @@
<Target Name="AfterBuild">
</Target>
-->
</Project>
</Project>
+16
View File
@@ -7,6 +7,22 @@
<assemblyIdentity name="NLog" publicKeyToken="5120e14c03d0593c" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="5.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.6.0" newVersion="4.0.6.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.2" newVersion="4.0.1.2" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Numerics.Vectors" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.4.0" newVersion="4.1.4.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
+3 -3
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -10,7 +10,7 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Dirichlet.Numerics</RootNamespace>
<AssemblyName>Dirichlet.Numerics</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile>
</TargetFrameworkProfile>
@@ -51,4 +51,4 @@
<Target Name="AfterBuild">
</Target>
-->
</Project>
</Project>
+3 -3
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -10,7 +10,7 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Encrypt</RootNamespace>
<AssemblyName>Encrypt</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<TargetFrameworkProfile>
</TargetFrameworkProfile>
<FileAlignment>512</FileAlignment>
@@ -63,4 +63,4 @@
<Target Name="AfterBuild">
</Target>
-->
</Project>
</Project>
+3 -3
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.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>
@@ -9,7 +9,7 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>EventViewer</RootNamespace>
<AssemblyName>EventViewer</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
@@ -142,4 +142,4 @@
<Target Name="AfterBuild">
</Target>
-->
</Project>
</Project>
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.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>
@@ -9,7 +9,7 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>FeatureVectorCalculator</RootNamespace>
<AssemblyName>FeatureVectorCalculator</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
@@ -97,4 +97,4 @@
<Target Name="AfterBuild">
</Target>
-->
</Project>
</Project>
+3 -3
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<PropertyGroup>
<ProjectType>Local</ProjectType>
@@ -28,7 +28,7 @@
<UpgradeBackupLocation>
</UpgradeBackupLocation>
<OldToolsVersion>3.5</OldToolsVersion>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
@@ -180,4 +180,4 @@
<PostBuildEvent>
</PostBuildEvent>
</PropertyGroup>
</Project>
</Project>
+3 -3
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="14.0">
<PropertyGroup>
<ProjectType>Local</ProjectType>
@@ -35,7 +35,7 @@
</FileUpgradeFlags>
<UpgradeBackupLocation>
</UpgradeBackupLocation>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<OldToolsVersion>2.0</OldToolsVersion>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
@@ -146,4 +146,4 @@
<PostBuildEvent>
</PostBuildEvent>
</PropertyGroup>
</Project>
</Project>
+3 -3
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -10,7 +10,7 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>GenericTest</RootNamespace>
<AssemblyName>GenericTest</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<TargetFrameworkProfile>
</TargetFrameworkProfile>
<FileAlignment>512</FileAlignment>
@@ -160,4 +160,4 @@
<Target Name="AfterBuild">
</Target>
-->
</Project>
</Project>
+16
View File
@@ -7,6 +7,22 @@
<assemblyIdentity name="NLog" publicKeyToken="5120e14c03d0593c" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="5.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.6.0" newVersion="4.0.6.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.2" newVersion="4.0.1.2" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Numerics.Vectors" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.4.0" newVersion="4.1.4.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
+17
View File
@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GenesisCordonelInterface.API
{
public class Enums
{
public enum DataStorageReaderTypes : sbyte
{
LoginPasswordsReader,
CalibrationParamsReader
}
}
}
@@ -42,7 +42,6 @@ namespace GenesisCordonelInterface.API
private readonly MeterBatch _meterBatch = new MeterBatch();
//Preadjustment
public PreAdjustmentSettingsContainer _settings = new PreAdjustmentSettingsContainer();
public ProcessProgress _progressProcess = new ProcessProgress();
public List<MeterStateControl> _meterControls = new List<MeterStateControl>();
public List<MeterStateControl> _tempMeterControls = new List<MeterStateControl>();
@@ -55,6 +54,11 @@ namespace GenesisCordonelInterface.API
private readonly ConcurrentDictionary<int, bool> _selectedSlots = new ConcurrentDictionary<int, bool>();
public InterfaceGCIToLaatzen()
{
}
#endregion
#region ================================== Worker ==================================
@@ -1592,22 +1596,30 @@ namespace GenesisCordonelInterface.API
IEnumerable<PublicModels.MeterBatchDebugStatus> selectedSlots,
CancellationToken token = default)
{
return Task.Run(() => Preadjustment_DetectCore(selectedSlots, token), token);
return Task.Run(() => Preadjustment_Detect(selectedSlots, token), token);
}
public PreadjustmentDetectResult PreAdjustment_DetectDirect(
IEnumerable<PublicModels.MeterBatchDebugStatus> selectedSlots,
CancellationToken token = default)
{
return Preadjustment_Detect(selectedSlots, token);
}
private PreadjustmentDetectResult Preadjustment_DetectCore(
private PreadjustmentDetectResult Preadjustment_Detect(
IEnumerable<PublicModels.MeterBatchDebugStatus> selectedSlots,
CancellationToken token)
CancellationToken token = default)
{
const string operation = nameof(Preadjustment_DetectCore);
const string operation = nameof(Preadjustment_Detect);
try
{
LogInfo(operation, "Start.");
MeterBatch globalMeterBatch = new MeterBatch();
MeterBatch thermoMeterBatch = new MeterBatch();
if (_settings == null)
throw new ArgumentNullException(nameof(_settings));
if (_progressProcess.Setting == null)
throw new ArgumentNullException(nameof(_progressProcess.Setting));
if (_meterControls == null)
throw new ArgumentNullException(nameof(_meterControls));
@@ -1624,7 +1636,7 @@ namespace GenesisCordonelInterface.API
globalMeterBatch = _meterBatch;
_meterControls = CreateMeterControls(selectedSlots);
if (!_settings.GetTempUseTempFlansh())
if (!_progressProcess.Setting.GetTempUseTempFlansh())
_tempMeterControls.Clear();
var allMeterControls = new List<MeterStateControl>();
@@ -1654,7 +1666,7 @@ namespace GenesisCordonelInterface.API
SetUnknownStatus(allMeterControls);
CheckTemperatureMeters(
_settings,
_progressProcess.Setting,
_tempMeterControls,
token);
@@ -1684,7 +1696,6 @@ namespace GenesisCordonelInterface.API
{
var ctl = new MeterStateControl(slot.Slot);
ctl.SetChecked(true);
ctl.IsEnabled = true;
controls.Add(ctl);
@@ -1818,11 +1829,16 @@ namespace GenesisCordonelInterface.API
token);
}
public PreAdjustmentProcessResult PreAdjustment_PreparationDirect()
{
return PreAdjustment_Preparation();
}
/// <summary>
/// Executes standalone preparation process.
/// </summary>
public PreAdjustmentProcessResult PreAdjustment_Preparation(
int slot)
int slot = -1)
{
const string operation = nameof(PreAdjustment_Preparation);
@@ -1830,9 +1846,6 @@ namespace GenesisCordonelInterface.API
{
LogInfo(operation, $"Start. Slot={slot}");
var meter = GetMeterThreadSafe(slot);
EnsureConnected(meter);
BaseProcess process = CreatePreparationProcess(_progressProcess);
bool success =
@@ -1891,6 +1904,17 @@ namespace GenesisCordonelInterface.API
PreAdjustmentControl.PredefinedMessages.PreparationFailed(pp.Setting.Culture),
60);
}
public bool PreAdjustment_PushCalibrationParams(double temperature)
{
if (_progressProcess != null)
{
_progressProcess.PushedTestBenchTemp = temperature;
_progressProcess.TempretureSelected = true;
return true;
}
return false;
}
#endregion
@@ -1904,8 +1928,13 @@ namespace GenesisCordonelInterface.API
token);
}
public PreAdjustmentProcessResult PreAdjustment_AmplitudeTestDirect()
{
return PreAdjustment_AmplitudeTest();
}
public PreAdjustmentProcessResult PreAdjustment_AmplitudeTest(
int slot)
int slot = -1)
{
const string operation = nameof(PreAdjustment_AmplitudeTest);
@@ -1913,9 +1942,6 @@ namespace GenesisCordonelInterface.API
{
LogInfo(operation, $"Start. Slot={slot}");
var meter = GetMeterThreadSafe(slot);
EnsureConnected(meter);
if (_progressProcess.Setting.TempOnly)
{
return new PreAdjustmentProcessResult
@@ -1992,19 +2018,19 @@ namespace GenesisCordonelInterface.API
token);
}
public PreAdjustmentProcessResult PreAdjustment_TemperatureCalibrationDirect()
{
return PreAdjustment_TemperatureCalibration();
}
public PreAdjustmentProcessResult PreAdjustment_TemperatureCalibration(
int slot)
int slot = -1)
{
const string operation = nameof(PreAdjustment_TemperatureCalibration);
try
{
LogInfo(operation, $"Start. Slot={slot}");
var meter =
GetMeterThreadSafe(slot);
EnsureConnected(meter);
LogInfo(operation, $"Start.");
BaseProcess process = CreateTemperatureCalibrationProcess(_progressProcess);
@@ -2039,6 +2065,18 @@ namespace GenesisCordonelInterface.API
}
}
public bool PreAdjustment_PushTemperature(double temperature)
{
if (_progressProcess != null)
{
_progressProcess.PushedTestBenchTemp = temperature;
_progressProcess.TempretureSelected = true;
return true;
}
return false;
}
/// <summary>
/// Creates temperature calibration process instance based on current configuration.
/// </summary>
@@ -2077,8 +2115,13 @@ namespace GenesisCordonelInterface.API
token);
}
public PreAdjustmentProcessResult PreAdjustment_OffsetTestDirect()
{
return PreAdjustment_OffsetTest();
}
public PreAdjustmentProcessResult PreAdjustment_OffsetTest(
int slot)
int slot = -1)
{
const string operation = nameof(PreAdjustment_OffsetTest);
@@ -2086,10 +2129,6 @@ namespace GenesisCordonelInterface.API
{
LogInfo(operation, $"Start. Slot={slot}");
var meter = GetMeterThreadSafe(slot);
EnsureConnected(meter);
if (_progressProcess.Setting.TempOnly)
{
return new PreAdjustmentProcessResult
@@ -2171,19 +2210,19 @@ namespace GenesisCordonelInterface.API
token);
}
public PreAdjustmentProcessResult PreAdjustment_CompletionDirect()
{
return PreAdjustment_Completion();
}
public PreAdjustmentProcessResult PreAdjustment_Completion(
int slot)
int slot = -1)
{
const string operation = nameof(PreAdjustment_Completion);
try
{
LogInfo(operation, $"Start. Slot={slot}");
var meter =
GetMeterThreadSafe(slot);
EnsureConnected(meter);
LogInfo(operation, $"Start.");
BaseProcess process = CreateCompletionProcess(_progressProcess);
@@ -1,11 +1,16 @@
using CordonelPreadjustmentUi;
using CordonelPreadjustmentUi.Processes.Itinerary;
using GenesisCordonelInterface.Core.DataStorage.Config;
using GenesisCordonelInterface.Core.DataStorage.Reading.Common.Models;
using GenesisCordonelInterface.Core.DataStorage.Reading.Implementation.MeterLoginPasswords;
using GenesisCordonelInterface.Core.DataStorage.Reading.Implementation.PreAdjustmentCalibrationParams;
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Threading;
using System.Threading.Tasks;
using Xylem.Common.Hardware.WaterMeter.WaterMeterCore;
using Xylem.Common.Logic.ProductionOrderCore.OrderData;
using Xylem.Common.Ui.CordonelPreadjustmentUi;
using static GenesisCordonelInterface.API.PublicModels;
@@ -35,13 +40,55 @@ namespace GenesisCordonelInterface.API
/// Occurs when meter batch status information changes.
/// </summary>
public event Action<List<MeterBatchDebugStatus>> MeterBatchStatusChanged;
private readonly IMeterLoginPasswordReader loginPasswordsReader;
private readonly IPreAdjustmentCalibrationParamsReader calibrationParamsReader;
/// <summary>
/// Initializes a new instance of the public GCI facade.
/// </summary>
public InterfaceOutsideToGCI()
{
_innerMeterAPI = new InterfaceGCIToLaatzen();
}
/// <summary>
/// Initializes a new instance of the public GCI facade.
/// </summary>
public InterfaceOutsideToGCI(
InterfaceGCIToLaatzen innerMeterApi,
IMeterLoginPasswordReader passwordReader,
IPreAdjustmentCalibrationParamsReader calibrationReader)
{
_innerMeterAPI = innerMeterApi?? throw new ArgumentNullException(nameof(innerMeterApi));
loginPasswordsReader = passwordReader ?? throw new ArgumentNullException(nameof(passwordReader));
calibrationParamsReader = calibrationReader ?? throw new ArgumentNullException(nameof(calibrationReader));
//init handlers
//_innerMeterAPI._progressProcess.OnRequestedCalibrationParamsFromDb += RequestedCalibrationParamsFromDb;
}
private async void RequestedCalibrationParamsFromDb(
object sender,
EventArgsProcessProgress e)
{
try
{
DataQuery query = new DataQuery();
query.QueryParams.Add(((int)e.Value.Setting.MeterSize).ToString());
Dictionary<string, UInt32> calibrationParams = await ReadPreAdjustmentCalibrationParamsAsync(query).ConfigureAwait(false);
e.Value.PushedCalibrationParams = calibrationParams;
}
catch (Exception ex)
{
e.Value.DebugMessage(
$"Calibration params reading failed: {ex.Message}");
}
finally
{
e.Value.CalibrationParamsReadEvent.Set();
}
}
// Laatzen ToolBox actions
@@ -50,7 +97,7 @@ namespace GenesisCordonelInterface.API
public PortDetectionResult DetectStreamingPort(int slot)
{
var result = _innerMeterAPI.DetectStreamingPort(slot);
var result = _innerMeterAPI?.DetectStreamingPort(slot);
//RaiseMeterBatchStatusChanged();
return result;
}
@@ -59,14 +106,14 @@ namespace GenesisCordonelInterface.API
int slot,
CancellationToken token = default(CancellationToken))
{
var result = await _innerMeterAPI.DetectStreamingPortAsync(slot, token);
var result = await _innerMeterAPI?.DetectStreamingPortAsync(slot, token);
//RaiseMeterBatchStatusChanged();
return result;
}
public PortDetectionResult DetectRequestPort(int slot)
{
var result = _innerMeterAPI.DetectRequestPort(slot);
var result = _innerMeterAPI?.DetectRequestPort(slot);
//RaiseMeterBatchStatusChanged();
return result;
}
@@ -75,7 +122,7 @@ namespace GenesisCordonelInterface.API
int slot,
CancellationToken token = default(CancellationToken))
{
var result = await _innerMeterAPI.DetectRequestPortAsync(slot, token);
var result = await _innerMeterAPI?.DetectRequestPortAsync(slot, token);
//RaiseMeterBatchStatusChanged();
return result;
}
@@ -484,6 +531,7 @@ namespace GenesisCordonelInterface.API
return result;
}
#endregion
#region ================================== DEBUG STATUS ==================================
@@ -497,7 +545,7 @@ namespace GenesisCordonelInterface.API
/// </returns>
public List<WorkerDebugStatus> GetWorkerDebugStatuses()
{
return _innerMeterAPI.GetWorkerDebugStatuses();
return _innerMeterAPI?.GetWorkerDebugStatuses();
}
/// <summary>
@@ -509,7 +557,7 @@ namespace GenesisCordonelInterface.API
/// </returns>
public List<MeterBatchDebugStatus> GetMeterBatchDebugStatuses()
{
return _innerMeterAPI.GetMeterBatchDebugStatuses();
return _innerMeterAPI?.GetMeterBatchDebugStatuses();
}
/// <summary>
@@ -538,7 +586,7 @@ namespace GenesisCordonelInterface.API
/// <param name="selected">Selection state.</param>
public void SetSlotSelected(int slot, bool selected)
{
_innerMeterAPI.SetSlotSelected(slot, selected);
_innerMeterAPI?.SetSlotSelected(slot, selected);
RaiseMeterBatchStatusChanged();
}
@@ -551,7 +599,7 @@ namespace GenesisCordonelInterface.API
/// </returns>
public bool IsSlotSelected(int slot)
{
return _innerMeterAPI.IsSlotSelected(slot);
return (bool)(_innerMeterAPI?.IsSlotSelected(slot));
}
/// <summary>
@@ -562,7 +610,7 @@ namespace GenesisCordonelInterface.API
/// </returns>
public List<int> GetSelectedSlots()
{
return _innerMeterAPI.GetSelectedSlots();
return _innerMeterAPI?.GetSelectedSlots();
}
#endregion
@@ -577,7 +625,7 @@ namespace GenesisCordonelInterface.API
/// </returns>
public List<string> GetAllRegisterNames()
{
return _innerMeterAPI.GetAllRegisterNames();
return _innerMeterAPI?.GetAllRegisterNames();
}
#endregion
@@ -589,7 +637,10 @@ namespace GenesisCordonelInterface.API
ProcessProgress pp,
List<MeterStateControl> mc)
{
return _innerMeterAPI.Preadjustment_Initialization(pp, mc);
//init handlers
pp.OnRequestedCalibrationParamsFromDb += RequestedCalibrationParamsFromDb;
return _innerMeterAPI?.Preadjustment_Initialization(pp, mc);
}
public Task<PreadjustmentDetectResult> PreAdjustment_DetectAsync(
@@ -599,6 +650,13 @@ namespace GenesisCordonelInterface.API
return _innerMeterAPI.PreAdjustment_DetectAsync(selectedSlots, token);
}
public PreadjustmentDetectResult PreAdjustment_DetectDirect(
IEnumerable<PublicModels.MeterBatchDebugStatus> selectedSlots,
CancellationToken token = default)
{
return _innerMeterAPI.PreAdjustment_DetectDirect(selectedSlots, token);
}
public Task<PreAdjustmentProcessResult> PreAdjustment_PreparationAsync(
int slot,
CancellationToken token = default)
@@ -606,6 +664,11 @@ namespace GenesisCordonelInterface.API
return _innerMeterAPI.PreAdjustment_PreparationAsync(slot, token);
}
public PreAdjustmentProcessResult PreAdjustment_PreparationDirect()
{
return _innerMeterAPI.PreAdjustment_PreparationDirect();
}
public Task<PreAdjustmentProcessResult> PreAdjustment_AmplitudeTestAsync(
int slot,
CancellationToken token = default)
@@ -613,6 +676,11 @@ namespace GenesisCordonelInterface.API
return _innerMeterAPI.PreAdjustment_AmplitudeTestAsync(slot, token);
}
public PreAdjustmentProcessResult PreAdjustment_AmplitudeTestDirect()
{
return _innerMeterAPI.PreAdjustment_AmplitudeTestDirect();
}
public Task<PreAdjustmentProcessResult> PreAdjustment_TemperatureCalibrationAsync(
int slot,
CancellationToken token = default)
@@ -620,6 +688,17 @@ namespace GenesisCordonelInterface.API
return _innerMeterAPI.PreAdjustment_TemperatureCalibrationAsync(slot, token);
}
public PreAdjustmentProcessResult PreAdjustment_TemperatureCalibrationDirect()
{
return _innerMeterAPI.PreAdjustment_TemperatureCalibrationDirect();
}
public bool PreAdjustment_PushTemperature(
double temperature)
{
return _innerMeterAPI.PreAdjustment_PushTemperature(temperature);
}
public Task<PreAdjustmentProcessResult> PreAdjustment_OffsetTestAsync(
int slot,
CancellationToken token = default)
@@ -627,6 +706,11 @@ namespace GenesisCordonelInterface.API
return _innerMeterAPI.PreAdjustment_OffsetTestAsync(slot, token);
}
public PreAdjustmentProcessResult PreAdjustment_OffsetTestDirect()
{
return _innerMeterAPI.PreAdjustment_OffsetTestDirect();
}
public Task<PreAdjustmentProcessResult> PreAdjustment_CompletionAsync(
int slot,
CancellationToken token = default)
@@ -634,6 +718,68 @@ namespace GenesisCordonelInterface.API
return _innerMeterAPI.PreAdjustment_CompletionAsync(slot, token);
}
public PreAdjustmentProcessResult PreAdjustment_CompletionDirect()
{
return _innerMeterAPI.PreAdjustment_CompletionDirect();
}
#endregion
#region ================================== UNI DATA STORAGE READER ==================================
//LoginPasswords reading
/// <summary>
/// Reads meter login password from configured GCI data storage.
/// </summary>
/// <param name="query">
/// Data query containing PCB ID or another configured lookup value.
/// </param>
/// <param name="token">
/// Cancellation token used to cancel the asynchronous operation.
/// </param>
/// <returns>
/// Password if found; otherwise null.
/// </returns>
public Task<string> ReadMeterLoginPasswordAsync(
DataQuery query,
CancellationToken token = default)
{
return loginPasswordsReader.ReadMeterLoginPasswordAsync(
query,
token);
}
//CalibrationParams reading
/// <summary>
/// Reads pre-adjustment calibration parameters
/// from configured GCI data storage.
/// </summary>
/// <param name="query">
/// Data query containing meter size or another configured lookup value.
/// </param>
/// <param name="token">
/// Cancellation token used to cancel the asynchronous operation.
/// </param>
/// <returns>
/// Dictionary:
///
/// Key:
/// Calibration parameter name
///
/// Value:
/// Calibration parameter value
/// </returns>
public Task<Dictionary<string, UInt32>> ReadPreAdjustmentCalibrationParamsAsync(
DataQuery query,
CancellationToken token = default)
{
return calibrationParamsReader.ReadCalibrationParamsAsync(
query,
token);
}
#endregion
}
}
@@ -1,5 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Xylem.Common.Hardware.Interfaces.Ports.PortCore;
using static GenesisCordonelInterface.API.InterfaceOutsideToGCI;
using static Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore.GenesisMeter;
namespace GenesisCordonelInterface.API
{
@@ -21,15 +21,16 @@
"PreAdjustmentCalibrationParams": {
"___Documentation___": {
"Description": "Reads pre-adjustment values from CSV",
"DataSource": "Relative path resolved from application directory",
"QueryTemplate": "CSV/JSON syntax: SELECT [ReturnColumn] WHERE [MatchColumn]=QUERYPARAM or SELECT COLUMN(1) WHERE COLUMN(0)=QUERYPARAM"
"Description": "Reads pre-adjustment calibration parameters by meter size",
"Type": "Supported: LocalDatabase, RemoteDatabase, LocalCsv, LocalJson, RestApi",
"DataSource": "Database connection string",
"QueryTemplate": "QUERYPARAM is placeholder for runtime value. Example: WHERE [MeterSize]=QUERYPARAM -> meter size provided during ReadCalibrationParamsAsync()."
},
"Name": "PreAdjustmentCalibrationParams",
"Type": "LocalCsv",
"DataSource": "Data\\preadjustment_params.csv",
"QueryTemplate": "SELECT [Offset] WHERE [PcbId] = QUERYPARAM"
"Type": "LocalDatabase",
"DataSource": "Server=(localdb)\\MojaDB;Database=UnionTownCalibAndSkeleton;Integrated Security=True;",
"QueryTemplate": "SELECT [ParameterName], [ParameterValue] FROM [dbo].[PreAdjustmentCalibrationParams] WHERE [MeterSize] = QUERYPARAM"
}
}
}
@@ -0,0 +1,32 @@
namespace GenesisCordonelInterface.Core.Config
{
/// <summary>
/// Root GCI configuration object loaded from gci_config.json.
///
/// This class represents the top-level configuration structure
/// and serves as an entry point for all configurable GCI features.
///
/// Example:
///
/// {
/// "DataStorageSection":
/// {
/// ...
/// }
/// }
/// </summary>
public class GciConfig
{
/// <summary>
/// Data storage configuration section.
///
/// Contains definitions for all configured readers and writers,
/// such as:
///
/// - MeterLoginPasswords
/// - PreAdjustmentCalibrationParams
/// - future storage providers
/// </summary>
public DataStorage.Config.GciDataStorageConfig DataStorageSection { get; set; }
}
}
@@ -0,0 +1,177 @@
using System;
using System.IO;
using GenesisCordonelInterface.Core.DataStorage.Reading.Common;
using GenesisCordonelInterface.Core.DataStorage.Reading.Common.Models;
using Newtonsoft.Json;
namespace GenesisCordonelInterface.Core.Config
{
/// <summary>
/// Loads GCI configuration from gci_config.json.
///
/// Responsibilities:
/// - Locate configuration file
/// - Deserialize JSON into strongly typed objects
/// - Normalize relative file paths
/// - Preserve database connection strings and REST URLs
///
/// Example:
///
/// Config/
/// gci_config.json
///
/// Data/
/// meter_passwords.csv
///
/// Relative paths:
/// Data\file.csv
///
/// become:
///
/// C:\App\bin\Debug\Data\file.csv
///
/// Database sources remain unchanged:
///
/// Server=(localdb)\MojaDB;Database=...
/// </summary>
public static class GciConfigLoader
{
/// <summary>
/// Loads default GCI configuration from:
///
/// Config\gci_config.json
/// </summary>
/// <returns>
/// Loaded GCI configuration.
/// </returns>
public static GciConfig LoadDefault()
{
string baseDirectory = AppDomain.CurrentDomain.BaseDirectory;
string configPath = Path.Combine(
baseDirectory,
"Config",
"gci_config.json");
return Load(configPath, baseDirectory);
}
/// <summary>
/// Loads GCI configuration from specified file.
/// </summary>
/// <param name="configPath">
/// Path to configuration json file.
/// </param>
/// <param name="baseDirectory">
/// Base directory used for resolving relative paths.
/// </param>
/// <returns>
/// Loaded configuration object.
/// </returns>
public static GciConfig Load(
string configPath,
string baseDirectory = null)
{
if (string.IsNullOrWhiteSpace(configPath))
throw new ArgumentException(
"Config path must not be empty.",
nameof(configPath));
if (!File.Exists(configPath))
throw new FileNotFoundException(
"GCI config file was not found.",
configPath);
string json = File.ReadAllText(configPath);
GciConfig config =
JsonConvert.DeserializeObject<GciConfig>(json);
if (config == null)
throw new InvalidOperationException(
"GCI config could not be loaded.");
NormalizeDataStoragePaths(
config,
baseDirectory ?? Path.GetDirectoryName(configPath));
return config;
}
/// <summary>
/// Normalizes paths for all configured data storage entries.
///
/// Converts relative file paths into absolute paths.
/// Database connection strings remain untouched.
/// </summary>
/// <param name="config">
/// Loaded configuration object.
/// </param>
/// <param name="baseDirectory">
/// Base path used for relative resolution.
/// </param>
private static void NormalizeDataStoragePaths(
GciConfig config,
string baseDirectory)
{
if (config.DataStorageSection == null)
return;
NormalizePath(
config.DataStorageSection.MeterLoginPasswords,
baseDirectory);
NormalizePath(
config.DataStorageSection.PreAdjustmentCalibrationParams,
baseDirectory);
}
/// <summary>
/// Converts relative file paths into absolute paths.
///
/// Applies only to:
/// - LocalCsv
/// - RemoteCsv
/// - LocalJson
/// - RemoteJson
///
/// Does not modify:
/// - Database connection strings
/// - REST URLs
/// </summary>
/// <param name="storageConfig">
/// Storage configuration.
/// </param>
/// <param name="baseDirectory">
/// Base path for resolution.
/// </param>
private static void NormalizePath(
DataStorageConfig storageConfig,
string baseDirectory)
{
if (storageConfig == null)
return;
if (string.IsNullOrWhiteSpace(storageConfig.DataSource))
return;
// Database connection strings and URLs
// must never be treated as file paths.
if (storageConfig.Type == DataStorageType.LocalDatabase ||
storageConfig.Type == DataStorageType.RemoteDatabase ||
storageConfig.Type == DataStorageType.RestApi)
{
return;
}
if (Path.IsPathRooted(storageConfig.DataSource))
return;
storageConfig.DataSource =
Path.GetFullPath(
Path.Combine(
baseDirectory,
storageConfig.DataSource));
}
}
}
@@ -0,0 +1,36 @@
{
"_Comment": "GCI DataStorage configuration",
"DataStorageSection": {
"MeterLoginPasswords": {
"___Documentation___": {
"Description": "Reads login passwords for meters by PCB ID",
"Type": "Supported: LocalDatabase, RemoteDatabase, LocalCsv, LocalJson, RestApi",
"DataSource": "Database connection string",
"QueryTemplate": "QUERYPARAM is placeholder for runtime value. Example: WHERE [PcbId]=QUERYPARAM -> PCB ID provided during GetPasswordAsync()."
},
"Name": "MeterLoginPasswords",
"Type": "LocalDatabase",
"DataSource": "Server=(localdb)\\SensusLocalDB;Database=UnionTownCalibAndSkeleton;Integrated Security=True;",
"QueryTemplate": "SELECT [Password] FROM [dbo].[SkeletonKeys] WHERE [PcbId] = QUERYPARAM"
},
"PreAdjustmentCalibrationParams": {
"___Documentation___": {
"Description": "Reads pre-adjustment calibration parameters by meter size",
"Type": "Supported: LocalDatabase, RemoteDatabase, LocalCsv, LocalJson, RestApi",
"DataSource": "Database connection string",
"QueryTemplate": "QUERYPARAM is placeholder for runtime value. Example: WHERE [MeterSize]=QUERYPARAM -> meter size provided during ReadCalibrationParamsAsync()."
},
"Name": "PreAdjustmentCalibrationParams",
"Type": "LocalDatabase",
"DataSource": "Server=(localdb)\\SensusLocalDB;Database=UnionTownCalibAndSkeleton;Integrated Security=True;",
"QueryTemplate": "SELECT [ParameterName], [ParameterValue] FROM [dbo].[PreAdjustmentCalibrationParams] WHERE [MeterSize] = QUERYPARAM"
}
}
}
@@ -46,5 +46,17 @@ namespace GenesisCordonelInterface.Core.DataStorage.Reading.Common.Models
/// WHERE [PcbId]=QUERYPARAM
/// </summary>
public string QueryTemplate { get; set; }
public DataStorageConfig(
string name,
DataStorageType type,
string dataSource,
string queryTemplate)
{
Name = name;
Type = type;
DataSource = dataSource;
QueryTemplate = queryTemplate;
}
}
}
@@ -2,17 +2,52 @@
namespace GenesisCordonelInterface.Core.DataStorage.Reading.Common.Models
{
public class DatabaseSearchResult
/// <summary>
/// Represents result returned by database-based
/// data storage readers.
///
/// Supports both:
///
/// - Single-row lookups
/// (e.g. MeterLoginPasswords)
///
/// - Multi-row queries
/// (e.g. PreAdjustmentCalibrationParams)
/// </summary>
internal class DatabaseSearchResult
{
/// <summary>
/// Indicates whether at least one record
/// was found.
/// </summary>
public bool Found { get; set; }
/// <summary>
/// Executed SQL query text.
/// Mainly intended for diagnostics
/// and troubleshooting.
/// </summary>
public string Query { get; set; }
public Dictionary<string, object> Values { get; set; }
/// <summary>
/// First returned row represented as
/// column/value pairs.
///
/// Preserved for backward compatibility
/// with existing readers expecting
/// a single database record.
/// </summary>
public Dictionary<string, object> Values { get; }
= new Dictionary<string, object>();
public DatabaseSearchResult()
{
Values = new Dictionary<string, object>();
}
/// <summary>
/// All returned rows represented as
/// a collection of column/value dictionaries.
///
/// Intended for queries returning
/// multiple records.
/// </summary>
public List<Dictionary<string, object>> Rows { get; }
= new List<Dictionary<string, object>>();
}
}
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using GenesisCordonelInterface.Core.DataStorage.Reading.Common.Models;
@@ -14,76 +15,152 @@ namespace GenesisCordonelInterface.Core.DataStorage.Reading.Common.Providers
/// QueryTemplate must contain QUERYPARAM placeholder.
///
/// Example:
/// SELECT [Password] FROM [dbo].[SkeletonKeys] WHERE [PcbId] = QUERYPARAM
///
/// The placeholder is internally converted to SQL parameter @value.
/// SELECT [Password]
/// FROM [dbo].[SkeletonKeys]
/// WHERE [PcbId] = QUERYPARAM
///
/// or
///
/// SELECT [ParameterName], [ParameterValue]
/// FROM [dbo].[PreAdjustmentCalibrationParams]
/// WHERE [Dn_InternalId] = QUERYPARAM
///
/// The placeholder is internally converted
/// to SQL parameter @value.
///
/// Supports both:
///
/// - Single-row lookups
/// - Multi-row result sets
/// </summary>
public class DatabaseDataStorageReader : IDataStorageReader
{
/// <summary>
/// Data storage configuration containing connection string and query template.
/// Data storage configuration containing
/// connection string and query template.
/// </summary>
private readonly DataStorageConfig config;
/// <summary>
/// Creates SQL Server data storage reader using provided configuration.
/// Creates SQL Server data storage reader
/// using provided configuration.
/// </summary>
/// <param name="config">
/// Data storage configuration loaded from gci_config.json.
/// Data storage configuration loaded
/// from gci_config.json.
/// </param>
public DatabaseDataStorageReader(DataStorageConfig config)
public DatabaseDataStorageReader(
DataStorageConfig config)
{
this.config = config ?? throw new ArgumentNullException(nameof(config));
this.config =
config ?? throw new ArgumentNullException(nameof(config));
}
/// <summary>
/// Executes configured SQL query and returns first matching row.
/// Executes configured SQL query and returns
/// matching database records.
///
/// Single-row queries populate:
/// DatabaseSearchResult.Values
///
/// Multi-row queries populate:
/// DatabaseSearchResult.Rows
///
/// For backward compatibility, the first row
/// is also stored in Values.
/// </summary>
/// <param name="query">
/// Query object containing lookup parameter.
/// </param>
/// <returns>
/// DatabaseSearchResult containing returned SQL columns and values.
/// DatabaseSearchResult containing returned
/// database records.
///
/// Values contains the first returned row.
///
/// Rows contains the complete result set.
/// </returns>
public object GetData(DataQuery query)
{
if (query == null)
throw new ArgumentNullException(nameof(query));
ReaderDiagnosticResult sourceResult = TestSource(true);
ReaderDiagnosticResult sourceResult =
TestSource(true);
if (!sourceResult.Success)
throw new InvalidOperationException(sourceResult.Message);
string sqlText = PrepareSqlText(config.QueryTemplate);
object queryValue = ExtractQueryValue(query);
string sqlText =
PrepareSqlText(config.QueryTemplate);
using (SqlConnection connection = new SqlConnection(config.DataSource))
using (SqlCommand command = new SqlCommand(sqlText, connection))
object queryValue =
ExtractQueryValue(query);
using (SqlConnection connection =
new SqlConnection(config.DataSource))
using (SqlCommand command =
new SqlCommand(sqlText, connection))
{
AddQueryParameter(command, queryValue);
connection.Open();
using (SqlDataReader reader = command.ExecuteReader(CommandBehavior.SingleRow))
// Full result set is required because some
// storage definitions return multiple records
// (e.g. PreAdjustmentCalibrationParams).
using (SqlDataReader reader =
command.ExecuteReader())
{
DatabaseSearchResult result = new DatabaseSearchResult
{
Query = sqlText
};
DatabaseSearchResult result =
new DatabaseSearchResult
{
Query = sqlText
};
if (!reader.Read())
while (reader.Read())
{
result.Found = false;
return result;
result.Found = true;
// Represents one database row.
Dictionary<string, object> row =
new Dictionary<string, object>();
for (int i = 0; i < reader.FieldCount; i++)
{
object value =
reader.GetValue(i);
object normalizedValue =
value == DBNull.Value
? null
: value;
row[reader.GetName(i)] =
normalizedValue;
}
// Preserve first row for legacy consumers
// expecting a single returned database record
// (e.g. MeterLoginPasswordReader).
if (result.Rows.Count == 0)
{
foreach (var item in row)
{
result.Values[item.Key] =
item.Value;
}
}
// Store complete database result set.
result.Rows.Add(row);
}
result.Found = true;
for (int i = 0; i < reader.FieldCount; i++)
if (result.Rows.Count == 0)
{
object value = reader.GetValue(i);
result.Values[reader.GetName(i)] =
value == DBNull.Value ? null : value;
result.Found = false;
}
return result;
@@ -92,7 +169,8 @@ namespace GenesisCordonelInterface.Core.DataStorage.Reading.Common.Providers
}
/// <summary>
/// Tests whether SQL Server connection can be opened.
/// Tests whether SQL Server connection
/// can be opened.
/// </summary>
/// <param name="enableDiagnostics">
/// Enables detailed diagnostic output.
@@ -100,45 +178,70 @@ namespace GenesisCordonelInterface.Core.DataStorage.Reading.Common.Providers
/// <returns>
/// Diagnostic result of SQL connection test.
/// </returns>
public ReaderDiagnosticResult TestSource(bool enableDiagnostics)
public ReaderDiagnosticResult TestSource(
bool enableDiagnostics)
{
ReaderDiagnosticResult result = new ReaderDiagnosticResult();
ReaderDiagnosticResult result =
new ReaderDiagnosticResult();
try
{
if (string.IsNullOrWhiteSpace(config.DataSource))
throw new InvalidOperationException("Data source is empty.");
{
throw new InvalidOperationException(
"Data source is empty.");
}
Log(result, enableDiagnostics, "Opening SQL connection.");
Log(
result,
enableDiagnostics,
"Opening SQL connection.");
using (SqlConnection connection = new SqlConnection(config.DataSource))
using (SqlConnection connection =
new SqlConnection(config.DataSource))
{
connection.Open();
Log(result, enableDiagnostics, "Connection opened successfully.");
Log(
result,
enableDiagnostics,
"Connection opened successfully.");
using (SqlCommand command = new SqlCommand("SELECT 1", connection))
using (SqlCommand command =
new SqlCommand("SELECT 1", connection))
{
object value = command.ExecuteScalar();
Log(result, enableDiagnostics, "Test query result: " + value);
object value =
command.ExecuteScalar();
Log(
result,
enableDiagnostics,
"Test query result: " + value);
}
}
result.Success = true;
result.Message = "Connection to SQL Server OK.";
result.Message =
"Connection to SQL Server OK.";
}
catch (Exception ex)
{
result.Success = false;
result.Message = "Failed to connect to SQL Server. " + ex.Message;
Log(result, enableDiagnostics, ex.ToString());
result.Message =
"Failed to connect to SQL Server. " + ex.Message;
Log(
result,
enableDiagnostics,
ex.ToString());
}
return result;
}
/// <summary>
/// Tests whether configured SQL query can be prepared and executed.
/// Tests whether configured SQL query
/// can be prepared and executed.
/// </summary>
/// <param name="enableDiagnostics">
/// Enables detailed diagnostic output.
@@ -146,16 +249,22 @@ namespace GenesisCordonelInterface.Core.DataStorage.Reading.Common.Providers
/// <returns>
/// Diagnostic result of query execution test.
/// </returns>
public ReaderDiagnosticResult TestQuery(bool enableDiagnostics)
public ReaderDiagnosticResult TestQuery(
bool enableDiagnostics)
{
ReaderDiagnosticResult result = new ReaderDiagnosticResult();
ReaderDiagnosticResult result =
new ReaderDiagnosticResult();
try
{
if (string.IsNullOrWhiteSpace(config.QueryTemplate))
throw new InvalidOperationException("Query template is empty.");
{
throw new InvalidOperationException(
"Query template is empty.");
}
string sqlText = PrepareSqlText(config.QueryTemplate);
string sqlText =
PrepareSqlText(config.QueryTemplate);
Log(result, enableDiagnostics, "Original template:");
Log(result, enableDiagnostics, config.QueryTemplate);
@@ -163,69 +272,91 @@ namespace GenesisCordonelInterface.Core.DataStorage.Reading.Common.Providers
Log(result, enableDiagnostics, "Prepared SQL:");
Log(result, enableDiagnostics, sqlText);
using (SqlConnection connection = new SqlConnection(config.DataSource))
using (SqlCommand command = new SqlCommand(sqlText, connection))
using (SqlConnection connection =
new SqlConnection(config.DataSource))
using (SqlCommand command =
new SqlCommand(sqlText, connection))
{
AddQueryParameter(command, "TEST");
connection.Open();
object value = command.ExecuteScalar();
object value =
command.ExecuteScalar();
result.Data = value;
Log(result, enableDiagnostics, "Query executed successfully.");
Log(
result,
enableDiagnostics,
"Query executed successfully.");
}
result.Success = true;
result.Message = "Query executed successfully.";
result.Message =
"Query executed successfully.";
}
catch (Exception ex)
{
result.Success = false;
result.Message = "Query execution failed. " + ex.Message;
Log(result, enableDiagnostics, ex.ToString());
result.Message =
"Query execution failed. " + ex.Message;
Log(
result,
enableDiagnostics,
ex.ToString());
}
return result;
}
/// <summary>
/// Converts configured QueryTemplate to executable SQL text.
/// Converts configured QueryTemplate
/// to executable SQL text.
/// </summary>
/// <param name="queryTemplate">
/// SQL query template containing QUERYPARAM placeholder.
/// SQL query template containing
/// QUERYPARAM placeholder.
/// </param>
/// <returns>
/// SQL text with QUERYPARAM replaced by @value parameter.
/// SQL text with QUERYPARAM replaced
/// by @value parameter.
/// </returns>
private static string PrepareSqlText(string queryTemplate)
private static string PrepareSqlText(
string queryTemplate)
{
if (string.IsNullOrWhiteSpace(queryTemplate))
{
throw new ArgumentException(
"Query template must not be empty.",
nameof(queryTemplate));
}
if (!queryTemplate.Contains("QUERYPARAM"))
{
throw new InvalidOperationException(
"Query template must contain QUERYPARAM placeholder.");
}
return queryTemplate.Replace("QUERYPARAM", "@value");
return queryTemplate.Replace(
"QUERYPARAM",
"@value");
}
/// <summary>
/// Extracts first query parameter value.
/// </summary>
/// <param name="query">
/// Data query containing query parameters.
/// </param>
/// <returns>
/// First query parameter value.
/// </returns>
private static object ExtractQueryValue(DataQuery query)
private static object ExtractQueryValue(
DataQuery query)
{
if (query.QueryParams == null || query.QueryParams.Count == 0)
if (query.QueryParams == null ||
query.QueryParams.Count == 0)
{
throw new InvalidOperationException(
"DataQuery does not contain any query parameter.");
}
return query.QueryParams[0];
}
@@ -233,32 +364,25 @@ namespace GenesisCordonelInterface.Core.DataStorage.Reading.Common.Providers
/// <summary>
/// Adds lookup parameter to SQL command.
/// </summary>
/// <param name="command">
/// SQL command.
/// </param>
/// <param name="value">
/// Query parameter value.
/// </param>
private static void AddQueryParameter(SqlCommand command, object value)
private static void AddQueryParameter(
SqlCommand command,
object value)
{
command.Parameters.Clear();
SqlParameter parameter = command.Parameters.Add("@value", SqlDbType.Variant);
parameter.Value = value ?? DBNull.Value;
SqlParameter parameter =
command.Parameters.Add(
"@value",
SqlDbType.Variant);
parameter.Value =
value ?? DBNull.Value;
}
/// <summary>
/// Adds diagnostic line when diagnostics are enabled.
/// Adds diagnostic line when diagnostics
/// are enabled.
/// </summary>
/// <param name="result">
/// Diagnostic result object.
/// </param>
/// <param name="enableDiagnostics">
/// Indicates whether diagnostics are enabled.
/// </param>
/// <param name="message">
/// Diagnostic message.
/// </param>
private static void Log(
ReaderDiagnosticResult result,
bool enableDiagnostics,
@@ -1,4 +1,5 @@
using System.Threading;
using GenesisCordonelInterface.Core.DataStorage.Reading.Common.Models;
using System.Threading;
using System.Threading.Tasks;
namespace GenesisCordonelInterface.Core.DataStorage.Reading.Implementation.MeterLoginPasswords
@@ -27,7 +28,7 @@ namespace GenesisCordonelInterface.Core.DataStorage.Reading.Implementation.Meter
/// <returns>
/// Password if found; otherwise null.
/// </returns>
string GetPassword(string queryParam);
string GetPassword(DataQuery query);
/// <summary>
/// Reads meter login password asynchronously.
@@ -43,8 +44,8 @@ namespace GenesisCordonelInterface.Core.DataStorage.Reading.Implementation.Meter
/// <returns>
/// Password if found; otherwise null.
/// </returns>
Task<string> GetPasswordAsync(
string queryParam,
Task<string> ReadMeterLoginPasswordAsync(
DataQuery query,
CancellationToken token = default);
}
}
@@ -7,85 +7,120 @@ using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
/// <summary>
/// Reads meter login password from configured GCI data storage.
/// </summary>
public class MeterLoginPasswordReader : IMeterLoginPasswordReader
namespace GenesisCordonelInterface.Core.DataStorage.Reading.Implementation.MeterLoginPasswords
{
/// <summary>
/// Universal data storage reader selected by configuration.
/// Can represent database, CSV, JSON or REST reader.
/// Reads meter login password from configured GCI data storage.
/// </summary>
private readonly IDataStorageReader reader;
/// <summary>
/// Ensures that only one password lookup is executed at a time.
/// </summary>
private readonly SemaphoreSlim readLock = new SemaphoreSlim(1, 1);
/// <summary>
/// Creates password reader using provided data storage configuration.
/// </summary>
/// <param name="config">Data storage configuration loaded from gci_config.json.</param>
public MeterLoginPasswordReader(DataStorageConfig config)
public class MeterLoginPasswordReader : IMeterLoginPasswordReader
{
reader = DataStorageReaderFactory.Create(config);
}
/// <summary>
/// Universal data storage reader selected by configuration.
/// Can represent database, CSV, JSON or REST reader.
/// </summary>
private readonly IDataStorageReader reader;
/// <summary>
/// Asynchronously reads meter login password by query parameter.
/// </summary>
/// <param name="queryParam">PCB ID or another configured lookup value.</param>
/// <param name="token">Cancellation token.</param>
/// <returns>Password if found; otherwise null.</returns>
public async Task<string> GetPasswordAsync(
string queryParam,
CancellationToken token = default)
{
if (string.IsNullOrWhiteSpace(queryParam))
throw new ArgumentException("Query parameter must not be empty.", nameof(queryParam));
/// <summary>
/// Ensures that only one password lookup is executed at a time.
/// </summary>
private readonly SemaphoreSlim readLock = new SemaphoreSlim(1, 1);
await readLock.WaitAsync(token);
try
/// <summary>
/// Creates password reader using provided data storage configuration.
/// </summary>
/// <param name="config">Data storage configuration loaded from gci_config.json.</param>
public MeterLoginPasswordReader(DataStorageConfig config)
{
return await Task.Run(
() => GetPassword(queryParam),
token);
}
finally
{
readLock.Release();
}
}
/// <summary>
/// Reads meter login password by query parameter.
/// </summary>
/// <param name="queryParam">PCB ID or another configured lookup value.</param>
/// <returns>Password if found; otherwise null.</returns>
public string GetPassword(string queryParam)
{
if (string.IsNullOrWhiteSpace(queryParam))
throw new ArgumentException("Query parameter must not be empty.", nameof(queryParam));
DataQuery query = new DataQuery();
query.QueryParams.Add(queryParam);
object result = reader.GetData(query);
if (result is ReaderDiagnosticResult csvResult)
return csvResult.Data?.ToString();
if (result is DatabaseSearchResult dbResult)
{
if (!dbResult.Found || dbResult.Values == null || dbResult.Values.Count == 0)
return null;
foreach (object value in dbResult.Values.Values)
return value?.ToString();
reader = DataStorageReaderFactory.Create(config);
}
return result?.ToString();
/// <summary>
/// Asynchronously reads meter login password using
/// the provided data query.
///
/// Thread-safe implementation may serialize
/// access to the underlying storage.
/// </summary>
/// <param name="query">
/// Data query containing lookup parameter values.
/// </param>
/// <param name="token">
/// Cancellation token.
/// </param>
/// <returns>
/// Password if found; otherwise null.
/// </returns>
public async Task<string> ReadMeterLoginPasswordAsync(
DataQuery query,
CancellationToken token = default)
{
if (query == null)
throw new ArgumentNullException(nameof(query));
if (query.QueryParams.Count == 0)
throw new ArgumentException(
"Query does not contain any parameter.",
nameof(query));
await readLock.WaitAsync(token);
try
{
return await Task.Run(
() => GetPassword(query),
token);
}
finally
{
readLock.Release();
}
}
/// <summary>
/// Reads meter login password using
/// the provided data query.
/// </summary>
/// <param name="query">
/// Data query containing lookup parameter values.
/// </param>
/// <returns>
/// Password if found; otherwise null.
/// </returns>
public string GetPassword(
DataQuery query)
{
if (query == null)
throw new ArgumentNullException(nameof(query));
if (query.QueryParams.Count == 0)
throw new ArgumentException(
"Query does not contain any parameter.",
nameof(query));
object result =
reader.GetData(query);
if (result is ReaderDiagnosticResult diagnosticResult)
{
return diagnosticResult.Data?.ToString();
}
if (result is DatabaseSearchResult dbResult)
{
if (!dbResult.Found ||
dbResult.Values == null ||
dbResult.Values.Count == 0)
{
return null;
}
foreach (object value in dbResult.Values.Values)
{
return value?.ToString();
}
}
return result?.ToString();
}
}
}
@@ -1,43 +1,62 @@
using System.Collections.Generic;
using GenesisCordonelInterface.Core.DataStorage.Reading.Common.Models;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace GenesisCordonelInterface.Core.DataStorage.Reading.Implementation.PreAdjustmentCalibrationParams
{
/// <summary>
/// Provides access to pre-adjustment calibration parameters
/// stored in the configured data source.
/// stored in the configured GCI data source.
///
/// Expected structure:
/// Dn_InternalId | ParameterName | ParameterValue
///
/// MeterSize | ParameterName | ParameterValue
///
/// Example:
/// 3 | GENESISFLOW_MinValidToF | 21990232
/// 3 | GENESISFLOW_Timeout | 1
///
/// Parameters are grouped by Dn_InternalId and returned
/// 2 | GENESISFLOW_MinValidToF | 21990232
/// 2 | GENESISFLOW_Timeout | 1
///
/// Parameters are grouped by MeterSize and returned
/// as key/value pairs where:
///
/// Key = ParameterName
/// Value = ParameterValue
/// </summary>
internal interface IPreAdjustmentCalibrationParamsReader
public interface IPreAdjustmentCalibrationParamsReader
{
/// <summary>
/// Reads all calibration parameters assigned
/// to a specific DN identifier.
/// Reads all pre-adjustment calibration parameters
/// using the provided data query synchronously.
/// </summary>
/// <param name="dnInternalId">
/// Internal DN identifier (meter size).
/// <param name="query">
/// Data query containing meter size as lookup parameter.
/// </param>
/// <returns>
/// Dictionary:
///
/// Key:
/// GENESISFLOW parameter name
///
/// Value:
/// Stored parameter value
/// Dictionary where key is GENESISFLOW parameter name
/// and value is stored parameter value.
/// </returns>
Task<Dictionary<string, string>> ReadParamsAsync(int dnInternalId);
Dictionary<string, UInt32> GetCalibrationParams(
DataQuery query);
/// <summary>
/// Reads all pre-adjustment calibration parameters
/// using the provided data query asynchronously.
/// </summary>
/// <param name="query">
/// Data query containing meter size as lookup parameter.
/// </param>
/// <param name="token">
/// Cancellation token.
/// </param>
/// <returns>
/// Dictionary where key is GENESISFLOW parameter name
/// and value is stored parameter value.
/// </returns>
Task<Dictionary<string, UInt32>> ReadCalibrationParamsAsync(
DataQuery query,
CancellationToken token = default);
}
}
@@ -1,87 +1,305 @@
using System;
using GenesisCordonelInterface.Core.DataStorage.Reading.Common;
using GenesisCordonelInterface.Core.DataStorage.Reading.Common.Contracts;
using GenesisCordonelInterface.Core.DataStorage.Reading.Common.Models;
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Threading;
using System.Threading.Tasks;
namespace GenesisCordonelInterface.Core.DataStorage.Reading.Implementation.PreAdjustmentCalibrationParams
{
/// <summary>
/// Reads pre-adjustment calibration parameters
/// from SQL database storage.
/// from configured GCI data storage.
///
/// Expected table:
/// The underlying storage type is selected
/// through IDataStorageReader and may represent:
///
/// dbo.PreAdjustmentCalibrationParams
/// - SQL database
/// - CSV
/// - JSON
/// - REST API
///
/// Columns:
/// Dn_InternalId
/// ParameterName
/// ParameterValue
/// Expected storage structure:
///
/// MeterSize | ParameterName | ParameterValue
///
/// Example:
///
/// 3 | GENESISFLOW_MinValidToF | 21990232
/// 3 | GENESISFLOW_Timeout | 1
/// 2 | GENESISFLOW_MinValidToF | 21990232
/// 2 | GENESISFLOW_Timeout | 1
///
/// Returns values as dictionary:
/// Returned data are represented as:
///
/// GENESISFLOW_MinValidToF -> 21990232
/// GENESISFLOW_Timeout -> 1
/// Key = ParameterName
/// Value = ParameterValue
/// </summary>
internal class PreAdjustmentCalibrationParamsReader: IPreAdjustmentCalibrationParamsReader
public class PreAdjustmentCalibrationParamsReader
: IPreAdjustmentCalibrationParamsReader
{
private readonly string _connectionString;
/// <summary>
/// Universal data storage reader selected by configuration.
/// Can represent database, CSV, JSON or REST reader.
/// </summary>
private readonly IDataStorageReader reader;
/// <summary>
/// Initializes calibration parameter reader.
/// Ensures that only one calibration parameter lookup
/// is executed at a time.
/// </summary>
/// <param name="connectionString">
/// SQL database connection string.
private readonly SemaphoreSlim readLock =
new SemaphoreSlim(1, 1);
/// <summary>
/// Creates calibration parameter reader using
/// provided data storage configuration.
/// </summary>
/// <param name="config">
/// Data storage configuration loaded from gci_config.json.
/// </param>
public PreAdjustmentCalibrationParamsReader(
string connectionString)
DataStorageConfig config)
{
_connectionString = connectionString?? throw new ArgumentNullException(nameof(connectionString));
if (config == null)
throw new ArgumentNullException(nameof(config));
reader = DataStorageReaderFactory.Create(config);
}
/// <inheritdoc/>
public async Task<Dictionary<string, string>> ReadParamsAsync(int dnInternalId)
/// <summary>
/// Reads all pre-adjustment calibration parameters
/// using the provided data query asynchronously.
///
/// The query is expected to contain meter size
/// as the first lookup parameter.
/// </summary>
/// <param name="query">
/// Data query containing lookup parameter values.
/// </param>
/// <param name="token">
/// Cancellation token.
/// </param>
/// <returns>
/// Dictionary:
///
/// Key:
/// GENESISFLOW parameter name
///
/// Value:
/// Stored parameter value
/// </returns>
public async Task<Dictionary<string, UInt32>> ReadCalibrationParamsAsync(
DataQuery query,
CancellationToken token = default)
{
var result = new Dictionary<string, string>();
ValidateQuery(query);
const string query = @"
SELECT ParameterName, ParameterValue
FROM dbo.PreAdjustmentCalibrationParams
WHERE Dn_InternalId=@Dn_InternalId";
return await Task.Run(
() => GetCalibrationParams(query),
token).ConfigureAwait(false); ;
using (var connection = new SqlConnection(_connectionString))
/*await readLock.WaitAsync(token);
using (var command = new SqlCommand(query, connection))
try
{
command.Parameters.AddWithValue(
"@Dn_InternalId",
dnInternalId);
return await Task.Run(
() => GetCalibrationParams(query),
token);
}
finally
{
readLock.Release();
}*/
}
await connection.OpenAsync();
/// <summary>
/// Reads all pre-adjustment calibration parameters
/// using the provided data query.
///
/// The query is expected to contain meter size
/// as the first lookup parameter.
/// </summary>
/// <param name="query">
/// Data query containing lookup parameter values.
/// </param>
/// <returns>
/// Dictionary:
///
/// Key:
/// GENESISFLOW parameter name
///
/// Value:
/// Stored parameter value
/// </returns>
public Dictionary<string, UInt32> GetCalibrationParams(
DataQuery query)
{
ValidateQuery(query);
using (var reader =
await command.ExecuteReaderAsync())
object result =
reader.GetData(query);
return ConvertResultToDictionary(result);
}
/// <summary>
/// Validates that data query exists
/// and contains at least one lookup parameter.
/// </summary>
/// <param name="query">
/// Data query to validate.
/// </param>
private static void ValidateQuery(
DataQuery query)
{
if (query == null)
throw new ArgumentNullException(nameof(query));
if (query.QueryParams == null ||
query.QueryParams.Count == 0)
{
throw new ArgumentException(
"Query does not contain any parameter.",
nameof(query));
}
}
/// <summary>
/// Converts provider-specific result objects
/// returned by IDataStorageReader into a unified
/// dictionary representation.
/// </summary>
/// <param name="result">
/// Raw result returned by the configured storage reader.
/// </param>
/// <returns>
/// Dictionary containing calibration parameter
/// name/value pairs.
/// </returns>
private Dictionary<string, UInt32> ConvertResultToDictionary(
object result)
{
Dictionary<string, UInt32> values =
new Dictionary<string, UInt32>();
if (result == null)
return values;
if (result is DatabaseSearchResult dbResult)
{
if (!dbResult.Found)
return values;
foreach (Dictionary<string, object> row in dbResult.Rows)
{
while (await reader.ReadAsync())
if (!row.TryGetValue("ParameterName", out object parameterNameObject))
continue;
if (!row.TryGetValue("ParameterValue", out object parameterValueObject))
continue;
string parameterName =
parameterNameObject?.ToString();
if (string.IsNullOrWhiteSpace(parameterName))
continue;
if (TryConvertToUInt32(parameterValueObject, out UInt32 parameterValue))
{
var parameterName = reader["ParameterName"].ToString();
var parameterValue = reader["ParameterValue"].ToString();
if (!string.IsNullOrWhiteSpace(parameterName))
{
result[parameterName] = parameterValue;
}
values[parameterName] =
parameterValue;
}
}
return values;
}
if (result is ReaderDiagnosticResult diagnosticResult)
{
if (diagnosticResult.Data is Dictionary<string, UInt32> uintDictionary)
return uintDictionary;
if (diagnosticResult.Data is Dictionary<string, string> stringDictionary)
{
foreach (var item in stringDictionary)
{
if (TryConvertToUInt32(item.Value, out UInt32 value))
values[item.Key] = value;
}
return values;
}
if (diagnosticResult.Data is Dictionary<string, object> objectDictionary)
{
foreach (var item in objectDictionary)
{
if (TryConvertToUInt32(item.Value, out UInt32 value))
values[item.Key] = value;
}
return values;
}
}
return result;
if (result is Dictionary<string, UInt32> directUIntDictionary)
return directUIntDictionary;
if (result is Dictionary<string, string> directStringDictionary)
{
foreach (var item in directStringDictionary)
{
if (TryConvertToUInt32(item.Value, out UInt32 value))
values[item.Key] = value;
}
return values;
}
if (result is Dictionary<string, object> directObjectDictionary)
{
foreach (var item in directObjectDictionary)
{
if (TryConvertToUInt32(item.Value, out UInt32 value))
values[item.Key] = value;
}
}
return values;
}
private static bool TryConvertToUInt32(
object value,
out UInt32 result)
{
result = 0;
if (value == null)
return false;
if (value is UInt32 uintValue)
{
result = uintValue;
return true;
}
if (value is int intValue && intValue >= 0)
{
result = Convert.ToUInt32(intValue);
return true;
}
if (value is long longValue &&
longValue >= 0 &&
longValue <= UInt32.MaxValue)
{
result = Convert.ToUInt32(longValue);
return true;
}
return UInt32.TryParse(
value.ToString(),
out result);
}
}
}
@@ -0,0 +1,73 @@
using GenesisCordonelInterface.API;
using GenesisCordonelInterface.Core.Config;
using GenesisCordonelInterface.Core.DataStorage.Reading.Common.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.AccessControl;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using UdsReaderType_CalibrationParams = GenesisCordonelInterface.Core.DataStorage.Reading.Implementation.PreAdjustmentCalibrationParams.PreAdjustmentCalibrationParamsReader;
using UdsReaderType_LoginPasswords = GenesisCordonelInterface.Core.DataStorage.Reading.Implementation.MeterLoginPasswords.MeterLoginPasswordReader;
using GciPublicModels = GenesisCordonelInterface.API.PublicModels;
using GciEnums = GenesisCordonelInterface.API.Enums;
using GciType = GenesisCordonelInterface.API.InterfaceOutsideToGCI;
using GciDataStorageReadingModels = GenesisCordonelInterface.Core.DataStorage.Reading.Common.Models;
using GciGUIType = GenesisCordonelInterface.UI.MainView;
namespace GenesisCordonelInterface.Core
{
public class Engine
{
GciConfig gciConfig;
public UdsReaderType_LoginPasswords loginPasswordsDataStorageReader;
public UdsReaderType_CalibrationParams calibrationParamsStorageReader;
//readonly UdsWriterType writer;
//diag GUI for GCI
GciGUIType gciGUI;
Form gciGuiHostForm;
//diag GUI for GciBridge
public UserControl gciBridgeGUIUserControl;
public UI.MainForm gciBridgeGuiForm;
public InterfaceOutsideToGCI gciExternalInterface;
/// <summary>
/// Initializes a new instance of the public GCI facade.
/// </summary>
public Engine()
{
gciConfig = GciConfigLoader.LoadDefault();
loginPasswordsDataStorageReader = new UdsReaderType_LoginPasswords
(
new GciDataStorageReadingModels.DataStorageConfig
(
nameof(GciEnums.DataStorageReaderTypes.LoginPasswordsReader),
GciDataStorageReadingModels.DataStorageType.LocalDatabase,
gciConfig.DataStorageSection.MeterLoginPasswords.DataSource,
gciConfig.DataStorageSection.MeterLoginPasswords.QueryTemplate
)
);
calibrationParamsStorageReader = new UdsReaderType_CalibrationParams
(
new GciDataStorageReadingModels.DataStorageConfig
(
nameof(GciEnums.DataStorageReaderTypes.CalibrationParamsReader),
GciDataStorageReadingModels.DataStorageType.LocalDatabase,
gciConfig.DataStorageSection.PreAdjustmentCalibrationParams.DataSource,
gciConfig.DataStorageSection.PreAdjustmentCalibrationParams.QueryTemplate
)
);
gciExternalInterface = new InterfaceOutsideToGCI(
new InterfaceGCIToLaatzen(),
loginPasswordsDataStorageReader,
calibrationParamsStorageReader);
}
}
}
@@ -81,6 +81,9 @@
<Reference Include="Xylem.Common.Hardware.WaterMeter.Genesis.GenesisConfig">
<HintPath>..\packages\Common\Xylem.Common.Hardware.WaterMeter.Genesis.GenesisConfig.dll</HintPath>
</Reference>
<Reference Include="Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore">
<HintPath>..\packages\Common\Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore.dll</HintPath>
</Reference>
<Reference Include="Xylem.Common.Hardware.WaterMeter.Genesis.Registers">
<HintPath>..\packages\Common\Xylem.Common.Hardware.WaterMeter.Genesis.Registers.dll</HintPath>
</Reference>
@@ -117,9 +120,10 @@
<Compile Include="API\InterfaceOutsideToGCI.cs" />
<Compile Include="API\InterfaceGCIToLaatzen.cs" />
<Compile Include="API\PublicModels.cs" />
<Compile Include="Core\DataStorage\Config\GciConfig.cs" />
<Compile Include="Core\DataStorage\Config\GciConfigLoader.cs" />
<Compile Include="Core\Config\GciConfig.cs" />
<Compile Include="Core\Config\GciConfigLoader.cs" />
<Compile Include="Core\DataStorage\Config\GciDataStorageConfig.cs" />
<Compile Include="API\Enums.cs" />
<Compile Include="Core\DataStorage\Reading\Common\Providers\CsvDataStorageReader.cs" />
<Compile Include="Core\DataStorage\Reading\Common\Providers\DatabaseDataStorageReader.cs" />
<Compile Include="Core\DataStorage\Reading\Common\Models\DatabaseSearchResult.cs" />
@@ -137,6 +141,7 @@
<Compile Include="Core\DataStorage\Reading\Implementation\MeterLoginPasswords\MeterLoginPasswordReader.cs" />
<Compile Include="Core\DataStorage\Reading\Implementation\PreAdjustmentCalibrationParams\IPreAdjustmentCalibrationParamsReader.cs" />
<Compile Include="Core\DataStorage\Reading\Implementation\PreAdjustmentCalibrationParams\PreAdjustmentCalibrationParamsReader.cs" />
<Compile Include="Core\Engine\Engine.cs" />
<Compile Include="Core\Logging\UiLogBus.cs" />
<Compile Include="Core\Logging\UiTarget.cs" />
<Compile Include="Core\Threading\ApiWorker\ApiWorker.cs" />
@@ -223,6 +228,8 @@
<Content Include="docs\images\GCI__Onboarding_Overview_drawio.svg" />
<Content Include="docs\images\GCI__Onboarding_Overview_drawio__API_architecture__Current_state.svg" />
<Content Include="docs\images\GCI__Onboarding_Overview_drawio__API_architecture__Target_state.svg" />
<Content Include="docs\images\GCI__Onboarding_Overview_drawio__Data_collection_domain.svg" />
<Content Include="docs\images\GCI__Onboarding_Overview_drawio__Meter_management_domain.svg" />
<Content Include="docs\images\logo\logo.png" />
<Content Include="docs\images\logo\logo.svg" />
<Content Include="docs\images\logo\sensus-logo-white-green-rgb.png" />
@@ -255,9 +262,11 @@
<EmbeddedResource Include="UI\StaraTuraAPI_GenesisCordonelInterface\FrmGCIAPI.resx">
<DependentUpon>FrmGCIAPI.cs</DependentUpon>
</EmbeddedResource>
<Content Include="Config\gci_config.json">
<Content Include="Core\Config\gci_config.json">
<Link>Config\gci_config.json</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<None Include="Core\Config\gci_config.json" />
<None Include="docs\articles\API\index.md" />
<None Include="docs\articles\API\PublicModels.md" />
<None Include="docs\articles\API\InterfaceGCIToLaatzen.md" />
@@ -279,6 +288,11 @@
<None Include="docs\pages\gci\page_gci__implementation_to_tbf.md" />
<None Include="docs\pages\gci\page_gci__implementation_universal.md" />
<None Include="docs\pages\gci\page_gci__workers.md" />
<None Include="docs\pages\platform\page_platform__configuration_domain.md" />
<None Include="docs\pages\platform\page_platform__data_collection_domain.md" />
<None Include="docs\pages\platform\page_platform__tbf_implementation.md" />
<None Include="docs\pages\platform\page_platform__current_state.md" />
<None Include="docs\pages\platform\page_platform__home.md" />
<None Include="docs\toc.yml" />
<None Include="packages.config" />
<None Include="Properties\Settings.settings">
@@ -295,6 +309,7 @@
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<Folder Include="Config\" />
<Folder Include="Core\DataStorage\Writing\NewFolder1\" />
<Folder Include="RuntimePackage\Package\" />
</ItemGroup>
@@ -302,10 +317,6 @@
<WCFMetadata Include="Connected Services\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ExternalProjects\Laatzen\Genesis\Common\Hardware\WaterMeter\Genesis\GenesisCore\GenesisCore.csproj">
<Project>{04201E95-90A0-4B73-A72F-379739B2A3AE}</Project>
<Name>GenesisCore</Name>
</ProjectReference>
<ProjectReference Include="..\ExternalProjects\Laatzen\Genesis\Common\CordonelPreadjustmentUi\CordonelPreadjustmentUi.csproj">
<Project>{D0C8D887-ED52-40AB-A069-90BCE0E801E2}</Project>
<Name>CordonelPreadjustmentUi</Name>
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="NLog" publicKeyToken="5120e14c03d0593c" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="5.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Xylem.Common.CommonCore" publicKeyToken="null" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.8.18.17954" newVersion="2.8.18.17954" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/></startup></configuration>
@@ -0,0 +1,15 @@
{
"Erase": [
"1\\tstfile",
"1\\fdrdata",
"1\\logdata",
"1\\blklist",
"1\\pulsedbg",
"1\\upg*",
"1\\img*"
],
"Restore": [
{
}
]
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,87 @@
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<variable name="BasePath" value="\\DELAZ1FSOPS01-1\CordonelDS$\${loggerpc}" />
<targets>
<!--CalibrationHelper-->
<target name="CalibrationHelper" xsi:type="File" fileName="${BasePath}\${shortdate}\${processname}\CalibrationHelper.log" CreateDirs="True" layout ="${longdate} | ${level} | ${message} ${exception:format=toString}" archiveAboveSize="50000000" archiveFileName="${BasePath}\${shortdate}\${processname}\{##}CalibrationHelper.log" />
<!--LedRawData-->
<target xsi:type="BufferingWrapper"
name="TargetLedRawDataBase"
bufferSize="10000"
flushTimeout="-1"
slidingTimeout="true"
>
<target name="LedRawDataBase" xsi:type="File" fileName="${BasePath}\${shortdate}\${processname}\LedRawData_BASE.log" CreateDirs="True" layout ="${longdate} | ${message} ${exception:format=toString}" archiveAboveSize="50000000" archiveFileName="${BasePath}\${shortdate}\${processname}\{##}_LedRawData_BASE.log" />
</target>
<!--C:\GenesisLog\${shortdate}
C:\GenesisLog\${shortdate}-->
<!--MeterBatch-->
<target name="MeterBatch" xsi:type="File" fileName="${BasePath}\${shortdate}\${processname}\Meter_BASE.log" CreateDirs="True" layout ="${longdate} | ${level} | ${message} ${exception:format=toString}" archiveAboveSize="50000000" archiveFileName="${BasePath}\${shortdate}\${processname}\{##}_Meter_BASE.log" />
<!--Meter-->
<target name="MeterBase" xsi:type="File" fileName="${BasePath}\${shortdate}\${processname}\Meter_BASE.log" CreateDirs="True" layout ="${longdate} | ${level} | ${message} ${exception:format=toString}" archiveAboveSize="50000000" archiveFileName="${BasePath}\${shortdate}\${processname}\{##}_Meter_BASE.log" />
<target name="Slot:0" xsi:type="File" fileName="${BasePath}\${shortdate}\${processname}\Meter_SlotSlot:0.log" CreateDirs="True" layout ="${longdate} | ${level} | ${message} ${exception:format=toString}" archiveAboveSize="50000000" archiveFileName="${BasePath}\${shortdate}\${processname}\{##}_Meter_SlotSlot:0.log" />
<!--COM-->
<target name="COMBase" xsi:type="File" fileName="${BasePath}\${shortdate}\${processname}\COM_BASE.log" CreateDirs="True" layout ="${longdate} | ${level} | ${message} ${exception:format=toString}" archiveAboveSize="50000000" archiveFileName="${BasePath}\${shortdate}\${processname}\{##}_COM_BASE.log" />
<!--ServiceFwUpdateBuilder-->
<target name="ServiceFwUpdateBuilder" xsi:type="File" fileName="${BasePath}\${shortdate}\${processname}\ServiceFwUpdateBuilder.log" CreateDirs="True" layout ="${longdate} | ${level} | ${message} ${exception:format=toString}" archiveAboveSize="50000000" archiveFileName="${BasePath}\${shortdate}\${processname}\{##}_ServiceFwUpdateBuilder.log" />
<!--ServiceFwUpdateLoader-->
<target name="ServiceFwUpdateLoader" xsi:type="File" fileName="${BasePath}\${shortdate}\${processname}\ServiceFwUpdateLoader.log" CreateDirs="True" layout ="${longdate} | ${level} | ${message} ${exception:format=toString}" archiveAboveSize="50000000" archiveFileName="${BasePath}\${shortdate}\${processname}\{##}_ServiceFwUpdateLoader.log" />
<!--ServiceFwUpdateSw-->
<target name="ServiceFwUpdateSw" xsi:type="File" fileName="${BasePath}\${shortdate}\${processname}\ServiceFwUpdateSw.log" CreateDirs="True" layout ="${longdate} | ${level} | ${message} ${exception:format=toString}" archiveAboveSize="50000000" archiveFileName="${BasePath}\${shortdate}\${processname}\{##}_ServiceFwUpdateSw.log" />
<!--default-->
<target name="default" xsi:type="File" fileName="${BasePath}\${shortdate}\${processname}\default.log" CreateDirs="True" layout ="${longdate} | ${level} | ${message} ${exception:format=toString}" archiveAboveSize="50000000" archiveFileName="${BasePath}\${shortdate}\${processname}\{##}_default.log" />
<target name="PreAdjWr" xsi:type="File" fileName="${BasePath}\${shortdate}\${processname}\PreAdjWr.log" CreateDirs="True" layout ="${longdate} | ${level} | ${message} ${exception:format=toString}" />
<target name="ctlBatch" xsi:type="File" fileName="${BasePath}\${shortdate}\${processname}\ctlBatch.log" CreateDirs="True" layout ="${longdate} | ${level} | ${message} ${exception:format=toString}" archiveAboveSize="50000000" archiveFileName="${BasePath}\${shortdate}\${processname}\{##}_ctlBatch.log" />
<target name="StreamingQualityFile" xsi:type="File" fileName="${BasePath}\${shortdate}\${processname}\StreamingQuality.log" CreateDirs="True" layout ="${longdate} | ${level} | ${message} ${exception:format=toString}" />
<target name="ProductionUIFile" xsi:type="File" fileName="${BasePath}\${shortdate}\${processname}\ProductionUIFile.log" CreateDirs="True" layout ="${longdate} | ${level} | ${message} ${exception:format=toString}" />
</targets>
<rules>
<!--ServiceFwUpdateBuilder-->
<logger name="ServiceFwUpdateBuilder" minLevel="Trace" appendTo="ServiceFwUpdateSw"/>
<!--ServiceFwUpdateLoader-->
<logger name="ServiceFwUpdateLoader" minLevel="Trace" appendTo="ServiceFwUpdateLoader"/>
<!--ServiceFwUpdateSw-->
<logger name="ServiceFwUpdateSw" minLevel="Trace" appendTo="ServiceFwUpdateSw"/>
<!--CalibrationHelper-->
<logger name="CalibrationHelper" minLevel="Trace" appendTo="CalibrationHelper"/>
<!--LedRawData-->
<logger name="LedRawDataBase" minLevel="Trace" appendTo="TargetLedRawDataBase"/>
<!--MeterBatch-->
<logger name="MeterBatch" minLevel="Trace" appendTo="MeterBatch"/>
<!--Meter-->
<logger name="MeterBase" minLevel="Trace" appendTo="MeterBase"/>
<logger name="Slot:0" minLevel="Trace" appendTo="Slot:0"/>
<logger name="GenesisRequestProtocolBase" minLevel="Trace" appendTo="MeterBase"/>
<logger name="MeasurementBase" minLevel="Trace" appendTo="MeterBase"/>
<!--COM-->
<logger name="SerialComPortBase" minLevel="Trace" appendTo="COMBase"/>
<logger name="IrdaBase" minLevel="Trace" appendTo="COMBase"/>
<logger name="RfidBase" minLevel="Trace" appendTo="COMBase"/>
<logger name="TransmitProtocolBase" minLevel="Trace" appendTo="COMBase"/>
<!--default-->
<logger name="*" minLevel="Debug" appendTo="default"/>
<!--Ui logger-->
<logger name="ctlBatch" minLevel="Trace" appendTo="ctlBatch"/>
<logger name="StreamingQuality" minLevel="Trace" appendTo="StreamingQualityFile"/>
<logger name="PreAdjWr" minLevel="Trace" appendTo="PreAdjWr"/>
<logger name="ProductionUI" minLevel="Trace" appendTo="ProductionUIFile"/>
</rules>
</nlog>
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/>
</startup>
</configuration>
@@ -0,0 +1,312 @@
<?xml version="1.0"?>
<doc>
<assembly>
<name>Xylem.Common.Hardware.Interfaces.Ports.PortCore</name>
</assembly>
<members>
<member name="T:Xylem.Common.Hardware.Interfaces.Ports.PortCore.EventArguments.BasePortDataEventArgs">
<inheritdoc cref="T:System.EventArgs" />
</member>
<member name="F:Xylem.Common.Hardware.Interfaces.Ports.PortCore.EventArguments.BasePortDataEventArgs._receivedTime">
<summary>
Marker for incoming record at time of the PC
</summary>
</member>
<member name="M:Xylem.Common.Hardware.Interfaces.Ports.PortCore.EventArguments.BasePortDataEventArgs.GetData">
<inheritdoc />
</member>
<member name="M:Xylem.Common.Hardware.Interfaces.Ports.PortCore.EventArguments.BasePortDataEventArgs.SetData(System.Object)">
<inheritdoc />
</member>
<member name="M:Xylem.Common.Hardware.Interfaces.Ports.PortCore.EventArguments.BasePortDataEventArgs.SetReceivedTime(System.DateTimeOffset)">
<inheritdoc />
</member>
<member name="M:Xylem.Common.Hardware.Interfaces.Ports.PortCore.EventArguments.BasePortDataEventArgs.GetReceivedTime">
<inheritdoc />
</member>
<member name="M:Xylem.Common.Hardware.Interfaces.Ports.PortCore.EventArguments.BasePortDataEventArgs.SetSyncMarkRecord(Xylem.Common.CommonCore.Consts.SyncMarkRecord)">
<inheritdoc />
</member>
<member name="M:Xylem.Common.Hardware.Interfaces.Ports.PortCore.EventArguments.BasePortDataEventArgs.GetSyncMarkRecord">
<inheritdoc />
</member>
<member name="T:Xylem.Common.Hardware.Interfaces.Ports.PortCore.EventArguments.IPortDataEventArgs">
<summary>
Interface for port data event arguments
</summary>
</member>
<member name="M:Xylem.Common.Hardware.Interfaces.Ports.PortCore.EventArguments.IPortDataEventArgs.GetData">
<summary>
Read data
</summary>
<returns></returns>
</member>
<member name="M:Xylem.Common.Hardware.Interfaces.Ports.PortCore.EventArguments.IPortDataEventArgs.SetData(System.Object)">
<summary>
Write data
</summary>
<param name="data"></param>
</member>
<member name="M:Xylem.Common.Hardware.Interfaces.Ports.PortCore.EventArguments.IPortDataEventArgs.GetReceivedTime">
<summary>
Reading received time
</summary>
<returns></returns>
</member>
<member name="M:Xylem.Common.Hardware.Interfaces.Ports.PortCore.EventArguments.IPortDataEventArgs.SetReceivedTime(System.DateTimeOffset)">
<summary>
Writing received time
</summary>
<param name="receivedTime"></param>
</member>
<member name="M:Xylem.Common.Hardware.Interfaces.Ports.PortCore.EventArguments.IPortDataEventArgs.SetSyncMarkRecord(Xylem.Common.CommonCore.Consts.SyncMarkRecord)">
<summary>
Setting the data marker
</summary>
<param name="syncMarkRecord"></param>
</member>
<member name="M:Xylem.Common.Hardware.Interfaces.Ports.PortCore.EventArguments.IPortDataEventArgs.GetSyncMarkRecord">
<summary>
Getting the data marker
</summary>
<returns></returns>
</member>
<member name="T:Xylem.Common.Hardware.Interfaces.Ports.PortCore.EventArguments.ListBytePortDataEventArgs">
<inheritdoc />
</member>
<member name="M:Xylem.Common.Hardware.Interfaces.Ports.PortCore.EventArguments.ListBytePortDataEventArgs.#ctor(System.Collections.Generic.List{System.Byte},System.DateTimeOffset,Xylem.Common.CommonCore.Consts.SyncMarkRecord)">
<inheritdoc />
</member>
<member name="M:Xylem.Common.Hardware.Interfaces.Ports.PortCore.EventArguments.ListBytePortDataEventArgs.GetData">
<inheritdoc />
</member>
<member name="M:Xylem.Common.Hardware.Interfaces.Ports.PortCore.EventArguments.ListBytePortDataEventArgs.SetData(System.Object)">
<inheritdoc />
</member>
<member name="T:Xylem.Common.Hardware.Interfaces.Ports.PortCore.EventArguments.StringPortDataEventArgs">
<inheritdoc />
</member>
<member name="M:Xylem.Common.Hardware.Interfaces.Ports.PortCore.EventArguments.StringPortDataEventArgs.#ctor(System.String,System.DateTimeOffset,Xylem.Common.CommonCore.Consts.SyncMarkRecord)">
<inheritdoc />
</member>
<member name="M:Xylem.Common.Hardware.Interfaces.Ports.PortCore.EventArguments.StringPortDataEventArgs.GetData">
<inheritdoc />
</member>
<member name="M:Xylem.Common.Hardware.Interfaces.Ports.PortCore.EventArguments.StringPortDataEventArgs.SetData(System.Object)">
<inheritdoc />
</member>
<member name="T:Xylem.Common.Hardware.Interfaces.Ports.PortCore.IPort">
<summary>
Interface for Ports
</summary>
</member>
<member name="E:Xylem.Common.Hardware.Interfaces.Ports.PortCore.IPort.OnRawRecordReceived">
<summary>
event for record received, either bytes or string
</summary>
</member>
<member name="E:Xylem.Common.Hardware.Interfaces.Ports.PortCore.IPort.OnRawRecordSendOut">
<summary>
event for record received, either bytes or string
</summary>
</member>
<member name="M:Xylem.Common.Hardware.Interfaces.Ports.PortCore.IPort.SynchronizeReceiveBuffer(Xylem.Common.CommonCore.Consts.SyncMarkRecord)">
<summary>
set specific mark
and flush or delete all incoming byte from buffer when SyncMarkRecord is <see cref="F:Xylem.Common.CommonCore.Consts.SyncMarkRecord.SyncStart"/> or
<see cref="F:Xylem.Common.CommonCore.Consts.SyncMarkRecord.SyncEnd"/>
</summary>
<param name="syncMarkRecord"></param>
</member>
<member name="M:Xylem.Common.Hardware.Interfaces.Ports.PortCore.IPort.Open">
<summary>
if the port needs stuff to open, always open for better logical handling
</summary>
</member>
<member name="M:Xylem.Common.Hardware.Interfaces.Ports.PortCore.IPort.Dispose">
<summary>
close and dispose all connections
</summary>
</member>
<member name="M:Xylem.Common.Hardware.Interfaces.Ports.PortCore.IPort.IsOpen">
<summary>
indicates if the Port is open (also on Ports that did not have an open state)
</summary>
<returns></returns>
</member>
<member name="M:Xylem.Common.Hardware.Interfaces.Ports.PortCore.IPort.PortWrite(System.Byte[])">
<summary>
Write byte[] to the Stream/Port on Child Class
wrapped with base class error handling
</summary>
<param name="data">Array of bytes to write</param>
</member>
<member name="M:Xylem.Common.Hardware.Interfaces.Ports.PortCore.IPort.Clear">
<summary>
discard all buffers
</summary>
</member>
<member name="M:Xylem.Common.Hardware.Interfaces.Ports.PortCore.IPort.GetPortName">
<summary>
Return the port name
</summary>
<returns>name of the port as string</returns>
</member>
<member name="T:Xylem.Common.Hardware.Interfaces.Ports.PortCore.PortConfig">
<summary>
Collection of port settings
</summary>
</member>
<member name="P:Xylem.Common.Hardware.Interfaces.Ports.PortCore.PortConfig.PortName">
<summary>
Assigns a port name and creates the serial port object
Port name e.g. "COM2"
</summary>
</member>
<member name="P:Xylem.Common.Hardware.Interfaces.Ports.PortCore.PortConfig.Type">
<summary>
setup of port type from name (referenced as "Type" in config file)
</summary>
</member>
<member name="M:Xylem.Common.Hardware.Interfaces.Ports.PortCore.PortConfig.GetSerialPort">
<summary>
using dotNets <see cref="M:Xylem.Common.Hardware.Interfaces.Ports.PortCore.PortConfig.GetSerialPort"/> for connection
</summary>
</member>
<member name="M:Xylem.Common.Hardware.Interfaces.Ports.PortCore.PortConfig.SetSerialPort(System.IO.Ports.SerialPort)">
<summary>
using dotNets <see cref="M:Xylem.Common.Hardware.Interfaces.Ports.PortCore.PortConfig.GetSerialPort"/> for connection
</summary>
</member>
<member name="T:Xylem.Common.Hardware.Interfaces.Ports.PortCore.SlotConfig">
<summary>
Container for port configuration
</summary>
</member>
<member name="P:Xylem.Common.Hardware.Interfaces.Ports.PortCore.SlotConfig.Slot">
<summary>
Slot number
</summary>
</member>
<member name="P:Xylem.Common.Hardware.Interfaces.Ports.PortCore.SlotConfig.Request">
<summary>
Request port settings
</summary>
</member>
<member name="P:Xylem.Common.Hardware.Interfaces.Ports.PortCore.SlotConfig.Streaming">
<summary>
Streaming port settings
</summary>
</member>
<member name="P:Xylem.Common.Hardware.Interfaces.Ports.PortCore.SlotConfig.Type">
<summary>
Streaming port settings
</summary>
</member>
<member name="T:Xylem.Common.Hardware.Interfaces.Ports.PortCore.SlotType">
<summary>
Definition of type for slot
</summary>
</member>
<member name="F:Xylem.Common.Hardware.Interfaces.Ports.PortCore.SlotType.DutMeter">
<summary>
Cordonel used as DUT with two serial ports
</summary>
</member>
<member name="F:Xylem.Common.Hardware.Interfaces.Ports.PortCore.SlotType.TemperatureMeter">
<summary>
Cordonel used as temperature meter with one serial port streaming the temperature
</summary>
</member>
<member name="T:Xylem.Common.Hardware.Interfaces.Ports.PortCore.TransmitPortSettings">
<summary>
Store Port settings set most likely from transmit protocol
</summary>
</member>
<member name="M:Xylem.Common.Hardware.Interfaces.Ports.PortCore.TransmitPortSettings.#ctor(System.Nullable{System.Byte},System.Nullable{System.UInt16},System.UInt16,System.Int32,System.UInt32,System.Nullable{System.UInt32},System.Boolean,System.Char,System.Int32,System.IO.Ports.Parity)">
<summary>
The transmission protocol needs to inform the communication port how to set up,
this is the data container.
</summary>
<param name="protSyncByte"></param>
<param name="protLengthIndex"></param>
<param name="protAddLength"></param>
<param name="responseTimeoutMs"></param>
<param name="baudRate"></param>
<param name="receiveBufferFlushThreshold"></param>
<param name="doubleSyncByte"></param>
<param name="stringDelimiter"></param>
<param name="dataBits"></param>
<param name="parity"></param>
<remarks date="2026-Jan-05" author="T.Wiedebusch">
- String delimiter for ASCII to support others than LF "\n",
- Flexible DataBits,
- Flexible parity.
</remarks>
</member>
<member name="F:Xylem.Common.Hardware.Interfaces.Ports.PortCore.TransmitPortSettings.StringDelimiter">
<summary>
String delimiter for ASCII to support others than LF "\n"
</summary>
</member>
<member name="F:Xylem.Common.Hardware.Interfaces.Ports.PortCore.TransmitPortSettings.DataBits">
<summary>
Flexible DataBits to support 7 bits.
</summary>
</member>
<member name="F:Xylem.Common.Hardware.Interfaces.Ports.PortCore.TransmitPortSettings.Parity">
<summary>
Flexible parity
</summary>
</member>
<member name="F:Xylem.Common.Hardware.Interfaces.Ports.PortCore.TransmitPortSettings.ProtSyncByte">
<summary>
start of receiving synchronization byte at byte receive routine
syncByte == null: use the readLine routine (ASCII) and NOT the BYTE routine,
lengthPosition and additionalLength are not used
</summary>
</member>
<member name="F:Xylem.Common.Hardware.Interfaces.Ports.PortCore.TransmitPortSettings.ProtLengthIndex">
<summary>
position of length information field in received BYTE record
lengthIndex == null: take the constant receive length of additionalLength
because the record doesn't contain length information
</summary>
</member>
<member name="F:Xylem.Common.Hardware.Interfaces.Ports.PortCore.TransmitPortSettings.ProtAddLength">
<summary>
additional record length NOT covert by the record length information field
lengthIndex == null: constant length for received record
Being used for the BYTE records indicated by a valid syncByte,
not being used for ASCII records.
</summary>
</member>
<member name="F:Xylem.Common.Hardware.Interfaces.Ports.PortCore.TransmitPortSettings.ResponseTimeoutMs">
<summary>
Response time out in milliseconds
</summary>
</member>
<member name="F:Xylem.Common.Hardware.Interfaces.Ports.PortCore.TransmitPortSettings.BaudRate">
<summary>
BaudRate for Port
</summary>
</member>
<member name="F:Xylem.Common.Hardware.Interfaces.Ports.PortCore.TransmitPortSettings.ReceiveBufferFlushThreshold">
<summary>
lower threshold for buffer flushing if dataMarker != SkipDecoding
receiveBufferFlushThreshold == null: never flush the communication buffer
receiveBufferFlushThreshold == 0: flush always the communication buffer
receiveBufferFlushThreshold == x: flush communication buffer if it exceeds x Byte
waste old records if an up-to-date record is being needed for start/stop synchronization
of a measurement. This is the level at which the old data have to be flushed because the
data have been dammed up in the communication port input buffer which means they are to
old for synchronization purposes.
/// </summary>
</member>
<member name="F:Xylem.Common.Hardware.Interfaces.Ports.PortCore.TransmitPortSettings.DoubleSyncByte">
<summary>
a special implementation may require the doubling of the sync byte to re-synchronize
</summary>
</member>
</members>
</doc>
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/></startup></configuration>
@@ -0,0 +1,384 @@
<?xml version="1.0"?>
<doc>
<assembly>
<name>Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages</name>
</assembly>
<members>
<member name="T:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.EventArguments.CalibDataEventArgs">
<inheritdoc />
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.EventArguments.CalibDataEventArgs.CalibChl">
<summary>
Stream record for calibration on channel
</summary>
</member>
<member name="M:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.EventArguments.CalibDataEventArgs.GetEventData">
<inheritdoc />
</member>
<member name="T:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.EventArguments.BendDetectDataEventArgs">
<inheritdoc />
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.EventArguments.BendDetectDataEventArgs.NewData">
<summary>
new record from Stream
</summary>
</member>
<member name="M:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.EventArguments.BendDetectDataEventArgs.GetEventData">
<inheritdoc />
</member>
<member name="T:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.EventArguments.FlowDataEventArgs">
<inheritdoc />
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.EventArguments.FlowDataEventArgs.NewData">
<summary>
new record from Stream
</summary>
</member>
<member name="M:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.EventArguments.FlowDataEventArgs.GetEventData">
<inheritdoc />
</member>
<member name="T:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.EventArguments.RegisterUpdatedEventArgs">
<inheritdoc />
</member>
<member name="M:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.EventArguments.RegisterUpdatedEventArgs.#ctor(Xylem.Common.Hardware.WaterMeter.Genesis.Registers.RegisterDefinition,System.Byte[])">
<inheritdoc />
<summary>
Ctor with base record
</summary>
<param name="register">base record <see cref="F:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.EventArguments.RegisterUpdatedEventArgs.Register" /></param>
<param name="value">base record <see cref="F:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.EventArguments.RegisterUpdatedEventArgs.Value" /></param>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.EventArguments.RegisterUpdatedEventArgs.Register">
<summary>
Register witch has updated
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.EventArguments.RegisterUpdatedEventArgs.Value">
<summary>
New Value in Register
</summary>
</member>
<member name="T:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.EventArguments.RequestResponseDataEventArgs">
<inheritdoc />
<summary>
EventArgs for Request Responses
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.EventArguments.RequestResponseDataEventArgs.RequestResponseData">
<summary>
Request response from meter
</summary>
</member>
<member name="M:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.EventArguments.RequestResponseDataEventArgs.GetEventData">
<inheritdoc />
</member>
<member name="T:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.MeasurementRecords.BendDetectionRecord">
<inheritdoc />
<summary>
Streaming record for protocol M (information about bend detection and correction)
</summary>
</member>
<member name="T:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.MeasurementRecords.BendDetectionRecord.StatusBendU0Enum">
<summary>
The status of the U0 detection for this measurement
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.MeasurementRecords.BendDetectionRecord.StatusBendU0Enum.OKAY">
<summary>
Status okay
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.MeasurementRecords.BendDetectionRecord.StatusBendU0Enum.ERROR_GENESISFLOW_INSTALLATION_HIGH_TIME_DIFF">
<summary>
Error code as defined by field name
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.MeasurementRecords.BendDetectionRecord.StatusBendU0Enum.ERROR_GENESISFLOW_INSTALLATION_LOW_FLOW_IGNORE">
<summary>
Error code as defined by field name
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.MeasurementRecords.BendDetectionRecord.StatusBendU0Enum.ERROR_GENESISFLOW_INSTALLATION_BAD_CHANNELS">
<summary>
Error code as defined by field name
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.MeasurementRecords.BendDetectionRecord.StatusBendU0Enum.ERROR_GENESISFLOW_INSTALLATION_FIXED">
<summary>
Error code as defined by field name
</summary>
</member>
<member name="T:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.MeasurementRecords.BendDetectionRecord.InstallationTypeEnum">
<summary>
An enum describing the installation type detected
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.MeasurementRecords.BendDetectionRecord.InstallationTypeEnum.INSTALLATION_U0_180_360">
<summary>
Installation type code as defined by field name
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.MeasurementRecords.BendDetectionRecord.InstallationTypeEnum.INSTALLATION_U0_90_270">
<summary>
Installation type code as defined by field name
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.MeasurementRecords.BendDetectionRecord.InstallationTypeEnum.INSTALLATION_UNDISTURBED">
<summary>
Installation type code as defined by field name
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.MeasurementRecords.BendDetectionRecord.StatusBendU0">
<summary>
Status of U0 Bend detection
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.MeasurementRecords.BendDetectionRecord.InstallationType">
<summary>
Installation type code
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.MeasurementRecords.BendDetectionRecord.CorrectionFactor_percent">
<summary>
The proportion of the installation correction to apply based on the detected
installation. 100% == 0x8000
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.MeasurementRecords.BendDetectionRecord.DefaultCorrectionFactor">
<summary>
The default proportion of the installation correction to apply based on the
detected installation. 100% == 0x8000
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.MeasurementRecords.BendDetectionRecord.CorrectionFactorScale">
<summary>
Scale for correction factor to apply to convert it to percentage value 100% == 0x8000
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.MeasurementRecords.BendDetectionRecord.PreCorrectionVolumeRaw">
<summary>
The volume in internal units before correction applied
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.MeasurementRecords.BendDetectionRecord.PostCorrectionVolumeRaw">
<summary>
The volume in internal units after correction applied
</summary>
</member>
<member name="M:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.MeasurementRecords.BendDetectionRecord.ToString">
<summary>
Get result as string
</summary>
<returns></returns>
</member>
<member name="T:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.MeasurementRecords.CalibrationRecord">
<inheritdoc />
<summary>
hold streaming record for protocol H (contains calibration record)
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.MeasurementRecords.CalibrationRecord.Validation">
<summary>
record validation
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.MeasurementRecords.CalibrationRecord.TotalTimeOfFlightS">
<summary>
total time of flight in seconds
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.MeasurementRecords.CalibrationRecord.DeltaTimeOfFlightS">
<summary>
delta time of flight in seconds
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.MeasurementRecords.CalibrationRecord.RawTotalTimeOfFlight">
<summary>
total time of flight in cordonel units
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.MeasurementRecords.CalibrationRecord.RawDeltaTimeOfFlight">
<summary>
delta time of flight in cordonel units
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.MeasurementRecords.CalibrationRecord.VolumeScaleRawPerMl">
<summary>
volume scale (default: 1024) means
1024digits = 1ml
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.MeasurementRecords.CalibrationRecord.VolumeFactorRawToQm">
<summary>
volume factor to convert raw to m³
uses 1E-6 (ml to m³) / VolumeScaleRawPerMl
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.MeasurementRecords.CalibrationRecord.DeltaVolumeRaw">
<summary>
raw volume between two samples
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.MeasurementRecords.CalibrationRecord.DeltaVolumeQm">
<summary>
calculated out of dRawVolume * VolumeFactorRawToQm .
in cubic meters
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.MeasurementRecords.CalibrationRecord.AccuVolumeRaw">
<summary>
accumulated raw volume
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.MeasurementRecords.CalibrationRecord.SampleIntervalS">
<summary>
sample interval between two samples in seconds
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.MeasurementRecords.CalibrationRecord.AmplitudeUpV">
<summary>
high threshold amplitude in V
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.MeasurementRecords.CalibrationRecord.AmplitudeDownV">
<summary>
low threshold amplitude in V
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.MeasurementRecords.CalibrationRecord.PulseWidthRatioUp">
<summary>
high ratio for pulse width
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.MeasurementRecords.CalibrationRecord.PulseWidthRatioDown">
<summary>
low ratio for pulse width
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.MeasurementRecords.CalibrationRecord.TemperatureRaw">
<summary>
raw temperature
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.MeasurementRecords.CalibrationRecord.TemperaturePowFactor">
<summary>
temperature scale
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.MeasurementRecords.CalibrationRecord.TemperatureDegC">
<summary>
calculated temperature in degree C
</summary>
</member>
<member name="M:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.MeasurementRecords.CalibrationRecord.ToString">
<summary>
Get result as string
</summary>
<returns></returns>
</member>
<member name="T:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.MeasurementRecords.FlowTestRecord">
<inheritdoc />
<summary>
struct to hold Led record for protocol F (contains measurement record)
</summary>
</member>
<member name="M:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.MeasurementRecords.FlowTestRecord.ToString">
<summary>
Get result as string
</summary>
<returns></returns>
</member>
<member name="T:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.RadioConfigurationParams">
<summary>
All parameters needed for radio setup
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.RadioConfigurationParams.PcbId">
<summary>
Pcb identification
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.RadioConfigurationParams.SerialNumber">
<summary>
Serial number
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.RadioConfigurationParams.RadioAddress">
<summary>
Radio address
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.RadioConfigurationParams.PowerLevel">
<summary>
Power level
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.RadioConfigurationParams.PowerLevelOption">
<summary>
Power level option
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.RadioConfigurationParams.ImpedanceCodeNew">
<summary>
New code for impedance
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.RadioConfigurationParams.ImpedanceCodeOption">
<summary>
Impedance code option
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.RadioConfigurationParams.EncryptionKey">
<summary>
Encryption key
</summary>
</member>
<member name="P:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.RadioConfigurationParams.FrqOffset">
<summary>
Frequency offset
</summary>
</member>
<member name="T:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.RegisterToDb">
<summary>
</summary>
</member>
<member name="M:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.RegisterToDb.#ctor(System.Byte[],System.Byte[])">
<summary>
Register address and value to DB
</summary>
<param name="adresse"></param>
<param name="value"></param>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.RegisterToDb.Adresse">
<summary>
Address
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.RegisterToDb.Value">
<summary>
Value
</summary>
</member>
<member name="T:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.TempTofCalc">
<summary>
Temperature Time Of Flight calculation
</summary>
</member>
<member name="P:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.TempTofCalc.RefDate">
<summary>
Reference data
</summary>
</member>
<member name="P:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.TempTofCalc.RefTemp">
<summary>
Reference temperature
</summary>
</member>
<member name="P:Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.TempTofCalc.Tof">
<summary>
Time Of Flight
</summary>
</member>
</members>
</doc>
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/></startup></configuration>
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/></startup></configuration>
@@ -0,0 +1,697 @@
<?xml version="1.0"?>
<doc>
<assembly>
<name>Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol</name>
</assembly>
<members>
<member name="T:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.Commands">
<summary>
Commands that the genesis meter support over the request protocol.
Functional Specification Breeze Core and Applications Revision:3.03(12748DOC11 - functional spec ICOE472.pdf)
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.Commands.Nop">
<summary>
9.2.5
Command 0x00 (NOP)
This command will do nothing, and will have no response.
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.Commands.QueryCaps">
<summary>
9.2.6
Command 0x01 (Query capabilities)
This command will be used by the external computer to discover the protocol parameters that may be varied.
These can then be compared with the external computers capabilities and the best match selected.
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.Commands.QueryCapsReply">
<summary>
response on <see cref="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.Commands.QueryCaps"/>
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.Commands.SetCaps">
<summary>
9.2.7
Command 0x03 (Set capabilities)
Used to finalize the baud rate and packet settings after negotiation.
The reply will be sent at the currently selected baud rate and packet length,
after which the settings will take effect
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.Commands.SetCapsReply">
<summary>
response on <see cref="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.Commands.SetCaps"/>
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.Commands.Train">
<summary>
9.2.8
Command 0x05 (Train)
This command will perform target driven data training, that is, where the target is in control of the data flow.
See also command 0x11.
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.Commands.TrainReply">
<summary>
response on <see cref="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.Commands.Train"/>
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.Commands.RepeatLast">
<summary>
9.2.9
Command 0x07 (Repeat last)
Used by the external computer to request the last response to be resent, for example if it was found to be corrupted.
Note that the response 0x08 will never be sent, the reply to command 0x07 will be a verbatim resend of the last response.
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.Commands.RepeatLastReply">
<summary>
response on <see cref="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.Commands.RepeatLast"/>
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.Commands.ReadData">
<summary>
9.2.10
Command 0x09 (Read data)
This command makes reads of any random selection of configuration registers, up to the maximum packet size negotiated.
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.Commands.ReadDataReply">
<summary>
response on <see cref="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.Commands.ReadData"/>
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.Commands.WriteData">
<summary>
9.2.11
Command 0x0B (Write data)
This command makes writes to any random selection of configuration registers, up to the maximum packet size negotiated.
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.Commands.WriteDataReply">
<summary>
response on <see cref="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.Commands.WriteData"/>
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.Commands.MultipleReadData">
<summary>
9.2.12
Command 0x0D (Multiple read data)
This command makes reads of one register multiple times, which will be more efficient than performing successive reads using command 0x09.
This command will be available from protocol version 0.40, for earlier protocol versions command 0x09 should be used.
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.Commands.MultipleReadDataReply">
<summary>
response on <see cref="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.Commands.MultipleReadData"/>
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.Commands.MultipleWriteData">
<summary>
9.2.13
Command 0x0F (Multiple write data)
This command makes writes to one register multiple times, which will be more efficient than performing successive reads using command 0x0B.
This command will be available from protocol version 0.40, for earlier protocol versions command 0x0B should be used.
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.Commands.MultipleWriteDataReply">
<summary>
response on <see cref="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.Commands.MultipleWriteData"/>
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.Commands.SetLevel">
<summary>
9.2.14
Command 0x11 (Set level)
This command will perform external driven data training, that is, where the external computer is in control of the data flow.
This command will be available from protocol version 0.42, for earlier protocol versions command 0x05 should be used.
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.Commands.SetLevelReply">
<summary>
response on <see cref="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.Commands.SetLevel"/>
</summary>
</member>
<member name="T:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.ConfigExErrors">
<summary>
Config Exchange error codes.
</summary>
</member>
<member name="T:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.HighLevelErrors">
<summary>
Transport errors for request protocol
</summary>
</member>
<member name="T:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.LowLevelErrors">
<summary>
List of constance for error codes from genesis meter
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.LowLevelErrors.NoError">
<summary>
everything is fine
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.LowLevelErrors.SerialPortClosed">
<summary>
Port is not open
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.LowLevelErrors.SerialPortWriteFailure">
<summary>
fails to write to serial port
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.LowLevelErrors.SerialPortReadFailure">
<summary>
fails to read from serial port
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.LowLevelErrors.MaxDataLength">
<summary>
Command is to long
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.LowLevelErrors.Exception">
<summary>
deeper exception, check out log if this happen
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.LowLevelErrors.CrcCalcError">
<summary>
wrong CRC
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.LowLevelErrors.Unknown">
<summary>
something strange
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.LowLevelErrors.Timeout">
<summary>
Timeout occur
</summary>
</member>
<member name="T:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.RequestAcknowledgeState">
<summary>
Acknowledge feedback from meter after communication
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.RequestAcknowledgeState.CommandNotAssigned">
<summary>
Acknowledge code for unassigned command
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.RequestAcknowledgeState.Unsent">
<summary>
Will be used initially as the record is not sent
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.RequestAcknowledgeState.NoResponse">
<summary>
Response missing
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.RequestAcknowledgeState.CommandError">
<summary>
Response command not match the required command
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.RequestAcknowledgeState.AuthorizationRequired">
<summary>
Lost connection (logged out from meter), a re-authorization is required
to access this command and/or register
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.RequestAcknowledgeState.MeterError">
<summary>
Meter error received, a retry may be useful
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.RequestAcknowledgeState.DecodingError">
<summary>
The response record couldn't be decoded
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.RequestAcknowledgeState.WakeupMessage">
<summary>
The meter sent a wakeup message instead of the required data
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.RequestAcknowledgeState.Ok">
<summary>
Valid meter response record
</summary>
</member>
<member name="T:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Exceptions.RequestProtocolException">
<summary>
Holds all errors can occur on the request protocol
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Exceptions.RequestProtocolException.Command">
<summary>
Exception occurred on this command
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Exceptions.RequestProtocolException.ReceivedData">
<summary>
Exception occurred while receiving this data
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Exceptions.RequestProtocolException.ConfigExErrorCode">
<summary>
Error is interpreted and has a define error code
if its not null is Genesis.Protocols.Request.Const.ConfigExErrors
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Exceptions.RequestProtocolException.HighLevelErrorCode">
<summary>
Error is interpreted and has a define error code
if its not null is Genesis.Protocols.Request.Const.HighLevelError
</summary>
</member>
<member name="M:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Exceptions.RequestProtocolException.#ctor(System.String)">
<summary>
Ctor with only message
</summary>
<param name="message">error message</param>
</member>
<member name="M:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Exceptions.RequestProtocolException.#ctor(System.String,System.Object)">
<summary>
Ctor with message and <see cref="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Exceptions.RequestProtocolException.Command"/>
</summary>
<param name="message">error message</param>
<param name="command"><see cref="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Exceptions.RequestProtocolException.Command"/></param>
</member>
<member name="M:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Exceptions.RequestProtocolException.#ctor(System.String,System.Object,System.Object)">
<summary>
Ctor with message, <see cref="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Exceptions.RequestProtocolException.Command"/> and <see cref="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Exceptions.RequestProtocolException.ReceivedData"/>
</summary>
<param name="message">error message</param>
<param name="command"><see cref="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Exceptions.RequestProtocolException.Command"/></param>
<param name="receivedData"><see cref="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Exceptions.RequestProtocolException.ReceivedData"/> </param>
</member>
<member name="T:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.RequestRecord">
<summary>
Holds request commands with detail parameters to see processing state
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.RequestRecord.ResponseCommand">
<summary>
Indicates the base command <see cref="T:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.Commands" />
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.RequestRecord.Register">
<summary>
the register the command refers to.
needed to set Register dictionary to link response with dictionary key
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.RequestRecord.Acknowledge">
<summary>
Command acknowledged
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.RequestRecord.RetryCtr">
<summary>
Retry counter
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.RequestRecord.WakeupMessageRetryCtr">
<summary>
Wakeup-message retry counter
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.RequestRecord.ResponseErrorBase">
<summary>
indicates error base on <see cref="T:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.RequestRecord"/>
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.RequestRecord.ResponseErrorReason">
<summary>
indicates error reason on <see cref="T:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.RequestRecord"/>
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.RequestRecord.ResponseErrorCode">
<summary>
Combined error code of base and reason
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.RequestRecord.ResponseErrorPosition">
<summary>
Chunk position of error on multiple read/write access
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.RequestRecord.RequestProtocolData">
<summary>
Data containing the request protocol
</summary>
</member>
<member name="P:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.RequestRecord.EncodedRequestData">
<summary>
Encoded with transmit protocol, ready to stream to port as is
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.RequestRecord.ResponsePayload">
<summary>
Extracted payload of response
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.RequestRecord.ResponseTimeoutMs">
<summary>
Extracted payload of response
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.RequestRecord.HideDataInLog">
<summary>
avoid logging for e.g. password
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.RequestRecord.SkipRetryErrorCode">
<summary>
error mask to skip retries for functional errors <see cref="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.RequestRecord.ResponseErrorCode"/>
</summary>
</member>
<member name="M:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.RequestRecord.#ctor(System.Byte,System.Collections.Generic.List{System.Byte},System.Collections.Generic.List{System.Byte},System.Int32,Xylem.Common.Hardware.WaterMeter.Genesis.Registers.RegisterDefinition,System.Boolean,System.UInt16)">
<summary>
Ctor for an base command <see cref="T:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.Commands" />
</summary>
<param name="command"><see cref="T:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.Commands" /> as an byte</param>
<param name="requestProtocolData">Request protocol data for logging</param>
<param name="encodedRequestData"> Ready to send data encoded with transmit protocol retries</param>
<param name="responseTimeoutMs">Timeout for response</param>
<param name="register"><see cref="T:Xylem.Common.Hardware.WaterMeter.Genesis.Registers.RegisterDefinition"/> to do command with</param>
<param name="hideDataInLog">hiding data in log file to avoid spying of passwords</param>
<param name="skipRetryErrorCode">error mask to skip retries <see cref="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.RequestRecord.ResponseErrorCode"/></param>
</member>
<member name="T:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.EventArguments.AuthorizationRequiredEventArgs">
<inheritdoc />
<summary>
if session is gone and a re authorization is necessary
</summary>
</member>
<member name="M:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.EventArguments.AuthorizationRequiredEventArgs.#ctor(Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.RequestRecord)">
<inheritdoc />
<summary>
Ctor
</summary>
<param name="command">this command will be resend after authorization</param>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.EventArguments.AuthorizationRequiredEventArgs.Command">
<summary>
Command to resend
</summary>
</member>
<member name="T:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.RequestProtocol">
<summary>
a bidirectional protocol support read and write genesis meter registers
needed for
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.RequestProtocol._recordsSendFifo">
<summary>
FIFO of records to be send next
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.RequestProtocol._recordInProcess">
<summary>
This is the actual record in the send loop
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.RequestProtocol.LastCommTime">
<summary>
Last communication time for session refresh
</summary>
</member>
<member name="E:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.RequestProtocol.OnRecordReadyToSend">
<inheritdoc />
</member>
<member name="E:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.RequestProtocol.OnRecordIsDecoded">
<inheritdoc />
</member>
<member name="E:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.RequestProtocol.OnAuthorizationGrant">
<summary>
Occurs when a meter Response for write password is good
</summary>
</member>
<member name="E:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.RequestProtocol.OnMeterRegisterUpdated">
<summary>
Event after a register entries changed
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.RequestProtocol.AdditionalRetryTimeoutMs">
<summary>
User adjustable additional retry timeout. This is 0 ms for standard operation.
</summary>
</member>
<member name="M:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.RequestProtocol.#ctor(System.String)">
<inheritdoc />
</member>
<member name="M:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.RequestProtocol.ProcessRecordList">
<summary>
Process all records needed to be sent, this routine has to be called
to kick-off the communication of all RequestRecords saved to the send
FIFO <see cref="M:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.RequestProtocol.AddRecordToSendFifo(System.Byte,System.Byte[],Xylem.Common.Hardware.WaterMeter.Genesis.Registers.RegisterDefinition,System.Boolean,System.UInt16)"/>
</summary>
<remarks date="2018-Dec-07" author="T.Wiedebusch">
- Initial
</remarks>
<remarks date="2018-Dec-09" author="T.Wiedebusch">
- Logging of raw RequestProtocol at time of sending,
- Logging of retries.
</remarks>
<remarks date="2018-Dec-12" author="T.Wiedebusch">
- Added timeout from transmit protocol.
</remarks>
<remarks date="2019-Jan-02" author="Drabesch">
- Added reorder FIFO to bring login at first position
</remarks>
<remarks date="2019-Apr-11" author="T.Wiedebusch">
- Hide data in logging for e.g. passwords
</remarks>
<remarks date="2019-Jun-06" author="T.Wiedebusch">
- Retry counter reset if authorization required and this record will be put back into FIFO,
- Retry delay corrected for all errors.
</remarks>
<remarks date="2019-Jun-12" author="T.Wiedebusch">
- Dynamic retry delay: ResponseTimeoutMs * Retry counter.
</remarks>
<remarks date="2019-Jun-28" author="T.Wiedebusch">
- Skip retries on specific error mask to speed up communication on functional errors
or informational feed backs (e.g FW not installed 0x0004)
<see cref="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.RequestRecord.ResponseErrorCode"/>
</remarks>
<remarks date="2019-Aug-29" author="T.Wiedebusch">
- User adjustable additional retry timeout.
</remarks>
<remarks date="2020-Jan-17/18" author="T.Wiedebusch">
- Response timeout message output,
- Initialize acknowledge code before communication to NoResponse.
</remarks>
<remarks date="2020-Jan-22" author="T.Wiedebusch">
- Response timeout deviated from system time.
</remarks>
<remarks date="2021-Feb-02" author="T.Wiedebusch">
- Avoid enqueue of _recordInProcess if retry counter is 0.
</remarks>
<remarks date="2022-Nov-04" author="T.Wiedebusch">
- Additional DEBUG information included about FIFO and loops.
</remarks>
<remarks date="2022-Nov-07" author="T.Wiedebusch">
- Command not assigned response for recordInProcess == null.
</remarks>
<remarks date="2024-Apr-22" author="T.Wiedebusch">
- Initial request acknowledge state changed from NotDecoded to NoResponse.
</remarks>
</member>
<member name="M:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.RequestProtocol.AddRecordToSendFifo(System.Byte,System.Byte[],Xylem.Common.Hardware.WaterMeter.Genesis.Registers.RegisterDefinition,System.Boolean,System.UInt16)">
<summary>
Assemble record with transmit protocol and put it to record-send-FIFO,
backup the ready-to-send, which is the dataEncodedWithTransmitProtocol,
to the RequestRecord object for sending including the retry capability.
</summary>
<param name="payload">Data package with all details like CRC, etc</param>
<param name="cmd">Command identifier <see cref="T:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.Commands" /></param>
<param name="register"><see cref="T:Xylem.Common.Hardware.WaterMeter.Genesis.Registers.RegisterDefinition" /> which is intend</param>
<param name="hideDataInLog">hiding data in log file to avoid spying of passwords</param>
<param name="skipRetryErrorCode">error mask to skip retries</param>
<returns>the assembled record for the send FIFO</returns>
<remarks date="2018-Dec-08" author="T.Wiedebusch">
- Initial
</remarks>
<remarks date="2018-Dec-09" author="T.Wiedebusch">
- Logging of raw data (RequestProtocol) moved to ProcessRecordList.
</remarks>
<remarks date="2018-Dec-12" author="T.Wiedebusch">
- Added timeout from transmit protocol.
</remarks>
<remarks date="2019-Apr-11" author="T.Wiedebusch">
- Hide data in logging for e.g. passwords
</remarks>
<remarks date="2019-Jun-28" author="T.Wiedebusch">
- Skip retries on specific error mask to speed up communication on functional errors
or informational feed backs (e.g FW not installed 0x0004)
<see cref="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.RequestRecord.ResponseErrorCode"/>
</remarks>
<remarks date="2020-Jan-18" author="T.Wiedebusch">
- Initial skip retry error code set to 0x0004 (e.g FW not installed 0x0004).
</remarks>
<remarks date="2023-Mai-16" author="T.Wiedebusch">
- Hide data in log forwarded to DecodeDateForPhysicalLayer to hide passwords in log files.
</remarks>
</member>
<member name="M:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.RequestProtocol.AddRecordToSendFifoUI1236(System.String,System.Byte[],Xylem.Common.Hardware.WaterMeter.Genesis.Registers.RegisterDefinition,System.Boolean,System.UInt16)">
<summary>
Record dispatcher to send FIFO of UI1236 command
</summary>
<remarks date="2022-Aug-24" author="R.Drabesch">
- Initial
</remarks>
<param name="ident">string for logging of slot</param>
<param name="payload">Data package with all details like CRC, etc</param>
<param name="register"><see cref="T:Xylem.Common.Hardware.WaterMeter.Genesis.Registers.RegisterDefinition" /> which is intend</param>
<param name="hideDataInLog">hiding data in log file to avoid spying of passwords</param>
<param name="skipRetryErrorCode">error mask to skip retries</param>
<returns>the assembled record for the send FIFO</returns>
</member>
<member name="M:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.RequestProtocol.DecodeRecord(Xylem.Common.Hardware.Interfaces.Ports.PortCore.EventArguments.IPortDataEventArgs)">
<summary>
Called after successful response.
Decode and check record, handle Errors and dispatch result.
Invokes <see cref="E:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.RequestProtocol.OnRecordIsDecoded" />if somebody is listening
</summary>
<remarks date="2018-Mar-15" author="R.Drahbesch">
- Initial
</remarks>
<remarks date="2018-Dec-08" author="T.Wiedebusch">
- First part reworked to extract the response protocol information
</remarks>
<remarks date="2019-Apr-11" author="T.Wiedebusch">
- Hide data in logging for e.g. passwords
</remarks>
<remarks date="2019-Jun-28" author="T.Wiedebusch">
- Error code extraction changed for <see cref="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.RequestRecord.SkipRetryErrorCode"/>
</remarks>
<remarks date="2019-Dec-12/16" author="T.Wiedebusch">
- Wakeup-message will avoid further timeout (during FW update this is in the range
of 15000ms).
- Allow one additional retry on decoding error, which is often the wakeup-message.
</remarks>
<remarks date="2019-Jan-17" author="T.Wiedebusch">
- Send time reminder for timeout time calculation as output in log-file,
- OnRecordIsDecoded?.Invoke moved before return to assure that the Acknowledge status is set.
</remarks>
<remarks date="2019-Jan-22" author="T.Wiedebusch">
- Avoid activation of wakeup retry if record is meanwhile acknowledged.
</remarks>
<remarks date="2022-Jul-19" author="T.Wiedebusch">
- Wakeup message handling changed,
- Multiple replies on wakeup message allowed.
</remarks>
<remarks date="2022-Oct-02" author="T.Wiedebusch">
- On wakeup message 5 retires are allowed to avoid an infinite loop.
</remarks>
<remarks date="2022-Oct-04" author="T.Wiedebusch">
- On wakeup message exit this routine.
</remarks>
<remarks date="2023-Feb-13" author="T.Wiedebusch">
- Early exit on _recordInProcess == null,
- Wakeup message retries from 5 to 2,
- Removed error base from error code decision as error base is only the AppId
</remarks>
<remarks date="2023-Sep-01" author="T.Wiedebusch">
- HideDataInLog.
</remarks>
<remarks date="2024-Jan-24" author="T.Wiedebusch">
- Ignore wakeup if message already acknowledged (avoid to set
"_recordInProcess.Acknowledge = RequestAcknowledgeState.NotDecoded"),
- Avoid to overwrite "_recordInProcess.Acknowledge = RequestAcknowledgeState.Acknowledge" with
"RequestAcknowledgeState.WakeupMessage".
</remarks>
</member>
<member name="M:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.RequestProtocol.CommandToMeter(System.Byte,Xylem.Common.Hardware.WaterMeter.Genesis.Registers.RegisterDefinition,System.Byte[],System.Nullable{System.Int32},System.Boolean,System.UInt16)">
<summary>
Method to send basic Commands to Meter. Creates an integer of 4 bytes for the payload.
Supported Commands are: <see cref="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.Commands.ReadData" />,<see cref="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.Commands.MultipleReadData" />,
<see cref="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.Commands.WriteData" />, <see cref="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.Commands.MultipleWriteData" /> and <see cref="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.Commands.QueryCaps" />.
Calculate CRCs and Command length and check if command is valid.
Use <see cref="M:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.RequestProtocol.AddRecordToSendFifo(System.Byte,System.Byte[],Xylem.Common.Hardware.WaterMeter.Genesis.Registers.RegisterDefinition,System.Boolean,System.UInt16)" /> to push data to Port/Meter.
</summary>
<param name="command">
Supported <see cref="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.Commands.ReadData" />,<see cref="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.Commands.MultipleReadData" />,
<see cref="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.Commands.WriteData" />, <see cref="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.Commands.MultipleWriteData" /> and <see cref="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.Commands.QueryCaps" />.
</param>
<param name="meterRegister">Register to Read or Write, null for <see cref="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.Commands.QueryCaps" /></param>
<param name="payload">
Data to push into the <see cref="T:Xylem.Common.Hardware.WaterMeter.Genesis.Registers.RegisterDefinition" />.
must be null on Read Commands ( <see cref="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.Commands.ReadData" />,<see cref="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.Commands.MultipleReadData" />)
and not null on WriteData (<see cref="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.Commands.WriteData" /> and <see cref="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts.Commands.MultipleWriteData" />)
</param>
<param name="expectedLength"></param>
<param name="hideDataInLog">hiding data in log file to avoid spying of passwords</param>
<param name="skipRetryErrorCode">mask to skip reties on error</param>
<returns>an new command just send to port/meter </returns>
<remarks date="2018-Mar-15" author="R.Drahbesch">
- Initial
</remarks>
<remarks date="2018-Dec-08" author="T.Wiedebusch">
- Reworked to zero pad payload with chunks of 4 bytes, the caller needn't take care of the size
</remarks>
<remarks date="2018-Dec-09" author="T.Wiedebusch">
- Corrected payload content in request protocol
</remarks>
<remarks date="2019-Apr-11" author="T.Wiedebusch">
- Hide data in logging for e.g. passwords
</remarks>
<remarks date="2019-Jun-28" author="T.Wiedebusch">
- Skip retries on specific error mask to speed up communication on functional errors
or informational feed backs (e.g FW not installed 0x0004)
<see cref="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.RequestRecord.ResponseErrorCode"/>
</remarks>
<remarks date="2019-Aug-28" author="R.Drabesch">
- Multiple read for string split to simple reads.
</remarks>
<remarks date="2019-Jan-18" author="T.Wiedebusch">
- Default <see cref="F:Xylem.Common.Hardware.WaterMeter.Genesis.GenesisConfig.CommunicationConfig.SkipRetryErrorCode"/> set.
</remarks>
<remarks date="2023-Sep-06" author="T.Wiedebusch">
- MultipleReadData based on data size.
</remarks>
<remarks date="2023-Nov-24" author="T.Wiedebusch">
- Exit multiple read date if retries exceeded.
</remarks>
<remarks date="2024-Apr-11" author="T.Wiedebusch">
- Exit multiple read date if retries exceeded increased to <see cref="F:Xylem.Common.Hardware.WaterMeter.Genesis.GenesisConfig.CommunicationConfig.MaxRequestRetries"/>.
</remarks>
<remarks date="2024-Apr-11 Version 2" author="T.Wiedebusch">
- Rewound to version from 06.09.2023 14:44:33 before Commit 8c9d7704.
</remarks>
<remarks date="2024-Apr-15" author="T.Wiedebusch">
- Removed useless too short comments as every string is going to be delimited by a 0 and usually won't match
to a 4 byte chunk.
</remarks>
<remarks date="2026-Jan-06" author="T.Wiedebusch">
- Removed redundant 'return cRecord'.
</remarks>
</member>
<member name="M:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.RequestProtocol.CheckErrorCode">
<summary>
Analyzes the error code
</summary>
</member>
<member name="M:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.RequestProtocol.ReorderRecordList(System.String)">
<summary>
Reorders the record list so that first entry is the defined topRegister
</summary>
<param name="topRegister"></param>
</member>
<member name="M:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.RequestProtocol.ContainsRegisterIdent(System.String)">
<summary>
Checks the active register to access
</summary>
<param name="registerName"></param>
<returns></returns>
</member>
</members>
</doc>
@@ -0,0 +1,144 @@
<?xml version="1.0"?>
<doc>
<assembly>
<name>Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.StreamingProtocol</name>
</assembly>
<members>
<member name="T:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.StreamingProtocol.StreamingProtocol">
<inheritdoc />
<summary>
Layer between <see cref="T:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.StreamingProtocol.StreamingDecoder" /> CRC16CCITT handler and Events
block trashy telegrams
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.StreamingProtocol.StreamingProtocol._streamingDecode">
<summary>
Decode data and hold results
</summary>
</member>
<member name="E:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.StreamingProtocol.StreamingProtocol.OnRecordIsDecoded">
<inheritdoc />
</member>
<member name="M:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.StreamingProtocol.StreamingProtocol.DecodeRecord(Xylem.Common.Hardware.Interfaces.Ports.PortCore.EventArguments.IPortDataEventArgs)">
<inheritdoc />
</member>
<member name="M:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.StreamingProtocol.StreamingProtocol.#ctor(System.String,System.Boolean)">
<inheritdoc />
</member>
<member name="T:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.StreamingProtocol.StreamingDecoder">
<summary>
Data fields and definitions for GENESIS streaming protocol
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.StreamingProtocol.StreamingDecoder._bendDetectionDefault">
<summary>
Default data for bend detection tests of Genesis
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.StreamingProtocol.StreamingDecoder._dataDefault">
<summary>
Default data for flow tests of Genesis
</summary>
</member>
<member name="F:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.StreamingProtocol.StreamingDecoder._rawDataDefault">
<summary>
Default data for calibration of Genesis
</summary>
</member>
<member name="M:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.StreamingProtocol.StreamingDecoder.#ctor(System.Boolean)">
<summary>
Constructor initializes all decoded members with default values
</summary>
</member>
<member name="P:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.StreamingProtocol.StreamingDecoder.DataCalib">
<summary>
Calibration data
</summary>
</member>
<member name="P:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.StreamingProtocol.StreamingDecoder.DataFlowTest">
<summary>
Flow test data
</summary>
</member>
<member name="P:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.StreamingProtocol.StreamingDecoder.DataBendDetectTest">
<summary>
Bend detection test data
</summary>
</member>
<member name="M:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.StreamingProtocol.StreamingDecoder.DecodeMsg(System.String)">
<summary>
Decoding the raw message
</summary>
<param name="rawMsg">message received as one line delimited with LF</param>
<returns>true if decoding was successful and data has been validated</returns>
<remarks date="2023-Mar-09" author="T.Wiedebusch">
- Modified using common CRC check before branching to the protocol specific decoder.
</remarks>
<remarks date="2023-Dec-06" author="T.Wiedebusch">
- Introduced protocol 'm' for bending detection.
</remarks>
</member>
<member name="M:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.StreamingProtocol.StreamingDecoder.DecodeProtocolM(Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.MeasurementRecords.BendDetectionRecord@,System.Collections.Generic.IList{System.String})">
<summary>
Extracting message from string fields for protocol 'm'
</summary>
<param name="dataBendTestRec">reference to bend detection test record</param>
<param name="fields">Separated fields containing the measurement as string</param>
<returns></returns>
<remarks date="2023-Mar-09" author="T.Wiedebusch">
- Modified using common CRC check in advance.
</remarks>
</member>
<member name="M:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.StreamingProtocol.StreamingDecoder.DecodeProtocolF(Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.MeasurementRecords.FlowTestRecord@,System.Collections.Generic.IList{System.String})">
<summary>
Extracting message from string fields for protocol 'f'
</summary>
<param name="dataFlowTestRec">reference to flow test record</param>
<param name="fields">Separated fields containing the measurement as string</param>
<returns></returns>
<remarks date="2023-Mar-09" author="T.Wiedebusch">
- Modified using common CRC check in advance.
</remarks>
</member>
<member name="M:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.StreamingProtocol.StreamingDecoder.DecodeProtocolG(Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.MeasurementRecords.CalibrationRecord@,System.Collections.Generic.IList{System.String})">
<summary>
Extracting message from string fields to individual raw channel for protocol 'g'
</summary>
<param name="dataProtGRec">Reference to result structure for raw data for one channel</param>
<param name="fields">Separated fields containing the measurement as string</param>
<returns>true if protocol is valid</returns>
<remarks date="2018-Mar-22" author="T.Wiedebusch">
- Usage of VolumeFactorRawToQm and calculation of AccuDutOverflowVolumeCm
</remarks>
<remarks date="2023-Mar-09" author="T.Wiedebusch">
- Modified using common CRC check in advance.
</remarks>
</member>
<member name="M:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.StreamingProtocol.StreamingDecoder.DecodeProtocolH(Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.MeasurementRecords.CalibrationRecord@,System.Collections.Generic.IList{System.String})">
<summary>
Extracting message from string fields to individual raw channel for protocol 'g'
</summary>
<param name="dataProtHRec">Reference to result structure for raw data for one channel</param>
<param name="fields">Separated fields containing the measurement as string</param>
<returns>true if protocol is valid</returns>
<remarks date="2018-Mar-22" author="T.Wiedebusch">
- Usage of VolumeFactorRawToQm and calculation of AccuDutOverflowVolumeCm
</remarks>
<remarks date="2023-Mar-09" author="T.Wiedebusch">
- Modified using common CRC check in advance.
</remarks>
</member>
<member name="T:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.StreamingProtocol.StreamingDecoder.ProtFsubString">
field position in protocol 'f'
</member>
<member name="T:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.StreamingProtocol.StreamingDecoder.ProtMsubString">
field position in protocol 'm'
</member>
<member name="T:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.StreamingProtocol.StreamingDecoder.ProtGsubString">
field position in protocol 'g'
</member>
<member name="T:Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.StreamingProtocol.StreamingDecoder.ProtHsubString">
field position in protocol 'h'
</member>
</members>
</doc>

Some files were not shown because too many files have changed in this diff Show More