Compare commits

...
Author SHA1 Message Date
michal 19ff06b01e PreAdjustment preparation 2026-06-09 16:23:00 +02:00
michal d73eac8332 Merge branch 'develop/SLM-PT50_genesisDirectDecode' into develop/SLM-PT50_genesisDirectDecode_special 2026-06-08 09:17:46 +02:00
marekf a3bfc7a43e Develop - GciBridge -> GCI -> PreadjustmentUI functions 5 2026-06-05 15:21:18 +02:00
michal 63041c0fc9 Increment assembly version to 3.9.3130.0, replace iPerl_Communication_in_progress with Meter_Communication_in_progress across resources and sequences, and update string resources for improved clarity and consistency. 2026-06-04 14:56:56 +02:00
michal 77c131f414 Increment assembly version to 3.9.3129.0, streamline context menu options in iPerlCommunicationForm, consolidate unused menu items, improve PBC_Read_Build_Async with retry logic for slot and PCB ID operations, and optimize GenesisSmartReader communication and debugging. 2026-06-04 11:00:20 +02:00
michal 4173512ecc Increment assembly version to 3.9.3128.0, enhance thread handling for iPerlCommunicationForm with improved delay logic and UI checks, and replace ReadRegisterAsync with ReadRegisterWithRetryAsync for more robust Genesis register operations. 2026-06-04 08:16:13 +02:00
michal c991d530d5 Increment assembly version to 3.9.3126.0. 2026-06-03 12:46:18 +02:00
michal 2ba0bfe2b1 Enhance PrepareSlotQ3Calibration and WriteSlotQ3Calibration methods with improved logging, refined error handling, and additional debug details for iHead operations. 2026-06-03 12:45:03 +02:00
michal 13490009a3 Increment assembly version to 3.9.3125.3. 2026-06-03 10:43:22 +02:00
michal c6849deaef Improve Q3Channel handling by refining water meter result copying logic, enhancing error handling, and updating calibration factor processing for multi-channel scenarios. 2026-06-03 10:27:45 +02:00
michal 0b7dd2bafa Store Q3Channel to DB
Refine water meter processing logic by adding Q3Channel checks and adjusting removal and test result evaluation conditions.
2026-06-03 09:50:31 +02:00
michal 2d8cc912a3 Increment assembly version to 3.9.3124.3, implement GetEachMeterTestRslt method, enhance error handling in calibration-related methods, refine Q3 calibration data simulation and storage logic, and improve debug logging across Genesis operations. 2026-06-03 09:49:34 +02:00
michal 0b246b2ff5 Merge branch 'develop/SLM-PT50_genesisDirectDecode_special_3121_17969' into develop/SLM-PT50_genesisDirectDecode_special
# Conflicts:
#	TBF/Rig/RegisterReaders/GenesisRegReader/communication/OptoHeadTest.cs
2026-05-29 15:52:16 +02:00
michal 8b025a0fca Increment assembly version to 3.9.3121.3, enhance debug logging in PrepareQ3Calibration and related methods, improve calibration factor handling with multi-value support, add exception handling for simulated DB responses, and refine Q3 calibration logic in GenesisSmartReader. 2026-05-29 15:40:20 +02:00
marekf d1b6247bb7 Develop - GciBridge -> GCI -> create database core in GCI - SkeletoKey - CalibParams 2026-05-29 09:43:51 +02:00
michal 0f407920ac Update predefined calibration value in PrepareMeterSizeAndCalibration from 15625 to 17969. 2026-05-29 08:51:51 +02:00
michal 347a8798b8 Enhance Q3 calibration logic by refining PrepareSlotQ3Calibration and WriteSlotQ3Calibration methods, improving handling of TestRsltCalibFactor storage across multiple channels, and extending exception handling and debug logging for Genesis operations. 2026-05-28 14:29:02 +02:00
michal 3cd488fc76 Increment assembly version to 3.9.3121.1, add FailedPrepare error constant and handling in iPerlCommunicationForm, enhance PrepareSlotQ3Calibration and WriteSlotQ3Calibration with exception handling and logging, introduce IsCalibFactorValid property and mappings for calibration logic, and extend debug logging across Genesis operations. 2026-05-27 14:00:40 +02:00
marekf c5f52e06fa Develop - GciBridge -> GCI -> PreadjustmentUI functions 4 2026-05-26 10:51:18 +02:00
michal e88e441875 Refactor preadjustmenActionsViewButton to preadjustmentActionsViewButton, add Q3Channel property to entities and mappings, implement schema migrations for Q3Channel, update GenesisSmartReader Q3Channel logic, replace file paths for clarity, upgrade projects to .NET Framework 4.8, and extend debug logging. 2026-05-25 09:21:32 +02:00
michal 89cfcb75e8 Merge branch 'develop/SLM-PT50_genesisDirectDecode' into develop/SLM-PT50_genesisDirectDecode_special
# Conflicts:
#	GenesisCordonelInterface/UI/LaatzenAPI_CordonelPreadjustmentUI/FrmCordonelPreadjustmentUI.cs
#	TBF/TBF.csproj
2026-05-22 12:58:48 +02:00
michal db90a096e3 Add calibration factor support to Genesis, implement TestRsltCalibFactor entity, related mappings, table creation logic, and data persistence methods. Extend GenesisSmartReader with Q3 calibration enhancements and introduce new debug logging. 2026-05-22 09:18:41 +02:00
marekf 9700ba7900 Develop - GciBridge -> GCI -> PreadjustmentUI functions 3 2026-05-22 08:52:40 +02:00
marekf bc72130d09 Develop - GciBridge -> GCI -> PreadjustmentUI functions 2 2026-05-21 08:16:02 +02:00
michal 6f919ede9b Increment assembly version to 3.9.3104.1, add CheckMeterPrepare functionality and CheckMeterPrepareStr constant in iPerlCommunicationForm, implement error handling and UI safeguarding for communication events, introduce TriggerIdle constant in RadioService, and enhance GenesisSmartReader with CheckMeterPrepare logic and improved debug logging. 2026-05-19 15:21:20 +02:00
marekf ad208f9633 Develop - GciBridge -> GCI -> PreadjustmentUI functions 2026-05-18 19:20:10 +02:00
michal 44b6060113 Increment assembly version to 3.9.3103.1, add HoldSlotStr constant and HoldOn functionality in iPerlCommunicationForm, implement message box synchronization for multi-threaded operations, enhance slot operation handling with ProcessWaterMetersDialogConfirmation, and improve debug logging and error management in Genesis operations. 2026-05-18 16:23:00 +02:00
michal fde090c437 Increment assembly version to 3.9.3102.1, enhance FlyingStartMassCollectionSeq by removing unused code, improve error handling for flow calculations in FlyingStartSeq, extend GenesisSmartReader integration, and introduce WaterMeterParentCopy method for multi-channel handling in test sequences. 2026-05-15 13:02:09 +02:00
michal 0af975f670 Increment assembly version to 3.9.3101.1, increase thread support to 10 across relevant configurations, extend Genesis communication ranges, enhance debug logging for slot initialization, and update Genesis configuration controls with parallel access parameters. 2026-05-15 10:39:37 +02:00
michal 6d0d2cd34e Increment assembly version to 3.9.3100.1. 2026-05-15 08:02:46 +02:00
michal d9a14ea3e1 Increment assembly version to 3.9.3098.1, add Q3 calibration support in iPerlCommunicationForm, implement PrepareSlotQ3Calibration and WriteSlotQ3Calibration methods in OptoHeadTest, extend GenesisSmartReader with Q3 calibration logic, and update slot operation and test sequence handling to include calibration-related data. 2026-05-15 08:02:28 +02:00
marekf ad2bfd3639 Upgrade (develop) - GCI - GciBridge - improved Disconnect 2026-05-14 13:05:21 +02:00
michal 2526e997e3 Increment assembly version to 3.9.3097.1, add SlotGroupedLogin support in iPerlCommunicationForm, implement GroupedLoginSlot method in OptoHeadTest, and update slot operation logic with enhanced error messaging. 2026-05-13 12:57:23 +02:00
michal d346dcfa03 Merge branch 'develop/SLM-PT50_genesisDirectDecode' into develop/SLM-PT50_genesisDirectDecode_special
# Conflicts:
#	GenesisCordonelInterface/API/InterfaceGCIToLaatzen.cs
#	TBF/Rig/BridgeComponents/GciBridge/GciBridge.cs
#	TBF/TBF.csproj
2026-05-13 10:03:46 +02:00
michal 8437952478 Increment assembly version to 3.9.3095.1, expand iPerlCommunicationForm with new slot-related constants and error definitions, implement slot handling methods in OptoHeadTest, introduce PcbReadResult for PCB reading flow, and enhance connection and slot operation logic. 2026-05-13 09:48:41 +02:00
marekf 5e637ae02e Upgrade (develop) - GCI - GciBridge - full parallel threading slots actions 2026-05-13 09:30:27 +02:00
michal 34bf5d5473 Increment assembly version to 3.9.3094.1, extend iPerlCommunicationForm with new context menu options and associated slot handling, introduce bend detection support in Genesis streaming protocol, add data members for radio configuration, and enhance asynchronous operations in JSON handling. 2026-05-12 16:03:28 +02:00
marekf 63f8dd7467 Upgrade (develop) - GCI - GciBridge - InitSlot() - only ports config update if slot already exists 2026-05-12 14:59:15 +02:00
marekf aac3af8714 Upgrade (develop) - GCI - GciBridge - delete meter.Logout() in GetPcbId() 2026-05-12 14:20:24 +02:00
michal 6c4c7e73bb Merge branch 'develop/SLM-PT50_genesisDirectDecode' into develop/SLM-PT50_genesisDirectDecode_special 2026-05-12 14:00:42 +02:00
marekf 378917f59d Upgrade (develop) - GCI - GciBridge - GCI-Laatzen interface debugging 2026-05-12 13:30:21 +02:00
michal f97c406ae8 Update DLL references for Xylem.Common components across hardware and metrology modules. 2026-05-12 07:51:02 +02:00
michal 9cfadb8075 Merge remote-tracking branch 'private-origin/develop/SLM-PT50_genesisDirectDecode_special' into develop/SLM-PT50_genesisDirectDecode_special 2026-05-12 07:50:18 +02:00
michal 1709ef842d Refactor iPerlCommunication module to integrate GenesisSmartReader, update related logic and methods, optimize asynchronous operations, and increment assembly version to 3.9.3091.1. 2026-05-12 07:50:03 +02:00
michal 8e694dc910 Refactor iPerlCommunication module to integrate GenesisSmartReader, update related logic and methods, optimize asynchronous operations, and increment assembly version to 3.9.3091.1. 2026-05-12 07:49:13 +02:00
michal 0b1e09e0df Merge branch 'develop/SLM-PT50_genesisDirectDecode' into develop/SLM-PT50_genesisDirectDecode_special
# Conflicts:
#	TBF/TBF.csproj
2026-05-11 17:29:13 +02:00
marekf 76e7ccb4a6 Update (develop) - GCI - GciBridge - better return for Connect 2026-05-11 17:14:56 +02:00
michal 84307f4bf4 Merge branch 'develop/SLM-PT50_genesisDirectDecode' into develop/SLM-PT50_genesisDirectDecode_special 2026-05-08 12:25:23 +02:00
michal 463fb16b23 Remove iPerlCommunication module entirely.
Deleted all related classes, configurations, and implementations for the `iPerlCommunication` module, including `TestMethod`, `TestMethodCfg`, and associated components. This cleanup reflects either a deprecated or unused feature.
2026-05-08 12:24:42 +02:00
marekf 953b02a6e8 Upgrade (develop) - GCI - GciBridge - new CleanSlot() - Disconnect Hard Dispose 2026-05-08 11:49:14 +02:00
michal b4c0384b57 Refactor RadioService for improved asynchronous handling, consolidate unused namespaces, update OptoHeadTest logic, and increment assembly version to 3.9.3085.1. 2026-05-08 10:44:27 +02:00
michal f4b8e42f59 Merge branch 'develop/SLM-PT50_genesisDirectDecode' into develop/SLM-PT50_genesisDirectDecode_special
# Conflicts:
#	TBF/Rig/RegisterReaders/GenesisRegReader/communication/RadioService.cs
2026-05-07 21:37:05 +02:00
michal abee5fa6b1 Update DLL references for Xylem.Common components across multiple modules. 2026-05-07 21:33:41 +02:00
michal b8926ef93f Add unit tests for OptoHeadTest handling simulated Genesis readers, refine project references, and increment assembly version to 3.9.3079.1. 2026-05-07 21:30:19 +02:00
marekf 71a66dca2d File modified due to the need for MF to compile in advance, but the change is ultimately not necessary for either MF or MB 2026-05-07 18:23:50 +02:00
marekf 978c620287 Update (develop) - GCI - GciBridge - improved PublicModels - fixed bugs 2026-05-07 18:20:18 +02:00
michal 502804c2de Merge remote-tracking branch 'private-origin/develop/SLM-PT50_genesisDirectDecode' into develop/SLM-PT50_genesisDirectDecode 2026-05-06 15:32:41 +02:00
michal 296621a590 * Increment assembly version to 3.9.3069.1
* Logs update
2026-05-06 15:32:33 +02:00
marekf 8489dafdf7 Update (develop) - GCI - GciBridge - progress 2026-05-06 14:58:44 +02:00
michal cfc52f195b Merge remote-tracking branch 'private-origin/develop/SLM-PT50_genesisDirectDecode' into develop/SLM-PT50_genesisDirectDecode
# Conflicts:
#	TBF/TBF.csproj
2026-05-06 10:26:15 +02:00
michal 68a1eb9941 Update project references and paths to replace project dependencies with direct DLL references. Standardize formatting in GenesisImplHeadTestCtrl and refine Operations enum declarations. 2026-05-06 10:24:33 +02:00
marekf c1573390b5 Merge branch 'develop/UnionTown' into develop/SLM-PT50 2026-05-06 09:08:09 +02:00
marekf 5d60523e87 Fixed - next issue with old Newtonsoft.Json v 12.0 - updated to 13.0 2026-05-06 07:38:49 +02:00
marekf 91c63e0792 Fixed - bad copying GenesisCordonelInterface runtime files to TBF target folder 2026-05-06 07:35:17 +02:00
marekf 0940df2f1a Fixed - issue with old Newtonsoft.Json v 12.0 - updated to 13.0 2026-05-06 07:32:55 +02:00
michal 16a76720b8 Update references and paths for Xylem.Common components, refine OptoHeadTest handling for connection requests, and increment assembly version to 3.9.3063.1. 2026-05-05 08:34:21 +02:00
marekf 7101fd679e Merge branch 'develop/UnionTown' into develop/SLM-PT50 2026-05-04 15:45:07 +02:00
marekf 86299da682 Fixed - bad runtime files copying in postbuilding of GenesisCordonelInterface project. Copying is replaced from TBF/Build/ to GCI/Build 2026-05-04 15:40:05 +02:00
marekf 39b951b709 Merge branch 'develop/UnionTown' into develop/SLM-PT50 2026-05-04 13:08:10 +02:00
marekf a475bd80f3 Change - ExternalProjects folder to gitignore 2026-05-04 13:07:28 +02:00
marekf 4e64bcd117 Merged branch Uniontown - GenesisCordonelInterface + GciBridge 2026-05-04 12:49:02 +02:00
marekf fbd0219a4a Update (develop) GCI - GciBridge - big change - for implement to GenesisHead and SmartReader 2026-05-04 11:29:13 +02:00
michal 104a68d9dc Remove unused System.IO.Ports, Common, Config, and other redundant namespaces. Update NuGet package configurations to reflect new paths and tools. 2026-04-29 09:51:05 +02:00
michal 33a5e479a9 Refactor RadioService to improve asynchronous handling, replace legacy code with CommInterfaceBridge, and standardize methods for GenesisHead communication. Remove unused GenesisCommunication components and increment assembly version to 3.9.3062.1. 2026-04-28 16:26:26 +02:00
michal 5482d4ac96 Merge remote-tracking branch 'private-origin/develop/SLM-PT50_genesisDirectDecode' into develop/SLM-PT50_genesisDirectDecode
# Conflicts:
#	TBF/Rig/TestMethods/GenesisCommunication/GenesisHead/GenesisHead.cs
#	TBF/TBF.csproj
2026-04-28 07:51:09 +02:00
michal 0d984a77b3 Refactor RadioService to utilize GciBridge for communication, replace SerialDriver, and add SlotNr support in Genesis configuration and UI. 2026-04-28 07:08:53 +02:00
marekf 7e95e18207 Fixed - genesis library path issue 2026-04-27 16:52:50 +02:00
marekf 38fa86d243 Merge branch 'develop/UnionTown' into develop/SLM-PT50 2026-04-27 16:42:47 +02:00
marekf 4c1ce73de9 Upgrade (develop) - GCI - GciBridge - big change 2026-04-27 16:40:42 +02:00
michal eea80d39c0 Remove GenesisCommunication test methods and components:
- Deleted `CalibrationStruct`, `ConfigStruct`, `Enums`, `Factory`, `GenesisHead`, and related files.
2026-04-27 10:48:27 +02:00
marekf 15dc325275 Upgrade (develop) - GCI - big change 2026-04-27 07:57:16 +02:00
marekf ca333d1772 Upgrade (develop) - GCI UI for TBF - change Forms to Views 2026-04-26 11:40:21 +02:00
marekf a4ece06b05 Upgrade (develop) - GCI UI for TBF - change Forms to Views 2026-04-26 11:39:35 +02:00
marekf 992452052e Upgrade GenesisCommunication - after adding GCI functionality to xylem DLL's updater, adding PortCore DLL is needed 2026-04-26 09:32:30 +02:00
marekf 75192bbd09 Add (develop) GCI - new functionality - xylem DLL's updater for TBF - actualize DLL's in TBF.packages.common of TBF project path - fixed problem witch multiple referencing of GenesisCommunication and GciBridge on one DLL but with difference version 2026-04-26 08:13:43 +02:00
marekf 6199bd48c5 Upgrade .NET Framework 4.7.2 to 4.8 for Laatzen + GCI + TBF compatibility 2026-04-24 13:00:53 +02:00
marekf 25434d70d4 Merge branch 'feature/task/Cordonel-communiation-tests' into develop/SLM-PT50 2026-04-23 10:00:59 +02:00
michal de6dd45dcb Fix Flow - Increment assembly version to 3.9.3059.1. 2026-04-23 09:56:32 +02:00
marekf 74f2e99ed3 Merge branch 'bugfix/Flow-meter-in-parallel-reverse-bug' into develop/SLM-PT50 2026-04-23 09:43:39 +02:00
marekf 99b1f4a171 Fixed FlowMetersInParallel - incorrect ltrPerPulse counting from average value of nominalFreq 2026-04-23 09:40:05 +02:00
marekf 8c10aa3752 Add (develop) GCI - GciBridge 2026-04-23 09:09:27 +02:00
michal 7170da4a70 Add GenesisCommunication test methods and related components:
- Introduce `TestMethod`, `SequenceConditionOp`, and `Factory` for `GenesisCommunication`.
- Add `TestMethodCfgCtrl` and its designer for test configuration UI.
- Update `.csproj` to include new files.
2026-04-22 10:18:42 +02:00
michal 842f009b42 Increment assembly version to 3.9.3058.1 and fix logging format issue in FlowMeter initialization. 2026-04-21 07:43:35 +02:00
michal 7f30ca0cd1 Merge branch 'develop/SLM-PT50_genesisDirectDecode' into develop/SLM-PT50_genesisDirectDecode_morisville
# Conflicts:
#	TBF/Properties/AssemblyInfo.cs
#	TBF/Rig/RegisterReaders/GenesisRegReader/implementations/GenesisSmartReader.cs
2026-04-20 14:25:13 +02:00
michal 93e207c211 Update GenesisSmartReader for refined start/end marker logic, add _endDeltaSeconds property, and improve telegram index resolution methods. Increment assembly version to 3.9.3031.1. 2026-04-20 13:25:25 +02:00
marekf 64cafc088a Merge branch 'bugfix/Flow-meter-in-parallel-reverse-bug' into develop/SLM-PT50 2026-04-20 12:45:25 +02:00
marekf 8a0da27a07 Fixed RegValve + FlowMetersInParallel - incorrect NominalFreq sum 2026-04-20 12:39:51 +02:00
michal 5a8478e782 Refactor GenesisSmartReader Q3 calibration tests and logic:
- Expand Q3 calibration tests with diverse scenarios in `GenesisSmartReader_Q3Test`.
- Introduce channel-specific validation for calibration tests.
- Adjust methods for Q3 calibration in `GenesisSmartReader` to support per-channel factors.
- Add utilities for preparing simulation data and refinements for test consistency.
- Update `CliRunner` with improved task management, timeout handling, and logging enhancements.
2026-04-17 16:05:16 +02:00
marekf 368cd95114 Bug (fixing) RegValve OK, FlowMeterInParallel NOK 2026-04-15 10:50:27 +02:00
michal 33ef914984 Update GenesisReaderTests: add real input parsing, format variation handling, and rollover cases; remove outdated Q3 calibration tests; increment version to 3.9.3056.1 2026-04-15 09:56:54 +02:00
michal 3eb0b87f0d Add Q3 calibration tests for GenesisSmartReader and refactor test cases:
- Introduce new `GenesisSmartReader_Q3Test` class with comprehensive Q3 calibration scenarios.
- Refactor existing tests to utilize simulation data for better consistency and validation.
- Adjust Q3 calibration logic in `GenesisSmartReader` to enhance calculation accuracy and validation criteria.
2026-04-15 09:22:09 +02:00
marekf c13cb725f0 Merged branch > UniDataStorageWriter-and-UniDataStorageReader 2026-04-15 09:13:57 +02:00
marekf c6d4a016b5 Add (develop) GCI - interface of GCI and Laatzen - GciBridge component 2026-04-15 08:46:19 +02:00
marekf eda0644b4b Add (develop) GCI - interface of GCI and Laatzen 2026-04-15 08:41:27 +02:00
michal 711dfc03ef Fix Q3 calibration logic in GenesisSmartReader: replace _rawStartEndByChannel with recalculatedVariablesByChannel for accurate data computation. 2026-04-14 15:54:28 +02:00
michal 93459ccfab Refactor water meter handling in SequenceBase and FlyingStartMassCollectionSeq:
- Enhance logic for enabling/disabling channels based on water meter data.
- Introduce Q3 calibration validation in `GenesisSmartReader` with configurable thresholds.
- Update `GenesisCfgCtrl` UI to disable certain inputs.
2026-04-14 15:41:13 +02:00
marekf 5b73835d94 Add (develop) GCI - interface of GCI and Laatzen 2026-04-14 12:33:06 +02:00
michal 009aefb7c9 Refactor GenesisSmartReader and SequenceBase logic, enhance channel handling in water meters, and update GUI components:
- Adjust `Disabled` logic for water meters in `SequenceBase` allowing conditional enabling of channels based on serial number.
- Introduce `EnableShowChanels` property in `GenesisSmartReader` and integrate into `FlyingStartMassCollectionSeq`.
- Modify `StartupFlushMs` to derive configuration dynamically.
- Update `GenesisCfgCtrl` with a checkbox for enabling channels and input for flush timing.
- Increment assembly version to `3.9.3054.1`.
2026-04-14 08:03:02 +02:00
michal d2e18d615d Bump assembly version to 3.9.3053.1. 2026-04-13 14:17:56 +02:00
michal 69b475eb77 Refactor GenesisSmartReader for improved simulation and testing:
- Add `PrepareCalculatedChannelDataSimulationForTest` and supporting utility methods for generating and cloning test data.
- Update `StartupFlushMs` and sampling intervals for increased flexibility.
- Revise water meter handling logic in `FlyingStartMassCollectionSeq` to support multiple channels.
2026-04-13 14:17:34 +02:00
marekf 9848b97082 Update (develop) UniDataStorageWriter - first successful version 2026-04-13 12:21:52 +02:00
marekf 0b429ffbc2 Merge branch UniDataStorageReader 2026-04-12 10:53:53 +02:00
marekf ef146efaf0 Merge branch UniDataStorageWriter 2026-04-12 10:49:16 +02:00
marekf 431061a685 Add (developing) UniDataStorageWriter 2026-04-12 02:38:58 +02:00
marekf b6edd9c0a0 Add (developing) UniDataStoreWriter 2026-04-12 02:37:14 +02:00
michal 2210bb8240 Enhance FlyingStartMassCollectionSeq with GenesisSmartReader support; add water meter handling logic and bump assembly version to 3.9.3050.1. 2026-04-11 21:55:34 +02:00
marekf 8d7c1adf37 Update (developing) UniDataStorageReader 2026-04-11 20:49:11 +02:00
marekf 3376ac41b4 Merge branch 'develop/SLM-PT50_genesisDirectDecode' of http://87.197.120.129:33300/michal/tbf into develop/SLM-PT50 2026-04-11 11:54:37 +02:00
marekf f9181fee74 Fixed SelectComponentDlg > missing assignment sharedSearchForListBox1.ListBoxEx = availCmpntsLstBox, because of this the application crashes 2026-04-11 11:04:00 +02:00
marekf 4c77d6c06e Add (develop) GenesisCordonelInterface changed project name 2026-04-11 09:33:05 +02:00
marekf b7db39853b Add (develop) GenesisCordonelinterface add TBF.sln project name 2026-04-09 16:44:48 +02:00
marekf 66157ba988 Add (develop) GenesisCordonelinterface - changed GenesisCordonelTester to GenesisCordonelInterface, Add new FormCordonelPreadjustmentUI by Laatzen tool 2026-04-09 16:41:29 +02:00
michal 65ab19290f simulate mode - flow reached 2026-04-09 12:49:00 +02:00
marekf e7e6fc7920 Add (develop) Genesis Cordonel interface - used Laatzen tools in our new tool GenesisCordonelTester 2026-04-09 10:12:00 +02:00
michal 94c7279da1 Add localized string resources for "Test in calculation" and integrate it into FlyingStartMassCollectionSeq
- Add `Test_in_calculation` localized strings to `.resx` files for English, Slovak, and Czech.
- Update `FlyingStartMassCollectionSeq` to display the new activity message during the calculation phase.
2026-04-09 10:08:50 +02:00
michal 2136695b80 Fix Stop 2026-04-08 16:37:27 +02:00
michal c0f9b0ffa0 Refactor GenesisSmartReader stop logic for enhanced thread safety and post-processing; bump assembly version to 3.9.3047.1. 2026-04-08 15:44:59 +02:00
michal c4ef22436f Update GenesisSmartReader Stop logic and bump assembly version to 3.9.3045.1:
- Refactor `Stop` for improved thread safety using `lock` on `_stateSync` and `_stopSync`.
- Enhance `Stop` behavior by introducing state updates during immediate stop requests.
- Fix redundant operations and reorganize log and processing statements for clarity.
- Update `RequestImmediateStopInternal` to accept a new state parameter.
2026-04-08 15:06:45 +02:00
michal 0b73871518 Refactor GenesisSmartReader and add advanced test utilities:
- Introduce `ForceProcessingEnabled`, `InstallSuccessfulProcessingOverride`, and `EnqueueIncomingLine` helpers to streamline test setup.
- Add new test suite `GenesisSmartReaderStopTests` to validate `Stop` behavior for different processing states.
- Enhance `GenesisSmartReader` state management with a dedicated `Reset` method and improved `Stop` logic.
- Improve buffer initialization in `ProcessOptoLine` to address null-value edge cases.
- Update assembly version to `3.9.3043.1`.
2026-04-08 13:51:55 +02:00
michal f7dc6fee5e immediate Stop improve 2026-04-07 16:37:19 +02:00
michal ba848a167d improve 2026-04-07 15:44:32 +02:00
michal dcb0bf9a88 Update GenesisSmartReader logging and bump assembly version to 3.9.3040.1:
- Enhance `Stop` logs with `registerReader` and `optoSerialPort` details for improved traceability.
2026-04-07 15:27:20 +02:00
michal f6433134c1 Add WaitForStartupFlushToFinish and EnableProcessingLoopForTests utilities for improved test reliability:
- Incorporate `WaitForStartupFlushToFinish` in `GenesisSmartReaderThreadedReadTests` to ensure startup flush completion before processing.
- Introduce `EnableProcessingLoopForTests` in `GenesisSmartReaderTest` to streamline test initialization.
- Fix thread-safety issues in startup flush handling and reorder operations in `GenesisSmartReader.Stop`.
- Bump assembly version to `3.9.3039.1`.
2026-04-07 14:45:37 +02:00
michal 7e3df77b5b Refactor GenesisSmartReader processing logic and tests for robust handling:
- Replace property getters with concise expressions in `GenesisSmartReader`.
- Implement FIFO and concurrent producer-consumer unit tests for `ProcessingLoop`.
- Add startup flush mechanism for improved input handling on initialization.
- Refactor processing loop with structured start/stop tasks and cancellation tokens.
- Fix thread-safety issues and enhance logic in `Stop` and `StopDataStreamProcessing`.
- Add internal visibility for tests in `TBFTests` via `InternalsVisibleTo`.
- Update assembly version to `3.9.3038.1`.
2026-04-07 10:42:27 +02:00
marekf ff5954d85b Bugfix FlowMeterInParallel and RegValve OUT OF RANGE regulation part1 2026-04-02 12:02:26 +02:00
michal 08dff1272b Add overflow volume/timestamp handling and related tests for GenesisSmartReader:
- Extend `CalibrationRecord` constructor to include overflow fields (`OverflowVolumeCm`, `OverflowTimeS`).
- Implement additional unit tests in `OptoTelegramRawTest` to validate multi-rollover scenarios and extended calculations.
- Add `GenesisSmartReaderThreadedReadTests` to cover threaded read-loop functionality and serial processing.
- Enhance logging in `Pump` classes (`TurnOff` methods).
- Update project file to include new test files.
2026-04-02 09:25:17 +02:00
marekf c09e266b2c Bugfix ComponentPropertiesDlg frm size 140x80 2026-04-01 12:12:04 +02:00
michal d5c8fd1c8f Refactor GenesisSmartReader with enhanced channel-specific volume and timestamp processing:
- Replace `AverageNullable` with `AverageCachedTime` and introduce `GetCachedVolume`/`GetCachedTime` helpers.
- Add recalibration logic with `_recalculatedStartEndByChannel` and `_rawStartEndByChannel`.
- Implement `PrepareCalculatedChannelData` for refined multi-channel synchronization.
- Add unit tests (`GenesisSmartReaderChannelTests`) for improved coverage and validation of new methods.
- Update `OptoTelegramRaw.Copy` to fix field assignment issues.
2026-03-27 15:12:43 +01:00
michal a34740e838 Update GenesisSmartReaderTest to handle DiscardOutCalls and configure block repetition resets:
- Modify tests to validate `DiscardOutCalls` alongside `DiscardInCalls`.
- Add support for configuring `ResetAfterBlockRepetitions` in test initialization.
2026-03-27 13:19:10 +01:00
michal 836ba5a41f Refactor GenesisSmartReader processing logic and add advanced multi-channel volume and timestamp handling:
- Introduce `TimeDeltaPerChannel` and `GroupRecordsPerChannel` for calculating time and volume deltas across channels.
- Add recalibration logic to synchronize volume and timestamp data with channel-specific maxima.
- Fix `ResetDataBuffer` implementation and replace redundant `ReasetDataBuffer` calls.
- Update handling of flow markers and block completion logic for improved buffer management.
- Add `Copy` method to `OptoTelegramRaw` for efficient cloning and recalculation.
- Bump `AssemblyVersion` and `AssemblyFileVersion` to `3.9.3019.1`.
2026-03-27 13:18:37 +01:00
marekf 545a747ebc Add UniDataStorageWriter component - initial commit 2026-03-27 12:49:35 +01:00
michal 23c83ab452 Enhance GenesisSmartReader multi-channel processing and add tests for telegram handling:
- Refactor `ProcessOptoLine` logic to support output buffer resets at configurable repetition intervals.
- Add tests:
  - `ProcessOptoLine_Block_f_h1_h2_h3_f_ShouldResetBuffersOnlyAfterLastF`
  - `ReadOptoData_FullBlock_ShouldDiscardBuffersAfterClosingF`
  - `ProcessOptoLine_LastF_AfterH3_ShouldRequestBufferReset`
  - `ProcessOptoLine_ShouldReset
2026-03-26 14:45:36 +01:00
michal bc9e583c29 FIX Add ChannelAverages to project and remove unused imports in GenesisHead. 2026-03-26 07:29:13 +01:00
michal 18cef617da Enhance Genesis SmartReader with channel-specific volume and timestamp tracking:
- Add per-channel `VolumeStart`, `VolumeEnd`, `TimeStart`, and `TimeEnd` processing for improved multi-channel support.
- Introduce `ChannelAverages` for centralized average calculations across channels.
- Refactor `GenesisSmartReader` to improve data decoding and logging for calibration and flow test records.
- Add telemetry unwrapping helpers for precise volume and timestamp calculations.
- Update `OptoTelegramRaw` to support channel-specific updates and robust data processing.
- Update `AssemblyVersion` and `AssemblyFileVersion` to `3.9.3013.1`.
2026-03-26 07:19:22 +01:00
michal 4ee736cff5 Add advanced multi-channel processing for Genesis SmartReader:
- Refactor `VolumeLtrStart` and `VolumeLtrEnd` to compute channel-specific averages at test boundaries.
- Implement `ProcessOptoLine_ShouldInsertTelegrams` tests for validating telegram insertion and channel updates.
- Add `VolumeLtrEnd_ShouldAverageOnlyAvailableChannels` to handle partial channel data gracefully.
- Introduce `VolumeFromChannelsAtStart` and `VolumeFromChannelsAtEnd` helpers for refined channel data handling.
- Update Opto telegram processing logic to support robust volume and timestamp unwrapping.
- Enhance `GenesisSmartReader.ToString()` for clearer configuration representation.
- Add `OptoTelegramRawTest` to validate telegram behavior, flag handling, and delta computations.
- Update `AssemblyVersion` to `3.9.3012.1`.
2026-03-24 15:23:06 +01:00
michal 4e40dc8601 Comment out Detect_BaudRate_By_ViewFactoryId test method in TouchReadBaudRateDetectionTests. 2026-03-24 10:07:24 +01:00
michal a5a68ec457 Refactor Genesis serial communication handling (ISerialDriver interface compatible with SerialPort):
- Replace method-based `IsOpen()` checks with property-based `IsOpen` usage in `ISerialDriver` and related classes.
- Simplify `Open()` and add `Close()` methods to unify connection management.
- Introduce `InitializeThreeChannelState()` helper in `GenesisSmartReaderTest` for multi-channel state initialization.
- Adjust calculations in `CalculateTimeByChannels()` and `CalculateVolumeByChannels()` for clarity.
- Add new tests for multi-channel processing and validation of updated telegram handling logic.
2026-03-24 10:04:30 +01:00
michal e26d88d437 Refactor Genesis use 3 chanels reader structure:
- Replace `Xylem.Common` namespace references with `TBF.Rig.RegisterReaders`.
- Introduce `GenesisSmartReaderTest` and `FakeSerialDriver` for unit testing.
- Revamp `FlowDirectionDetection` to support multiple channels.
- Make constants in `StreamingDecoder` public for enhanced accessibility.
- Update `AssemblyVersion` and `AssemblyFileVersion` to `3.9.3010.1`.
2026-03-24 08:53:16 +01:00
marekf 98ba7d2dee Update UniDataStorageReader developing 2026-03-19 19:28:16 +01:00
marekf 78835c1af6 Add UniDataStorageReader initial commit 2026-03-19 16:30:32 +01:00
michal 2522d1da9f Add Genesis radio/opto communication and configuration components
- Replace `OpthoHeadService` with `RadioService` to enhance Genesis communication handling via serial interface.
- Introduce `OptoReceivedEventArgs` to manage event-driven communication.
- Add foundational protocol implementations (`BaseProtocol`, `IProtocol`, etc.) for Genesis configuration and processing.
- Implement `SirtConfig`, `MeterConfig`, and `ProcessConfig` classes for flexible Genesis configuration management.
- Expand Genesis framework to support diagnostics, activity modes, and version retrieval.
2026-03-18 15:57:04 +01:00
michal 8983c01591 Add integration tests for IperlHat communication and diagnostic LED parsing
- Implement `IperlHatIntegrationTests` to validate serial communication, diagnostic LED states, and Opto data handling.
- Add `HexFormatterTest` for verifying Hex formatting utilities.
- Add `DiagnosticLedParserTest` to test parsing for all diagnostic LED states.
2026-03-17 12:15:52 +01:00
michal 61b1320d4f Add Genesis COM port configuration and update Genesis meter setup logic
- Introduce `OptoComPortNr` and `HeadComPortNr` properties in `GenesisHead`.
- Update `SetupGenesisMeter` to use new COM port configurations.
- Add reference to `Xylem.Common.Hardware.WaterMeter.Genesis.GenesisConfig`.
2026-03-16 15:48:41 +01:00
michal 2c8a0922d1 Genesis dialog with Com ports 2026-03-16 15:47:12 +01:00
michal b078d9586d Add detailed logging for Genesis operations in FlyingStartMassCollectionSeq and FlyingStartSeq.
- Introduce debug and info logs for Genesis initialization, calibration, measurement, and data storage.
- Ensure proper logging during Genesis operations' start and stop phases.
2026-03-16 15:42:45 +01:00
michal 6e35de5f4d Update AssemblyVersion and AssemblyFileVersion to 3.9.3001.1 2026-03-16 15:36:25 +01:00
michal 2dbe4cded4 Genesis slot max count 10, Add DB writer component
Integrate `DatabaseWriter` component and update GenesisHead configuration:

- Add `DatabaseWriter` factory and related classes (`WriteDBCfgCtrl`, `WriterCfg`, `WritingToDB`).
- Extend GenesisHead slot number range to 1-10 and adjust UI layout accordingly.
2026-03-16 15:36:02 +01:00
michal 10865c6878 Update AssemblyVersion and AssemblyFileVersion to 3.9.3000.1 2026-03-16 15:35:06 +01:00
michal ee1353fe54 Add DatabaseWriter component:
- Implement `DatabaseWriter` factory and configuration logic.
- Add `WriteDbCfgCtrl` for component configuration UI.
- Introduce database connection handling, network adapter selection, and tracing record management.
2026-03-16 15:31:58 +01:00
michal 5cefd7fc3a Integrate Genesis meter support into FlyingStartMassCollectionSeq:
- Add initialization, calibration, and measurement logic for Genesis meters.
- Extend result handling to capture Genesis-specific data (timestamps, volumes, errors).
- Ensure proper cleanup of Genesis meters at test conclusion.
2026-03-16 15:31:49 +01:00
michal ab0e5ea82a Genesis heap 2026-03-16 15:17:56 +01:00
michal b2276c086c Merge branch 'develop/SLM-PT50' into develop/Mexico 2026-03-16 13:33:21 +01:00
michal 4fa462661c Merge remote-tracking branch 'remotes/private-origin/develop/SLM-PT50' into develop/Goeteborg 2026-03-16 13:11:34 +01:00
michal 2b30d0cf34 packages add/clean up 2026-03-13 13:51:42 +01:00
michal df2c56e6c4 FIX NaN - devide by zero
Add simulation logic to `StandingStartStopTestOp` and handle zero `TestTime` edge cases in `FlyingStartMassCollectionSeq`
2026-03-12 16:25:26 +01:00
michal a997c3d7be iPerl ASIC - implementation 2026-03-12 14:50:47 +01:00
marekf 3c964f2aab BugFix - repair test RegisterReader deserialize - FSMC method as in SSMC 2026-03-09 14:37:51 +01:00
marekf c445b3e098 BugFix - after applying the transition valve 40% in procedure-purge begin, the RegValve was not regulating correctly after starting the test 2026-03-09 14:20:37 +01:00
marekf 2ea2a2592e Merge branch 'feature/task_6-add-new-admins' into develop/SLM-PT50 2026-03-04 19:14:22 +01:00
marekf 27072598cd Merge branch 'feature/task_5-new-app-icon' into develop/SLM-PT50 2026-03-04 19:14:02 +01:00
marekf 4a2d4772d7 Add new icon to forms of application 2026-03-04 18:48:46 +01:00
marekf 2bf00606d3 Merge branch 'feature/task_4-ListView-ListBox-navigation' into develop/SLM-PT50 2026-03-04 18:42:25 +01:00
marekf 3773e1d96c Merge branch 'feature/task_3-new-pump-grundfoss' into develop/SLM-PT50 2026-03-04 18:42:15 +01:00
marekf 19ddc753c7 Merge branch 'feature/task_2-dripping-on-the-scale-meassure-mass' into develop/SLM-PT50 2026-03-04 18:33:20 +01:00
marekf 0c41c750e8 Add parameter and management IsOffline for components: Modbus>TempMeter>Groch, Meret and Modbus>PressureMeter>Meret and Rig>Keithley>TempMeter and add indicator redColor itemValue for SchematicDrawing 2026-03-04 18:25:28 +01:00
marekf 4bfd5c8e11 Update output printer OnePerMeter - 1. printer configuration in PrintResultsSelectionDlg, 2. document preview, 3. edit document name, 4. enable more save destinations 2026-03-04 13:21:45 +01:00
marekf f0fb70e38b Add new type of pump - Grundfoss 2026-03-04 11:54:39 +01:00
marekf 6e5bcafec0 Update dripping on the scale and measuring the start mass 2026-03-04 10:37:35 +01:00
marekf d5cb18c910 Fixed incorrect loading of RegisterReader in the StandingStartMassCollection method, when the RR Units and RR Quantity variables in results were filled with only string.empty 2026-03-04 09:44:42 +01:00
marekf 3a2069b255 Refactor variable naming in results in response to mass meter pulse processing 2026-03-04 09:42:55 +01:00
marekf 80c651dbfd Add search and navigation as UI>shared for ListBox-es and ListView-s to components listview, components listbox, procedure listview 2026-02-25 13:22:56 +01:00
marekf 5a3b9b57c4 Add new admins marek and michal 2026-02-25 10:02:09 +01:00
marekf ead350eef3 Add initial MassMeter implementation 2026-02-19 19:22:02 +01:00
marekf b43657a4db Initial import from local copy 2026-02-19 12:02:07 +01:00
1811 changed files with 2284606 additions and 15847 deletions
+11 -1
View File
@@ -90,4 +90,14 @@ Users/obj/
.idea/
*.suo
*.bak
TBF.sln.DotSettings.user
TBF.sln.DotSettings.user
/ExternalProjects
/GenesisCordonelTester
/packages
/GenesisCordonelInterface/bin/Debug/GenesisCordonelInterfaceLogger.log
/GenesisCordonelInterface/bin/Debug/GenesisCordonelTesterLogger.log
/GenesisCordonelInterface/bin/Debug/SirtConfig.json
/GenesisCordonelInterface/bin/Release
/GenesisCordonelInterface/obj/Debug
/GenesisCordonelInterface/obj/Release
/ExternalProjects
+6 -2
View File
@@ -8,7 +8,7 @@
<OutputType>WinExe</OutputType>
<RootNamespace>AppDiagnostic</RootNamespace>
<AssemblyName>AppDiagnostic</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
@@ -76,6 +76,7 @@
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
<DesignTime>True</DesignTime>
</Compile>
<None Include="packages.config" />
<None Include="Properties\Settings.settings">
@@ -97,5 +98,8 @@
<Name>SharedComponents</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="Resources\TBF_icon.ico" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
</Project>
+2
View File
@@ -29,6 +29,8 @@ namespace AppDiagnostic
public MainForm()
{
this.Icon = Properties.Resources.TBF_icon;
InitializeComponent();
// Inicializujeme LogAdapter a priradíme ho k memoListView
+28 -26
View File
@@ -8,10 +8,10 @@
// </auto-generated>
//------------------------------------------------------------------------------
namespace AppDiagnostic.Properties
{
namespace AppDiagnostic.Properties {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
@@ -19,53 +19,55 @@ namespace AppDiagnostic.Properties
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources
{
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources()
{
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager
{
get
{
if ((resourceMan == null))
{
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("AppDiagnostic.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture
{
get
{
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set
{
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
/// </summary>
internal static System.Drawing.Icon TBF_icon {
get {
object obj = ResourceManager.GetObject("TBF_icon", resourceCulture);
return ((System.Drawing.Icon)(obj));
}
}
}
}
+12 -5
View File
@@ -46,7 +46,7 @@
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
@@ -60,6 +60,7 @@
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
@@ -68,9 +69,10 @@
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
@@ -85,9 +87,10 @@
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
@@ -109,9 +112,13 @@
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="TBF_icon" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\TBF_icon.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root>
Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

+11 -4
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.7.2</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
@@ -33,9 +33,14 @@
<Reference Include="log4net, Version=2.0.15.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
<HintPath>..\packages\log4net.2.0.15\lib\net45\log4net.dll</HintPath>
</Reference>
<Reference Include="NLog, Version=5.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<HintPath>..\packages\NLog.5.2.2\lib\net46\NLog.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.IO.Compression" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
@@ -90,7 +95,9 @@
<Compile Include="Utils.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup />
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Forms\ListViewEx.resx">
<DependentUpon>ListViewEx.cs</DependentUpon>
@@ -107,4 +114,4 @@
<Target Name="AfterBuild">
</Target>
-->
</Project>
</Project>
+21 -2
View File
@@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.InteropServices;
namespace Common
{
@@ -289,11 +290,20 @@ namespace Common
CompoundAux,
Compound,
HeatMeterVolume,
HeatMeterEnergy,
HeatMeterMass,//...MF
HeatMeterEnergy,
SingleOrCompound, /// Only used when querying results
}
public enum Medium
public enum PulsesTypeByQuantity : short
{
[Description("dm3")] Volume_dm3,
[Description("kg")] Mass_kg,
Count
}
public enum Medium
{
[Description("")] NotSpecified,
#if LANG_PL
@@ -829,6 +839,15 @@ namespace Common
E63 = (1L << 62),
}
//...MF
public enum FlowType : int
{
none,
volume,
mass,
Count,
}
#region iPERL enums
public enum Side
+67 -2
View File
@@ -33,6 +33,20 @@ namespace Common
[Description("m3/m")] m3pm, /// 1 m3/m = 60 m3/h
[Description("cf/s")] cfs, /// 1 cubic foot per second = 101.9406477312 m3/h
[Description("g/s")] gps, /// 1 g/s = 0.0036 t/h
[Description("g/min")] gpm, /// 1 g/min = 0.00006 t/h
[Description("g/h")] gph, /// 1 g/h = 0.000001 t/h
[Description("kg/s")] kgps, /// 1 kg/s = 3.6 t/h
[Description("kg/min")] kgpm, /// 1 kg/min = 0.06 t/h
[Description("kg/h")] kgph, /// 1 kg/h = 0.001 t/h
[Description("t/s")] tps, /// 1 t/s = 3600 t/h
[Description("t/min")] tpm, /// 1 t/min = 60 t/h
[Description("t/h")] tph, /// 1 t/h = 1 t/h
[Description("lb/s")] lbps, /// 1 lb/s ≈ 1.633 t/h
[Description("lb/min")] lbpm, /// 1 lb/min ≈ 0.027216 t/h
[Description("lb/h")] lbph, /// 1 lb/h ≈ 0.0004536 t/h
[Description("g")] g, /// 0.001 kg
[Description("oz")] oz, /// 0.0283495231 kg
[Description("lb")] lb, /// 0.45359237 kg
@@ -221,9 +235,13 @@ namespace Common
[Description("Corrente")] Current,
[Description("Voltaggio")] Voltage,
#else
[Description("RegisterReader")] RegisterReader,
[Description("MultiFunctionalVariables")] MultiFunctionalVariables,
[Description("VolumeFlow")] VolumeFlow,
[Description("Volume")] Volume,
[Description("Flow")] Flow,
[Description("Mass")] Mass,
[Description("MassFlow")] MassFlow,
[Description("Mass")] Mass,
[Description("Time")] Time,
[Description("Temperature")] Temperature,
[Description("Pressure")] Pressure,
@@ -234,6 +252,8 @@ namespace Common
[Description("Energy")] Energy,
[Description("Pulses")] Pulses,
[Description("Pulses/liter")] PulsePerLtr,
[Description("Pulses/kg")] PulsePerKilogram, //...MF
[Description("Pulses/Unit")] PulsePerUnit,//...MF
[Description("Pulses/kWh")] PulsePerKWh,
[Description("Conductivity")] Conductivity,
@@ -278,29 +298,72 @@ namespace Common
return Quantity.Pulses;
case Unit.ml:
return Quantity.Volume;
case Unit.l:
return Quantity.Volume;
case Unit.dm3:
return Quantity.Volume;
case Unit.USgal:
return Quantity.Volume;
case Unit.UKgal:
return Quantity.Volume;
case Unit.cf:
return Quantity.Volume;
case Unit.m3:
return Quantity.Volume;
case Unit.lph:
return Quantity.Flow;
case Unit.cfph:
return Quantity.Flow;
case Unit.lpm:
return Quantity.Flow;
case Unit.USgalpm:
return Quantity.Flow;
case Unit.m3ph:
return Quantity.Flow;
case Unit.lps:
return Quantity.Flow;
case Unit.USgalps:
return Quantity.Flow;
case Unit.m3pm:
return Quantity.Flow;
case Unit.cfs:
return Quantity.Flow;
case Unit.gps:
return Quantity.MassFlow;
case Unit.gpm:
return Quantity.MassFlow;
case Unit.gph:
return Quantity.MassFlow;
case Unit.kgps:
return Quantity.MassFlow;
case Unit.kgpm:
return Quantity.MassFlow;
case Unit.kgph:
return Quantity.MassFlow;
case Unit.tps:
return Quantity.MassFlow;
case Unit.tpm:
return Quantity.MassFlow;
case Unit.tph:
return Quantity.MassFlow;
case Unit.lbps:
return Quantity.MassFlow;
case Unit.lbpm:
return Quantity.MassFlow;
case Unit.lbph:
return Quantity.MassFlow;
case Unit.g:
return Quantity.Mass;
case Unit.oz:
return Quantity.Mass;
case Unit.lb:
return Quantity.Mass;
case Unit.kg:
return Quantity.Mass;
case Unit.t:
return Quantity.Mass;
@@ -384,8 +447,10 @@ namespace Common
}
}
public static bool IsVolume(Unit unit) { return IsQuantity(unit, Quantity.Volume); }
public static bool IsVolumeFlow(Unit unit) { return IsQuantity(unit, Quantity.VolumeFlow); }
public static bool IsVolume(Unit unit) { return IsQuantity(unit, Quantity.Volume); }
public static bool IsFlow(Unit unit) { return IsQuantity(unit, Quantity.Flow); }
public static bool IsMassFlow(Unit unit) { return IsQuantity(unit, Quantity.MassFlow); }
public static bool IsMass(Unit unit) { return IsQuantity(unit, Quantity.Mass); }
public static bool IsTime(Unit unit) { return IsQuantity(unit, Quantity.Time); }
public static bool IsTemperature(Unit unit) { return IsQuantity(unit, Quantity.Temperature); }
+3 -1
View File
@@ -302,7 +302,7 @@ namespace Common
string passwordOfDay = Convert.ToString(number, 8);
return (userName.Equals("milan") && password.Equals("kraken")) ||
(userName.Equals("BuMi") && password.Equals("70630")) ||
(userName.Equals("bumi") && password.Equals("70630")) ||
(userName.Equals("igor") && password.Equals("mojronko8")) ||
(userName.Equals("lubo1212") && password.Equals("Tatry52")) ||
(userName.Equals("Michal") && password.Equals("Plok789456123")) ||
@@ -311,6 +311,8 @@ namespace Common
(userName.Equals("jan") && password.Equals("jaugust")) ||
(userName.Equals("JCermak") && password.Equals("Zt6911")) ||
(userName.Equals("gilles") && password.Equals("alibaba")) ||
(userName.Equals("michal") && password.Equals("mojnelson8")) ||
(userName.Equals("marek") && password.Equals("mareciino")) ||
#if DEBUG
(userName.Equals("Sensus Developers") && password.Equals("5fbg12gf5hn8nhy1fr")) ||
#endif
+1
View File
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="log4net" version="2.0.15" targetFramework="net472" />
<package id="NLog" version="5.2.2" targetFramework="net472" />
</packages>
+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.7.2</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.8</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.7.2</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.8</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.7.2</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.8</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.7.2</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.8</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.7.2</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<TargetFrameworkProfile>
</TargetFrameworkProfile>
<FileAlignment>512</FileAlignment>
@@ -114,4 +114,4 @@
<Target Name="AfterBuild">
</Target>
-->
</Project>
</Project>
+11 -2
View File
@@ -1,3 +1,12 @@
<?xml version="1.0"?>
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2"/></startup></configuration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" /></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>
</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.7.2</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.8</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.7.2</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.8</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.7.2</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
@@ -142,4 +142,4 @@
<Target Name="AfterBuild">
</Target>
-->
</Project>
</Project>
Binary file not shown.
@@ -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.7.2</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.8</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.7.2</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.8</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.7.2</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.8</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.7.2</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<TargetFrameworkProfile>
</TargetFrameworkProfile>
<FileAlignment>512</FileAlignment>
@@ -160,4 +160,4 @@
<Target Name="AfterBuild">
</Target>
-->
</Project>
</Project>
-1
View File
@@ -5,7 +5,6 @@ using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Threading;
using System.Windows.Forms;
+11 -2
View File
@@ -1,3 +1,12 @@
<?xml version="1.0"?>
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup></configuration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0" /></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>
</assemblyBinding>
</runtime>
</configuration>
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,639 @@
using CordonelPreadjustmentUi;
using CordonelPreadjustmentUi.Processes.Itinerary;
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.Ui.CordonelPreadjustmentUi;
using static GenesisCordonelInterface.API.PublicModels;
namespace GenesisCordonelInterface.API
{
/// <summary>
/// Public-facing facade for external applications integrating with
/// Genesis Cordonel Interface.
/// </summary>
/// <remarks>
/// This class exposes a simplified and controlled API for external callers.
/// It validates public input, maps public request models to internal models,
/// forwards operations to the internal GCI implementation and exposes status
/// notifications for meter batch changes.
///
/// This layer should stay thin. Business logic and meter communication are
/// handled by <see cref="InterfaceGCIToLaatzen"/>.
/// </remarks>
public class InterfaceOutsideToGCI
{
/// <summary>
/// Internal GCI implementation used by this public facade.
/// </summary>
public readonly InterfaceGCIToLaatzen _innerMeterAPI;
/// <summary>
/// Occurs when meter batch status information changes.
/// </summary>
public event Action<List<MeterBatchDebugStatus>> MeterBatchStatusChanged;
/// <summary>
/// Initializes a new instance of the public GCI facade.
/// </summary>
public InterfaceOutsideToGCI()
{
_innerMeterAPI = new InterfaceGCIToLaatzen();
}
// Laatzen ToolBox actions
#region ================================== PORT DETECTION ==================================
public PortDetectionResult DetectStreamingPort(int slot)
{
var result = _innerMeterAPI.DetectStreamingPort(slot);
//RaiseMeterBatchStatusChanged();
return result;
}
public async Task<PortDetectionResult> DetectStreamingPortAsync(
int slot,
CancellationToken token = default(CancellationToken))
{
var result = await _innerMeterAPI.DetectStreamingPortAsync(slot, token);
//RaiseMeterBatchStatusChanged();
return result;
}
public PortDetectionResult DetectRequestPort(int slot)
{
var result = _innerMeterAPI.DetectRequestPort(slot);
//RaiseMeterBatchStatusChanged();
return result;
}
public async Task<PortDetectionResult> DetectRequestPortAsync(
int slot,
CancellationToken token = default(CancellationToken))
{
var result = await _innerMeterAPI.DetectRequestPortAsync(slot, token);
//RaiseMeterBatchStatusChanged();
return result;
}
#endregion
#region ================================== INIT/UPDATE/GET slot ==================================
/// <summary>
/// Initializes a meter slot using the provided slot configuration.
/// </summary>
/// <param name="request">
/// Slot initialization request containing slot id, configuration source,
/// password source, request port and streaming port.
/// </param>
/// <param name="token">Cancellation token used to cancel the asynchronous operation.</param>
/// <returns>
/// Result describing whether the slot was created, updated, already existed or failed.
/// </returns>
/// <exception cref="ArgumentNullException">
/// Thrown when <paramref name="request"/> is null.
/// </exception>
public async Task<GciInitSlotResult> InitSlotAsync(
GciInitSlotRequest request,
CancellationToken token = default)
{
if (request == null)
throw new ArgumentNullException(nameof(request));
var result = await _innerMeterAPI.InitSlotAsync(
request.SlotId,
ModelsMapping.MapConfigSource(request.ConfigSource),
ModelsMapping.MapPasswordSource(request.PasswordSource),
ModelsMapping.MapPort(request.RequestPort),
ModelsMapping.MapPort(request.StreamingPort),
token).ConfigureAwait(false);
//RaiseMeterBatchStatusChanged();
return result;
}
/// <summary>
/// Updates configuration of an existing meter slot.
/// </summary>
/// <param name="request">
/// Slot configuration request containing updated configuration source,
/// password source and port settings.
/// </param>
/// <param name="token">Cancellation token used to cancel the asynchronous operation.</param>
/// <returns>
/// Result describing whether the slot update succeeded or failed.
/// </returns>
/// <exception cref="ArgumentNullException">
/// Thrown when <paramref name="request"/> is null.
/// </exception>
public async Task<GciInitSlotResult> UpdateSlotAsync(
GciInitSlotRequest request,
CancellationToken token = default)
{
if (request == null)
throw new ArgumentNullException(nameof(request));
var result = await _innerMeterAPI.UpdateSlotAsync(
request.SlotId,
ModelsMapping.MapConfigSource(request.ConfigSource),
ModelsMapping.MapPasswordSource(request.PasswordSource),
ModelsMapping.MapPort(request.RequestPort),
ModelsMapping.MapPort(request.StreamingPort),
token).ConfigureAwait(false);
//RaiseMeterBatchStatusChanged();
return result;
}
/// <summary>
/// Gets information about one meter slot.
/// </summary>
/// <param name="slotId">Slot id to query. Must be greater than zero.</param>
/// <param name="token">Cancellation token used to cancel the asynchronous operation.</param>
/// <returns>
/// Slot information including existence, connection state, login state,
/// PCB id and configured communication ports.
/// </returns>
/// <exception cref="ArgumentException">
/// Thrown when <paramref name="slotId"/> is invalid.
/// </exception>
public async Task<GciSlotInfo> GetSlotAsync(
int slotId,
CancellationToken token = default)
{
if (slotId <= 0)
throw new ArgumentException("Invalid slot id.");
var result = await _innerMeterAPI.GetOneMeterInfo(slotId, token).ConfigureAwait(false);
return result;
}
/// <summary>
/// Gets information about all currently initialized meter slots.
/// </summary>
/// <param name="token">Cancellation token used to cancel the asynchronous operation.</param>
/// <returns>
/// Collection of slot information records for all known meters.
/// </returns>
public async Task<GciAllSlotsInfo> GetAllSlotsAsync(
CancellationToken token = default)
{
var result = await _innerMeterAPI.GetAllMetersInfo(token).ConfigureAwait(false);
return result;
}
/// <summary>
/// Cleans one meter slot and releases its runtime resources.
/// </summary>
/// <param name="slot">Slot id to clean. Must be greater than zero.</param>
/// <param name="token">Cancellation token used to cancel the asynchronous operation.</param>
/// <returns>
/// Result describing whether the slot cleanup succeeded or failed.
/// </returns>
/// <exception cref="ArgumentException">
/// Thrown when <paramref name="slot"/> is invalid.
/// </exception>
public async Task<GciCleanSlotResult> CleanSlotAsync(
int slot,
CancellationToken token = default)
{
if (slot <= 0)
throw new ArgumentException("Invalid slot id.", nameof(slot));
var result = await _innerMeterAPI.CleanSlotAsync(slot, token).ConfigureAwait(false);
//RaiseMeterBatchStatusChanged();
return result;
}
/// <summary>
/// Cleans all initialized meter slots and releases related runtime resources.
/// </summary>
/// <param name="token">Cancellation token used to cancel the asynchronous operation.</param>
/// <returns>
/// Result describing whether cleanup of all slots succeeded or failed.
/// </returns>
public async Task<GciCleanAllSlotsResult> CleanAllSlotsAsync(
CancellationToken token = default)
{
var result = await _innerMeterAPI.CleanAllSlotsAsync(token).ConfigureAwait(false);
//RaiseMeterBatchStatusChanged();
return result;
}
#endregion
#region ================================== PASSWORD ==================================
/// <summary>
/// Sets runtime password for the meter assigned to the specified slot.
/// </summary>
/// <param name="slot">Slot id. Must be greater than zero.</param>
/// <param name="password">Password to assign to the meter.</param>
/// <param name="token">Cancellation token used to cancel the asynchronous operation.</param>
/// <returns>Result containing password update status.</returns>
/// <exception cref="ArgumentException">
/// Thrown when slot id is invalid or password is empty.
/// </exception>
public async Task<GciSetPasswordResult> SetPasswordAsync(
int slot,
string password,
CancellationToken token = default)
{
if (slot <= 0)
throw new ArgumentException("Invalid slot id.");
if (string.IsNullOrWhiteSpace(password))
throw new ArgumentException("Password is empty.");
var result = await _innerMeterAPI.SetMeterPasswordAsync(slot, password, token).ConfigureAwait(false);
//RaiseMeterBatchStatusChanged();
return result;
}
#endregion
#region ================================== LOGIN ==================================
/// <summary>
/// Logs in to the meter assigned to the specified slot.
/// </summary>
/// <param name="slot">Slot id. Must be greater than zero.</param>
/// <param name="token">Cancellation token used to cancel the asynchronous operation.</param>
/// <returns>Login result containing login state and status message.</returns>
/// <exception cref="ArgumentException">
/// Thrown when <paramref name="slot"/> is invalid.
/// </exception>
public async Task<PublicModels.GciLoginResult> LoginOneSlotAsync(
int slot,
CancellationToken token = default)
{
if (slot <= 0)
throw new ArgumentException("Invalid slot id.");
var result = await _innerMeterAPI.LoginOneSlotAsync(slot, token).ConfigureAwait(false);
return result;
//RaiseMeterBatchStatusChanged();
}
#endregion
#region ================================== CONNECTION ==================================
/// <summary>
/// Connects the meter assigned to the specified slot.
/// </summary>
/// <param name="slot">Slot id. Must be greater than zero.</param>
/// <param name="token">Cancellation token used to cancel the asynchronous operation.</param>
/// <returns>Connection result containing connection state and status message.</returns>
/// <exception cref="ArgumentException">
/// Thrown when <paramref name="slot"/> is invalid.
/// </exception>
public async Task<GciConnectResult> ConnectOneSlotAsync(
int slot,
CancellationToken token = default)
{
if (slot <= 0)
throw new ArgumentException("Invalid slot id.");
var result = await _innerMeterAPI.ConnectOneSlotAsync(slot, token).ConfigureAwait(false);
//RaiseMeterBatchStatusChanged();
return result;
}
/// <summary>
/// Disconnects the meter assigned to the specified slot.
/// </summary>
/// <param name="slot">Slot id. Must be greater than zero.</param>
/// <param name="token">Cancellation token used to cancel the asynchronous operation.</param>
/// <returns>Disconnect result containing final connection state and status message.</returns>
/// <exception cref="ArgumentException">
/// Thrown when <paramref name="slot"/> is invalid.
/// </exception>
public async Task<GciDisconnectResult> DisconnectAsync(
int slot,
CancellationToken token = default)
{
if (slot <= 0)
throw new ArgumentException("Invalid slot id.");
var result = await _innerMeterAPI.DisconnectAsync(slot, token).ConfigureAwait(false);
//RaiseMeterBatchStatusChanged();
return result;
}
#endregion
#region ================================== PCB ==================================
/// <summary>
/// Reads PCB identifier from the meter assigned to the specified slot.
/// </summary>
/// <param name="slot">Slot id. Must be greater than zero.</param>
/// <param name="token">Cancellation token used to cancel the asynchronous operation.</param>
/// <returns>Result containing PCB id and read status.</returns>
/// <exception cref="ArgumentException">
/// Thrown when <paramref name="slot"/> is invalid.
/// </exception>
public async Task<GciGetPcbIdResult> GetPcbIdAsync(
int slot,
CancellationToken token = default)
{
if (slot <= 0)
throw new ArgumentException("Invalid slot id.");
var result = await _innerMeterAPI.GetPcbIdAsync(slot, token).ConfigureAwait(false);
return result;
}
#endregion
#region ================================== READ ==================================
/// <summary>
/// Reads a firmware register value from the meter assigned to the specified slot.
/// </summary>
/// <param name="slot">Slot id. Must be greater than zero.</param>
/// <param name="registerName">Register identifier to read.</param>
/// <param name="token">Cancellation token used to cancel the asynchronous operation.</param>
/// <returns>
/// Register read result containing raw register value and operation status.
/// </returns>
/// <exception cref="ArgumentException">
/// Thrown when slot id or register name is invalid.
/// </exception>
public async Task<RegisterReadResult> ReadRegisterAsync(
int slot,
string registerName,
CancellationToken token = default)
{
if (slot <= 0)
throw new ArgumentException("Invalid slot id.", nameof(slot));
if (string.IsNullOrWhiteSpace(registerName))
throw new ArgumentException("Register name is empty.", nameof(registerName));
var result = await _innerMeterAPI
.ReadRegisterAsync(slot, registerName, token)
.ConfigureAwait(false);
//RaiseMeterBatchStatusChanged();
return result;
}
#endregion
#region ================================== WRITE ==================================
/// <summary>
/// Writes a value to a firmware register.
/// </summary>
/// <param name="slot">Slot id. Must be greater than zero.</param>
/// <param name="registerName">Register identifier to write.</param>
/// <param name="value">Value to write.</param>
/// <param name="storeToDevice">
/// Indicates whether configuration should be permanently stored.
/// </param>
/// <param name="refreshSystemState">
/// Indicates whether firmware system state should be refreshed after write.
/// </param>
/// <param name="token">Cancellation token used to cancel the asynchronous operation.</param>
/// <returns>
/// Register write result describing write status.
/// </returns>
/// <exception cref="ArgumentException">
/// Thrown when slot id or register name is invalid.
/// </exception>
public async Task<RegisterWriteResult> WriteRegisterAsync(
int slot,
string registerName,
object value,
bool storeToDevice = false,
bool refreshSystemState = false,
CancellationToken token = default)
{
if (slot <= 0)
throw new ArgumentException("Invalid slot id.", nameof(slot));
if (string.IsNullOrWhiteSpace(registerName))
throw new ArgumentException("Register name is empty.", nameof(registerName));
var result = await _innerMeterAPI
.WriteRegisterAsync(
slot,
registerName,
value,
storeToDevice,
refreshSystemState,
token)
.ConfigureAwait(false);
//RaiseMeterBatchStatusChanged();
return result;
}
#endregion
#region ================================== Password ==================================
/// <summary>
/// Updates meter password for the specified slot.
/// </summary>
/// <param name="slot">Slot id. Must be greater than zero.</param>
/// <param name="password">New password.</param>
/// <param name="token">Cancellation token used to cancel the asynchronous operation.</param>
/// <returns>
/// Password update result.
/// </returns>
/// <exception cref="ArgumentException">
/// Thrown when slot id or password is invalid.
/// </exception>
public async Task<GciSetPasswordResult> SetMeterPasswordAsync(
int slot,
string password,
CancellationToken token = default)
{
if (slot <= 0)
throw new ArgumentException("Invalid slot id.", nameof(slot));
if (string.IsNullOrWhiteSpace(password))
throw new ArgumentException("Password is empty.", nameof(password));
var result = await _innerMeterAPI
.SetMeterPasswordAsync(slot, password, token)
.ConfigureAwait(false);
//RaiseMeterBatchStatusChanged();
return result;
}
#endregion
#region ================================== DEBUG STATUS ==================================
/// <summary>
/// Gets runtime diagnostic information for all active workers.
/// </summary>
/// <returns>
/// Collection containing worker state, queue information,
/// current operation and activity timestamps.
/// </returns>
public List<WorkerDebugStatus> GetWorkerDebugStatuses()
{
return _innerMeterAPI.GetWorkerDebugStatuses();
}
/// <summary>
/// Gets runtime diagnostic information for all meter slots.
/// </summary>
/// <returns>
/// Collection containing slot state, connection state,
/// selected state and communication configuration.
/// </returns>
public List<MeterBatchDebugStatus> GetMeterBatchDebugStatuses()
{
return _innerMeterAPI.GetMeterBatchDebugStatuses();
}
/// <summary>
/// Raises meter batch status change notification.
/// </summary>
/// <remarks>
/// Intended to notify external consumers after changes in meter state.
/// </remarks>
public void RaiseMeterBatchStatusChanged()
{
var statuses = GetMeterBatchDebugStatuses();
var handler = MeterBatchStatusChanged;
if (handler != null)
handler(statuses);
}
#endregion
#region ================================== SLOT SELECTION ==================================
/// <summary>
/// Sets selection state for a slot.
/// </summary>
/// <param name="slot">Slot id.</param>
/// <param name="selected">Selection state.</param>
public void SetSlotSelected(int slot, bool selected)
{
_innerMeterAPI.SetSlotSelected(slot, selected);
RaiseMeterBatchStatusChanged();
}
/// <summary>
/// Determines whether the specified slot is selected.
/// </summary>
/// <param name="slot">Slot id.</param>
/// <returns>
/// True if slot is selected; otherwise false.
/// </returns>
public bool IsSlotSelected(int slot)
{
return _innerMeterAPI.IsSlotSelected(slot);
}
/// <summary>
/// Gets all selected slot identifiers.
/// </summary>
/// <returns>
/// Ordered collection of selected slot ids.
/// </returns>
public List<int> GetSelectedSlots()
{
return _innerMeterAPI.GetSelectedSlots();
}
#endregion
#region ================================== Register names ==================================
/// <summary>
/// Gets all available firmware register identifiers.
/// </summary>
/// <returns>
/// Ordered collection of register names.
/// </returns>
public List<string> GetAllRegisterNames()
{
return _innerMeterAPI.GetAllRegisterNames();
}
#endregion
// Laatzen Preadjustment processes
#region ================================== PreAdjustment ==================================
public PreAdjustmentInitializationResult Preadjustment_Initialization(
ProcessProgress pp,
List<MeterStateControl> mc)
{
return _innerMeterAPI.Preadjustment_Initialization(pp, mc);
}
public Task<PreadjustmentDetectResult> PreAdjustment_DetectAsync(
IEnumerable<PublicModels.MeterBatchDebugStatus> selectedSlots,
CancellationToken token = default)
{
return _innerMeterAPI.PreAdjustment_DetectAsync(selectedSlots, token);
}
public Task<PreAdjustmentProcessResult> PreAdjustment_PreparationAsync(
int slot,
CancellationToken token = default)
{
return _innerMeterAPI.PreAdjustment_PreparationAsync(slot, token);
}
public Task<PreAdjustmentProcessResult> PreAdjustment_AmplitudeTestAsync(
int slot,
CancellationToken token = default)
{
return _innerMeterAPI.PreAdjustment_AmplitudeTestAsync(slot, token);
}
public Task<PreAdjustmentProcessResult> PreAdjustment_TemperatureCalibrationAsync(
int slot,
CancellationToken token = default)
{
return _innerMeterAPI.PreAdjustment_TemperatureCalibrationAsync(slot, token);
}
public Task<PreAdjustmentProcessResult> PreAdjustment_OffsetTestAsync(
int slot,
CancellationToken token = default)
{
return _innerMeterAPI.PreAdjustment_OffsetTestAsync(slot, token);
}
public Task<PreAdjustmentProcessResult> PreAdjustment_CompletionAsync(
int slot,
CancellationToken token = default)
{
return _innerMeterAPI.PreAdjustment_CompletionAsync(slot, token);
}
#endregion
}
}
@@ -0,0 +1,170 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xylem.Common.Hardware.Interfaces.Ports.PortCore;
using static GenesisCordonelInterface.API.InterfaceOutsideToGCI;
using static GenesisCordonelInterface.API.PublicModels;
using static Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore.GenesisMeter;
namespace GenesisCordonelInterface.API
{
/// <summary>
/// Public data contract layer for the Genesis Cordonel Interface (GCI).
///
/// This class defines all Data Transfer Objects (DTOs) that are exposed
/// to external consumers (e.g. TBF, UI, or other integration layers).
///
/// Responsibilities:
/// - Provide stable, dependency-free models for external usage
/// - Decouple internal GCI implementation (GenesisMeter, Xylem libraries)
/// from external systems
/// - Define request/response contracts for all supported operations
/// - Contain mapping methods between public DTOs and internal domain models
///
/// Architecture:
/// External world (TBF / UI)
/// ↓
/// GciPublicModels (this layer)
/// ↓
/// Internal GCI API (InterfaceGCIToLaatzen, GenesisMeter, etc.)
///
/// Notes:
/// - Public models must NOT expose internal types (e.g. GenesisMeter, IPort, etc.)
/// - All mapping between internal and external representations must be done here
/// - DTOs are designed to be simple, serializable, and stable over time
/// - Any change in internal implementation should not affect these models
///
/// Pattern:
/// Each operation follows a consistent structure:
/// Request → Operation → Result
///
/// Example:
/// GciInitSlotRequest → InitSlot → GciInitSlotResult
/// GetSlot → GciSlotInfo
/// GetPcbId → GciGetPcbIdResult
///
/// This layer acts as a boundary between domain logic and integration logic.
/// </summary>
public class ModelsMapping
{
/// <summary>
/// Mapping methods between public DTOs and internal GCI models.
/// Ensures separation between external contracts and internal domain objects.
/// </summary>
#region ================================== OUTERN/INTERN and back models mapping ==================================
public static PasswordSource MapPasswordSource(PublicModels.GciPasswordSource src)
{
return (PasswordSource)src;
}
public static ConfigSource MapConfigSource(PublicModels.GciConfigSource src)
{
return (ConfigSource)src;
}
public static Xylem.Common.Hardware.Interfaces.Ports.PortCore.PortConfig? MapPort(PublicModels.GciPortConfig port)
{
if (port == null)
return null;
Xylem.Common.Hardware.Interfaces.Ports.PortCore.PortConfig result = new Xylem.Common.Hardware.Interfaces.Ports.PortCore.PortConfig();
result.PortName = port.PortName;
result.Type = port.Type;
return result;
}
public static PublicModels.GciInitSlotResult MapInitResult(PublicModels.GciInitSlotResult result)
{
if (result == null)
return null;
return new PublicModels.GciInitSlotResult
{
SlotId = result.SlotId,
Success = result.Success,
Message = result.Message
};
}
public static PublicModels.GciPasswordSource MapPasswordSourceBack(PasswordSource src)
{
return (PublicModels.GciPasswordSource)src;
}
public static PublicModels.GciConfigSource MapConfigSourceBack(ConfigSource src)
{
return (PublicModels.GciConfigSource)src;
}
public static PublicModels.GciPortConfig MapPortBack(PortConfig? port)
{
if (!port.HasValue)
return null;
PortConfig value = port.Value;
return new PublicModels.GciPortConfig
{
PortName = value.PortName,
Type = value.Type
};
}
public static PublicModels.GciPortConfig MapPortBack(IPort port)
{
if (port == null)
return null;
return new PublicModels.GciPortConfig
{
PortName = port.GetPortName(),
Type = port.GetType().Name
};
}
public static PublicModels.GciPortConfig MapPortBack(string portName, string portTyoe)
{
return new PublicModels.GciPortConfig
{
PortName = portName,
Type = portTyoe
};
}
public static MeterBatchDebugStatus ToMeterBatchDebugStatus(GciSlotInfo slot)
{
if (slot == null)
return null;
return new MeterBatchDebugStatus
{
Slot = slot.SlotId,
Selected = true,
PcbId = slot.PcbId,
IsConnected = false,
IsLoggedOn = false,
RequestPort = slot.RequestPort == null ? "" : slot.RequestPort.PortName,
StreamingPort = slot.StreamingPort == null ? "" : slot.StreamingPort.PortName,
FwVersion = "",
InterfaceVersion = ""
};
}
public static List<MeterBatchDebugStatus> ToMeterBatchDebugStatusList(
IEnumerable<GciSlotInfo> slots)
{
if (slots == null)
return new List<MeterBatchDebugStatus>();
return slots
.Where(x => x != null)
.Select(ToMeterBatchDebugStatus)
.ToList();
}
#endregion
}
}
@@ -0,0 +1,497 @@
using System;
using System.Collections.Generic;
namespace GenesisCordonelInterface.API
{
/// <summary>
/// Public data contract layer for the Genesis Cordonel Interface (GCI).
///
/// This class defines all Data Transfer Objects (DTOs) that are exposed
/// to external consumers (e.g. TBF, UI, or other integration layers).
///
/// Responsibilities:
/// - Provide stable, dependency-free models for external usage
/// - Decouple internal GCI implementation (GenesisMeter, Xylem libraries)
/// from external systems
/// - Define request/response contracts for all supported operations
/// - Contain mapping methods between public DTOs and internal domain models
///
/// Architecture:
/// External world (TBF / UI)
/// ↓
/// GciPublicModels (this layer)
/// ↓
/// Internal GCI API (InterfaceGCIToLaatzen, GenesisMeter, etc.)
///
/// Notes:
/// - Public models must NOT expose internal types (e.g. GenesisMeter, IPort, etc.)
/// - All mapping between internal and external representations must be done here
/// - DTOs are designed to be simple, serializable, and stable over time
/// - Any change in internal implementation should not affect these models
///
/// Pattern:
/// Each operation follows a consistent structure:
/// Request → Operation → Result
///
/// Example:
/// GciInitSlotRequest → InitSlot → GciInitSlotResult
/// GetSlot → GciSlotInfo
/// GetPcbId → GciGetPcbIdResult
///
/// This layer acts as a boundary between domain logic and integration logic.
/// </summary>
public class PublicModels
{
public static bool HideSensitiveValues { get; set; } = true;
private static string FormatPassword(string password)
{
if (!HideSensitiveValues)
return password ?? "<null>";
if (string.IsNullOrEmpty(password))
return "<empty>";
return "********";
}
/// <summary>
/// Public DTOs exposed to external systems.
/// These models represent the contract of the GCI API.
/// They must remain stable and independent of internal implementation.
/// </summary>
#region ================================== PUBLIC MODELS ===========================================
public class RegisterReadResult
{
public bool Success { get; set; }
public string RegisterName { get; set; }
public string RawHex { get; set; }
public string ErrorMessage { get; set; }
public override string ToString()
{
return string.Format(
"Success={0}, RegisterName={1}, RawHex={2}, ErrorMessage={3}",
Success,
RegisterName,
RawHex,
ErrorMessage);
}
}
public class WorkerDebugStatus
{
public int Slot { get; set; }
public string Name { get; set; }
public int QueueLength { get; set; }
public bool IsBusy { get; set; }
public string CurrentOperation { get; set; }
public string LastError { get; set; }
public DateTime LastActivity { get; set; }
}
public class MeterBatchDebugStatus
{
public int Slot { get; set; }
public bool Selected { get; set; }
public string PcbId { get; set; }
public bool IsConnected { get; set; }
public bool IsLoggedOn { get; set; }
public string RequestPort { get; set; }
public string StreamingPort { get; set; }
public string RequestPortType { get; set; }
public string FwVersion { get; set; }
public string InterfaceVersion { get; set; }
}
public class RegisterWriteResult
{
public bool Success { get; set; }
public string RegisterName { get; set; }
public object WrittenValue { get; set; }
public bool StoreToDevice { get; set; }
public bool RefreshSystemState { get; set; }
public string ErrorMessage { get; set; }
public override string ToString()
{
return $"Success={Success}, " +
$"Register={RegisterName ?? "<null>"}, " +
$"Value={WrittenValue ?? "<null>"}, " +
$"StoreToDevice={StoreToDevice}, " +
$"RefreshSystemState={RefreshSystemState}, " +
$"Error={ErrorMessage ?? "<none>"}";
}
}
public class PortDetectionResult
{
public bool Success { get; set; }
public int Slot { get; set; }
public string PortName { get; set; }
public string PcbId { get; set; }
public string ErrorMessage { get; set; }
public override string ToString()
{
return string.Format(
"Slot={0}, Success={1}, PortName={2}, PcbId={3}, ErrorMessage={4}",
Slot,
Success,
PortName,
PcbId,
ErrorMessage);
}
}
public class GciSlotInfo
{
public int SlotId { get; set; }
public bool Exists { get; set; }
public bool Success { get; set; }
public bool IsConnected { get; set; }
public bool IsLoggedOn { get; set; }
public string Message { get; set; }
public string PcbId { get; set; }
public string Password { get; set; }
public GciConfigSource ConfigSource { get; set; }
public GciPasswordSource PasswordSource { get; set; }
public GciPortConfig RequestPort { get; set; }
public GciPortConfig StreamingPort { get; set; }
public override string ToString()
{
return string.Format(
"SlotId={0}, Exists={1}, Success={2}, IsConnected={3}, IsLoggedOn={4}, Message={5}, PcbId={6}, Password={7}, ConfigSource={8}, PasswordSource={9}, RequestPort={10}, StreamingPort={11}",
SlotId,
Exists,
Success,
IsConnected,
IsLoggedOn,
Message,
PcbId,
FormatPassword(Password),
ConfigSource,
PasswordSource,
RequestPort,
StreamingPort);
}
}
public class GciAllSlotsInfo
{
public bool Success { get; set; }
public string Message { get; set; }
public List<GciSlotInfo> Slots { get; set; }
public override string ToString()
{
return $"Success={Success}, Count={Slots?.Count ?? 0}, Message={Message}";
}
}
public class Result
{
public int SlotId { get; set; }
public bool Success { get; set; }
public string Message { get; set; }
public override string ToString()
{
return string.Format(
"SlotId={0}, Success={1}, Message={2}",
SlotId,
Success,
Message);
}
}
public enum GciPasswordSource
{
RestApi = 0,
OfflineFile = 1,
InterfaceInputPassword = 2,
}
public enum GciConfigSource
{
FileConfig = 0,
InterfaceInputConfig = 1,
}
/// <summary>
/// Collection of port settings
/// </summary>
public class GciPortConfig
{
public string PortName { get; set; }
public string Type { get; set; }
public override string ToString()
{
return string.Format("PortName={0}, Type={1}", PortName, Type);
}
}
public static GciPortConfig CreatePortConfig(string portName, string type)
{
if (string.IsNullOrWhiteSpace(portName))
return null;
return new GciPortConfig
{
PortName = portName,
Type = MapPortType(type)
};
}
public static string MapPortType(string type)
{
switch ((type ?? "").Trim().ToUpperInvariant())
{
case "RFID":
return "Xylem.Common.Hardware.Interfaces.Ports.SerialPorts.RfidSerialPort";
case "UART":
return "Xylem.Common.Hardware.Interfaces.Ports.SerialPorts.UartSerialPort";
case "IRDA":
return "Xylem.Common.Hardware.Interfaces.Ports.SerialPorts.IrdaSerialPort";
default:
return "Xylem.Common.Hardware.Interfaces.Ports.SerialPorts.IrdaSerialPort";
}
}
public class GciInitSlotRequest
{
public int SlotId { get; set; }
public GciConfigSource ConfigSource { get; set; }
public GciPasswordSource PasswordSource { get; set; }
public GciPortConfig RequestPort { get; set; }
public GciPortConfig StreamingPort { get; set; }
public string Password { get; set; }
public override string ToString()
{
return string.Format(
"SlotId={0}, GciConfigSource={1}, PasswordSource={2}, RequestPort={3}, StreamingPort={4}, Password={5}",
SlotId,
ConfigSource,
PasswordSource,
RequestPort,
StreamingPort,
FormatPassword(Password));
}
}
public class GciInitSlotResult
{
public int SlotId { get; set; }
public bool Success { get; set; }
public string Message { get; set; }
public string PcbId { get; set; }
public bool Created { get; set; }
public bool Updated { get; set; }
public bool AlreadyExists { get; set; }
public override string ToString()
{
return string.Format(
"SlotId={0}, Success={1}, Message={2}, PcbId={3}, Created={4}, Updated={5}, AlreadyExists={6}",
SlotId,
Success,
Message,
PcbId,
Created,
Updated,
AlreadyExists);
}
}
public class GciCleanAllSlotsResult
{
public bool Success { get; set; }
public string Message { get; set; }
public override string ToString()
{
return string.Format(
"Success={0}, Message={1}",
Success,
Message);
}
}
public class GciCleanSlotResult
{
public int SlotId { get; set; }
public bool Success { get; set; }
public string Message { get; set; }
public override string ToString()
{
return string.Format(
"SlotId={0}, Success={1}, Message={2}",
SlotId,
Success,
Message);
}
}
public class GciGetPcbIdResult
{
public int SlotId { get; set; }
public bool Success { get; set; }
public string PcbId { get; set; }
public string Message { get; set; }
public override string ToString()
{
return string.Format(
"SlotId={0}, Success={1}, PcbId={2}, Message={3}",
SlotId,
Success,
PcbId,
Message);
}
}
public class GciConnectResult
{
public int SlotId { get; set; }
public bool Success { get; set; }
public string PcbId { get; set; }
public bool IsConnected { get; set; }
public string Message { get; set; }
public override string ToString()
{
return string.Format(
"SlotId={0}, Success={1}, PcbId={2}, IsConnected={3}, Message={4}",
SlotId,
Success,
PcbId,
IsConnected,
Message);
}
}
public class GciLoginResult
{
public int SlotId { get; set; }
public bool Success { get; set; }
public string PcbId { get; set; }
public bool IsLoggedOn { get; set; }
public string Message { get; set; }
public override string ToString()
{
return $"Slot={SlotId}, Success={Success}, PcbId={PcbId}, IsLoggedOn={IsLoggedOn}, Message={Message ?? "<none>"}";
}
}
public class GciRegisterSnapshot
{
public string Name { get; set; }
public string Type { get; set; }
public string RawValue { get; set; }
public string Min { get; set; }
public string Max { get; set; }
public string Description { get; set; }
public string Version { get; set; }
public string IsAvailable { get; set; }
public string Privilege { get; set; }
}
public class GciDisconnectResult
{
public int SlotId { get; set; }
public bool Success { get; set; }
public string Message { get; set; }
public override string ToString()
{
return string.Format(
"SlotId={0}, Success={1}, Message={2}",
SlotId,
Success,
Message);
}
}
public class GciSetPasswordResult
{
public int SlotId { get; set; }
public bool Success { get; set; }
public string Password { get; set; }
public string Message { get; set; }
public override string ToString()
{
return string.Format(
"SlotId={0}, Success={1}, Password={2}, Message={3}",
SlotId,
Success,
FormatPassword(Password),
Message);
}
}
public class PreAdjustmentProcessResult
{
public bool Success { get; set; }
public int Slot { get; set; }
public string ProcessName { get; set; }
public string ErrorMessage { get; set; }
/// <inheritdoc />
public override string ToString()
{
return
$"Success={Success}, " +
$"Slot={Slot}, " +
$"Process={ProcessName}, " +
$"Error={ErrorMessage ?? "None"}";
}
}
public class PreadjustmentDetectResult
{
public bool Success { get; set; }
public int DetectedMeterCount { get; set; }
public int DetectedThermometerCount { get; set; }
public string ErrorMessage { get; set; }
/// <inheritdoc />
public override string ToString()
{
return
$"Success={Success}, " +
$"Meters={DetectedMeterCount}, " +
$"Thermometers={DetectedThermometerCount}, " +
$"Error={ErrorMessage ?? "None"}";
}
}
public class PreAdjustmentInitializationResult
{
public bool Success { get; set; }
public string Slots { get; set; }
public string ErrorMessage { get; set; }
/// <inheritdoc />
public override string ToString()
{
return
$"Success={Success}, " +
$"Slots={Slots}, " +
$"Error={ErrorMessage ?? "None"}";
}
}
#endregion
}
}
+18
View File
@@ -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,35 @@
{
"_Comment": "GCI DataStorage configuration",
"DataStorage": {
"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)\\MojaDB;Database=UnionTownCalibAndSkeleton;Integrated Security=True;",
"QueryTemplate": "SELECT [Password] FROM [dbo].[SkeletonKeys] WHERE [PcbId] = QUERYPARAM"
},
"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"
},
"Name": "PreAdjustmentCalibrationParams",
"Type": "LocalCsv",
"DataSource": "Data\\preadjustment_params.csv",
"QueryTemplate": "SELECT [Offset] WHERE [PcbId] = QUERYPARAM"
}
}
}
@@ -0,0 +1,32 @@
namespace GenesisCordonelInterface.Core.DataStorage.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:
///
/// {
/// "DataStorage":
/// {
/// ...
/// }
/// }
/// </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 GciDataStorageConfig DataStorage { 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.DataStorage.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.DataStorage == null)
return;
NormalizePath(
config.DataStorage.MeterLoginPasswords,
baseDirectory);
NormalizePath(
config.DataStorage.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,30 @@
using GenesisCordonelInterface.Core.DataStorage.Reading.Common.Models;
namespace GenesisCordonelInterface.Core.DataStorage.Config
{
/// <summary>
/// Contains all configured GCI data storage sources.
///
/// Each property represents one logical use-case
/// and points to its storage configuration.
///
/// Example:
/// MeterLoginPasswords
/// -> SQL database
///
/// PreAdjustmentCalibrationParams
/// -> CSV file
/// </summary>
public class GciDataStorageConfig
{
/// <summary>
/// Configuration for meter login password lookup.
/// </summary>
public DataStorageConfig MeterLoginPasswords { get; set; }
/// <summary>
/// Configuration for pre-adjustment calibration data lookup.
/// </summary>
public DataStorageConfig PreAdjustmentCalibrationParams { get; set; }
}
}
@@ -0,0 +1,49 @@
namespace GenesisCordonelInterface.Core.DataStorage.Reading.Common.Contracts
{
/// <summary>
/// Defines common contract for all GCI data storage readers.
///
/// Implementations can read data from different storage types:
/// - SQL database
/// - CSV file
/// - JSON file
/// - REST API
///
/// Consumers should use this interface instead of concrete readers.
/// </summary>
public interface IDataStorageReader
{
/// <summary>
/// Reads data from configured storage using provided query.
/// </summary>
/// <param name="query">
/// Query object containing lookup parameters.
/// </param>
/// <returns>
/// Storage-specific result object.
/// </returns>
object GetData(Models.DataQuery query);
/// <summary>
/// Tests whether configured data source is accessible.
/// </summary>
/// <param name="enableDiagnostics">
/// Enables detailed diagnostic output.
/// </param>
/// <returns>
/// Diagnostic result of source test.
/// </returns>
Models.ReaderDiagnosticResult TestSource(bool enableDiagnostics);
/// <summary>
/// Tests whether configured query is valid for the data source.
/// </summary>
/// <param name="enableDiagnostics">
/// Enables detailed diagnostic output.
/// </param>
/// <returns>
/// Diagnostic result of query test.
/// </returns>
Models.ReaderDiagnosticResult TestQuery(bool enableDiagnostics);
}
}
@@ -0,0 +1,94 @@
using System;
using GenesisCordonelInterface.Core.DataStorage.Reading.Common.Models;
using GenesisCordonelInterface.Core.DataStorage.Reading.Common.Contracts;
namespace GenesisCordonelInterface.Core.DataStorage.Reading.Common
{
/// <summary>
/// Factory responsible for creating appropriate
/// data storage reader implementations.
///
/// The reader type is selected according to:
///
/// DataStorageConfig.Type
///
/// Example:
///
/// LocalDatabase
/// -> DatabaseDataStorageReader
///
/// LocalCsv
/// -> CsvDataStorageReader
///
/// LocalJson
/// -> JsonDataStorageReader
///
/// RestApi
/// -> RestApiDataStorageReader
///
/// This factory hides implementation details from
/// higher layers and keeps consumers independent
/// of storage technology.
///
/// Trace:
///
/// MeterLoginPasswordReader
/// -> DataStorageReaderFactory.Create()
/// -> DatabaseDataStorageReader
/// -> CsvDataStorageReader
/// -> JsonDataStorageReader
/// -> RestApiDataStorageReader
/// </summary>
public static class DataStorageReaderFactory
{
/// <summary>
/// Creates appropriate reader implementation
/// according to storage configuration.
/// </summary>
/// <param name="config">
/// Data storage configuration loaded from gci_config.json.
/// </param>
/// <returns>
/// Configured storage reader implementation.
/// </returns>
/// <exception cref="ArgumentNullException">
/// Configuration is null.
/// </exception>
/// <exception cref="NotSupportedException">
/// Unsupported storage type.
/// </exception>
public static IDataStorageReader Create(
DataStorageConfig config)
{
if (config == null)
throw new ArgumentNullException(nameof(config));
switch (config.Type)
{
case DataStorageType.RemoteDatabase:
case DataStorageType.LocalDatabase:
return new Providers.DatabaseDataStorageReader(config);
case DataStorageType.RemoteCsv:
case DataStorageType.LocalCsv:
return new Providers.CsvDataStorageReader(config);
case DataStorageType.RemoteJson:
case DataStorageType.LocalJson:
return new Providers.JsonDataStorageReader(config);
case DataStorageType.RestApi:
return new Providers.RestApiDataStorageReader(config);
default:
throw new NotSupportedException(
$"Unsupported DataStorageType: '{config.Type}'");
}
}
}
}
@@ -0,0 +1,58 @@
using System.Collections.Generic;
namespace GenesisCordonelInterface.Core.DataStorage.Reading.Common.Models
{
/// <summary>
/// Represents query input for data storage readers.
///
/// Query parameters are used as lookup values
/// during storage search operations.
///
/// A single parameter:
///
/// 231630279
///
/// executes one lookup.
///
/// Multiple parameters:
///
/// 231630279
/// 231630243
/// 231630148
///
/// can execute batch operations.
///
/// Example:
///
/// QueryTemplate:
///
/// SELECT [Password]
/// WHERE [PcbId]=QUERYPARAM
///
/// Query:
///
/// QueryParams:
/// 231630279
///
/// Result:
///
/// Password belonging to 231630279.
/// </summary>
public class DataQuery
{
/// <summary>
/// Collection of query values.
///
/// Single item:
///
/// QueryParams[0]
///
/// represents one lookup.
///
/// Multiple items may be processed
/// as batch requests.
/// </summary>
public List<string> QueryParams { get; }
= new List<string>();
}
}
@@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GenesisCordonelInterface.Core.DataStorage.Reading.Common.Models
{
/// <summary>
/// Configuration for one storage source.
/// Loaded from gci_config.json
/// </summary>
public class DataStorageConfig
{
/// <summary>
/// Logical storage name.
/// Example:
/// MeterLoginPasswords
/// CalibrationParameters
/// </summary>
public string Name { get; set; }
/// <summary>
/// Storage implementation type.
/// </summary>
public DataStorageType Type { get; set; }
/// <summary>
/// Connection string,
/// file path,
/// URL etc.
/// </summary>
public string DataSource { get; set; }
/// <summary>
/// Query template.
/// Example:
///
/// SQL:
/// SELECT Password
/// FROM Passwords
/// WHERE PcbId=QUERYPARAM
///
/// CSV:
/// SELECT [Password]
/// WHERE [PcbId]=QUERYPARAM
/// </summary>
public string QueryTemplate { get; set; }
}
}
@@ -0,0 +1,79 @@
namespace GenesisCordonelInterface.Core.DataStorage.Reading.Common.Models
{
/// <summary>
/// Identifies supported data storage implementations.
///
/// The type determines which reader implementation
/// will be created by DataStorageReaderFactory.
///
/// Example:
///
/// LocalDatabase
/// -> DatabaseDataStorageReader
///
/// LocalCsv
/// -> CsvDataStorageReader
///
/// RestApi
/// -> RestApiDataStorageReader
///
/// Source:
///
/// gci_config.json
///
/// Example:
///
/// "Type":"LocalDatabase"
/// </summary>
public enum DataStorageType
{
/// <summary>
/// REST API endpoint.
///
/// Example:
///
/// https://api.company.com/passwords
/// </summary>
RestApi,
/// <summary>
/// Database located on remote server.
///
/// Example:
///
/// SQL server on network machine.
/// </summary>
RemoteDatabase,
/// <summary>
/// Database located on local machine.
///
/// Example:
///
/// SQL LocalDB
/// SQLite
/// local SQL Server instance
/// </summary>
LocalDatabase,
/// <summary>
/// JSON source stored remotely.
/// </summary>
RemoteJson,
/// <summary>
/// JSON file stored locally.
/// </summary>
LocalJson,
/// <summary>
/// CSV source stored remotely.
/// </summary>
RemoteCsv,
/// <summary>
/// CSV file stored locally.
/// </summary>
LocalCsv
}
}
@@ -0,0 +1,18 @@
using System.Collections.Generic;
namespace GenesisCordonelInterface.Core.DataStorage.Reading.Common.Models
{
public class DatabaseSearchResult
{
public bool Found { get; set; }
public string Query { get; set; }
public Dictionary<string, object> Values { get; set; }
public DatabaseSearchResult()
{
Values = new Dictionary<string, object>();
}
}
}
@@ -0,0 +1,141 @@
using System.Collections.Generic;
using System.Text;
namespace GenesisCordonelInterface.Core.DataStorage.Reading.Common.Models
{
/// <summary>
/// Represents diagnostic result of data storage operations.
///
/// Used for:
/// - source validation
/// - query validation
/// - connection tests
/// - detailed diagnostic logging
///
/// Example:
///
/// TestSource()
/// -> connection successful
///
/// TestQuery()
/// -> column validation
///
/// Can also carry additional payload data.
/// </summary>
public class ReaderDiagnosticResult
{
/// <summary>
/// Indicates whether operation completed successfully.
/// </summary>
public bool Success { get; set; }
/// <summary>
/// Human readable summary message.
///
/// Example:
///
/// "Connection successful."
///
/// or:
///
/// "Column not found."
/// </summary>
public string Message { get; set; }
/// <summary>
/// Detailed diagnostic output lines.
///
/// Used for debugging and troubleshooting.
/// </summary>
public List<string> Diagnostics { get; set; }
/// <summary>
/// Optional operation payload.
///
/// Example:
///
/// loaded CSV lines
/// SQL test value
/// parsed content
/// </summary>
public object Data { get; set; }
/// <summary>
/// Creates empty diagnostic result.
/// </summary>
public ReaderDiagnosticResult()
{
Diagnostics = new List<string>();
}
/// <summary>
/// Creates successful diagnostic result.
/// </summary>
/// <param name="message">
/// Success message.
/// </param>
/// <returns>
/// Successful result object.
/// </returns>
public static ReaderDiagnosticResult SuccessResult(
string message = "OK")
{
return new ReaderDiagnosticResult
{
Success = true,
Message = message
};
}
/// <summary>
/// Creates failed diagnostic result.
/// </summary>
/// <param name="message">
/// Failure message.
/// </param>
/// <returns>
/// Failed result object.
/// </returns>
public static ReaderDiagnosticResult Failure(
string message)
{
return new ReaderDiagnosticResult
{
Success = false,
Message = message
};
}
/// <summary>
/// Converts diagnostic information into display text.
///
/// Output contains:
///
/// diagnostic lines
/// +
/// summary message
/// </summary>
/// <returns>
/// Formatted text representation.
/// </returns>
public string ToDisplayDiag()
{
StringBuilder sb = new StringBuilder();
if (Diagnostics != null &&
Diagnostics.Count > 0)
{
foreach (string line in Diagnostics)
sb.AppendLine(line);
if (!string.IsNullOrWhiteSpace(Message))
sb.AppendLine();
}
if (!string.IsNullOrWhiteSpace(Message))
sb.AppendLine(Message);
return sb.ToString();
}
}
}
@@ -0,0 +1,394 @@
using System;
using System.Collections.Generic;
using System.IO;
using GenesisCordonelInterface.Core.DataStorage.Reading.Common.Searching;
using GenesisCordonelInterface.Core.DataStorage.Reading.Common.Models;
using GenesisCordonelInterface.Core.DataStorage.Reading.Common.Contracts;
namespace GenesisCordonelInterface.Core.DataStorage.Reading.Common.Providers
{
/// <summary>
/// Reads and searches CSV based data sources.
///
/// Supported query syntax:
/// SELECT [ReturnColumn] WHERE [MatchColumn] = QUERYPARAM
///
/// Example:
/// SELECT [Password] WHERE [PcbId] = QUERYPARAM
///
/// Supports:
/// - column names: [ColumnName]
/// - column indexes: COLUMN(n)
///
/// Trace:
/// MeterLoginPasswordReader
/// -> CsvDataStorageReader.GetData()
/// -> ConnectToSource()
/// -> ExecuteQuery()
/// </summary>
public class CsvDataStorageReader : IDataStorageReader
{
private readonly DataStorageConfig config;
private string resolvedPath;
private string[] loadedLines;
private string[] loadedHeaders;
/// <summary>
/// Creates CSV data storage reader using provided configuration.
/// </summary>
/// <param name="config">
/// Data storage configuration loaded from gci_config.json.
/// </param>
public CsvDataStorageReader(DataStorageConfig config)
{
this.config = config ?? throw new ArgumentNullException(nameof(config));
}
/// <summary>
/// Reads values from CSV using configured QueryTemplate.
/// </summary>
/// <param name="query">
/// Query parameters used for lookup.
/// </param>
/// <returns>
/// ReaderDiagnosticResult containing lookup result.
/// </returns>
public object GetData(DataQuery query)
{
if (query == null)
throw new ArgumentNullException(nameof(query));
ReaderDiagnosticResult sourceResult = ConnectToSource(true);
if (!sourceResult.Success)
throw new InvalidOperationException(sourceResult.Message);
ReaderDiagnosticResult queryResult = ExecuteQuery(query, true);
if (!queryResult.Success)
throw new InvalidOperationException(queryResult.Message);
return queryResult;
}
/// <summary>
/// Validates CSV source accessibility and content.
/// </summary>
/// <param name="enableDiagnostics">
/// Enables detailed diagnostic output.
/// </param>
/// <returns>
/// Diagnostic result.
/// </returns>
public ReaderDiagnosticResult TestSource(bool enableDiagnostics)
{
return ConnectToSource(enableDiagnostics);
}
/// <summary>
/// Validates configured QueryTemplate against CSV header.
/// </summary>
/// <param name="enableDiagnostics">
/// Enables detailed diagnostic output.
/// </param>
/// <returns>
/// Diagnostic result.
/// </returns>
public ReaderDiagnosticResult TestQuery(bool enableDiagnostics)
{
ReaderDiagnosticResult sourceResult = ConnectToSource(enableDiagnostics);
if (!sourceResult.Success)
return sourceResult;
ReaderDiagnosticResult result = new ReaderDiagnosticResult();
try
{
Log(result, enableDiagnostics, "Starting QueryTemplate validation.");
SearchOrderDefinition definition =
SearchOrderParser.Parse(config.QueryTemplate);
int selectIndex = ResolveColumnIndex(
loadedHeaders,
definition.SelectColumn);
int whereIndex = ResolveColumnIndex(
loadedHeaders,
definition.WhereColumn);
Log(result, enableDiagnostics, "QueryTemplate parsed successfully.");
Log(result, enableDiagnostics, "Select column index: " + selectIndex);
Log(result, enableDiagnostics, "Where column index: " + whereIndex);
result.Success = true;
result.Message = "QueryTemplate validation finished successfully.";
}
catch (Exception ex)
{
result.Success = false;
result.Message = ex.Message;
Log(result, enableDiagnostics, "ERROR: " + ex.Message);
}
return result;
}
/// <summary>
/// Opens CSV file and loads its content.
/// Validates file existence and header.
/// </summary>
/// <param name="enableDiagnostics">
/// Enables detailed diagnostic output.
/// </param>
/// <returns>
/// Source validation result.
/// </returns>
private ReaderDiagnosticResult ConnectToSource(bool enableDiagnostics)
{
ReaderDiagnosticResult result = new ReaderDiagnosticResult();
try
{
Log(result, enableDiagnostics, "Starting CSV source connection test.");
if (string.IsNullOrWhiteSpace(config.DataSource))
throw new InvalidOperationException("CSV data source is empty.");
resolvedPath = Path.GetFullPath(config.DataSource);
Log(result, enableDiagnostics, "Resolved full path: " + resolvedPath);
if (!File.Exists(resolvedPath))
throw new FileNotFoundException("CSV file was not found.", resolvedPath);
loadedLines = File.ReadAllLines(resolvedPath);
if (loadedLines == null || loadedLines.Length == 0)
throw new InvalidOperationException("CSV file is empty.");
loadedHeaders = SplitCsvLine(loadedLines[0]);
if (loadedHeaders == null || loadedHeaders.Length == 0)
throw new InvalidOperationException("CSV header is empty.");
Log(result, enableDiagnostics, "CSV line count: " + loadedLines.Length);
Log(result, enableDiagnostics, "CSV header column count: " + loadedHeaders.Length);
result.Success = true;
result.Message = "CSV source connection finished successfully.";
result.Data = loadedLines;
}
catch (Exception ex)
{
result.Success = false;
result.Message = ex.Message;
result.Data = null;
Log(result, enableDiagnostics, "ERROR: " + ex.Message);
}
return result;
}
/// <summary>
/// Executes configured QueryTemplate against loaded CSV data.
/// </summary>
/// <param name="query">
/// Query values used for matching.
/// </param>
/// <param name="enableDiagnostics">
/// Enables detailed diagnostic output.
/// </param>
/// <returns>
/// Query result.
/// </returns>
private ReaderDiagnosticResult ExecuteQuery(
DataQuery query,
bool enableDiagnostics)
{
ReaderDiagnosticResult result = new ReaderDiagnosticResult();
try
{
if (query.QueryParams == null || query.QueryParams.Count == 0)
throw new InvalidOperationException("DataQuery.QueryParams is empty.");
SearchOrderDefinition definition =
SearchOrderParser.Parse(config.QueryTemplate);
int selectIndex = ResolveColumnIndex(
loadedHeaders,
definition.SelectColumn);
int whereIndex = ResolveColumnIndex(
loadedHeaders,
definition.WhereColumn);
List<string> matchedValues = new List<string>();
foreach (string param in query.QueryParams)
{
string queryValue = (param ?? string.Empty).Trim();
bool found = false;
for (int lineIndex = 1; lineIndex < loadedLines.Length; lineIndex++)
{
if (string.IsNullOrWhiteSpace(loadedLines[lineIndex]))
continue;
string[] values = SplitCsvLine(loadedLines[lineIndex]);
if (whereIndex >= values.Length)
continue;
string currentValue = (values[whereIndex] ?? string.Empty).Trim();
if (!string.Equals(
currentValue,
queryValue,
StringComparison.OrdinalIgnoreCase))
{
continue;
}
string returnValue =
selectIndex < values.Length
? values[selectIndex]
: string.Empty;
matchedValues.Add(returnValue);
found = true;
break;
}
if (!found)
Log(result, enableDiagnostics, "No match found for: " + queryValue);
}
result.Success = true;
if (query.QueryParams.Count == 1)
{
result.Data = matchedValues.Count > 0 ? matchedValues[0] : null;
result.Message = matchedValues.Count > 0
? "Value found."
: "No match found.";
}
else
{
result.Data = matchedValues;
result.Message =
"Batch query finished. Matches found: " +
matchedValues.Count +
" of " +
query.QueryParams.Count +
".";
}
}
catch (Exception ex)
{
result.Success = false;
result.Message = ex.Message;
result.Data = null;
Log(result, enableDiagnostics, "ERROR: " + ex.Message);
}
return result;
}
/// <summary>
/// Resolves column index either by name or by explicit index.
/// </summary>
/// <param name="headers">
/// CSV header columns.
/// </param>
/// <param name="columnReference">
/// Parsed QueryTemplate column definition.
/// </param>
/// <returns>
/// Zero-based column index.
/// </returns>
private int ResolveColumnIndex(
string[] headers,
ColumnReference columnReference)
{
if (columnReference == null)
throw new InvalidOperationException("Column reference is null.");
if (columnReference.HasIndex)
{
int index = columnReference.Index.Value;
if (index < 0 || index >= headers.Length)
throw new InvalidOperationException("Column index is out of range.");
return index;
}
if (columnReference.HasName)
{
for (int i = 0; i < headers.Length; i++)
{
if (string.Equals(
headers[i]?.Trim(),
columnReference.Name?.Trim(),
StringComparison.OrdinalIgnoreCase))
{
return i;
}
}
throw new InvalidOperationException(
"Column '" + columnReference.Name + "' was not found in CSV header.");
}
throw new InvalidOperationException("Column reference is not defined.");
}
/// <summary>
/// Splits CSV line using common separators.
/// Supports:
/// ';'
/// ','
/// '\t'
/// </summary>
/// <param name="line">
/// Input CSV line.
/// </param>
/// <returns>
/// Parsed columns.
/// </returns>
private string[] SplitCsvLine(string line)
{
if (string.IsNullOrEmpty(line))
return new string[0];
if (line.Contains(";"))
return line.Split(';');
if (line.Contains(","))
return line.Split(',');
if (line.Contains("\t"))
return line.Split('\t');
return new[] { line };
}
/// <summary>
/// Adds diagnostic line when diagnostics are enabled.
/// </summary>
private void Log(
ReaderDiagnosticResult result,
bool enableDiagnostics,
string message)
{
if (!enableDiagnostics || result == null)
return;
result.Diagnostics.Add(message);
}
}
}
@@ -0,0 +1,273 @@
using System;
using System.Data;
using System.Data.SqlClient;
using GenesisCordonelInterface.Core.DataStorage.Reading.Common.Models;
using GenesisCordonelInterface.Core.DataStorage.Reading.Common.Contracts;
namespace GenesisCordonelInterface.Core.DataStorage.Reading.Common.Providers
{
/// <summary>
/// Reads data from SQL Server based data storage.
///
/// The reader uses configuration loaded from gci_config.json.
///
/// QueryTemplate must contain QUERYPARAM placeholder.
///
/// Example:
/// SELECT [Password] FROM [dbo].[SkeletonKeys] WHERE [PcbId] = QUERYPARAM
///
/// The placeholder is internally converted to SQL parameter @value.
/// </summary>
public class DatabaseDataStorageReader : IDataStorageReader
{
/// <summary>
/// Data storage configuration containing connection string and query template.
/// </summary>
private readonly DataStorageConfig config;
/// <summary>
/// Creates SQL Server data storage reader using provided configuration.
/// </summary>
/// <param name="config">
/// Data storage configuration loaded from gci_config.json.
/// </param>
public DatabaseDataStorageReader(DataStorageConfig config)
{
this.config = config ?? throw new ArgumentNullException(nameof(config));
}
/// <summary>
/// Executes configured SQL query and returns first matching row.
/// </summary>
/// <param name="query">
/// Query object containing lookup parameter.
/// </param>
/// <returns>
/// DatabaseSearchResult containing returned SQL columns and values.
/// </returns>
public object GetData(DataQuery query)
{
if (query == null)
throw new ArgumentNullException(nameof(query));
ReaderDiagnosticResult sourceResult = TestSource(true);
if (!sourceResult.Success)
throw new InvalidOperationException(sourceResult.Message);
string sqlText = PrepareSqlText(config.QueryTemplate);
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))
{
DatabaseSearchResult result = new DatabaseSearchResult
{
Query = sqlText
};
if (!reader.Read())
{
result.Found = false;
return result;
}
result.Found = true;
for (int i = 0; i < reader.FieldCount; i++)
{
object value = reader.GetValue(i);
result.Values[reader.GetName(i)] =
value == DBNull.Value ? null : value;
}
return result;
}
}
}
/// <summary>
/// Tests whether SQL Server connection can be opened.
/// </summary>
/// <param name="enableDiagnostics">
/// Enables detailed diagnostic output.
/// </param>
/// <returns>
/// Diagnostic result of SQL connection test.
/// </returns>
public ReaderDiagnosticResult TestSource(bool enableDiagnostics)
{
ReaderDiagnosticResult result = new ReaderDiagnosticResult();
try
{
if (string.IsNullOrWhiteSpace(config.DataSource))
throw new InvalidOperationException("Data source is empty.");
Log(result, enableDiagnostics, "Opening SQL connection.");
using (SqlConnection connection = new SqlConnection(config.DataSource))
{
connection.Open();
Log(result, enableDiagnostics, "Connection opened successfully.");
using (SqlCommand command = new SqlCommand("SELECT 1", connection))
{
object value = command.ExecuteScalar();
Log(result, enableDiagnostics, "Test query result: " + value);
}
}
result.Success = true;
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());
}
return result;
}
/// <summary>
/// Tests whether configured SQL query can be prepared and executed.
/// </summary>
/// <param name="enableDiagnostics">
/// Enables detailed diagnostic output.
/// </param>
/// <returns>
/// Diagnostic result of query execution test.
/// </returns>
public ReaderDiagnosticResult TestQuery(bool enableDiagnostics)
{
ReaderDiagnosticResult result = new ReaderDiagnosticResult();
try
{
if (string.IsNullOrWhiteSpace(config.QueryTemplate))
throw new InvalidOperationException("Query template is empty.");
string sqlText = PrepareSqlText(config.QueryTemplate);
Log(result, enableDiagnostics, "Original template:");
Log(result, enableDiagnostics, config.QueryTemplate);
Log(result, enableDiagnostics, "Prepared SQL:");
Log(result, enableDiagnostics, sqlText);
using (SqlConnection connection = new SqlConnection(config.DataSource))
using (SqlCommand command = new SqlCommand(sqlText, connection))
{
AddQueryParameter(command, "TEST");
connection.Open();
object value = command.ExecuteScalar();
result.Data = value;
Log(result, enableDiagnostics, "Query executed successfully.");
}
result.Success = true;
result.Message = "Query executed successfully.";
}
catch (Exception ex)
{
result.Success = false;
result.Message = "Query execution failed. " + ex.Message;
Log(result, enableDiagnostics, ex.ToString());
}
return result;
}
/// <summary>
/// Converts configured QueryTemplate to executable SQL text.
/// </summary>
/// <param name="queryTemplate">
/// SQL query template containing QUERYPARAM placeholder.
/// </param>
/// <returns>
/// SQL text with QUERYPARAM replaced by @value parameter.
/// </returns>
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");
}
/// <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)
{
if (query.QueryParams == null || query.QueryParams.Count == 0)
throw new InvalidOperationException(
"DataQuery does not contain any query parameter.");
return query.QueryParams[0];
}
/// <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)
{
command.Parameters.Clear();
SqlParameter parameter = command.Parameters.Add("@value", SqlDbType.Variant);
parameter.Value = value ?? DBNull.Value;
}
/// <summary>
/// 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,
string message)
{
if (!enableDiagnostics || result == null)
return;
result.Diagnostics.Add(message);
}
}
}
@@ -0,0 +1,31 @@
using System;
using GenesisCordonelInterface.Core.DataStorage.Reading.Common.Models;
using GenesisCordonelInterface.Core.DataStorage.Reading.Common.Contracts;
namespace GenesisCordonelInterface.Core.DataStorage.Reading.Common.Providers
{
public class JsonDataStorageReader : IDataStorageReader
{
private readonly DataStorageConfig config;
public JsonDataStorageReader(DataStorageConfig config)
{
this.config = config ?? throw new ArgumentNullException(nameof(config));
}
public object GetData(DataQuery query)
{
throw new NotImplementedException();
}
public ReaderDiagnosticResult TestSource(bool enableDiagnostics)
{
throw new NotImplementedException();
}
public ReaderDiagnosticResult TestQuery(bool enableDiagnostics)
{
throw new NotImplementedException();
}
}
}
@@ -0,0 +1,31 @@
using System;
using GenesisCordonelInterface.Core.DataStorage.Reading.Common.Models;
using GenesisCordonelInterface.Core.DataStorage.Reading.Common.Contracts;
namespace GenesisCordonelInterface.Core.DataStorage.Reading.Common.Providers
{
public class RestApiDataStorageReader : IDataStorageReader
{
private readonly DataStorageConfig config;
public RestApiDataStorageReader(DataStorageConfig config)
{
this.config = config ?? throw new ArgumentNullException(nameof(config));
}
public object GetData(DataQuery query)
{
throw new NotImplementedException();
}
public ReaderDiagnosticResult TestSource(bool enableDiagnostics)
{
throw new NotImplementedException();
}
public ReaderDiagnosticResult TestQuery(bool enableDiagnostics)
{
throw new NotImplementedException();
}
}
}
@@ -0,0 +1,125 @@
using System;
namespace GenesisCordonelInterface.Core.DataStorage.Reading.Common.Searching
{
/// <summary>
/// Parsed representation of QueryTemplate expression.
///
/// Example:
///
/// SELECT [Password] WHERE [PcbId] = QUERYPARAM
///
/// becomes:
///
/// SelectColumn:
/// [Password]
///
/// WhereColumn:
/// [PcbId]
/// </summary>
public class SearchOrderDefinition
{
/// <summary>
/// Column to be returned from lookup result.
///
/// Example:
///
/// SELECT [Password]
///
/// returns:
///
/// [Password]
/// </summary>
public ColumnReference SelectColumn { get; set; }
/// <summary>
/// Column used for row matching.
///
/// Example:
///
/// WHERE [PcbId] = QUERYPARAM
///
/// uses:
///
/// [PcbId]
/// </summary>
public ColumnReference WhereColumn { get; set; }
}
/// <summary>
/// Represents one column definition inside QueryTemplate.
///
/// Supports two forms:
///
/// [ColumnName]
///
/// or:
///
/// COLUMN(number)
///
/// Examples:
///
/// [Password]
///
/// COLUMN(2)
/// </summary>
public class ColumnReference
{
/// <summary>
/// Column name used in named lookup mode.
///
/// Example:
///
/// [Password]
/// </summary>
public string Name { get; set; }
/// <summary>
/// Zero-based column index used in indexed lookup mode.
///
/// Example:
///
/// COLUMN(2)
/// </summary>
public int? Index { get; set; }
/// <summary>
/// Indicates whether column uses name-based lookup.
/// </summary>
public bool HasName
{
get
{
return !string.IsNullOrWhiteSpace(Name);
}
}
/// <summary>
/// Indicates whether column uses index-based lookup.
/// </summary>
public bool HasIndex
{
get
{
return Index.HasValue;
}
}
/// <summary>
/// Returns human readable representation.
/// </summary>
/// <returns>
/// Column expression text.
/// </returns>
public override string ToString()
{
if (HasName)
return "[" + Name + "]";
if (HasIndex)
return "COLUMN(" + Index.Value + ")";
return "<undefined column reference>";
}
}
}
@@ -0,0 +1,167 @@
using System;
using System.Text.RegularExpressions;
namespace GenesisCordonelInterface.Core.DataStorage.Reading.Common.Searching
{
/// <summary>
/// Parses SQL-like QueryTemplate expressions used by GCI data storage readers.
///
/// Supported syntax:
///
/// SELECT [ReturnColumn] WHERE [MatchColumn] = QUERYPARAM
///
/// Examples:
///
/// SELECT [Password] WHERE [PcbId] = QUERYPARAM
///
/// SELECT COLUMN(1) WHERE COLUMN(0) = QUERYPARAM
///
/// Mixed forms are also supported:
///
/// SELECT [Password] WHERE COLUMN(0)=QUERYPARAM
///
/// The parser converts text expressions into structured
/// SearchOrderDefinition objects which are later consumed
/// by CSV and other readers.
/// </summary>
public static class SearchOrderParser
{
/// <summary>
/// Full QueryTemplate validation pattern.
///
/// Expected syntax:
///
/// SELECT [Column] WHERE [Column] = QUERYPARAM
/// </summary>
private static readonly Regex FullPattern = new Regex(
@"^\s*SELECT\s+(?<select>\[[^\]]+\]|COLUMN\(\d+\))\s+WHERE\s+(?<where>\[[^\]]+\]|COLUMN\(\d+\))\s*=\s*QUERYPARAM\s*$",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
/// <summary>
/// Matches:
///
/// [ColumnName]
/// </summary>
private static readonly Regex NamedColumnPattern = new Regex(
@"^\[(?<name>[^\]]+)\]$",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
/// <summary>
/// Matches:
///
/// COLUMN(number)
/// </summary>
private static readonly Regex IndexedColumnPattern = new Regex(
@"^COLUMN\((?<index>\d+)\)$",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
/// <summary>
/// Parses QueryTemplate text into structured definition.
///
/// Example:
///
/// SELECT [Password] WHERE [PcbId] = QUERYPARAM
///
/// Result:
///
/// SelectColumn:
/// Password
///
/// WhereColumn:
/// PcbId
/// </summary>
/// <param name="searchOrder">
/// QueryTemplate expression.
/// </param>
/// <returns>
/// Parsed query definition.
/// </returns>
public static SearchOrderDefinition Parse(string searchOrder)
{
if (string.IsNullOrWhiteSpace(searchOrder))
throw new InvalidOperationException(
"QueryTemplate is empty.");
Match match = FullPattern.Match(searchOrder);
if (!match.Success)
{
throw new InvalidOperationException(
"Invalid QueryTemplate syntax. Expected: SELECT [ReturnColumn] WHERE [MatchColumn] = QUERYPARAM");
}
return new SearchOrderDefinition
{
SelectColumn =
ParseColumnReference(
match.Groups["select"].Value),
WhereColumn =
ParseColumnReference(
match.Groups["where"].Value)
};
}
/// <summary>
/// Parses single column definition.
///
/// Supported forms:
///
/// [ColumnName]
///
/// COLUMN(number)
/// </summary>
/// <param name="token">
/// Raw token extracted from QueryTemplate.
/// </param>
/// <returns>
/// Parsed column reference.
/// </returns>
private static ColumnReference ParseColumnReference(
string token)
{
if (string.IsNullOrWhiteSpace(token))
throw new InvalidOperationException(
"Column reference token is empty.");
Match nameMatch =
NamedColumnPattern.Match(token);
if (nameMatch.Success)
{
return new ColumnReference
{
Name =
nameMatch
.Groups["name"]
.Value
.Trim(),
Index = null
};
}
Match indexMatch =
IndexedColumnPattern.Match(token);
if (indexMatch.Success)
{
return new ColumnReference
{
Name = null,
Index =
int.Parse(
indexMatch
.Groups["index"]
.Value)
};
}
throw new InvalidOperationException(
"Invalid column reference '" +
token +
"'. Use [ColumnName] or COLUMN(number).");
}
}
}
@@ -0,0 +1,50 @@
using System.Threading;
using System.Threading.Tasks;
namespace GenesisCordonelInterface.Core.DataStorage.Reading.Implementation.MeterLoginPasswords
{
/// <summary>
/// Defines contract for reading meter login passwords
/// from configured GCI data storage.
///
/// Implementations hide storage details and provide
/// a unified API for password lookup.
///
/// Supported storage types:
/// - SQL database
/// - CSV
/// - JSON
/// - REST API
/// </summary>
public interface IMeterLoginPasswordReader
{
/// <summary>
/// Reads meter login password synchronously.
/// </summary>
/// <param name="queryParam">
/// PCB ID or another configured lookup value.
/// </param>
/// <returns>
/// Password if found; otherwise null.
/// </returns>
string GetPassword(string queryParam);
/// <summary>
/// Reads meter login password asynchronously.
/// Thread-safe implementation may serialize
/// access to the underlying storage.
/// </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>
Task<string> GetPasswordAsync(
string queryParam,
CancellationToken token = default);
}
}
@@ -0,0 +1,91 @@
using GenesisCordonelInterface.Core.DataStorage.Reading.Common;
using GenesisCordonelInterface.Core.DataStorage.Reading.Common.Models;
using GenesisCordonelInterface.Core.DataStorage.Reading.Common.Contracts;
using GenesisCordonelInterface.Core.DataStorage.Reading.Implementation.MeterLoginPasswords;
using System;
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
{
/// <summary>
/// Universal data storage reader selected by configuration.
/// Can represent database, CSV, JSON or REST reader.
/// </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)
{
reader = DataStorageReaderFactory.Create(config);
}
/// <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));
await readLock.WaitAsync(token);
try
{
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();
}
return result?.ToString();
}
}
@@ -0,0 +1,43 @@
using System.Collections.Generic;
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.
///
/// Expected structure:
/// Dn_InternalId | ParameterName | ParameterValue
///
/// Example:
/// 3 | GENESISFLOW_MinValidToF | 21990232
/// 3 | GENESISFLOW_Timeout | 1
///
/// Parameters are grouped by Dn_InternalId and returned
/// as key/value pairs where:
///
/// Key = ParameterName
/// Value = ParameterValue
/// </summary>
internal interface IPreAdjustmentCalibrationParamsReader
{
/// <summary>
/// Reads all calibration parameters assigned
/// to a specific DN identifier.
/// </summary>
/// <param name="dnInternalId">
/// Internal DN identifier (meter size).
/// </param>
/// <returns>
/// Dictionary:
///
/// Key:
/// GENESISFLOW parameter name
///
/// Value:
/// Stored parameter value
/// </returns>
Task<Dictionary<string, string>> ReadParamsAsync(int dnInternalId);
}
}
@@ -0,0 +1,87 @@
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Threading.Tasks;
namespace GenesisCordonelInterface.Core.DataStorage.Reading.Implementation.PreAdjustmentCalibrationParams
{
/// <summary>
/// Reads pre-adjustment calibration parameters
/// from SQL database storage.
///
/// Expected table:
///
/// dbo.PreAdjustmentCalibrationParams
///
/// Columns:
/// Dn_InternalId
/// ParameterName
/// ParameterValue
///
/// Example:
///
/// 3 | GENESISFLOW_MinValidToF | 21990232
/// 3 | GENESISFLOW_Timeout | 1
///
/// Returns values as dictionary:
///
/// GENESISFLOW_MinValidToF -> 21990232
/// GENESISFLOW_Timeout -> 1
/// </summary>
internal class PreAdjustmentCalibrationParamsReader: IPreAdjustmentCalibrationParamsReader
{
private readonly string _connectionString;
/// <summary>
/// Initializes calibration parameter reader.
/// </summary>
/// <param name="connectionString">
/// SQL database connection string.
/// </param>
public PreAdjustmentCalibrationParamsReader(
string connectionString)
{
_connectionString = connectionString?? throw new ArgumentNullException(nameof(connectionString));
}
/// <inheritdoc/>
public async Task<Dictionary<string, string>> ReadParamsAsync(int dnInternalId)
{
var result = new Dictionary<string, string>();
const string query = @"
SELECT ParameterName, ParameterValue
FROM dbo.PreAdjustmentCalibrationParams
WHERE Dn_InternalId=@Dn_InternalId";
using (var connection = new SqlConnection(_connectionString))
using (var command = new SqlCommand(query, connection))
{
command.Parameters.AddWithValue(
"@Dn_InternalId",
dnInternalId);
await connection.OpenAsync();
using (var reader =
await command.ExecuteReaderAsync())
{
while (await reader.ReadAsync())
{
var parameterName = reader["ParameterName"].ToString();
var parameterValue = reader["ParameterValue"].ToString();
if (!string.IsNullOrWhiteSpace(parameterName))
{
result[parameterName] = parameterValue;
}
}
}
}
return result;
}
}
}
@@ -0,0 +1,23 @@
Navod na logovanie projektu Laatzen/Common/ pre Genesis Cordonel meradla:
1. Princip:
- logovanie je zabezpecene pomocou nastroja NLog, ktory pouziva Laatzen
- Laatzen vsak pouziva nad NLogom svoj wrapper NLogHelper.cs a teda sa na pracu pri ich projektoch konfiguruje NLog pomocou ich suboru Nlogconfig.xml,
no nakolko ja som nechcel zasahovat do ich konfiguracneho suboru NLogu, pouzil som svoj, ktory je definovany v mojom projekte GenesisCordonelInterface,
s nazvom nlog.config
- z dovodu, ze som teda nechcel zasahovat do ich konfiguracie a zaroven som musel NLog na svoje ucely (presmerovanie logov do mema v mojom projekte),
musel som teda konfigurovat svojim konfiguracnym suborom, a zaroven plati ze pouzivam raw NLog.
- btw ked som pouzil ich wrapper a zaroven moj konfiguracny subor NLogu, tak pri spusten appky ho aj nacitalo, no nasledne sa nacitali Laatzenacke projekty
a nacital sa aj ich konfigurak Nlogu, ci sa prepisal ten moj. Pouzil som ten raw Nlog a uz to bolo ok
- takto je mozne presmerovat pomocou nizsie uvedenej metody logy az do mema v mojom projekte a tiez aj do suboru, pricom vsetko definujem v nlog.config
mojho projektu a nie v projekte Laatzenu
2. prilozene subory UiLogBus.cs a UiTarget.cs musia byt nakopirovane do projektu v ramci Solution s nazvom Common od Laatzenu
- kopiruju sa do top adresara projektu
- musia obsahovat ""namespace Xylem.Common.Utils.Logging"
- v mieste kde chcem logovat, je potrebne:
- zadefinovat:
private readonly ILogger Logger = NLogHelper.CreateOrGetLogger("GenesisCordonelInterface");
- pouzit log:
Logger.Error(ex, $"Slot #{slotNR} failed: {ex.Message}");
Logger.Trace("CONFIG: Setup loaded.");
Logger.Info("CONFIG: Setup loaded.");
...whatever
@@ -0,0 +1,18 @@
using System;
/*namespace Xylem.Common.Utils.Logging
{
public static class UiLogBus
{
public static event Action<string> MessageReceived;
public static void Publish(string message)
{
var handler = MessageReceived;
if (handler != null)
{
handler(message);
}
}
}
}*/
@@ -0,0 +1,15 @@
using NLog;
using NLog.Targets;
/*namespace Xylem.Common.Utils.Logging
{
[Target("UiTarget")]
public class UiTarget : TargetWithLayout
{
protected override void Write(LogEventInfo logEvent)
{
string message = Layout.Render(logEvent);
UiLogBus.Publish(message);
}
}
}*/
@@ -0,0 +1,364 @@
using System;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
namespace GenesisCordonelInterface.Core.Threading
{
/*
ApiWorker per-slot sequential execution worker
This class provides a lightweight background worker that executes actions
sequentially on a dedicated thread.
PRIMARY PURPOSE
---------------
ApiWorker is designed to safely execute hardware-related operations
(e.g. meter communication) without blocking the UI thread and without
allowing concurrent access to the same device.
Each ApiWorker instance typically represents:
1 worker = 1 slot = 1 meter = 1 communication channel
KEY PROPERTIES
--------------
- Single dedicated background thread
- FIFO queue (first-in, first-out)
- Sequential execution (NO parallelism inside one worker)
- Thread-safe enqueueing
- Task-based async interface for callers
WHY THIS IS IMPORTANT
--------------------
Hardware communication (serial ports, meters, etc.) is usually NOT thread-safe.
If multiple commands are executed in parallel, communication may break or corrupt data.
ApiWorker guarantees:
- operations are executed one-by-one
- order is preserved
- no race conditions on the device
HIGH-LEVEL FLOW
---------------
Caller (UI/API)
|
v
RunAsync(...)
|
v
TaskCompletionSource created
|
v
Action wrapped into queue item
|
v
Added to BlockingCollection queue
|
v
Worker thread consumes queue
|
v
Action executed (blocking HW call)
|
v
Result propagated via TaskCompletionSource
|
v
Caller receives result via await
GRAPH
-----
Caller thread (UI)
|
v
RunAsync()
|
v
Queue (BlockingCollection)
|
v
-----------------------------
| Worker Thread (background)|
| while(queue) |
| Execute Action |
-----------------------------
|
v
Task result (await)
THREADING MODEL
---------------
- Producer/Consumer pattern
- Producer: any thread calling RunAsync
- Consumer: single worker thread
- Synchronization handled by BlockingCollection
MAIN COMPONENTS
---------------
1. BlockingCollection<Action> queue
- thread-safe queue
- stores work items
- supports blocking consumption
2. Dedicated Thread
- runs WorkerLoop()
- continuously processes queue
3. TaskCompletionSource<T>
- bridges sync execution → async API
- allows caller to await result
METHODS
-------
RunAsync<T>(Func<T>)
--------------------
- Enqueues a function returning a value
- Wraps it into Action
- Executes on worker thread
- Returns Task<T> to caller
RunAsync(Action)
----------------
- Convenience overload for void methods
- Internally wraps into Func<object>
WorkerLoop()
------------
- Infinite loop consuming queue
- Executes actions one-by-one
- Stops when queue is completed
Dispose()
---------
- Stops accepting new items
- Cleans up queue
- Does NOT forcibly stop running task
CANCELLATION
------------
- CancellationToken is checked BEFORE execution
- If cancelled → Task is cancelled
- Does NOT interrupt running operation
IMPORTANT LIMITATIONS
--------------------
- No parallel execution inside one worker (by design)
- Long-running action blocks worker thread
- No built-in timeout handling
- Dispose does not abort running work
WHEN TO USE
-----------
✔ Per-device communication (serial, TCP, HW)
✔ Ordered execution required
✔ UI must stay responsive
WHEN NOT TO USE
---------------
✘ CPU parallel processing (use Task.Run / Parallel)
✘ High-throughput parallel workloads
✘ Fire-and-forget background tasks
SUMMARY
-------
ApiWorker is a simple, robust solution for:
"Execute commands sequentially per resource, asynchronously from UI"
It is a perfect fit for:
- hardware interfaces
- device drivers
- IO-bound serialized workflows
*/
public sealed class ApiWorker : IDisposable
{
private static readonly NLog.ILogger Logger = NLog.LogManager.GetLogger("GenesisCordonelInterface-threading");
/// <summary>
/// Thread-safe FIFO queue holding work items.
/// </summary>
private readonly BlockingCollection<Action> queue = new BlockingCollection<Action>();
/// <summary>
/// Dedicated worker thread processing the queue.
/// </summary>
private readonly Thread thread;
/// <summary>
/// Indicates whether this worker has been disposed.
/// </summary>
private bool disposed;
public string Name { get; private set; }
public int QueueLength
{
get
{
if (disposed || queue == null)
return 0;
try
{
return queue.Count;
}
catch (ObjectDisposedException)
{
return 0;
}
}
}
public bool IsBusy { get; private set; }
public string CurrentOperation { get; private set; }
public string LastError { get; private set; }
public DateTime LastActivity { get; private set; }
public bool IsDisposed
{
get { return disposed; }
}
/// <summary>
/// Creates a new ApiWorker with its own background thread.
/// </summary>
public ApiWorker(string name)
{
Name = name;
LastActivity = DateTime.Now;
thread = new Thread(WorkerLoop)
{
IsBackground = true,
Name = name
};
thread.Start();
}
/// <summary>
/// Enqueues a function returning a value for sequential execution.
/// </summary>
public Task<T> RunAsync<T>(
Func<T> action,
CancellationToken token = default,
string operationName = null)
{
if (action == null)
throw new ArgumentNullException(nameof(action));
if (disposed)
throw new ObjectDisposedException(nameof(ApiWorker));
var tcs = new TaskCompletionSource<T>(
TaskCreationOptions.RunContinuationsAsynchronously);
try
{
Debug.WriteLine($"ENQUEUE {operationName} slot worker={Name} time={DateTime.Now:HH:mm:ss.fff}");
queue.Add(() =>
{
if (token.IsCancellationRequested)
{
tcs.TrySetCanceled();
return;
}
try
{
IsBusy = true;
CurrentOperation = operationName ?? action.Method.Name;
LastActivity = DateTime.Now;
LastError = null;
var result = action();
tcs.TrySetResult(result);
}
catch (Exception ex)
{
LastError = ex.Message;
tcs.TrySetException(ex);
}
finally
{
IsBusy = false;
CurrentOperation = null;
LastActivity = DateTime.Now;
}
}, token);
}
catch (ObjectDisposedException ex)
{
tcs.TrySetException(ex);
}
catch (InvalidOperationException ex)
{
tcs.TrySetException(new ObjectDisposedException(nameof(ApiWorker), ex));
}
return tcs.Task;
}
public Task RunAsync(
Action action,
CancellationToken token = default(CancellationToken),
string operationName = null)
{
return RunAsync<object>(() =>
{
action();
return null;
}, token, operationName);
}
/// <summary>
/// Enqueues a void action for sequential execution.
/// </summary>
public Task RunAsync(Action action, CancellationToken token = default)
{
return RunAsync<object>(() =>
{
action();
return null;
}, token);
}
/// <summary>
/// Main worker loop processing queued actions.
/// </summary>
private void WorkerLoop()
{
try
{
foreach (var item in queue.GetConsumingEnumerable())
{
if (item == null)
continue;
item();
}
}
catch (ObjectDisposedException)
{
// worker is shutting down
}
}
/// <summary>
/// Stops the worker and releases resources.
/// </summary>
public void Dispose()
{
if (disposed)
return;
disposed = true;
queue.CompleteAdding();
if (Thread.CurrentThread != thread && thread.IsAlive)
thread.Join(1000);
queue.Dispose();
}
}
}
@@ -0,0 +1,150 @@
using System;
using System.Threading.Tasks;
namespace GenesisCordonelInterface.Core.Threading
{
public sealed class RetryResult<T>
{
public T Result { get; set; }
public bool Success { get; set; }
public int Attempts { get; set; }
public TimeSpan Duration { get; set; }
public bool TimedOut { get; set; }
public override string ToString()
{
return string.Format(
"Success={0}, Attempts={1}, Duration={2} ms, TimedOut={3}, Result={4}",
Success,
Attempts,
(int)Duration.TotalMilliseconds,
TimedOut,
Result == null ? "<null>" : Result.ToString());
}
}
public static class RetryWorker
{
/// <summary>
/// Executes an asynchronous operation with retry and timeout protection.
///
/// Important:
/// The timeout here protects the caller from waiting forever, but it does not forcibly abort
/// the underlying hardware operation. Because hardware/COM calls may continue running after
/// the timeout signal, this method waits for the original action to finish before starting
/// the next retry. This prevents overlapping COM requests on the same device.
/// </summary>
public static async Task<RetryResult<T>> RunWithRetryAsync<T>(
Func<Task<T>> action,
Func<T, bool> isSuccess,
Action<string> log,
Action<string, T> logResult,
string operationName,
int maxAttempts = 3,
int delayMs = 500,
int timeoutMs = 30000)
{
var started = DateTime.Now;
T lastResult = default(T);
bool timedOut = false;
for (int attempt = 1; attempt <= maxAttempts; attempt++)
{
Task<T> actionTask = null;
try
{
log?.Invoke($"{operationName} started. Attempt {attempt}/{maxAttempts}");
// Start real operation, for example Connect/GetPcbId/Login.
actionTask = action();
// Start independent timeout timer.
var timeoutTask = Task.Delay(timeoutMs);
// Wait until either operation completes or timeout expires.
var completedTask = await Task.WhenAny(actionTask, timeoutTask)
.ConfigureAwait(false);
if (completedTask == timeoutTask)
{
timedOut = true;
log?.Invoke(
$"{operationName} timed out. Attempt {attempt}/{maxAttempts}. " +
"Waiting for the running operation to finish before retry.");
// Critical part:
// Do NOT immediately start another retry.
// The hardware operation may still be active in ApiWorker.
// Starting another attempt immediately could corrupt communication.
try
{
lastResult = await actionTask.ConfigureAwait(false);
}
catch (Exception ex)
{
log?.Invoke(
$"{operationName} finished after timeout with exception: " +
$"{ex.GetType().Name}: {ex.Message}");
}
}
else
{
// Operation completed before timeout.
lastResult = await actionTask.ConfigureAwait(false);
}
// Decide whether the returned result means success.
if (lastResult != null && isSuccess(lastResult))
{
return new RetryResult<T>
{
Result = lastResult,
Success = true,
Attempts = attempt,
Duration = DateTime.Now - started,
TimedOut = timedOut
};
}
logResult?.Invoke(
$"{operationName} failed. Attempt {attempt}/{maxAttempts}",
lastResult);
}
catch (Exception ex)
{
// Covers exceptions thrown before timeout handling or by action startup.
log?.Invoke(
$"{operationName} exception on attempt {attempt}/{maxAttempts}: " +
$"{ex.GetType().Name}: {ex.Message}");
}
// Delay before next retry, except after the final attempt.
if (attempt < maxAttempts)
{
log?.Invoke($"{operationName} waiting {delayMs} ms before retry.");
await Task.Delay(delayMs).ConfigureAwait(false);
}
}
return new RetryResult<T>
{
Result = lastResult,
Success = false,
Attempts = maxAttempts,
Duration = DateTime.Now - started,
TimedOut = timedOut
};
}
public static void EnsureSuccess<T>(
RetryResult<T> retryResult,
string operationName)
{
if (!retryResult.Success)
throw new Exception($"{operationName} failed after {retryResult.Attempts} attempts.");
}
}
}
@@ -0,0 +1,321 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{C955D8AC-76B8-42D8-A83F-8AEB56CF2567}</ProjectGuid>
<OutputType>WinExe</OutputType>
<RootNamespace>GenesisCordonelInterface</RootNamespace>
<AssemblyName>GenesisCordonelInterface</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<LangVersion>7.3</LangVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Common">
<HintPath>..\packages\Common\Common.dll</HintPath>
</Reference>
<Reference Include="Logic.ProductionToProductMapper">
<HintPath>..\packages\Common\Logic.ProductionToProductMapper.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="NLog, Version=5.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<HintPath>..\packages\NLog.5.2.2\lib\net46\NLog.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.Core" />
<Reference Include="System.IO.Compression" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Deployment" />
<Reference Include="System.Drawing" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
<Reference Include="Xylem.Common.CommonCore">
<HintPath>..\packages\Common\Xylem.Common.CommonCore.dll</HintPath>
</Reference>
<Reference Include="Xylem.Common.CommonCore.Configuration">
<HintPath>..\packages\Common\Xylem.Common.CommonCore.Configuration.dll</HintPath>
</Reference>
<Reference Include="Xylem.Common.CommonCore.ThreadWatcher">
<HintPath>..\packages\Common\Xylem.Common.CommonCore.ThreadWatcher.dll</HintPath>
</Reference>
<Reference Include="Xylem.Common.Hardware.Interfaces.Ports.PortCore">
<HintPath>..\packages\Common\Xylem.Common.Hardware.Interfaces.Ports.PortCore.dll</HintPath>
</Reference>
<Reference Include="Xylem.Common.Hardware.Interfaces.Ports.SerialPorts">
<HintPath>..\packages\Common\Xylem.Common.Hardware.Interfaces.Ports.SerialPorts.dll</HintPath>
</Reference>
<Reference Include="Xylem.Common.Hardware.WaterMeter.Genesis.Applications">
<HintPath>..\packages\Common\Xylem.Common.Hardware.WaterMeter.Genesis.Applications.dll</HintPath>
</Reference>
<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.Registers">
<HintPath>..\packages\Common\Xylem.Common.Hardware.WaterMeter.Genesis.Registers.dll</HintPath>
</Reference>
<Reference Include="Xylem.Common.Hardware.WaterMeter.MagFlux.Protocols.RequestProtocol">
<HintPath>..\packages\Common\Xylem.Common.Hardware.WaterMeter.MagFlux.Protocols.RequestProtocol.dll</HintPath>
</Reference>
<Reference Include="Xylem.Common.Hardware.WaterMeter.WaterMeterCore">
<HintPath>..\packages\Common\Xylem.Common.Hardware.WaterMeter.WaterMeterCore.dll</HintPath>
</Reference>
<Reference Include="Xylem.Common.Hardware.WaterMeter.WaterMeterRegisters">
<HintPath>..\packages\Common\Xylem.Common.Hardware.WaterMeter.WaterMeterRegisters.dll</HintPath>
</Reference>
<Reference Include="Xylem.Common.Logic.ProductionOrderCore">
<HintPath>..\packages\Common\Xylem.Common.Logic.ProductionOrderCore.dll</HintPath>
</Reference>
<Reference Include="Xylem.Common.Logic.SoftwareAccessHelper">
<HintPath>..\packages\Common\Xylem.Common.Logic.SoftwareAccessHelper.dll</HintPath>
</Reference>
<Reference Include="Xylem.Common.Utils.ByteArrayStyle">
<HintPath>..\packages\Common\Xylem.Common.Utils.ByteArrayStyle.dll</HintPath>
</Reference>
<Reference Include="Xylem.Common.Utils.Crc16Ccitt">
<HintPath>..\packages\Common\Xylem.Common.Utils.Crc16Ccitt.dll</HintPath>
</Reference>
<Reference Include="Xylem.Common.Utils.Logging">
<HintPath>..\packages\Common\Xylem.Common.Utils.Logging.dll</HintPath>
</Reference>
<Reference Include="Xylem.Common.Utils.ProcessExec">
<HintPath>..\packages\Common\Xylem.Common.Utils.ProcessExec.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="API\ModelsMapping.cs" />
<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\DataStorage\Config\GciDataStorageConfig.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" />
<Compile Include="Core\DataStorage\Reading\Common\Models\DataQuery.cs" />
<Compile Include="Core\DataStorage\Reading\Common\Models\DataStorageConfig.cs" />
<Compile Include="Core\DataStorage\Reading\Common\DataStorageReaderFactory.cs" />
<Compile Include="Core\DataStorage\Reading\Common\Models\DataStorageType.cs" />
<Compile Include="Core\DataStorage\Reading\Common\Contracts\IDataStorageReader..cs" />
<Compile Include="Core\DataStorage\Reading\Common\Providers\JsonDataStorageReader.cs" />
<Compile Include="Core\DataStorage\Reading\Common\Models\ReaderDiagnosticResult.cs" />
<Compile Include="Core\DataStorage\Reading\Common\Providers\RestApiDataStorageReader.cs" />
<Compile Include="Core\DataStorage\Reading\Common\Searching\SearchOrderDefinition.cs" />
<Compile Include="Core\DataStorage\Reading\Common\Searching\SearchOrderParser.cs" />
<Compile Include="Core\DataStorage\Reading\Implementation\MeterLoginPasswords\IMeterLoginPasswordReader.cs" />
<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\Logging\UiLogBus.cs" />
<Compile Include="Core\Logging\UiTarget.cs" />
<Compile Include="Core\Threading\ApiWorker\ApiWorker.cs" />
<Compile Include="Core\Threading\RetryWorker\RetryWorker.cs" />
<Compile Include="UI\Debug\MeterBatchConfigPanel.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="UI\Debug\MeterBatchConfigPanel.Designer.cs">
<DependentUpon>MeterBatchConfigPanel.cs</DependentUpon>
</Compile>
<Compile Include="UI\Debug\WorkerDebugPanel.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="UI\Debug\WorkerDebugPanel.Designer.cs">
<DependentUpon>WorkerDebugPanel.cs</DependentUpon>
</Compile>
<Compile Include="UI\Grid\MeterGridColumnConfig.cs" />
<Compile Include="UI\Grid\MeterGridConfigProvider.cs" />
<Compile Include="UI\Grid\MeterGridManager.cs" />
<Compile Include="UI\Grid\MeterRowDto.cs" />
<Compile Include="UI\LaatzenAPI_GenesisToolBox\FrmConfigurations.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="UI\LaatzenAPI_GenesisToolBox\FrmConfigurations.Designer.cs">
<DependentUpon>FrmConfigurations.cs</DependentUpon>
</Compile>
<Compile Include="UI\LaatzenAPI_CordonelPreadjustmentUI\FrmCordonelPreadjustmentUI.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="UI\LaatzenAPI_CordonelPreadjustmentUI\FrmCordonelPreadjustmentUI.Designer.cs">
<DependentUpon>FrmCordonelPreadjustmentUI.cs</DependentUpon>
</Compile>
<Compile Include="UI\LaatzenAPI_GenesisToolBox\FrmRegisterStore.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="UI\LaatzenAPI_GenesisToolBox\FrmRegisterStore.Designer.cs">
<DependentUpon>FrmRegisterStore.cs</DependentUpon>
</Compile>
<Compile Include="UI\LaatzenAPI_GenesisToolBox\FrmSetup.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="UI\LaatzenAPI_GenesisToolBox\FrmSetup.Designer.cs">
<DependentUpon>FrmSetup.cs</DependentUpon>
</Compile>
<Compile Include="UI\MainForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="UI\MainForm.Designer.cs">
<DependentUpon>MainForm.cs</DependentUpon>
</Compile>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="UI\LaatzenAPI_CordonelPreadjustmentUI\PreAdjustmentControl.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="UI\LaatzenAPI_CordonelPreadjustmentUI\PreAdjustmentControl.Designer.cs">
<DependentUpon>PreAdjustmentControl.cs</DependentUpon>
</Compile>
<Compile Include="UI\MainView.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="UI\MainView.Designer.cs">
<DependentUpon>MainView.cs</DependentUpon>
</Compile>
<Compile Include="UI\StaraTuraAPI_GenesisCordonelInterface\FrmGCIAPI.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="UI\StaraTuraAPI_GenesisCordonelInterface\FrmGCIAPI.Designer.cs">
<DependentUpon>FrmGCIAPI.cs</DependentUpon>
</Compile>
<Compile Include="UI\StaraTuraAPI_GenesisCordonelInterface\MeterInitView.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="UI\StaraTuraAPI_GenesisCordonelInterface\MeterInitView.Designer.cs">
<DependentUpon>MeterInitView.cs</DependentUpon>
</Compile>
<Compile Include="UI\StaraTuraAPI_GenesisCordonelInterface\MetersActionView.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="UI\StaraTuraAPI_GenesisCordonelInterface\MetersActionView.Designer.cs">
<DependentUpon>MetersActionView.cs</DependentUpon>
</Compile>
<Content Include="docs\images\GciBridge_component_GUI.png" />
<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\logo\logo.png" />
<Content Include="docs\images\logo\logo.svg" />
<Content Include="docs\images\logo\sensus-logo-white-green-rgb.png" />
<Content Include="docs\images\logo\sensus-logo-white-green-rgb.svg" />
<Content Include="docs\styles\main.css" />
<Content Include="RuntimePackage\Build\Copy.targets.xml" />
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
<DesignTime>True</DesignTime>
</Compile>
<EmbeddedResource Include="UI\LaatzenAPI_GenesisToolBox\FrmSetup.resx">
<DependentUpon>FrmSetup.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="UI\MainForm.resx">
<DependentUpon>MainForm.cs</DependentUpon>
</EmbeddedResource>
<Content Include="Core\Logging\ImportantInstructions.txt" />
<Content Include="nlog.config">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<EmbeddedResource Include="UI\LaatzenAPI_CordonelPreadjustmentUI\PreAdjustmentControl.resx">
<DependentUpon>PreAdjustmentControl.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="UI\StaraTuraAPI_GenesisCordonelInterface\FrmGCIAPI.resx">
<DependentUpon>FrmGCIAPI.cs</DependentUpon>
</EmbeddedResource>
<Content Include="Config\gci_config.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<None Include="docs\articles\API\index.md" />
<None Include="docs\articles\API\PublicModels.md" />
<None Include="docs\articles\API\InterfaceGCIToLaatzen.md" />
<None Include="docs\articles\API\InterfaceOutsideToGCI.md" />
<None Include="docs\docfx.json" />
<None Include="docs\index.md" />
<None Include="docs\pages\development\page_dev__current_state.md" />
<None Include="docs\pages\development\page_dev__home.md" />
<None Include="docs\pages\development\page_dev__target_state.md" />
<None Include="docs\pages\development\page_dev__migration.md" />
<None Include="docs\pages\development\page_dev__refactoring.md" />
<None Include="docs\pages\development\page_dev__target_architecture.md" />
<None Include="docs\pages\gci\page_gci__app_environment.md" />
<None Include="docs\pages\gci\page_gci__internal_architecture.md" />
<None Include="docs\pages\gci\page_gci__datastorage.md" />
<None Include="docs\pages\gci\page_gci__home.md" />
<None Include="docs\pages\gci\page_gci__interfaces.md" />
<None Include="docs\pages\gci\page_gci__runtime.md" />
<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\toc.yml" />
<None Include="packages.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<Folder Include="Core\DataStorage\Writing\NewFolder1\" />
<Folder Include="RuntimePackage\Package\" />
</ItemGroup>
<ItemGroup>
<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>
</ProjectReference>
<ProjectReference Include="..\ExternalProjects\Laatzen\Genesis\Common\Ui\GenesisToolBox\GenesisToolBox.csproj">
<Project>{95A50087-99EE-4349-9A17-C547290DB42F}</Project>
<Name>GenesisToolBox</Name>
</ProjectReference>
</ItemGroup>
<!-- Import custom GCI runtime packaging logic -->
<Import Project="RuntimePackage\Build\Copy.targets.xml" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
+22
View File
@@ -0,0 +1,22 @@
using GenesisCordonelInterface.UI;
using NLog;
using System;
using System.Windows.Forms;
using Xylem.Common.Utils.Logging;
using System.IO;
namespace GenesisCordonelInterface
{
static class Program
{
private static readonly ILogger Logger = NLogHelper.CreateOrGetLogger("GenesisCordonelInterface");
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
}
}
@@ -0,0 +1,33 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("GenesisCordonelInterface")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Windows Org")]
[assembly: AssemblyProduct("GenesisCordonelInterface")]
[assembly: AssemblyCopyright("Copyright © Windows Org 2026")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("c955d8ac-76b8-42d8-a83f-8aeb56cf2567")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
@@ -0,0 +1,63 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace GenesisCordonelInterface.Properties {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("GenesisCordonelInterface.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
}
}
@@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
+26
View File
@@ -0,0 +1,26 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace GenesisCordonelInterface.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.14.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default {
get {
return defaultInstance;
}
}
}
}
@@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>
@@ -0,0 +1,38 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="CopyGciRuntimeToRuntimePackage" AfterTargets="Build">
<PropertyGroup>
<GciRuntimePackageDir>$(ProjectDir)RuntimePackage\Package\</GciRuntimePackageDir>
<TbfPackageCommonDir>$(ProjectDir)..\packages\Common\</TbfPackageCommonDir>
</PropertyGroup>
<MakeDir Directories="$(GciRuntimePackageDir)" />
<MakeDir Directories="$(TbfPackageCommonDir)" />
<ItemGroup>
<GciRuntimeFiles Include="$(TargetDir)*.dll" />
<GciRuntimeFiles Include="$(TargetDir)*.pdb" />
<GciRuntimeFiles Include="$(TargetDir)*.xml" />
<GciRuntimeFiles Include="$(TargetDir)*.exe" />
<GciRuntimeFiles Include="$(TargetDir)*.config" />
<GciRuntimeFiles Include="$(TargetDir)*.json" />
</ItemGroup>
<Message Text="Copying GCI runtime package to $(GciRuntimePackageDir)" Importance="High" />
<Copy
SourceFiles="@(GciRuntimeFiles)"
DestinationFolder="$(GciRuntimePackageDir)"
SkipUnchangedFiles="false"
OverwriteReadOnlyFiles="true" />
<Message Text="Copying GCI runtime package to TBF package common: $(TbfPackageCommonDir)" Importance="High" />
<Copy
SourceFiles="@(GciRuntimeFiles)"
DestinationFolder="$(TbfPackageCommonDir)"
SkipUnchangedFiles="false"
OverwriteReadOnlyFiles="true" />
</Target>
</Project>
@@ -0,0 +1,57 @@
namespace GenesisCordonelInterface.UI.Debug
{
partial class MeterBatchConfigPanel
{
private System.ComponentModel.IContainer components = null;
private System.Windows.Forms.DataGridView grid;
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (components != null)
components.Dispose();
if (api != null)
api.MeterBatchStatusChanged -= Api_MeterBatchStatusChanged;
}
base.Dispose(disposing);
}
#region Component Designer generated code
private void InitializeComponent()
{
this.grid = new System.Windows.Forms.DataGridView();
((System.ComponentModel.ISupportInitialize)(this.grid)).BeginInit();
this.SuspendLayout();
// grid
this.grid.AllowUserToAddRows = false;
this.grid.AllowUserToDeleteRows = false;
this.grid.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.Fill;
this.grid.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.grid.Dock = System.Windows.Forms.DockStyle.Fill;
this.grid.Name = "grid";
this.grid.RowHeadersWidth = 30;
this.grid.TabIndex = 0;
// events
this.grid.CellValueChanged += new System.Windows.Forms.DataGridViewCellEventHandler(this.grid_CellValueChanged);
this.grid.CurrentCellDirtyStateChanged += new System.EventHandler(this.grid_CurrentCellDirtyStateChanged);
this.grid.DataError += new System.Windows.Forms.DataGridViewDataErrorEventHandler(this.grid_DataError);
// MeterBatchConfigPanel
this.Controls.Add(this.grid);
this.Name = "MeterBatchConfigPanel";
this.Size = new System.Drawing.Size(600, 200);
((System.ComponentModel.ISupportInitialize)(this.grid)).EndInit();
this.ResumeLayout(false);
}
#endregion
}
}
@@ -0,0 +1,402 @@
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using GenesisCordonelInterface.API;
using static GenesisCordonelInterface.API.PublicModels;
namespace GenesisCordonelInterface.UI.Debug
{
public partial class MeterBatchConfigPanel : UserControl
{
private readonly InterfaceOutsideToGCI api;
private bool isRefreshing;
private List<string> comPorts = new List<string>();
public MeterBatchConfigPanel(InterfaceOutsideToGCI api)
{
this.api = api;
InitializeComponent();
RefreshComPorts();
InitializeGridColumns();
api.MeterBatchStatusChanged += Api_MeterBatchStatusChanged;
UpdateGrid(api.GetMeterBatchDebugStatuses());
}
#region INIT
// ----------------------------------------------------
private void InitializeGridColumns()
{
grid.Columns.Clear();
grid.Columns.Add("Slot", "Slot");
grid.Columns.Add(new DataGridViewCheckBoxColumn { Name = "Selected", HeaderText = "Selected" });
grid.Columns.Add("PcbId", "PcbId");
grid.Columns.Add(new DataGridViewCheckBoxColumn { Name = "IsLoggedOn", HeaderText = "IsLoggedOn" });
grid.Columns.Add(CreateComPortColumn("RequestPort", "RequestPort"));
grid.Columns.Add(CreateComPortColumn("StreamingPort", "StreamingPort"));
grid.Columns.Add(CreateButtonColumn("DetectRequest", "DetectRequest", "..."));
grid.Columns.Add(CreateButtonColumn("DetectStreaming", "DetectStreaming", "..."));
grid.Columns.Add("FwVersion", "FwVersion");
grid.Columns.Add("InterfaceVersion", "InterfaceVersion");
foreach (DataGridViewColumn col in grid.Columns)
{
col.ReadOnly =
col.Name != "Selected" &&
col.Name != "RequestPort" &&
col.Name != "StreamingPort" &&
col.Name != "DetectRequest" &&
col.Name != "DetectStreaming";
}
EnableDoubleBuffering(grid);
}
private DataGridViewComboBoxColumn CreateComPortColumn(string name, string headerText)
{
return new DataGridViewComboBoxColumn
{
Name = name,
HeaderText = headerText,
DataSource = new List<string>(comPorts),
FlatStyle = FlatStyle.Flat,
DisplayStyle = DataGridViewComboBoxDisplayStyle.DropDownButton
};
}
private DataGridViewButtonColumn CreateButtonColumn(string name, string headerText, string text)
{
return new DataGridViewButtonColumn
{
Name = name,
HeaderText = headerText,
Text = text,
UseColumnTextForButtonValue = true
};
}
private void RefreshComPorts()
{
comPorts = SerialPort.GetPortNames()
.OrderBy(NaturalComPortOrder)
.ToList();
if (!comPorts.Contains(""))
comPorts.Insert(0, "");
}
// ----------------------------------------------------
#endregion
#region REFRESH EVENT DRIVEN
// ----------------------------------------------------
private void Api_MeterBatchStatusChanged(
List<MeterBatchDebugStatus> data)
{
if (IsDisposed)
return;
if (InvokeRequired)
{
BeginInvoke(new Action(() => UpdateGrid(data)));
return;
}
UpdateGrid(data);
}
private void UpdateGrid(List<MeterBatchDebugStatus> data)
{
isRefreshing = true;
foreach (var meter in data)
{
EnsurePortValueExists(meter.RequestPort);
EnsurePortValueExists(meter.StreamingPort);
var row = FindOrCreateRow(meter.Slot);
Set(row, "Slot", meter.Slot);
Set(row, "Selected", meter.Selected);
Set(row, "PcbId", meter.PcbId);
Set(row, "IsLoggedOn", meter.IsLoggedOn);
Set(row, "RequestPort", meter.RequestPort);
Set(row, "StreamingPort", meter.StreamingPort);
Set(row, "FwVersion", meter.FwVersion);
Set(row, "InterfaceVersion", meter.InterfaceVersion);
}
isRefreshing = false;
}
// ----------------------------------------------------
#endregion
#region COM PORT HELPERS
// ----------------------------------------------------
private void UpdateComPortColumnItems(string columnName)
{
var col = grid.Columns[columnName] as DataGridViewComboBoxColumn;
if (col == null)
return;
col.DataSource = null;
col.DataSource = new List<string>(comPorts);
}
private void EnsurePortValueExists(string port)
{
if (string.IsNullOrWhiteSpace(port))
return;
if (comPorts.Contains(port))
return;
comPorts.Add(port);
comPorts = comPorts.OrderBy(NaturalComPortOrder).ToList();
if (!comPorts.Contains(""))
comPorts.Insert(0, "");
UpdateComPortColumnItems("RequestPort");
UpdateComPortColumnItems("StreamingPort");
}
private static int NaturalComPortOrder(string port)
{
if (string.IsNullOrWhiteSpace(port))
return 0;
string number = new string(port.Where(char.IsDigit).ToArray());
int parsed;
if (int.TryParse(number, out parsed))
return parsed;
return int.MaxValue;
}
// ----------------------------------------------------
#endregion
#region GRID HELPERS
// ----------------------------------------------------
private DataGridViewRow FindOrCreateRow(int slot)
{
foreach (DataGridViewRow row in grid.Rows)
{
if (row.Cells["Slot"].Value != null &&
Convert.ToInt32(row.Cells["Slot"].Value) == slot)
{
return row;
}
}
int idx = grid.Rows.Add();
var newRow = grid.Rows[idx];
newRow.Cells["Slot"].Value = slot;
return newRow;
}
private void Set(DataGridViewRow row, string col, object value)
{
if (!grid.Columns.Contains(col))
return;
if (value == null)
value = "";
var cell = row.Cells[col];
if (!Equals(cell.Value, value))
cell.Value = value;
}
// ----------------------------------------------------
#endregion
#region USER EDIT
// ----------------------------------------------------
private void grid_CurrentCellDirtyStateChanged(object sender, EventArgs e)
{
if (grid.IsCurrentCellDirty)
grid.CommitEdit(DataGridViewDataErrorContexts.Commit);
}
private void grid_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
if (isRefreshing)
return;
if (e.RowIndex < 0)
return;
string columnName = grid.Columns[e.ColumnIndex].Name;
if (columnName != "Selected" &&
columnName != "RequestPort" &&
columnName != "StreamingPort")
return;
int slot = Convert.ToInt32(grid.Rows[e.RowIndex].Cells["Slot"].Value);
if (columnName == "Selected")
{
bool selected = Convert.ToBoolean(grid.Rows[e.RowIndex].Cells["Selected"].Value);
api.SetSlotSelected(slot, selected);
return;
}
string port = Convert.ToString(grid.Rows[e.RowIndex].Cells[columnName].Value);
if (columnName == "RequestPort")
{
//api.SetSlotRequestPort(slot, port);
return;
}
if (columnName == "StreamingPort")
{
//api.SetSlotStreamingPort(slot, port);
return;
}
}
private async void grid_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
if (e.RowIndex < 0)
return;
string columnName = grid.Columns[e.ColumnIndex].Name;
if (columnName != "DetectRequest" &&
columnName != "DetectStreaming")
return;
int slot = Convert.ToInt32(grid.Rows[e.RowIndex].Cells["Slot"].Value);
if (columnName == "DetectRequest")
{
await DetectRequestPortAsync(slot);
return;
}
if (columnName == "DetectStreaming")
{
await DetectStreamingPortAsync(slot);
return;
}
}
private async Task DetectRequestPortAsync(int slot)
{
try
{
grid.Enabled = false;
await api.DetectRequestPortAsync(slot);
api.RaiseMeterBatchStatusChanged();
}
finally
{
grid.Enabled = true;
}
}
private async Task DetectStreamingPortAsync(int slot)
{
try
{
grid.Enabled = false;
await api.DetectStreamingPortAsync(slot);
api.RaiseMeterBatchStatusChanged();
}
finally
{
grid.Enabled = true;
}
}
private void grid_DataError(object sender, DataGridViewDataErrorEventArgs e)
{
e.ThrowException = false;
}
// ----------------------------------------------------
#endregion
#region PERFORMANCE
// ----------------------------------------------------
private void EnableDoubleBuffering(DataGridView dgv)
{
typeof(DataGridView)
.GetProperty(
"DoubleBuffered",
System.Reflection.BindingFlags.Instance |
System.Reflection.BindingFlags.NonPublic)
?.SetValue(dgv, true, null);
}
// ----------------------------------------------------
#endregion
public void AddEmptySlotRow()
{
int nextSlot = 1;
var existing = grid.Rows
.Cast<DataGridViewRow>()
.Where(r => r.Cells["Slot"].Value != null)
.Select(r => Convert.ToInt32(r.Cells["Slot"].Value))
.ToList();
if (existing.Count > 0)
nextSlot = existing.Max() + 1;
int idx = grid.Rows.Add();
var row = grid.Rows[idx];
row.Cells["Slot"].Value = nextSlot;
row.Cells["Selected"].Value = true;
row.Cells["RequestPort"].Value = "";
row.Cells["StreamingPort"].Value = "";
}
public List<MeterBatchDebugStatus> GetGridData()
{
var list = new List<MeterBatchDebugStatus>();
foreach (DataGridViewRow row in grid.Rows)
{
if (row.Cells["Slot"].Value == null)
continue;
list.Add(new MeterBatchDebugStatus
{
Slot = Convert.ToInt32(row.Cells["Slot"].Value),
Selected = Convert.ToBoolean(row.Cells["Selected"].Value),
RequestPort = Convert.ToString(row.Cells["RequestPort"].Value),
StreamingPort = Convert.ToString(row.Cells["StreamingPort"].Value)
});
}
return list;
}
}
}
@@ -0,0 +1,37 @@
namespace GenesisCordonelInterface.UI.Debug
{
partial class WorkerDebugPanel
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
}
#endregion
}
}
@@ -0,0 +1,52 @@
using System;
using System.Windows.Forms;
using GenesisCordonelInterface.API;
using static GenesisCordonelInterface.API.PublicModels;
namespace GenesisCordonelInterface.UI.Debug
{
public partial class WorkerDebugPanel : UserControl
{
private readonly InterfaceOutsideToGCI api;
private readonly Timer timer = new Timer();
private readonly DataGridView grid = new DataGridView();
public WorkerDebugPanel(InterfaceOutsideToGCI api)
{
this.api = api;
grid.Dock = DockStyle.Fill;
grid.ReadOnly = true;
grid.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
Controls.Add(grid);
timer.Interval = 300;
timer.Tick += (s, e) =>
{
grid.DataSource = null;
grid.DataSource = api.GetWorkerDebugStatuses();
};
timer.Start();
}
private void InitializeLayout()
{
grid.Dock = DockStyle.Fill;
grid.ReadOnly = true;
grid.AllowUserToAddRows = false;
grid.AllowUserToDeleteRows = false;
grid.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
Controls.Add(grid);
Dock = DockStyle.Fill;
}
private void Timer_Tick(object sender, EventArgs e)
{
grid.DataSource = null;
grid.DataSource = api.GetWorkerDebugStatuses();
}
}
}
@@ -0,0 +1,12 @@
namespace GenesisCordonelInterface.UI.Grid
{
public class MeterGridColumnConfig
{
public string Name { get; set; }
public string HeaderText { get; set; }
public bool Visible { get; set; } = true;
public int DisplayIndex { get; set; }
public int Width { get; set; } = 80;
public bool ReadOnly { get; set; } = false;
}
}
@@ -0,0 +1,23 @@
using System.Collections.Generic;
namespace GenesisCordonelInterface.UI.Grid
{
public static class MeterGridConfigProvider
{
public static List<MeterGridColumnConfig> GetDefault()
{
return new List<MeterGridColumnConfig>
{
new MeterGridColumnConfig { Name = "Slot", HeaderText = "Slot", DisplayIndex = 0, Width = 50, ReadOnly = true },
new MeterGridColumnConfig { Name = "Selected", HeaderText = "Selected", DisplayIndex = 1, Width = 40 },
new MeterGridColumnConfig { Name = "PcbId", HeaderText = "PcbId", DisplayIndex = 2, Width = 80 },
new MeterGridColumnConfig { Name = "IsConnected", HeaderText = "IsConnected", DisplayIndex = 3, Width = 40 },
new MeterGridColumnConfig { Name = "IsLoggedOn", HeaderText = "IsLoggedOn", DisplayIndex = 3, Width = 40 },
new MeterGridColumnConfig { Name = "RequestPort", HeaderText = "RequestPort", DisplayIndex = 4, Width = 90 },
new MeterGridColumnConfig { Name = "StreamingPort", HeaderText = "StreamingPort", DisplayIndex = 5, Width = 100 },
new MeterGridColumnConfig { Name = "FwVersion", HeaderText = "FwVersion", DisplayIndex = 6, Width = 80 },
new MeterGridColumnConfig { Name = "InterfaceVersion", HeaderText = "InterfaceVersion", DisplayIndex = 7, Width = 110 },
};
}
}
}
@@ -0,0 +1,108 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;
namespace GenesisCordonelInterface.UI.Grid
{
public class MeterGridManager
{
private readonly DataGridView grid;
public MeterGridManager(DataGridView grid)
{
this.grid = grid;
EnableDoubleBuffering(grid);
}
public void Init(List<MeterGridColumnConfig> columns)
{
grid.SuspendLayout();
grid.AutoGenerateColumns = false;
grid.Columns.Clear();
grid.AllowUserToAddRows = false;
grid.AllowUserToDeleteRows = false;
grid.RowHeadersVisible = true;
foreach (var cfg in columns.OrderBy(c => c.DisplayIndex))
{
DataGridViewColumn col;
if (cfg.Name == "Selected" || cfg.Name == "IsLoggedOn")
col = new DataGridViewCheckBoxColumn();
else
col = new DataGridViewTextBoxColumn();
col.Name = cfg.Name;
col.HeaderText = cfg.HeaderText;
col.Visible = cfg.Visible;
col.Width = cfg.Width;
col.ReadOnly = cfg.ReadOnly;
grid.Columns.Add(col);
}
grid.ResumeLayout();
}
public void Update(List<MeterRowDto> meters)
{
grid.SuspendLayout();
foreach (var meter in meters)
{
var row = FindOrCreateRow(meter.Slot);
SetCell(row, "Slot", meter.Slot);
SetCell(row, "Selected", meter.Selected);
SetCell(row, "PcbId", meter.PcbId);
SetCell(row, "IsConnected", meter.IsConnected);
SetCell(row, "IsLoggedOn", meter.IsLoggedOn);
SetCell(row, "RequestPort", meter.RequestPort);
SetCell(row, "StreamingPort", meter.StreamingPort);
SetCell(row, "FwVersion", meter.FwVersion);
SetCell(row, "InterfaceVersion", meter.InterfaceVersion);
}
grid.ResumeLayout();
}
private DataGridViewRow FindOrCreateRow(int slot)
{
foreach (DataGridViewRow row in grid.Rows)
{
if (row.Cells["Slot"].Value != null &&
Convert.ToInt32(row.Cells["Slot"].Value) == slot)
{
return row;
}
}
int idx = grid.Rows.Add();
var newRow = grid.Rows[idx];
newRow.Cells["Slot"].Value = slot;
return newRow;
}
private void SetCell(DataGridViewRow row, string colName, object value)
{
if (!grid.Columns.Contains(colName))
return;
var cell = row.Cells[colName];
if (!Equals(cell.Value, value))
cell.Value = value;
}
private void EnableDoubleBuffering(DataGridView dgv)
{
typeof(DataGridView)
.GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic)
?.SetValue(dgv, true, null);
}
}
}
@@ -0,0 +1,15 @@
namespace GenesisCordonelInterface.UI.Grid
{
public class MeterRowDto
{
public int Slot { get; set; }
public bool Selected { get; set; }
public string PcbId { get; set; }
public bool IsConnected { get; set; }
public bool IsLoggedOn { get; set; }
public string RequestPort { get; set; }
public string StreamingPort { get; set; }
public string FwVersion { get; set; }
public string InterfaceVersion { get; set; }
}
}
@@ -0,0 +1,415 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Xylem.Common.CommonCore.Consts;
using Xylem.Common.Hardware.Interfaces.Ports.PortCore;
using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisConfig;
using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore;
using Xylem.Common.Hardware.WaterMeter.WaterMeterCore;
using Xylem.Common.Ui.CordonelPreadjustmentUi;
using CordonelPreadjustmentUi;
using static Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore.GenesisMeter;
using System.Linq;//...MF
namespace GenesisCordonelInterface.UI.LaatzenAPI_CordonelPreadjustmentUI
{
public partial class FrmCordonelPreadjustmentUI : Form
{
public PreAdjustmentControl preadjustCtl;//...MF
private PreAdjustmentSettingsContainer mainSettings = new PreAdjustmentSettingsContainer();
public MeterBatch _externMetersBatch;
public FrmCordonelPreadjustmentUI()
{
}
public FrmCordonelPreadjustmentUI(MeterBatch externMetersBatch)
{
_externMetersBatch = externMetersBatch;
InitializeComponent();
}
private void MainForm_Load(object sender, EventArgs e)
{
preadjustCtl = new PreAdjustmentControl(mainSettings, _externMetersBatch);
tab_ZeroFlowCal.Controls.Add(preadjustCtl);
cB_SinglePath.Checked = mainSettings.NumberOfPaths == 1 ? true : false;
nUD_SettingsTempMonitorLowerValue.Value = (decimal)mainSettings.LowerTempLimit;
nUD_SettingsTempMonitorUpperValue.Value = (decimal)mainSettings.UpperTempLimit;
nUD_SettingsTempMonitorDeviation.Value = (decimal)mainSettings.TempDeviationLimit;
// nUD_SettingsPreparationMetersize.Value = mainSettings.MeterSize.GetHashCode();
cB_OffsetTestLogFiles.Checked = mainSettings.OffsetTestGenerateLogfiles;
nUD_Settings_ZeroflowOffsetTestActivityCheckInterval.Value = mainSettings.OffsetTestActivityCheckInverval;
nUD_Settings_ZeroflowOffsetTestNumberOfLines.Value = mainSettings.OffsetTestNumberOfLines;
nUD_Settings_ZeroflowOffsetTestSettlingTime.Value = mainSettings.OffsetTestSettlingTime;
nUD_Settings_ZeroflowOffsetTestOffsetLimit.Value = mainSettings.OffsetTestOffsetLimitPS;
nUD_Settings_ZeroflowOffsetTestLowerLimit.Value = mainSettings.OffsetTestLowerVoltageLimitMV;
nUD_Settings_ZeroflowOffsetTestUpperLimit.Value = mainSettings.OffsetTestUpperVoltageLimitMV;
cB_AmpLogFiles.Checked = mainSettings.AmpTestGenerateLogfiles;
nUD_Settings_AmplitudeActivityCheckInterval.Value = mainSettings.AmpTestActivityCheckInverval;
cB_MeanAmplitudeFiles.Checked = mainSettings.AmpTestGenerateMeanValuesFile;
nUD_PercentageStop.Value = mainSettings.AmpTestPercentageStop;
nUD_PercentageStart.Value = mainSettings.AmpTestPercentageStart;
nUD_Settings_AmplitudeTestMinDistance.Value = mainSettings.AmpTestAmpTestDistance;
nUD_Settings_AmplitudeTestLowerLimit.Value = mainSettings.AmpTestFirstHitLevelPropMin;
nUD_Settings_AmplitudeTestUpperLimit.Value = mainSettings.AmpTestFirstHitLevelPropMax;
nUD_Settings_Samplerate.Value = mainSettings.Samplerate;
}
private void tab_Maintab_Selected(object sender, TabControlEventArgs e)
{
if (e.TabPage.Name == tab_ZeroFlowCal.Name)
{
/*try
{
var _serialConfigFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Genesis", ProgramConfig.SerialConfigFileName);
SlotConfig[] meterConfigList;
using (var tr = new StreamReader(_serialConfigFile))
{
var _fileString = tr.ReadToEnd();
meterConfigList = JsonConvert.DeserializeObject<SlotConfig[]>(_fileString);
}
mainSettings.Meters = new List<int>();
mainSettings.TempMeters = new List<int>();
foreach (var item in meterConfigList)
{
if (item.Type != SlotType.TemperatureMeter)
{
mainSettings.Meters.Add(item.Slot);
}
else
{
mainSettings.TempMeters.Add(item.Slot);
}
}
}
catch (Exception ex)
{
MessageBox.Show($"use default meters because of {ex.Message}");
}*/
try //...MF
{
mainSettings.Meters = new List<int>();
mainSettings.TempMeters = new List<int>();
// ==========================================
// Try loading configuration from GCI meters
// ==========================================
bool loadedFromInterface = false;
if (_externMetersBatch != null &&
_externMetersBatch.ListOfMeters.Any())
{
foreach (GenesisMeter meter in _externMetersBatch.ListOfMeters)
{
// Skip meters that should use file configuration
if (meter.useConfigSource != ConfigSource.InterfaceInputConfig)
continue;
loadedFromInterface = true;
// Split normal and temperature meters
//if (meter.Type == SlotType.TemperatureMeter)
//{
// mainSettings.TempMeters.Add(meter.Slot);
//}
//else
//{
mainSettings.Meters.Add(meter.Slot);
//}
}
}
// ==========================================
// Fallback to configuration file
// ==========================================
if (!loadedFromInterface)
{
var _serialConfigFile =
Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
"Genesis",
ProgramConfig.SerialConfigFileName);
SlotConfig[] meterConfigList;
using (var tr = new StreamReader(_serialConfigFile))
{
var _fileString = tr.ReadToEnd();
meterConfigList =
JsonConvert.DeserializeObject<SlotConfig[]>(_fileString);
}
foreach (var item in meterConfigList)
{
if (item.Type != SlotType.TemperatureMeter)
{
mainSettings.Meters.Add(item.Slot);
}
else
{
mainSettings.TempMeters.Add(item.Slot);
}
}
}
}
catch (Exception ex)
{
MessageBox.Show($"Use default meters because of {ex.Message}");
}
mainSettings.NumberOfPaths = cB_SinglePath.Checked ? 1 : 3;
mainSettings.LowerTempLimit = (double)nUD_SettingsTempMonitorLowerValue.Value;
mainSettings.UpperTempLimit = (double)nUD_SettingsTempMonitorUpperValue.Value;
mainSettings.TempDeviationLimit = (double)nUD_SettingsTempMonitorDeviation.Value;
//mainSettings.MeterSize = (Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore.Consts.MeterSize)nUD_SettingsPreparationMetersize.Value;
mainSettings.TempOnly = cB_TempOnly.Checked;
mainSettings.SetTempUseTempFlansh(true);
if (cB_TempManualAcquisition.Checked)
{
mainSettings.SetTempUseManualInput(true);
mainSettings.SetTempUseTempFlansh(false);
}
else
{
mainSettings.SetTempUseTempFlansh(true);
mainSettings.SetTempUseManualInput(false);
}
mainSettings.OffsetTestGenerateLogfiles = cB_OffsetTestLogFiles.Checked;
mainSettings.OffsetTestActivityCheckInverval = (int)nUD_Settings_ZeroflowOffsetTestActivityCheckInterval.Value;
mainSettings.OffsetTestNumberOfLines = (int)nUD_Settings_ZeroflowOffsetTestNumberOfLines.Value;
mainSettings.OffsetTestSettlingTime = (int)nUD_Settings_ZeroflowOffsetTestSettlingTime.Value;
mainSettings.OffsetTestOffsetLimitPS = (int)nUD_Settings_ZeroflowOffsetTestOffsetLimit.Value;
mainSettings.OffsetTestLowerVoltageLimitMV = (int)nUD_Settings_ZeroflowOffsetTestLowerLimit.Value;
mainSettings.OffsetTestUpperVoltageLimitMV = (int)nUD_Settings_ZeroflowOffsetTestUpperLimit.Value;
mainSettings.AmpTestGenerateLogfiles = cB_AmpLogFiles.Checked;
mainSettings.AmpTestActivityCheckInverval = (int)nUD_Settings_AmplitudeActivityCheckInterval.Value;
mainSettings.AmpTestGenerateMeanValuesFile = cB_MeanAmplitudeFiles.Checked;
mainSettings.AmpTestPercentageStop = (int)nUD_PercentageStop.Value;
mainSettings.AmpTestPercentageStart = (int)nUD_PercentageStart.Value;
mainSettings.AmpTestAmpTestDistance = (int)nUD_Settings_AmplitudeTestMinDistance.Value;
mainSettings.AmpTestFirstHitLevelPropMin = (int)nUD_Settings_AmplitudeTestLowerLimit.Value;
mainSettings.AmpTestFirstHitLevelPropMax = (int)nUD_Settings_AmplitudeTestUpperLimit.Value;
mainSettings.Samplerate = (int)nUD_Settings_Samplerate.Value;
preadjustCtl.SetSettings(mainSettings);
}
}
/*private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
if (preadjustCtl != null)
{
preadjustCtl.CloseConnections();
preadjustCtl.Dispose();
}
if (ThermoMeterBatch != null)
{
ThermoMeterBatch.Dispose();
}
if (TempMeterStateCtls != null)
{
foreach (var item in TempMeterStateCtls)
{
item.Dispose();
}
}
}*/
/// <summary>
/// Raised when user closes the preadjustment window
/// using the window close button (X).
///
/// Note:
/// Form is hidden, not disposed.
/// This event allows external code to continue
/// workflow asynchronously.
/// </summary>
public event EventHandler OnUserClosed;
private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
// User clicked X button - hide form only
if (e.CloseReason == CloseReason.UserClosing)
{
e.Cancel = true;
this.Hide();
OnUserClosed?.Invoke(this, EventArgs.Empty);
return;
}
// Real application shutdown / dispose
DisposeResources();
}
/// <summary>
/// Dispose all internal resources that should
/// only be released during real application shutdown.
///
/// Do not call when form is hidden.
/// </summary>
private void DisposeResources()
{
if (preadjustCtl != null)
{
preadjustCtl.CloseConnections();
preadjustCtl.Dispose();
preadjustCtl = null;
}
if (ThermoMeterBatch != null)
{
ThermoMeterBatch.Dispose();
ThermoMeterBatch = null;
}
if (TempMeterStateCtls != null)
{
foreach (var item in TempMeterStateCtls)
{
item.Dispose();
}
TempMeterStateCtls.Clear();
TempMeterStateCtls = null;
}
}
private MeterBatch ThermoMeterBatch = new MeterBatch();
private List<MeterStateControl> TempMeterStateCtls = new List<MeterStateControl>();
private void tmpStart(int slot, bool RaspiMode = false)
{
var ctlZehn = new TempMeterStateControl(slot);
ctlZehn.Location = new Point(5 + ((TempMeterStateCtls.Count + 1) * ctlZehn.Width), 15);
TempMeterStateCtls.Add(ctlZehn);
gB_TempMeters.Controls.Add(ctlZehn);
ctlZehn.Enabled = true;
var currentMeter = new ZeroFlowGenesisMeter(ctlZehn.Slot, 3, !RaspiMode);
currentMeter.LogOnEnable = true;
currentMeter.LoginFailed = false;
currentMeter.PreparationFailed = false;
currentMeter.AmplitudeFailed = false;
currentMeter.ZeroFlowOffsetFailed = false;
currentMeter.AmplitudeFailed = false;
currentMeter.CompletionFailed = false;
currentMeter.Ok = false;
currentMeter.EmptyPipeCheckEnable = false;
currentMeter.EmptyPipeCheckFailed = false;
ThermoMeterBatch.AddMeter(currentMeter);
ctlZehn.IsEnabled = true;
ctlZehn.Meter = currentMeter;
ctlZehn.EnableOpening = true;
ctlZehn.Ok = ctlZehn.Meter.CheckStreamingPort();
ctlZehn.SetUi();
ctlZehn.Meter.StartRecordData();
ctlZehn.Meter.LogRawData(true);
if (RaspiMode)
{
ctlZehn.StartTempWatch(MeterStateControl.TempMode.CalcTof);
}
else
{
ctlZehn.StartTempWatch(MeterStateControl.TempMode.Meter);
}
ctlZehn.SetTemperature(0);
ctlZehn.DisableTemperatureinput(true);
ctlZehn.IsEnabled = true;
}
private void btn_LoadTempe_Click(object sender, EventArgs e)
{
tmpStart((int)nudTempSlot.Value, false);
}
private void btnTempRaspi_Click(object sender, EventArgs e)
{
tmpStart((int)nudTempSlot.Value, true);
}
private void button1_Click(object sender, EventArgs e)
{
if (TempMeterStateCtls != null)
{
StringBuilder sb = new StringBuilder();
foreach (var item in TempMeterStateCtls)
{
sb.AppendLine();
sb.AppendLine($"##########Meter{item.Slot}#############");
sb.Append(item.GetLog());
sb.AppendLine();
}
richTextBox1.Text = sb.ToString();
richTextBox1.ScrollToCaret();
}
}
private void tab_ZeroFlowCal_Click(object sender, EventArgs e)
{
}
}
}
@@ -0,0 +1,673 @@
using Xylem.Common.Ui.CordonelPreadjustmentUi;
namespace GenesisCordonelInterface.UI
{
partial class PreAdjustmentControl
{
/// <summary>
/// Erforderliche Designervariable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Verwendete Ressourcen bereinigen.
/// </summary>
/// <param name="disposing">True, wenn verwaltete Ressourcen gelöscht werden sollen; andernfalls False.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Vom Komponenten-Designer generierter Code
/// <summary>
/// Erforderliche Methode für die Designerunterstützung.
/// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(PreAdjustmentControl));
this.pB_Logo1 = new System.Windows.Forms.PictureBox();
this.gB_Meters = new System.Windows.Forms.GroupBox();
this.pB_Bubbles1 = new System.Windows.Forms.PictureBox();
this.l_ZeroFlowCal_Status = new System.Windows.Forms.Label();
this.gB_Progress = new System.Windows.Forms.GroupBox();
this.p_ZeroFlowCal_Completion = new System.Windows.Forms.Panel();
this.l_ZeroFlowCal_Completion = new System.Windows.Forms.Label();
this.p_ZeroFlowCal_Offset = new System.Windows.Forms.Panel();
this.l_ZeroFlowCal_Offset = new System.Windows.Forms.Label();
this.cB_ZeroFlowOffsetTestEnable = new System.Windows.Forms.CheckBox();
this.cB_AmplitudeTestEnable = new System.Windows.Forms.CheckBox();
this.cB_TempCalEnable = new System.Windows.Forms.CheckBox();
this.p_ZeroFlowCal_Detect = new System.Windows.Forms.Panel();
this.l_ZeroFlowCal_Detect = new System.Windows.Forms.Label();
this.p_ZeroFlowCal_TempCal = new System.Windows.Forms.Panel();
this.l_ZeroFlowCal_TempCal = new System.Windows.Forms.Label();
this.p_ZeroFlowCal_Prepare = new System.Windows.Forms.Panel();
this.l_ZeroFlowCal_Prepare = new System.Windows.Forms.Label();
this.p_ZeroFlowCal_Amplitude = new System.Windows.Forms.Panel();
this.l_ZeroFlowCal_Amplitude = new System.Windows.Forms.Label();
this.gB_TempMeters = new System.Windows.Forms.GroupBox();
this.btn_StoreTempe = new System.Windows.Forms.Button();
this.pB_ZeroFlowCal_Progress = new System.Windows.Forms.ProgressBar();
this.l_ZeroFlowCal_ResttimeDisplayValue = new System.Windows.Forms.Label();
this.l_ZeroFlowCal_Resttime = new System.Windows.Forms.Label();
this.btn_ZeroFlowCal_Abort = new System.Windows.Forms.Button();
this.btn_ZeroFlowCal_Start = new System.Windows.Forms.Button();
this.btn_ZeroFlowCal_Pdf = new System.Windows.Forms.Button();
this.btn_ZeroFlowCal_Save = new System.Windows.Forms.Button();
this.btn_ZeroFlowCal_Clear = new System.Windows.Forms.Button();
this.btn_ZeroFlowCal_Detect = new System.Windows.Forms.Button();
this.gB_MeterLog = new System.Windows.Forms.GroupBox();
this.btn_ShowAll = new System.Windows.Forms.Button();
this.rTB_ZeroFlowCalMeter = new System.Windows.Forms.RichTextBox();
this.pB_ZeroFlowCal_SubProgress = new System.Windows.Forms.ProgressBar();
this.l_ZeroFlowCal_SubResttimeDisplayValue = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.rTB_ZeroFlowCal = new System.Windows.Forms.RichTextBox();
this.l_SettingsPreparationMetersize = new System.Windows.Forms.Label();
this.cb_Metersize = new System.Windows.Forms.ComboBox();
this.lblBuildDate = new System.Windows.Forms.Label();
((System.ComponentModel.ISupportInitialize)(this.pB_Logo1)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.pB_Bubbles1)).BeginInit();
this.gB_Progress.SuspendLayout();
this.p_ZeroFlowCal_Completion.SuspendLayout();
this.p_ZeroFlowCal_Offset.SuspendLayout();
this.p_ZeroFlowCal_Detect.SuspendLayout();
this.p_ZeroFlowCal_TempCal.SuspendLayout();
this.p_ZeroFlowCal_Prepare.SuspendLayout();
this.p_ZeroFlowCal_Amplitude.SuspendLayout();
this.gB_TempMeters.SuspendLayout();
this.gB_MeterLog.SuspendLayout();
this.SuspendLayout();
//
// pB_Logo1
//
this.pB_Logo1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.pB_Logo1.BackColor = System.Drawing.SystemColors.Control;
this.pB_Logo1.Image = ((System.Drawing.Image)(resources.GetObject("pB_Logo1.Image")));
this.pB_Logo1.InitialImage = null;
this.pB_Logo1.Location = new System.Drawing.Point(781, 0);
this.pB_Logo1.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.pB_Logo1.Name = "pB_Logo1";
this.pB_Logo1.Size = new System.Drawing.Size(158, 86);
this.pB_Logo1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
this.pB_Logo1.TabIndex = 69;
this.pB_Logo1.TabStop = false;
//
// gB_Meters
//
this.gB_Meters.Location = new System.Drawing.Point(1, 98);
this.gB_Meters.Margin = new System.Windows.Forms.Padding(10, 10, 10, 10);
this.gB_Meters.Name = "gB_Meters";
this.gB_Meters.Padding = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.gB_Meters.Size = new System.Drawing.Size(950, 174);
this.gB_Meters.TabIndex = 71;
this.gB_Meters.TabStop = false;
this.gB_Meters.Text = "Meters";
//
// pB_Bubbles1
//
this.pB_Bubbles1.Anchor = System.Windows.Forms.AnchorStyles.Top;
this.pB_Bubbles1.Image = ((System.Drawing.Image)(resources.GetObject("pB_Bubbles1.Image")));
this.pB_Bubbles1.Location = new System.Drawing.Point(20, 2);
this.pB_Bubbles1.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.pB_Bubbles1.Name = "pB_Bubbles1";
this.pB_Bubbles1.Size = new System.Drawing.Size(267, 93);
this.pB_Bubbles1.TabIndex = 70;
this.pB_Bubbles1.TabStop = false;
this.pB_Bubbles1.Visible = false;
//
// l_ZeroFlowCal_Status
//
this.l_ZeroFlowCal_Status.AutoSize = true;
this.l_ZeroFlowCal_Status.Font = new System.Drawing.Font("Microsoft Sans Serif", 22.2F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.l_ZeroFlowCal_Status.Location = new System.Drawing.Point(10, 478);
this.l_ZeroFlowCal_Status.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
this.l_ZeroFlowCal_Status.Name = "l_ZeroFlowCal_Status";
this.l_ZeroFlowCal_Status.Size = new System.Drawing.Size(243, 36);
this.l_ZeroFlowCal_Status.TabIndex = 72;
this.l_ZeroFlowCal_Status.Text = "Press \'DETECT\'";
//
// gB_Progress
//
this.gB_Progress.Controls.Add(this.p_ZeroFlowCal_Completion);
this.gB_Progress.Controls.Add(this.p_ZeroFlowCal_Offset);
this.gB_Progress.Controls.Add(this.p_ZeroFlowCal_Detect);
this.gB_Progress.Controls.Add(this.p_ZeroFlowCal_TempCal);
this.gB_Progress.Controls.Add(this.p_ZeroFlowCal_Prepare);
this.gB_Progress.Controls.Add(this.p_ZeroFlowCal_Amplitude);
this.gB_Progress.Location = new System.Drawing.Point(8, 517);
this.gB_Progress.Margin = new System.Windows.Forms.Padding(10, 10, 10, 10);
this.gB_Progress.Name = "gB_Progress";
this.gB_Progress.Padding = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.gB_Progress.Size = new System.Drawing.Size(744, 89);
this.gB_Progress.TabIndex = 80;
this.gB_Progress.TabStop = false;
//
// p_ZeroFlowCal_Completion
//
this.p_ZeroFlowCal_Completion.BackColor = System.Drawing.Color.Gainsboro;
this.p_ZeroFlowCal_Completion.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
this.p_ZeroFlowCal_Completion.Controls.Add(this.l_ZeroFlowCal_Completion);
this.p_ZeroFlowCal_Completion.Location = new System.Drawing.Point(607, 17);
this.p_ZeroFlowCal_Completion.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.p_ZeroFlowCal_Completion.Name = "p_ZeroFlowCal_Completion";
this.p_ZeroFlowCal_Completion.Size = new System.Drawing.Size(117, 65);
this.p_ZeroFlowCal_Completion.TabIndex = 32;
//
// l_ZeroFlowCal_Completion
//
this.l_ZeroFlowCal_Completion.AutoSize = true;
this.l_ZeroFlowCal_Completion.Font = new System.Drawing.Font("Microsoft Sans Serif", 10.2F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.l_ZeroFlowCal_Completion.ForeColor = System.Drawing.Color.Gray;
this.l_ZeroFlowCal_Completion.Location = new System.Drawing.Point(0, 22);
this.l_ZeroFlowCal_Completion.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
this.l_ZeroFlowCal_Completion.Name = "l_ZeroFlowCal_Completion";
this.l_ZeroFlowCal_Completion.Size = new System.Drawing.Size(108, 17);
this.l_ZeroFlowCal_Completion.TabIndex = 40;
this.l_ZeroFlowCal_Completion.Text = "COMPLETION";
this.l_ZeroFlowCal_Completion.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// p_ZeroFlowCal_Offset
//
this.p_ZeroFlowCal_Offset.BackColor = System.Drawing.Color.Gainsboro;
this.p_ZeroFlowCal_Offset.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
this.p_ZeroFlowCal_Offset.Controls.Add(this.l_ZeroFlowCal_Offset);
this.p_ZeroFlowCal_Offset.Controls.Add(this.cB_ZeroFlowOffsetTestEnable);
this.p_ZeroFlowCal_Offset.Controls.Add(this.cB_AmplitudeTestEnable);
this.p_ZeroFlowCal_Offset.Controls.Add(this.cB_TempCalEnable);
this.p_ZeroFlowCal_Offset.Location = new System.Drawing.Point(486, 17);
this.p_ZeroFlowCal_Offset.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.p_ZeroFlowCal_Offset.Name = "p_ZeroFlowCal_Offset";
this.p_ZeroFlowCal_Offset.Size = new System.Drawing.Size(121, 65);
this.p_ZeroFlowCal_Offset.TabIndex = 94;
//
// l_ZeroFlowCal_Offset
//
this.l_ZeroFlowCal_Offset.AutoSize = true;
this.l_ZeroFlowCal_Offset.Font = new System.Drawing.Font("Microsoft Sans Serif", 10.2F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.l_ZeroFlowCal_Offset.ForeColor = System.Drawing.Color.Gray;
this.l_ZeroFlowCal_Offset.Location = new System.Drawing.Point(24, 12);
this.l_ZeroFlowCal_Offset.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
this.l_ZeroFlowCal_Offset.Name = "l_ZeroFlowCal_Offset";
this.l_ZeroFlowCal_Offset.Size = new System.Drawing.Size(68, 34);
this.l_ZeroFlowCal_Offset.TabIndex = 40;
this.l_ZeroFlowCal_Offset.Text = "OFFSET\r\nTEST";
this.l_ZeroFlowCal_Offset.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// cB_ZeroFlowOffsetTestEnable
//
this.cB_ZeroFlowOffsetTestEnable.AutoSize = true;
this.cB_ZeroFlowOffsetTestEnable.Checked = true;
this.cB_ZeroFlowOffsetTestEnable.CheckState = System.Windows.Forms.CheckState.Checked;
this.cB_ZeroFlowOffsetTestEnable.Enabled = false;
this.cB_ZeroFlowOffsetTestEnable.Location = new System.Drawing.Point(24, 15);
this.cB_ZeroFlowOffsetTestEnable.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.cB_ZeroFlowOffsetTestEnable.Name = "cB_ZeroFlowOffsetTestEnable";
this.cB_ZeroFlowOffsetTestEnable.Size = new System.Drawing.Size(58, 17);
this.cB_ZeroFlowOffsetTestEnable.TabIndex = 90;
this.cB_ZeroFlowOffsetTestEnable.Text = "enable";
this.cB_ZeroFlowOffsetTestEnable.UseVisualStyleBackColor = true;
this.cB_ZeroFlowOffsetTestEnable.Visible = false;
//
// cB_AmplitudeTestEnable
//
this.cB_AmplitudeTestEnable.AutoSize = true;
this.cB_AmplitudeTestEnable.Checked = true;
this.cB_AmplitudeTestEnable.CheckState = System.Windows.Forms.CheckState.Checked;
this.cB_AmplitudeTestEnable.Enabled = false;
this.cB_AmplitudeTestEnable.Location = new System.Drawing.Point(-216, 48);
this.cB_AmplitudeTestEnable.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.cB_AmplitudeTestEnable.Name = "cB_AmplitudeTestEnable";
this.cB_AmplitudeTestEnable.Size = new System.Drawing.Size(58, 17);
this.cB_AmplitudeTestEnable.TabIndex = 92;
this.cB_AmplitudeTestEnable.Text = "enable";
this.cB_AmplitudeTestEnable.UseVisualStyleBackColor = true;
//
// cB_TempCalEnable
//
this.cB_TempCalEnable.AutoSize = true;
this.cB_TempCalEnable.Checked = true;
this.cB_TempCalEnable.CheckState = System.Windows.Forms.CheckState.Checked;
this.cB_TempCalEnable.Enabled = false;
this.cB_TempCalEnable.Location = new System.Drawing.Point(-96, 48);
this.cB_TempCalEnable.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.cB_TempCalEnable.Name = "cB_TempCalEnable";
this.cB_TempCalEnable.Size = new System.Drawing.Size(58, 17);
this.cB_TempCalEnable.TabIndex = 94;
this.cB_TempCalEnable.Text = "enable";
this.cB_TempCalEnable.UseVisualStyleBackColor = true;
//
// p_ZeroFlowCal_Detect
//
this.p_ZeroFlowCal_Detect.BackColor = System.Drawing.Color.Gainsboro;
this.p_ZeroFlowCal_Detect.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
this.p_ZeroFlowCal_Detect.Controls.Add(this.l_ZeroFlowCal_Detect);
this.p_ZeroFlowCal_Detect.Location = new System.Drawing.Point(4, 17);
this.p_ZeroFlowCal_Detect.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.p_ZeroFlowCal_Detect.Name = "p_ZeroFlowCal_Detect";
this.p_ZeroFlowCal_Detect.Size = new System.Drawing.Size(121, 65);
this.p_ZeroFlowCal_Detect.TabIndex = 40;
//
// l_ZeroFlowCal_Detect
//
this.l_ZeroFlowCal_Detect.AutoSize = true;
this.l_ZeroFlowCal_Detect.Font = new System.Drawing.Font("Microsoft Sans Serif", 10.2F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.l_ZeroFlowCal_Detect.ForeColor = System.Drawing.Color.Gray;
this.l_ZeroFlowCal_Detect.Location = new System.Drawing.Point(24, 22);
this.l_ZeroFlowCal_Detect.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
this.l_ZeroFlowCal_Detect.Name = "l_ZeroFlowCal_Detect";
this.l_ZeroFlowCal_Detect.Size = new System.Drawing.Size(69, 17);
this.l_ZeroFlowCal_Detect.TabIndex = 39;
this.l_ZeroFlowCal_Detect.Text = "DETECT";
//
// p_ZeroFlowCal_TempCal
//
this.p_ZeroFlowCal_TempCal.BackColor = System.Drawing.Color.Gainsboro;
this.p_ZeroFlowCal_TempCal.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
this.p_ZeroFlowCal_TempCal.Controls.Add(this.l_ZeroFlowCal_TempCal);
this.p_ZeroFlowCal_TempCal.Location = new System.Drawing.Point(365, 17);
this.p_ZeroFlowCal_TempCal.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.p_ZeroFlowCal_TempCal.Name = "p_ZeroFlowCal_TempCal";
this.p_ZeroFlowCal_TempCal.Size = new System.Drawing.Size(121, 65);
this.p_ZeroFlowCal_TempCal.TabIndex = 41;
//
// l_ZeroFlowCal_TempCal
//
this.l_ZeroFlowCal_TempCal.AutoSize = true;
this.l_ZeroFlowCal_TempCal.Font = new System.Drawing.Font("Microsoft Sans Serif", 10.2F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.l_ZeroFlowCal_TempCal.ForeColor = System.Drawing.Color.Gray;
this.l_ZeroFlowCal_TempCal.Location = new System.Drawing.Point(0, 12);
this.l_ZeroFlowCal_TempCal.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
this.l_ZeroFlowCal_TempCal.Name = "l_ZeroFlowCal_TempCal";
this.l_ZeroFlowCal_TempCal.Size = new System.Drawing.Size(123, 34);
this.l_ZeroFlowCal_TempCal.TabIndex = 40;
this.l_ZeroFlowCal_TempCal.Text = "TEMPERATURE\r\nCALIBRATION";
this.l_ZeroFlowCal_TempCal.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// p_ZeroFlowCal_Prepare
//
this.p_ZeroFlowCal_Prepare.BackColor = System.Drawing.Color.Gainsboro;
this.p_ZeroFlowCal_Prepare.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
this.p_ZeroFlowCal_Prepare.Controls.Add(this.l_ZeroFlowCal_Prepare);
this.p_ZeroFlowCal_Prepare.Location = new System.Drawing.Point(124, 17);
this.p_ZeroFlowCal_Prepare.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.p_ZeroFlowCal_Prepare.Name = "p_ZeroFlowCal_Prepare";
this.p_ZeroFlowCal_Prepare.Size = new System.Drawing.Size(121, 65);
this.p_ZeroFlowCal_Prepare.TabIndex = 31;
//
// l_ZeroFlowCal_Prepare
//
this.l_ZeroFlowCal_Prepare.AutoSize = true;
this.l_ZeroFlowCal_Prepare.Font = new System.Drawing.Font("Microsoft Sans Serif", 10.2F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.l_ZeroFlowCal_Prepare.ForeColor = System.Drawing.Color.Gray;
this.l_ZeroFlowCal_Prepare.Location = new System.Drawing.Point(18, 22);
this.l_ZeroFlowCal_Prepare.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
this.l_ZeroFlowCal_Prepare.Name = "l_ZeroFlowCal_Prepare";
this.l_ZeroFlowCal_Prepare.Size = new System.Drawing.Size(80, 17);
this.l_ZeroFlowCal_Prepare.TabIndex = 39;
this.l_ZeroFlowCal_Prepare.Text = "PREPARE";
//
// p_ZeroFlowCal_Amplitude
//
this.p_ZeroFlowCal_Amplitude.BackColor = System.Drawing.Color.Gainsboro;
this.p_ZeroFlowCal_Amplitude.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
this.p_ZeroFlowCal_Amplitude.Controls.Add(this.l_ZeroFlowCal_Amplitude);
this.p_ZeroFlowCal_Amplitude.Location = new System.Drawing.Point(244, 17);
this.p_ZeroFlowCal_Amplitude.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.p_ZeroFlowCal_Amplitude.Name = "p_ZeroFlowCal_Amplitude";
this.p_ZeroFlowCal_Amplitude.Size = new System.Drawing.Size(121, 65);
this.p_ZeroFlowCal_Amplitude.TabIndex = 32;
//
// l_ZeroFlowCal_Amplitude
//
this.l_ZeroFlowCal_Amplitude.AutoSize = true;
this.l_ZeroFlowCal_Amplitude.Font = new System.Drawing.Font("Microsoft Sans Serif", 10.2F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.l_ZeroFlowCal_Amplitude.ForeColor = System.Drawing.Color.Gray;
this.l_ZeroFlowCal_Amplitude.Location = new System.Drawing.Point(12, 15);
this.l_ZeroFlowCal_Amplitude.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
this.l_ZeroFlowCal_Amplitude.Name = "l_ZeroFlowCal_Amplitude";
this.l_ZeroFlowCal_Amplitude.Size = new System.Drawing.Size(95, 34);
this.l_ZeroFlowCal_Amplitude.TabIndex = 39;
this.l_ZeroFlowCal_Amplitude.Text = "AMPLITUDE\r\nTEST";
this.l_ZeroFlowCal_Amplitude.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// gB_TempMeters
//
this.gB_TempMeters.Controls.Add(this.btn_StoreTempe);
this.gB_TempMeters.Location = new System.Drawing.Point(8, 275);
this.gB_TempMeters.Margin = new System.Windows.Forms.Padding(10, 10, 10, 10);
this.gB_TempMeters.Name = "gB_TempMeters";
this.gB_TempMeters.Padding = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.gB_TempMeters.Size = new System.Drawing.Size(403, 193);
this.gB_TempMeters.TabIndex = 72;
this.gB_TempMeters.TabStop = false;
this.gB_TempMeters.Text = "Temp. Meters";
//
// btn_StoreTempe
//
this.btn_StoreTempe.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.btn_StoreTempe.Enabled = false;
this.btn_StoreTempe.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.btn_StoreTempe.Location = new System.Drawing.Point(4, 158);
this.btn_StoreTempe.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.btn_StoreTempe.Name = "btn_StoreTempe";
this.btn_StoreTempe.Size = new System.Drawing.Size(395, 31);
this.btn_StoreTempe.TabIndex = 95;
this.btn_StoreTempe.Text = "SAVE TEMP";
this.btn_StoreTempe.UseVisualStyleBackColor = true;
this.btn_StoreTempe.Click += new System.EventHandler(this.btn_StoreTempe_Click);
//
// pB_ZeroFlowCal_Progress
//
this.pB_ZeroFlowCal_Progress.Location = new System.Drawing.Point(8, 634);
this.pB_ZeroFlowCal_Progress.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.pB_ZeroFlowCal_Progress.Name = "pB_ZeroFlowCal_Progress";
this.pB_ZeroFlowCal_Progress.Size = new System.Drawing.Size(724, 18);
this.pB_ZeroFlowCal_Progress.Step = 1;
this.pB_ZeroFlowCal_Progress.TabIndex = 35;
//
// l_ZeroFlowCal_ResttimeDisplayValue
//
this.l_ZeroFlowCal_ResttimeDisplayValue.AutoSize = true;
this.l_ZeroFlowCal_ResttimeDisplayValue.Location = new System.Drawing.Point(843, 634);
this.l_ZeroFlowCal_ResttimeDisplayValue.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
this.l_ZeroFlowCal_ResttimeDisplayValue.Name = "l_ZeroFlowCal_ResttimeDisplayValue";
this.l_ZeroFlowCal_ResttimeDisplayValue.Size = new System.Drawing.Size(49, 13);
this.l_ZeroFlowCal_ResttimeDisplayValue.TabIndex = 37;
this.l_ZeroFlowCal_ResttimeDisplayValue.Text = "00:00:00";
//
// l_ZeroFlowCal_Resttime
//
this.l_ZeroFlowCal_Resttime.AutoSize = true;
this.l_ZeroFlowCal_Resttime.Location = new System.Drawing.Point(736, 634);
this.l_ZeroFlowCal_Resttime.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
this.l_ZeroFlowCal_Resttime.Name = "l_ZeroFlowCal_Resttime";
this.l_ZeroFlowCal_Resttime.Size = new System.Drawing.Size(54, 13);
this.l_ZeroFlowCal_Resttime.TabIndex = 36;
this.l_ZeroFlowCal_Resttime.Text = "Est. total: ";
//
// btn_ZeroFlowCal_Abort
//
this.btn_ZeroFlowCal_Abort.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.btn_ZeroFlowCal_Abort.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.btn_ZeroFlowCal_Abort.Location = new System.Drawing.Point(672, 44);
this.btn_ZeroFlowCal_Abort.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.btn_ZeroFlowCal_Abort.Name = "btn_ZeroFlowCal_Abort";
this.btn_ZeroFlowCal_Abort.Size = new System.Drawing.Size(102, 52);
this.btn_ZeroFlowCal_Abort.TabIndex = 84;
this.btn_ZeroFlowCal_Abort.Text = "STOP";
this.btn_ZeroFlowCal_Abort.UseVisualStyleBackColor = true;
this.btn_ZeroFlowCal_Abort.Click += new System.EventHandler(this.btn_ZeroFlowCal_Abort_Click);
//
// btn_ZeroFlowCal_Start
//
this.btn_ZeroFlowCal_Start.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.btn_ZeroFlowCal_Start.Enabled = false;
this.btn_ZeroFlowCal_Start.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.btn_ZeroFlowCal_Start.Location = new System.Drawing.Point(566, 44);
this.btn_ZeroFlowCal_Start.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.btn_ZeroFlowCal_Start.Name = "btn_ZeroFlowCal_Start";
this.btn_ZeroFlowCal_Start.Size = new System.Drawing.Size(102, 51);
this.btn_ZeroFlowCal_Start.TabIndex = 83;
this.btn_ZeroFlowCal_Start.Text = "START";
this.btn_ZeroFlowCal_Start.UseVisualStyleBackColor = true;
this.btn_ZeroFlowCal_Start.Click += new System.EventHandler(this.btn_ZeroFlowCal_Start_Click);
//
// btn_ZeroFlowCal_Pdf
//
this.btn_ZeroFlowCal_Pdf.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.btn_ZeroFlowCal_Pdf.Font = new System.Drawing.Font("Microsoft Sans Serif", 7.8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.btn_ZeroFlowCal_Pdf.Location = new System.Drawing.Point(846, 529);
this.btn_ZeroFlowCal_Pdf.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.btn_ZeroFlowCal_Pdf.Name = "btn_ZeroFlowCal_Pdf";
this.btn_ZeroFlowCal_Pdf.Size = new System.Drawing.Size(63, 38);
this.btn_ZeroFlowCal_Pdf.TabIndex = 91;
this.btn_ZeroFlowCal_Pdf.Text = "PDF";
this.btn_ZeroFlowCal_Pdf.UseVisualStyleBackColor = true;
//
// btn_ZeroFlowCal_Save
//
this.btn_ZeroFlowCal_Save.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.btn_ZeroFlowCal_Save.Font = new System.Drawing.Font("Microsoft Sans Serif", 7.8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.btn_ZeroFlowCal_Save.Location = new System.Drawing.Point(779, 529);
this.btn_ZeroFlowCal_Save.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.btn_ZeroFlowCal_Save.Name = "btn_ZeroFlowCal_Save";
this.btn_ZeroFlowCal_Save.Size = new System.Drawing.Size(63, 38);
this.btn_ZeroFlowCal_Save.TabIndex = 90;
this.btn_ZeroFlowCal_Save.Text = "Save";
this.btn_ZeroFlowCal_Save.UseVisualStyleBackColor = true;
//
// btn_ZeroFlowCal_Clear
//
this.btn_ZeroFlowCal_Clear.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.btn_ZeroFlowCal_Clear.Font = new System.Drawing.Font("Microsoft Sans Serif", 7.8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.btn_ZeroFlowCal_Clear.Location = new System.Drawing.Point(779, 571);
this.btn_ZeroFlowCal_Clear.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.btn_ZeroFlowCal_Clear.Name = "btn_ZeroFlowCal_Clear";
this.btn_ZeroFlowCal_Clear.Size = new System.Drawing.Size(130, 28);
this.btn_ZeroFlowCal_Clear.TabIndex = 89;
this.btn_ZeroFlowCal_Clear.Text = "Clear";
this.btn_ZeroFlowCal_Clear.UseVisualStyleBackColor = true;
//
// btn_ZeroFlowCal_Detect
//
this.btn_ZeroFlowCal_Detect.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.btn_ZeroFlowCal_Detect.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.btn_ZeroFlowCal_Detect.Location = new System.Drawing.Point(291, 44);
this.btn_ZeroFlowCal_Detect.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.btn_ZeroFlowCal_Detect.Name = "btn_ZeroFlowCal_Detect";
this.btn_ZeroFlowCal_Detect.Size = new System.Drawing.Size(102, 51);
this.btn_ZeroFlowCal_Detect.TabIndex = 82;
this.btn_ZeroFlowCal_Detect.Text = "DETECT";
this.btn_ZeroFlowCal_Detect.UseVisualStyleBackColor = true;
this.btn_ZeroFlowCal_Detect.Click += new System.EventHandler(this.btn_ZeroFlowCal_Detect_Click);
//
// gB_MeterLog
//
this.gB_MeterLog.Controls.Add(this.btn_ShowAll);
this.gB_MeterLog.Controls.Add(this.rTB_ZeroFlowCalMeter);
this.gB_MeterLog.Location = new System.Drawing.Point(419, 275);
this.gB_MeterLog.Margin = new System.Windows.Forms.Padding(10, 10, 10, 10);
this.gB_MeterLog.Name = "gB_MeterLog";
this.gB_MeterLog.Padding = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.gB_MeterLog.Size = new System.Drawing.Size(532, 193);
this.gB_MeterLog.TabIndex = 72;
this.gB_MeterLog.TabStop = false;
this.gB_MeterLog.Text = "Meters";
this.gB_MeterLog.Visible = false;
//
// btn_ShowAll
//
this.btn_ShowAll.Location = new System.Drawing.Point(5, 14);
this.btn_ShowAll.Name = "btn_ShowAll";
this.btn_ShowAll.Size = new System.Drawing.Size(123, 20);
this.btn_ShowAll.TabIndex = 97;
this.btn_ShowAll.Text = "ShowAll";
this.btn_ShowAll.UseVisualStyleBackColor = true;
this.btn_ShowAll.Click += new System.EventHandler(this.btn_ShowAll_Click);
//
// rTB_ZeroFlowCalMeter
//
this.rTB_ZeroFlowCalMeter.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.rTB_ZeroFlowCalMeter.Location = new System.Drawing.Point(4, 39);
this.rTB_ZeroFlowCalMeter.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.rTB_ZeroFlowCalMeter.Name = "rTB_ZeroFlowCalMeter";
this.rTB_ZeroFlowCalMeter.ReadOnly = true;
this.rTB_ZeroFlowCalMeter.ScrollBars = System.Windows.Forms.RichTextBoxScrollBars.Vertical;
this.rTB_ZeroFlowCalMeter.Size = new System.Drawing.Size(516, 139);
this.rTB_ZeroFlowCalMeter.TabIndex = 96;
this.rTB_ZeroFlowCalMeter.Text = "";
//
// pB_ZeroFlowCal_SubProgress
//
this.pB_ZeroFlowCal_SubProgress.Location = new System.Drawing.Point(8, 612);
this.pB_ZeroFlowCal_SubProgress.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.pB_ZeroFlowCal_SubProgress.Name = "pB_ZeroFlowCal_SubProgress";
this.pB_ZeroFlowCal_SubProgress.Size = new System.Drawing.Size(724, 18);
this.pB_ZeroFlowCal_SubProgress.Step = 1;
this.pB_ZeroFlowCal_SubProgress.TabIndex = 92;
//
// l_ZeroFlowCal_SubResttimeDisplayValue
//
this.l_ZeroFlowCal_SubResttimeDisplayValue.AutoSize = true;
this.l_ZeroFlowCal_SubResttimeDisplayValue.Location = new System.Drawing.Point(845, 617);
this.l_ZeroFlowCal_SubResttimeDisplayValue.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
this.l_ZeroFlowCal_SubResttimeDisplayValue.Name = "l_ZeroFlowCal_SubResttimeDisplayValue";
this.l_ZeroFlowCal_SubResttimeDisplayValue.Size = new System.Drawing.Size(49, 13);
this.l_ZeroFlowCal_SubResttimeDisplayValue.TabIndex = 94;
this.l_ZeroFlowCal_SubResttimeDisplayValue.Text = "00:00:00";
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(736, 616);
this.label2.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(105, 13);
this.label2.TabIndex = 93;
this.label2.Text = "Est. finish Proccess: ";
//
// rTB_ZeroFlowCal
//
this.rTB_ZeroFlowCal.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.rTB_ZeroFlowCal.Location = new System.Drawing.Point(419, 280);
this.rTB_ZeroFlowCal.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.rTB_ZeroFlowCal.Name = "rTB_ZeroFlowCal";
this.rTB_ZeroFlowCal.ReadOnly = true;
this.rTB_ZeroFlowCal.ScrollBars = System.Windows.Forms.RichTextBoxScrollBars.Vertical;
this.rTB_ZeroFlowCal.Size = new System.Drawing.Size(528, 193);
this.rTB_ZeroFlowCal.TabIndex = 101;
this.rTB_ZeroFlowCal.Text = "";
//
// l_SettingsPreparationMetersize
//
this.l_SettingsPreparationMetersize.AutoSize = true;
this.l_SettingsPreparationMetersize.Location = new System.Drawing.Point(416, 72);
this.l_SettingsPreparationMetersize.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
this.l_SettingsPreparationMetersize.Name = "l_SettingsPreparationMetersize";
this.l_SettingsPreparationMetersize.Size = new System.Drawing.Size(55, 13);
this.l_SettingsPreparationMetersize.TabIndex = 104;
this.l_SettingsPreparationMetersize.Text = "Metersize:";
//
// cb_Metersize
//
this.cb_Metersize.FormattingEnabled = true;
this.cb_Metersize.Location = new System.Drawing.Point(476, 66);
this.cb_Metersize.Name = "cb_Metersize";
this.cb_Metersize.Size = new System.Drawing.Size(73, 21);
this.cb_Metersize.TabIndex = 105;
//
// lblBuildDate
//
this.lblBuildDate.AutoSize = true;
this.lblBuildDate.Location = new System.Drawing.Point(779, 88);
this.lblBuildDate.Name = "lblBuildDate";
this.lblBuildDate.Size = new System.Drawing.Size(10, 13);
this.lblBuildDate.TabIndex = 106;
this.lblBuildDate.Text = "-";
//
// PreAdjustmentControl
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.SystemColors.Window;
this.Controls.Add(this.lblBuildDate);
this.Controls.Add(this.cb_Metersize);
this.Controls.Add(this.l_SettingsPreparationMetersize);
this.Controls.Add(this.rTB_ZeroFlowCal);
this.Controls.Add(this.l_ZeroFlowCal_SubResttimeDisplayValue);
this.Controls.Add(this.label2);
this.Controls.Add(this.pB_ZeroFlowCal_SubProgress);
this.Controls.Add(this.gB_MeterLog);
this.Controls.Add(this.gB_TempMeters);
this.Controls.Add(this.btn_ZeroFlowCal_Pdf);
this.Controls.Add(this.btn_ZeroFlowCal_Save);
this.Controls.Add(this.btn_ZeroFlowCal_Clear);
this.Controls.Add(this.btn_ZeroFlowCal_Abort);
this.Controls.Add(this.l_ZeroFlowCal_ResttimeDisplayValue);
this.Controls.Add(this.pB_ZeroFlowCal_Progress);
this.Controls.Add(this.btn_ZeroFlowCal_Start);
this.Controls.Add(this.l_ZeroFlowCal_Resttime);
this.Controls.Add(this.btn_ZeroFlowCal_Detect);
this.Controls.Add(this.l_ZeroFlowCal_Status);
this.Controls.Add(this.gB_Progress);
this.Controls.Add(this.pB_Logo1);
this.Controls.Add(this.gB_Meters);
this.Controls.Add(this.pB_Bubbles1);
this.Name = "PreAdjustmentControl";
this.Size = new System.Drawing.Size(970, 674);
this.Load += new System.EventHandler(this.PreAdjustmentControl_Load);
((System.ComponentModel.ISupportInitialize)(this.pB_Logo1)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.pB_Bubbles1)).EndInit();
this.gB_Progress.ResumeLayout(false);
this.p_ZeroFlowCal_Completion.ResumeLayout(false);
this.p_ZeroFlowCal_Completion.PerformLayout();
this.p_ZeroFlowCal_Offset.ResumeLayout(false);
this.p_ZeroFlowCal_Offset.PerformLayout();
this.p_ZeroFlowCal_Detect.ResumeLayout(false);
this.p_ZeroFlowCal_Detect.PerformLayout();
this.p_ZeroFlowCal_TempCal.ResumeLayout(false);
this.p_ZeroFlowCal_TempCal.PerformLayout();
this.p_ZeroFlowCal_Prepare.ResumeLayout(false);
this.p_ZeroFlowCal_Prepare.PerformLayout();
this.p_ZeroFlowCal_Amplitude.ResumeLayout(false);
this.p_ZeroFlowCal_Amplitude.PerformLayout();
this.gB_TempMeters.ResumeLayout(false);
this.gB_MeterLog.ResumeLayout(false);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.PictureBox pB_Logo1;
private System.Windows.Forms.GroupBox gB_Meters;
private System.Windows.Forms.PictureBox pB_Bubbles1;
private System.Windows.Forms.Label l_ZeroFlowCal_Status;
private System.Windows.Forms.GroupBox gB_Progress;
private System.Windows.Forms.Panel p_ZeroFlowCal_Completion;
private System.Windows.Forms.Label l_ZeroFlowCal_Completion;
private System.Windows.Forms.ProgressBar pB_ZeroFlowCal_Progress;
private System.Windows.Forms.Label l_ZeroFlowCal_ResttimeDisplayValue;
private System.Windows.Forms.Panel p_ZeroFlowCal_Offset;
private System.Windows.Forms.Label l_ZeroFlowCal_Offset;
private System.Windows.Forms.Label l_ZeroFlowCal_Resttime;
private System.Windows.Forms.Panel p_ZeroFlowCal_Detect;
private System.Windows.Forms.Label l_ZeroFlowCal_Detect;
private System.Windows.Forms.Panel p_ZeroFlowCal_TempCal;
private System.Windows.Forms.Label l_ZeroFlowCal_TempCal;
private System.Windows.Forms.Panel p_ZeroFlowCal_Prepare;
private System.Windows.Forms.Label l_ZeroFlowCal_Prepare;
private System.Windows.Forms.Panel p_ZeroFlowCal_Amplitude;
private System.Windows.Forms.Label l_ZeroFlowCal_Amplitude;
private System.Windows.Forms.Button btn_ZeroFlowCal_Abort;
private System.Windows.Forms.Button btn_ZeroFlowCal_Start;
private System.Windows.Forms.Button btn_ZeroFlowCal_Pdf;
private System.Windows.Forms.Button btn_ZeroFlowCal_Save;
private System.Windows.Forms.Button btn_ZeroFlowCal_Clear;
private System.Windows.Forms.Button btn_ZeroFlowCal_Detect;
private System.Windows.Forms.GroupBox gB_TempMeters;
private System.Windows.Forms.CheckBox cB_ZeroFlowOffsetTestEnable;
private System.Windows.Forms.CheckBox cB_TempCalEnable;
private System.Windows.Forms.CheckBox cB_AmplitudeTestEnable;
private System.Windows.Forms.Button btn_StoreTempe;
private System.Windows.Forms.GroupBox gB_MeterLog;
private System.Windows.Forms.RichTextBox rTB_ZeroFlowCalMeter;
private System.Windows.Forms.ProgressBar pB_ZeroFlowCal_SubProgress;
private System.Windows.Forms.Label l_ZeroFlowCal_SubResttimeDisplayValue;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Button btn_ShowAll;
private System.Windows.Forms.RichTextBox rTB_ZeroFlowCal;
private System.Windows.Forms.Label l_SettingsPreparationMetersize;
private System.Windows.Forms.ComboBox cb_Metersize;
private System.Windows.Forms.Label lblBuildDate;
}
}
@@ -0,0 +1,553 @@
namespace GenesisCordonelInterface.UI.LaatzenAPI_GenesisToolBox
{
partial class FrmConfigurations
{
/// <summary>
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.lblState = new System.Windows.Forms.Label();
this.btnConnect = new System.Windows.Forms.Button();
this.label1 = new System.Windows.Forms.Label();
this.cbComSlot = new System.Windows.Forms.ComboBox();
this.tabControl1 = new System.Windows.Forms.TabControl();
this.tabPage1 = new System.Windows.Forms.TabPage();
this.cbPulseWiegth = new System.Windows.Forms.ComboBox();
this.panel1 = new System.Windows.Forms.Panel();
this.rbEvenDistOff = new System.Windows.Forms.RadioButton();
this.rbEvenDistOn = new System.Windows.Forms.RadioButton();
this.lblPrencesInMin = new System.Windows.Forms.Label();
this.label13 = new System.Windows.Forms.Label();
this.label14 = new System.Windows.Forms.Label();
this.lblPulseWeightInternal = new System.Windows.Forms.Label();
this.label11 = new System.Windows.Forms.Label();
this.label10 = new System.Windows.Forms.Label();
this.nudPulseResolution = new System.Windows.Forms.NumericUpDown();
this.cbxPulseMode = new System.Windows.Forms.ComboBox();
this.cbxPulseLength = new System.Windows.Forms.ComboBox();
this.label8 = new System.Windows.Forms.Label();
this.label9 = new System.Windows.Forms.Label();
this.nudAdapterPresence = new System.Windows.Forms.NumericUpDown();
this.rbTestModeOff = new System.Windows.Forms.RadioButton();
this.rbTestModeOn = new System.Windows.Forms.RadioButton();
this.lblPulsesequence = new System.Windows.Forms.Label();
this.label7 = new System.Windows.Forms.Label();
this.label6 = new System.Windows.Forms.Label();
this.label5 = new System.Windows.Forms.Label();
this.label4 = new System.Windows.Forms.Label();
this.label3 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.btnDisplayDefault = new System.Windows.Forms.Button();
this.btnWrite = new System.Windows.Forms.Button();
this.btnRead = new System.Windows.Forms.Button();
this.btnLogout = new System.Windows.Forms.Button();
this.lblPulseWeightMl = new System.Windows.Forms.Label();
this.label12 = new System.Windows.Forms.Label();
this.lblP2000PulseSetup = new System.Windows.Forms.Label();
this.tabControl1.SuspendLayout();
this.tabPage1.SuspendLayout();
this.panel1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.nudPulseResolution)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.nudAdapterPresence)).BeginInit();
this.SuspendLayout();
//
// lblState
//
this.lblState.AutoSize = true;
this.lblState.Location = new System.Drawing.Point(12, 51);
this.lblState.Name = "lblState";
this.lblState.Size = new System.Drawing.Size(78, 13);
this.lblState.TabIndex = 9;
this.lblState.Text = "Not connected";
//
// btnConnect
//
this.btnConnect.Location = new System.Drawing.Point(212, 8);
this.btnConnect.Name = "btnConnect";
this.btnConnect.Size = new System.Drawing.Size(85, 30);
this.btnConnect.TabIndex = 8;
this.btnConnect.Text = "Connect";
this.btnConnect.UseVisualStyleBackColor = true;
this.btnConnect.Click += new System.EventHandler(this.btnConnect_Click);
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(12, 21);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(25, 13);
this.label1.TabIndex = 7;
this.label1.Text = "Slot";
//
// cbComSlot
//
this.cbComSlot.FormattingEnabled = true;
this.cbComSlot.Location = new System.Drawing.Point(83, 12);
this.cbComSlot.Name = "cbComSlot";
this.cbComSlot.Size = new System.Drawing.Size(104, 21);
this.cbComSlot.TabIndex = 6;
this.cbComSlot.Text = "1";
//
// tabControl1
//
this.tabControl1.Controls.Add(this.tabPage1);
this.tabControl1.Location = new System.Drawing.Point(6, 92);
this.tabControl1.Name = "tabControl1";
this.tabControl1.SelectedIndex = 0;
this.tabControl1.Size = new System.Drawing.Size(574, 324);
this.tabControl1.TabIndex = 11;
//
// tabPage1
//
this.tabPage1.Controls.Add(this.lblP2000PulseSetup);
this.tabPage1.Controls.Add(this.label12);
this.tabPage1.Controls.Add(this.lblPulseWeightMl);
this.tabPage1.Controls.Add(this.cbPulseWiegth);
this.tabPage1.Controls.Add(this.panel1);
this.tabPage1.Controls.Add(this.lblPrencesInMin);
this.tabPage1.Controls.Add(this.label13);
this.tabPage1.Controls.Add(this.label14);
this.tabPage1.Controls.Add(this.lblPulseWeightInternal);
this.tabPage1.Controls.Add(this.label11);
this.tabPage1.Controls.Add(this.label10);
this.tabPage1.Controls.Add(this.nudPulseResolution);
this.tabPage1.Controls.Add(this.cbxPulseMode);
this.tabPage1.Controls.Add(this.cbxPulseLength);
this.tabPage1.Controls.Add(this.label8);
this.tabPage1.Controls.Add(this.label9);
this.tabPage1.Controls.Add(this.nudAdapterPresence);
this.tabPage1.Controls.Add(this.rbTestModeOff);
this.tabPage1.Controls.Add(this.rbTestModeOn);
this.tabPage1.Controls.Add(this.lblPulsesequence);
this.tabPage1.Controls.Add(this.label7);
this.tabPage1.Controls.Add(this.label6);
this.tabPage1.Controls.Add(this.label5);
this.tabPage1.Controls.Add(this.label4);
this.tabPage1.Controls.Add(this.label3);
this.tabPage1.Controls.Add(this.label2);
this.tabPage1.Controls.Add(this.btnDisplayDefault);
this.tabPage1.Controls.Add(this.btnWrite);
this.tabPage1.Controls.Add(this.btnRead);
this.tabPage1.Location = new System.Drawing.Point(4, 22);
this.tabPage1.Name = "tabPage1";
this.tabPage1.Padding = new System.Windows.Forms.Padding(3);
this.tabPage1.Size = new System.Drawing.Size(566, 298);
this.tabPage1.TabIndex = 0;
this.tabPage1.Text = "Pluse";
this.tabPage1.UseVisualStyleBackColor = true;
this.tabPage1.Click += new System.EventHandler(this.tabPage1_Click);
//
// cbPulseWiegth
//
this.cbPulseWiegth.FormattingEnabled = true;
this.cbPulseWiegth.Items.AddRange(new object[] {
" 1 l/Imp.",
"10 l/Imp.",
"100 l/Imp.",
"1.000 l/Imp.",
"1 Gallons/Imp.",
"10 Gallons/Imp.",
"100 Gallons/Imp.",
"1.000 Gallons/Imp.",
"1 Cub. Feet/Imp.",
"10 Cub. Feet/Imp.",
"100 Cub. Feet/Imp.",
"1.000 Cub. Feet/Imp.",
"1 Barrel/Imp.",
"10 Barrels/Imp.",
"100 Barrels/Imp.",
"1.000 Barrels/Imp.",
"ohne"});
this.cbPulseWiegth.Location = new System.Drawing.Point(237, 180);
this.cbPulseWiegth.Name = "cbPulseWiegth";
this.cbPulseWiegth.Size = new System.Drawing.Size(111, 21);
this.cbPulseWiegth.TabIndex = 37;
this.cbPulseWiegth.SelectedIndexChanged += new System.EventHandler(this.cbPulseWiegth_SelectedIndexChanged);
//
// panel1
//
this.panel1.Controls.Add(this.rbEvenDistOff);
this.panel1.Controls.Add(this.rbEvenDistOn);
this.panel1.Location = new System.Drawing.Point(237, 74);
this.panel1.Name = "panel1";
this.panel1.Size = new System.Drawing.Size(124, 21);
this.panel1.TabIndex = 36;
//
// rbEvenDistOff
//
this.rbEvenDistOff.AutoSize = true;
this.rbEvenDistOff.Location = new System.Drawing.Point(59, 3);
this.rbEvenDistOff.Name = "rbEvenDistOff";
this.rbEvenDistOff.Size = new System.Drawing.Size(39, 17);
this.rbEvenDistOff.TabIndex = 27;
this.rbEvenDistOff.TabStop = true;
this.rbEvenDistOff.Text = "Off";
this.rbEvenDistOff.UseVisualStyleBackColor = true;
//
// rbEvenDistOn
//
this.rbEvenDistOn.AutoSize = true;
this.rbEvenDistOn.Location = new System.Drawing.Point(3, 3);
this.rbEvenDistOn.Name = "rbEvenDistOn";
this.rbEvenDistOn.Size = new System.Drawing.Size(39, 17);
this.rbEvenDistOn.TabIndex = 26;
this.rbEvenDistOn.TabStop = true;
this.rbEvenDistOn.Text = "On";
this.rbEvenDistOn.UseVisualStyleBackColor = true;
//
// lblPrencesInMin
//
this.lblPrencesInMin.AutoSize = true;
this.lblPrencesInMin.Location = new System.Drawing.Point(401, 34);
this.lblPrencesInMin.Name = "lblPrencesInMin";
this.lblPrencesInMin.Size = new System.Drawing.Size(13, 13);
this.lblPrencesInMin.TabIndex = 35;
this.lblPrencesInMin.Text = "0";
//
// label13
//
this.label13.AutoSize = true;
this.label13.Location = new System.Drawing.Point(485, 34);
this.label13.Name = "label13";
this.label13.Size = new System.Drawing.Size(54, 13);
this.label13.TabIndex = 34;
this.label13.Text = "in minutes";
//
// label14
//
this.label14.AutoSize = true;
this.label14.Location = new System.Drawing.Point(354, 34);
this.label14.Name = "label14";
this.label14.Size = new System.Drawing.Size(41, 13);
this.label14.TabIndex = 33;
this.label14.Text = "internal";
//
// lblPulseWeightInternal
//
this.lblPulseWeightInternal.AutoSize = true;
this.lblPulseWeightInternal.Location = new System.Drawing.Point(467, 206);
this.lblPulseWeightInternal.Name = "lblPulseWeightInternal";
this.lblPulseWeightInternal.Size = new System.Drawing.Size(13, 13);
this.lblPulseWeightInternal.TabIndex = 32;
this.lblPulseWeightInternal.Text = "0";
//
// label11
//
this.label11.AutoSize = true;
this.label11.Location = new System.Drawing.Point(467, 183);
this.label11.Name = "label11";
this.label11.Size = new System.Drawing.Size(72, 13);
this.label11.TabIndex = 31;
this.label11.Text = "in internal unit";
//
// label10
//
this.label10.AutoSize = true;
this.label10.Location = new System.Drawing.Point(354, 183);
this.label10.Name = "label10";
this.label10.Size = new System.Drawing.Size(28, 13);
this.label10.TabIndex = 30;
this.label10.Text = "in ml";
//
// nudPulseResolution
//
this.nudPulseResolution.Location = new System.Drawing.Point(237, 152);
this.nudPulseResolution.Maximum = new decimal(new int[] {
7,
0,
0,
0});
this.nudPulseResolution.Name = "nudPulseResolution";
this.nudPulseResolution.Size = new System.Drawing.Size(111, 20);
this.nudPulseResolution.TabIndex = 28;
this.nudPulseResolution.Value = new decimal(new int[] {
7,
0,
0,
0});
//
// cbxPulseMode
//
this.cbxPulseMode.FormattingEnabled = true;
this.cbxPulseMode.Location = new System.Drawing.Point(237, 127);
this.cbxPulseMode.Name = "cbxPulseMode";
this.cbxPulseMode.Size = new System.Drawing.Size(111, 21);
this.cbxPulseMode.TabIndex = 27;
//
// cbxPulseLength
//
this.cbxPulseLength.FormattingEnabled = true;
this.cbxPulseLength.Location = new System.Drawing.Point(237, 103);
this.cbxPulseLength.Name = "cbxPulseLength";
this.cbxPulseLength.Size = new System.Drawing.Size(111, 21);
this.cbxPulseLength.TabIndex = 26;
//
// label8
//
this.label8.AutoSize = true;
this.label8.Location = new System.Drawing.Point(6, 178);
this.label8.Name = "label8";
this.label8.Size = new System.Drawing.Size(169, 13);
this.label8.TabIndex = 23;
this.label8.Text = "METROLOGYASST_PulseWeight";
//
// label9
//
this.label9.AutoSize = true;
this.label9.Location = new System.Drawing.Point(6, 154);
this.label9.Name = "label9";
this.label9.Size = new System.Drawing.Size(185, 13);
this.label9.TabIndex = 22;
this.label9.Text = "METROLOGYASST_PulseResolution";
//
// nudAdapterPresence
//
this.nudAdapterPresence.Location = new System.Drawing.Point(237, 27);
this.nudAdapterPresence.Name = "nudAdapterPresence";
this.nudAdapterPresence.Size = new System.Drawing.Size(111, 20);
this.nudAdapterPresence.TabIndex = 21;
this.nudAdapterPresence.ValueChanged += new System.EventHandler(this.nudAdapterPresence_ValueChanged);
//
// rbTestModeOff
//
this.rbTestModeOff.AutoSize = true;
this.rbTestModeOff.Location = new System.Drawing.Point(293, 8);
this.rbTestModeOff.Name = "rbTestModeOff";
this.rbTestModeOff.Size = new System.Drawing.Size(39, 17);
this.rbTestModeOff.TabIndex = 18;
this.rbTestModeOff.TabStop = true;
this.rbTestModeOff.Text = "Off";
this.rbTestModeOff.UseVisualStyleBackColor = true;
//
// rbTestModeOn
//
this.rbTestModeOn.AutoSize = true;
this.rbTestModeOn.Location = new System.Drawing.Point(237, 8);
this.rbTestModeOn.Name = "rbTestModeOn";
this.rbTestModeOn.Size = new System.Drawing.Size(39, 17);
this.rbTestModeOn.TabIndex = 17;
this.rbTestModeOn.TabStop = true;
this.rbTestModeOn.Text = "On";
this.rbTestModeOn.UseVisualStyleBackColor = true;
//
// lblPulsesequence
//
this.lblPulsesequence.AutoSize = true;
this.lblPulsesequence.Location = new System.Drawing.Point(234, 58);
this.lblPulsesequence.Name = "lblPulsesequence";
this.lblPulsesequence.Size = new System.Drawing.Size(13, 13);
this.lblPulsesequence.TabIndex = 16;
this.lblPulsesequence.Text = "0";
//
// label7
//
this.label7.AutoSize = true;
this.label7.Location = new System.Drawing.Point(5, 10);
this.label7.Name = "label7";
this.label7.Size = new System.Drawing.Size(55, 13);
this.label7.TabIndex = 15;
this.label7.Text = "TestMode";
//
// label6
//
this.label6.AutoSize = true;
this.label6.Location = new System.Drawing.Point(6, 130);
this.label6.Name = "label6";
this.label6.Size = new System.Drawing.Size(162, 13);
this.label6.TabIndex = 14;
this.label6.Text = "METROLOGYASST_PulseMode";
//
// label5
//
this.label5.AutoSize = true;
this.label5.Location = new System.Drawing.Point(6, 106);
this.label5.Name = "label5";
this.label5.Size = new System.Drawing.Size(168, 13);
this.label5.TabIndex = 13;
this.label5.Text = "METROLOGYASST_PulseLength";
//
// label4
//
this.label4.AutoSize = true;
this.label4.Location = new System.Drawing.Point(6, 82);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(212, 13);
this.label4.TabIndex = 12;
this.label4.Text = "METROLOGYASST_PulseEvenDistribution";
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(5, 58);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(114, 13);
this.label3.TabIndex = 11;
this.label3.Text = "IRDA_PulseSequence";
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(5, 34);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(142, 13);
this.label2.TabIndex = 10;
this.label2.Text = "IRDA_AdapterPresenceLimit";
//
// btnDisplayDefault
//
this.btnDisplayDefault.Location = new System.Drawing.Point(282, 239);
this.btnDisplayDefault.Name = "btnDisplayDefault";
this.btnDisplayDefault.Size = new System.Drawing.Size(113, 53);
this.btnDisplayDefault.TabIndex = 8;
this.btnDisplayDefault.Text = "Set DisplayDefault";
this.btnDisplayDefault.UseVisualStyleBackColor = true;
this.btnDisplayDefault.Click += new System.EventHandler(this.btnDisplayDefault_Click);
//
// btnWrite
//
this.btnWrite.Location = new System.Drawing.Point(147, 239);
this.btnWrite.Name = "btnWrite";
this.btnWrite.Size = new System.Drawing.Size(129, 53);
this.btnWrite.TabIndex = 1;
this.btnWrite.Text = "Write";
this.btnWrite.UseVisualStyleBackColor = true;
this.btnWrite.Click += new System.EventHandler(this.btnWrite_Click);
//
// btnRead
//
this.btnRead.Location = new System.Drawing.Point(3, 239);
this.btnRead.Name = "btnRead";
this.btnRead.Size = new System.Drawing.Size(129, 53);
this.btnRead.TabIndex = 0;
this.btnRead.Text = "Read";
this.btnRead.UseVisualStyleBackColor = true;
this.btnRead.Click += new System.EventHandler(this.btnRead_Click);
//
// btnLogout
//
this.btnLogout.Location = new System.Drawing.Point(303, 8);
this.btnLogout.Name = "btnLogout";
this.btnLogout.Size = new System.Drawing.Size(85, 30);
this.btnLogout.TabIndex = 12;
this.btnLogout.Text = "Logout";
this.btnLogout.UseVisualStyleBackColor = true;
this.btnLogout.Click += new System.EventHandler(this.btnLogout_Click);
//
// lblPulseWeightMl
//
this.lblPulseWeightMl.AutoSize = true;
this.lblPulseWeightMl.Location = new System.Drawing.Point(354, 206);
this.lblPulseWeightMl.Name = "lblPulseWeightMl";
this.lblPulseWeightMl.Size = new System.Drawing.Size(13, 13);
this.lblPulseWeightMl.TabIndex = 38;
this.lblPulseWeightMl.Text = "0";
//
// label12
//
this.label12.AutoSize = true;
this.label12.Location = new System.Drawing.Point(466, 223);
this.label12.Name = "label12";
this.label12.Size = new System.Drawing.Size(94, 13);
this.label12.TabIndex = 39;
this.label12.Text = "p2000 PulseSetup";
//
// lblP2000PulseSetup
//
this.lblP2000PulseSetup.AutoSize = true;
this.lblP2000PulseSetup.Location = new System.Drawing.Point(467, 249);
this.lblP2000PulseSetup.Name = "lblP2000PulseSetup";
this.lblP2000PulseSetup.Size = new System.Drawing.Size(13, 13);
this.lblP2000PulseSetup.TabIndex = 40;
this.lblP2000PulseSetup.Text = "0";
//
// FrmConfigurations
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(587, 450);
this.Controls.Add(this.btnLogout);
this.Controls.Add(this.tabControl1);
this.Controls.Add(this.lblState);
this.Controls.Add(this.btnConnect);
this.Controls.Add(this.label1);
this.Controls.Add(this.cbComSlot);
this.Name = "FrmConfigurations";
this.Text = "FrmConfigurations";
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FrmConfigurations_FormClosing);
this.tabControl1.ResumeLayout(false);
this.tabPage1.ResumeLayout(false);
this.tabPage1.PerformLayout();
this.panel1.ResumeLayout(false);
this.panel1.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.nudPulseResolution)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.nudAdapterPresence)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Label lblState;
private System.Windows.Forms.Button btnConnect;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.ComboBox cbComSlot;
private System.Windows.Forms.TabControl tabControl1;
private System.Windows.Forms.TabPage tabPage1;
private System.Windows.Forms.Button btnLogout;
private System.Windows.Forms.Button btnWrite;
private System.Windows.Forms.Button btnRead;
private System.Windows.Forms.Label label7;
private System.Windows.Forms.Label label6;
private System.Windows.Forms.Label label5;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Button btnDisplayDefault;
private System.Windows.Forms.Label lblPulsesequence;
private System.Windows.Forms.RadioButton rbTestModeOff;
private System.Windows.Forms.RadioButton rbTestModeOn;
private System.Windows.Forms.NumericUpDown nudAdapterPresence;
private System.Windows.Forms.Label label8;
private System.Windows.Forms.Label label9;
private System.Windows.Forms.NumericUpDown nudPulseResolution;
private System.Windows.Forms.ComboBox cbxPulseMode;
private System.Windows.Forms.ComboBox cbxPulseLength;
private System.Windows.Forms.Label lblPulseWeightInternal;
private System.Windows.Forms.Label label11;
private System.Windows.Forms.Label label10;
private System.Windows.Forms.Label lblPrencesInMin;
private System.Windows.Forms.Label label13;
private System.Windows.Forms.Label label14;
private System.Windows.Forms.Panel panel1;
private System.Windows.Forms.RadioButton rbEvenDistOff;
private System.Windows.Forms.RadioButton rbEvenDistOn;
private System.Windows.Forms.ComboBox cbPulseWiegth;
private System.Windows.Forms.Label lblPulseWeightMl;
private System.Windows.Forms.Label lblP2000PulseSetup;
private System.Windows.Forms.Label label12;
}
}
@@ -0,0 +1,405 @@
using GenesisCordonelInterface.API;
using Newtonsoft.Json;
using NLog;
using System;
using System.Collections.Generic;
using System.IO;
using System.Windows.Forms;
using Xylem.Common.CommonCore.Consts;
using Xylem.Common.Hardware.Interfaces.Ports.PortCore;
using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore;
using Xylem.Common.Hardware.WaterMeter.Genesis.Registers;
using Xylem.Common.Hardware.WaterMeter.WaterMeterCore;
using Xylem.Common.Utils.Logging;
namespace GenesisCordonelInterface.UI.LaatzenAPI_GenesisToolBox
{
public enum METROLOGYASST_PulseMode
{
OFF = 0, /* No pulse output */
FOR_REV_AB, /* Forward/reverse on A/B */
FOR_REV_BA, /* Forward/reverse on B/A */
PUL_DIR_AB, /* Pulse/direction on A/B */
PUL_DIR_BA, /* Pulse/direction on B/A */
PUL_BAL_A, /* Balanced pulse on A? */
PUL_BAL_B, /* Balanced pulse on B? */
TEST_PUL_DIR_AB, /* Test mode, pulse/direction on A/B */
};
public enum METROLOGYASST_PulseLength
{
L_1MS_NotSupported = 0, /* 1ms pulse <- not supported */
L_2MS_NotSupported, /* 2ms pulse <- not supported */
L_5MS, /* 5ms pulse */
L_10MS, /* 10ms pulse */
L_20MS, /* 20ms pulse */
L_50MS, /* 50ms pulse */
L_100MS_NotSupported, /* 100ms pulse <- not supported */
L_200MS, /* 200ms pulse */
L_500MS, /* 500ms pulse */
L_DYNAMIC, /* Dynamic pulse width */
L_1_5MS, /* 1.5ms pulse */
};
public partial class FrmConfigurations : Form
{
private static readonly NLog.ILogger Logger = NLog.LogManager.GetLogger("GenesisCordonelInterface");
private readonly InterfaceGCIToLaatzen interfaceToLaatzen = new InterfaceGCIToLaatzen();
private GenesisMeter _currentGenesis;
private String _currentPcbId;
private MeterBatch _meterBatch = new MeterBatch();
public FrmConfigurations()
{
InitializeComponent();
cbxPulseLength.DataSource = Enum.GetValues(typeof(METROLOGYASST_PulseLength));
cbxPulseMode.DataSource = Enum.GetValues(typeof(METROLOGYASST_PulseMode));
_meterBatch = new MeterBatch();
var configfile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), nameof(Xylem.Common.Hardware.WaterMeter.Genesis), ProgramConfig.SerialConfigFileName);
if (!File.Exists(configfile))
{
throw new ApplicationException($"Configuration file {configfile} not found ");
}
var tr = new StreamReader(configfile);
var meterConfigList = JsonConvert.DeserializeObject<SlotConfig[]>(tr.ReadToEnd());
cbComSlot.Items.Clear();
var listSlots = new List<Int32>();
foreach (var item in meterConfigList)
{
cbComSlot.Items.Add(item.Slot);
listSlots.Add(item.Slot);
}
if (cbComSlot.Items.Count >= 1)
{
cbComSlot.SelectedItem = cbComSlot.Items[0];
}
//foreach (var info in typeof(Register).GetNestedTypes())
//{
// cbPreselection.Items.Add(info.Name);
//}
}
private void btnLogout_Click(Object sender, EventArgs e)
{
if (_currentGenesis != null && _currentGenesis.IsLoggedOn)
{
_currentGenesis.Logout();
}
_currentPcbId = "";
}
private void btnConnect_Click(Object sender, EventArgs e)
{
if (cbComSlot.SelectedItem != null) // && cbComSlot.SelectedValue is ListBoxItem)
{
Int32 slotNR = 0;
if (!string.IsNullOrEmpty(cbComSlot.SelectedItem.ToString()) &&
int.TryParse(cbComSlot.SelectedItem.ToString(), out slotNR))
{
conntect(slotNR);
}
}
}
private void btnRead_Click(Object sender, EventArgs e)
{
if (_currentGenesis != null && _currentGenesis.IsLoggedOn)
{
Boolean TriggerTest = false;
Boolean PulseEvenDistributio = false;
Byte AdapterPresenceLimit;
Byte PulseSequence;
Int32 PulseLength;
Int32 PulseMode;
Byte PulseResolution = 0;
UInt32 PulseWeight;
TriggerTest = RegisterConverter.ByteArrayToValue<Boolean>(_currentGenesis.ReadRegister("GENESISFLOW_TriggerTest"));
try
{
PulseEvenDistributio = RegisterConverter.ByteArrayToValue<Boolean>(_currentGenesis.ReadRegister("METROLOGYASST_PulseEvenDistribution"));
PulseResolution = RegisterConverter.ByteArrayToValue<Byte>(_currentGenesis.ReadRegister("METROLOGYASST_PulseResolution"));
}
catch (Exception)
{
}
AdapterPresenceLimit = RegisterConverter.ByteArrayToValue<Byte>(_currentGenesis.ReadRegister("IRDA_AdapterPresenceLimit"));
PulseSequence = RegisterConverter.ByteArrayToValue<Byte>(_currentGenesis.ReadRegister("IRDA_PulseSequence"));
PulseLength = RegisterConverter.ByteArrayToValue<Int32>(_currentGenesis.ReadRegister("METROLOGYASST_PulseLength"));
PulseMode = RegisterConverter.ByteArrayToValue<Int32>(_currentGenesis.ReadRegister("METROLOGYASST_PulseMode"));
PulseWeight = RegisterConverter.ByteArrayToValue<UInt32>(_currentGenesis.ReadRegister("METROLOGYASST_PulseWeight"));
rbTestModeOn.Checked = false;
rbTestModeOff.Checked = true;
if (TriggerTest)
{
rbTestModeOff.Checked = false;
rbTestModeOn.Checked = true;
}
rbEvenDistOn.Checked = false;
rbEvenDistOff.Checked = true;
if (PulseEvenDistributio)
{
rbEvenDistOff.Checked = false;
rbEvenDistOn.Checked = true;
}
nudAdapterPresence.Value = AdapterPresenceLimit;
lblPulsesequence.Text = PulseSequence.ToString();
cbxPulseLength.SelectedItem = ((METROLOGYASST_PulseLength)PulseLength);
cbxPulseMode.SelectedItem = ((METROLOGYASST_PulseMode)PulseMode);
nudPulseResolution.Value = PulseResolution;
lblPulseWeightMl.Text = (PulseWeight * (Decimal)0.03125).ToString();
lblPulseWeightInternal.Text = PulseWeight.ToString();
cbPulseWiegth.SelectedText = getText(PulseWeight);
}
}
private void btnWrite_Click(Object sender, EventArgs e)
{
if (_currentGenesis != null && _currentGenesis.IsLoggedOn)
{
Boolean TriggerTest = rbTestModeOn.Checked;
Boolean PulseEvenDistributio = rbEvenDistOn.Checked;
Byte AdapterPresenceLimit = (Byte)nudAdapterPresence.Value;
Int32 PulseLength = ((METROLOGYASST_PulseLength)cbxPulseLength.SelectedItem).GetHashCode();
Int32 PulseMode = ((METROLOGYASST_PulseMode)cbxPulseMode.SelectedItem).GetHashCode();
Byte PulseResolution = (Byte)nudPulseResolution.Value;
UInt32 PulseWeight = getValue(cbPulseWiegth.SelectedText);
actionResult = null;
try
{
setActionResult(_currentGenesis.WriteRegister("METROLOGYASST_PulseEvenDistribution", PulseEvenDistributio));
// setActionResult(_currentGenesis.WriteRegister("METROLOGYASST_PulseResolution", PulseResolution));
}
catch (Exception)
{
}
if (TriggerTest)
{
setActionResult(_currentGenesis.WriteRegister("GENESISFLOW_TriggerTest", 1));
}
else
{
setActionResult(_currentGenesis.WriteRegister("GENESISFLOW_TriggerActive", 1));
}
setActionResult(_currentGenesis.WriteRegister("IRDA_AdapterPresenceLimit", AdapterPresenceLimit));
setActionResult(_currentGenesis.WriteRegister("METROLOGYASST_PulseLength", PulseLength));
setActionResult(_currentGenesis.WriteRegister("METROLOGYASST_PulseMode", PulseMode));
setActionResult(_currentGenesis.WriteRegister("METROLOGYASST_PulseWeight", PulseWeight));
setActionResult(_currentGenesis.StoreAllConfigurations());
setActionResult(_currentGenesis.WriteRegister("SENSUSRADIO_SYSTEMSTATE", 0xFF, true, false));
}
}
private void tabPage1_Click(Object sender, EventArgs e)
{
}
private void conntect(Int32 slotNR)
{
try
{
_meterBatch.RemoveAllMeters();
_currentGenesis = new GenesisMeter();
//_currentGenesis.IsDevelopmentUsage = true; //Make sure to set this before login
try
{
_currentGenesis.SetupFromConfigFile(slotNR);
_currentGenesis.EnableAutoLogon();
_meterBatch.AddMeter(_currentGenesis);
}
catch (Exception ex)
{
Logger.Error(ex, $"Slot #{slotNR} failed: {ex.Message}");
}
_currentGenesis.Login();
_currentPcbId = _currentGenesis.PcbId;
}
catch (Exception ex)
{
Logger.Error(ex, ex.Message);
}
}
private void nudAdapterPresence_ValueChanged(Object sender, EventArgs e)
{
lblPrencesInMin.Text = (nudAdapterPresence.Value * 15).ToString();
}
private void nudPulseWeight_ValueChanged(Object sender, EventArgs e)
{
}
private void btnDisplayDefault_Click(Object sender, EventArgs e)
{
if (_currentGenesis != null && _currentGenesis.IsLoggedOn)
{
actionResult = null;
setActionResult(_currentGenesis.WriteRegister("GENESISFLOW_SealDisplay", 0));
setActionResult(_currentGenesis.WriteRegister("CUSTOMER_Locale", 0));
setActionResult(_currentGenesis.WriteRegister("GENESISFLOW_DisplayPow10", 253));
setActionResult(_currentGenesis.WriteRegister("GENESISFLOW_DisplayUnits", 0));
setActionResult(_currentGenesis.WriteRegister("METROLOGYASST_FlowUnits", 1));
setActionResult(_currentGenesis.StoreAllConfigurations());
setActionResult(_currentGenesis.WriteRegister("SENSUSRADIO_SYSTEMSTATE", 0xFF, true, false));
}
}
private void setActionResult(Boolean v)
{
if (!actionResult.HasValue)
{
actionResult = v;
}
if (!v)
{
actionResult = false;
}
}
private Boolean? actionResult = null;
private void FrmConfigurations_FormClosing(Object sender, FormClosingEventArgs e)
{
_meterBatch.Dispose();
}
private void cbPulseWiegth_SelectedIndexChanged(Object sender, EventArgs e)
{
var PInternal = getValue(cbPulseWiegth.SelectedItem.ToString().Trim());
lblPulseWeightMl.Text = (PInternal * (Decimal)0.03125).ToString();
lblPulseWeightInternal.Text = (PInternal).ToString();
var PulseFQm3 = (PInternal * (Decimal)0.03125);
lblP2000PulseSetup.Text = (1000000 / PulseFQm3).ToString();
}
private String getText(UInt32 v)
{
String intHelper = "NA";
switch (v)
{
case 0x00007D00: intHelper = "1 l/Imp."; break;
case 0x0004E200: intHelper = "10 l/Imp."; break;
case 0x0030D400: intHelper = "100 l/Imp."; break;
case 0x01E84800: intHelper = "1.000 l/Imp."; break;
case 0x0001D92D: intHelper = "1 Gallons/Imp."; break;
case 0x00127BC3: intHelper = "10 Gallons/Imp."; break;
case 0x00B8D5A0: intHelper = "100 Gallons/Imp."; break;
case 0x07382500: intHelper = "1.000 Gallons/Imp."; break;
case 0x000DD399: intHelper = "1 Cub. Feet/Imp."; break;
case 0x008A4400: intHelper = "10 Cub. Feet/Imp."; break;
case 0x0566D000: intHelper = "100 Cub. Feet/Imp."; break;
case 0x36042000: intHelper = "1.000 Cub. Feet/Imp."; break;
case 0x004DA169: intHelper = "1 Barrel/Imp."; break;
case 0x03084E1E: intHelper = "10 Barrels/Imp."; break;
case 0x1E530D2F: intHelper = "100 Barrels/Imp."; break;
case 0xFFF0279D: intHelper = "1.000 Barrels/Imp."; break;
case 0x00000000: intHelper = "ohne"; break;
default: intHelper = "ohne"; break;
}
return intHelper;
}
private UInt32 getValue(String v)
{
UInt32 intHelper = 0;
switch (v.Replace(" ", ""))
{
case "1l/Imp.": intHelper = 0x00007D00; break;
case "10l/Imp.": intHelper = 0x0004E200; break;
case "100l/Imp.": intHelper = 0x0030D400; break;
case "1.000l/Imp.": intHelper = 0x01E84800; break;
case "1Gallons/Imp.": intHelper = 0x0001D92D; break;
case "10Gallons/Imp.": intHelper = 0x00127BC3; break;
case "100Gallons/Imp.": intHelper = 0x00B8D5A0; break;
case "1.000Gallons/Imp.": intHelper = 0x07382500; break;
case "1Cub.Feet/Imp.": intHelper = 0x000DD399; break;
case "10Cub.Feet/Imp.": intHelper = 0x008A4400; break;
case "100Cub.Feet/Imp.": intHelper = 0x0566D000; break;
case "1.000Cub.Feet/Imp.": intHelper = 0x36042000; break;
case "1Barrel/Imp.": intHelper = 0x004DA169; break;
case "10Barrels/Imp.": intHelper = 0x03084E1E; break;
case "100Barrels/Imp.": intHelper = 0x1E530D2F; break;
case "1.000Barrels/Imp.": intHelper = 0xFFF0279D; break;
case "ohne": intHelper = 0; break;
default: intHelper = 0; break;
}
return intHelper;
}
}
}
@@ -0,0 +1,410 @@
namespace GenesisCordonelInterface.UI.LaatzenAPI_GenesisToolBox
{
partial class FrmRegisterStore
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.cbComSlot = new System.Windows.Forms.ComboBox();
this.label1 = new System.Windows.Forms.Label();
this.btnReadRegister = new System.Windows.Forms.Button();
this.registerGridView = new System.Windows.Forms.DataGridView();
this.btnConnect = new System.Windows.Forms.Button();
this.lblState = new System.Windows.Forms.Label();
this.timProgress = new System.Windows.Forms.Timer(this.components);
this.btnGetPCbID = new System.Windows.Forms.Button();
this.pnlBussy = new System.Windows.Forms.Panel();
this.lblProgress = new System.Windows.Forms.Label();
this.lblAction = new System.Windows.Forms.Label();
this.probarBusy = new System.Windows.Forms.ProgressBar();
this.label3 = new System.Windows.Forms.Label();
this.btnReadFwVersions = new System.Windows.Forms.Button();
this.btnCalibrationRestore = new System.Windows.Forms.Button();
this.btnBatteryIdle = new System.Windows.Forms.Button();
this.btnSetDefaultPulse = new System.Windows.Forms.Button();
this.btnStoreAll = new System.Windows.Forms.Button();
this.btnRegisterToFile = new System.Windows.Forms.Button();
this.timer1 = new System.Windows.Forms.Timer(this.components);
this.btnBatLife = new System.Windows.Forms.Button();
this.btnRadioPressure = new System.Windows.Forms.Button();
this.nundCalResultID = new System.Windows.Forms.NumericUpDown();
this.lblGtbVersion = new System.Windows.Forms.Label();
this.lblConfigVersion = new System.Windows.Forms.Label();
this.btnFileToRegister = new System.Windows.Forms.Button();
this.cbxUseOfflinePwds = new System.Windows.Forms.CheckBox();
((System.ComponentModel.ISupportInitialize)(this.registerGridView)).BeginInit();
this.pnlBussy.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.nundCalResultID)).BeginInit();
this.SuspendLayout();
//
// cbComSlot
//
this.cbComSlot.FormattingEnabled = true;
this.cbComSlot.Location = new System.Drawing.Point(44, 91);
this.cbComSlot.Name = "cbComSlot";
this.cbComSlot.Size = new System.Drawing.Size(58, 21);
this.cbComSlot.TabIndex = 0;
this.cbComSlot.Text = "1";
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(10, 94);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(28, 13);
this.label1.TabIndex = 1;
this.label1.Text = "Slot:";
this.label1.Click += new System.EventHandler(this.label1_Click);
//
// btnRead
//
this.btnReadRegister.Location = new System.Drawing.Point(251, 123);
this.btnReadRegister.Name = "btnReadRegister";
this.btnReadRegister.Size = new System.Drawing.Size(110, 30);
this.btnReadRegister.TabIndex = 2;
this.btnReadRegister.Text = "Read Meter";
this.btnReadRegister.UseVisualStyleBackColor = true;
this.btnReadRegister.Click += new System.EventHandler(this.btnRead_Click);
//
// registerGridView
//
this.registerGridView.AllowUserToAddRows = false;
this.registerGridView.AllowUserToDeleteRows = false;
this.registerGridView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.registerGridView.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.registerGridView.Location = new System.Drawing.Point(8, 171);
this.registerGridView.Name = "registerGridView";
this.registerGridView.Size = new System.Drawing.Size(778, 370);
this.registerGridView.TabIndex = 3;
this.registerGridView.CellClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.registerGridView_CellClick);
this.registerGridView.CellEndEdit += new System.Windows.Forms.DataGridViewCellEventHandler(this.registerGridView_CellEndEdit);
//
// btnConnect
//
this.btnConnect.Location = new System.Drawing.Point(125, 87);
this.btnConnect.Name = "btnConnect";
this.btnConnect.Size = new System.Drawing.Size(110, 30);
this.btnConnect.TabIndex = 4;
this.btnConnect.Text = "Connect";
this.btnConnect.UseVisualStyleBackColor = true;
this.btnConnect.Click += new System.EventHandler(this.btnConnect_Click);
//
// lblState
//
this.lblState.AutoSize = true;
this.lblState.Location = new System.Drawing.Point(12, 132);
this.lblState.Name = "lblState";
this.lblState.Size = new System.Drawing.Size(78, 13);
this.lblState.TabIndex = 5;
this.lblState.Text = "Not connected";
this.lblState.Click += new System.EventHandler(this.lblState_Click);
//
// timProgress
//
this.timProgress.Tick += new System.EventHandler(this.TimeProgress_tick);
//
// btnGetPCbID
//
this.btnGetPCbID.Location = new System.Drawing.Point(399, 16);
this.btnGetPCbID.Name = "btnGetPCbID";
this.btnGetPCbID.Size = new System.Drawing.Size(110, 30);
this.btnGetPCbID.TabIndex = 11;
this.btnGetPCbID.Text = "Get PCB ID";
this.btnGetPCbID.UseVisualStyleBackColor = true;
this.btnGetPCbID.Click += new System.EventHandler(this.btnGetPCbID_Click);
//
// pnlBussy
//
this.pnlBussy.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.pnlBussy.BackColor = System.Drawing.Color.Transparent;
this.pnlBussy.Controls.Add(this.lblProgress);
this.pnlBussy.Controls.Add(this.lblAction);
this.pnlBussy.Controls.Add(this.probarBusy);
this.pnlBussy.Controls.Add(this.label3);
this.pnlBussy.Location = new System.Drawing.Point(8, 171);
this.pnlBussy.Name = "pnlBussy";
this.pnlBussy.Size = new System.Drawing.Size(803, 398);
this.pnlBussy.TabIndex = 51;
this.pnlBussy.Visible = false;
//
// lblProgress
//
this.lblProgress.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.lblProgress.AutoSize = true;
this.lblProgress.Location = new System.Drawing.Point(240, 334);
this.lblProgress.Name = "lblProgress";
this.lblProgress.Size = new System.Drawing.Size(0, 13);
this.lblProgress.TabIndex = 3;
//
// lblAction
//
this.lblAction.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.lblAction.AutoSize = true;
this.lblAction.Location = new System.Drawing.Point(240, 312);
this.lblAction.Name = "lblAction";
this.lblAction.Size = new System.Drawing.Size(0, 13);
this.lblAction.TabIndex = 2;
//
// probarBusy
//
this.probarBusy.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.probarBusy.Location = new System.Drawing.Point(12, 286);
this.probarBusy.Name = "probarBusy";
this.probarBusy.Size = new System.Drawing.Size(779, 23);
this.probarBusy.TabIndex = 1;
//
// label3
//
this.label3.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(240, 270);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(64, 13);
this.label3.TabIndex = 0;
this.label3.Text = "Please wait!";
//
// btnReadFwVersions
//
this.btnReadFwVersions.Location = new System.Drawing.Point(399, 51);
this.btnReadFwVersions.Name = "btnReadFwVersions";
this.btnReadFwVersions.Size = new System.Drawing.Size(110, 30);
this.btnReadFwVersions.TabIndex = 52;
this.btnReadFwVersions.Text = "Read FW Versions";
this.btnReadFwVersions.UseVisualStyleBackColor = true;
this.btnReadFwVersions.Click += new System.EventHandler(this.btnReadFwVersions_Click);
//
// btnCalibrationRestore
//
this.btnCalibrationRestore.Location = new System.Drawing.Point(560, 14);
this.btnCalibrationRestore.Name = "btnCalibrationRestore";
this.btnCalibrationRestore.Size = new System.Drawing.Size(110, 30);
this.btnCalibrationRestore.TabIndex = 58;
this.btnCalibrationRestore.Text = "CalibrationRestore";
this.btnCalibrationRestore.UseVisualStyleBackColor = true;
this.btnCalibrationRestore.Visible = false;
this.btnCalibrationRestore.Click += new System.EventHandler(this.btnCalibrationRestore_Click);
//
// btnBatteryIdle
//
this.btnBatteryIdle.Location = new System.Drawing.Point(399, 87);
this.btnBatteryIdle.Name = "btnBatteryIdle";
this.btnBatteryIdle.Size = new System.Drawing.Size(110, 30);
this.btnBatteryIdle.TabIndex = 60;
this.btnBatteryIdle.Text = "Battery Idle";
this.btnBatteryIdle.UseVisualStyleBackColor = true;
this.btnBatteryIdle.Visible = false;
this.btnBatteryIdle.Click += new System.EventHandler(this.btnBatteryIdle_Click);
//
// btnSetDefaultPulse
//
this.btnSetDefaultPulse.Location = new System.Drawing.Point(560, 85);
this.btnSetDefaultPulse.Name = "btnSetDefaultPulse";
this.btnSetDefaultPulse.Size = new System.Drawing.Size(110, 30);
this.btnSetDefaultPulse.TabIndex = 61;
this.btnSetDefaultPulse.Text = "Set default Pulse";
this.btnSetDefaultPulse.UseVisualStyleBackColor = true;
this.btnSetDefaultPulse.Click += new System.EventHandler(this.btnSetDefaultPulse_Click);
//
// btnStoreAll
//
this.btnStoreAll.Location = new System.Drawing.Point(251, 16);
this.btnStoreAll.Name = "btnStoreAll";
this.btnStoreAll.Size = new System.Drawing.Size(110, 28);
this.btnStoreAll.TabIndex = 62;
this.btnStoreAll.Text = "Store All";
this.btnStoreAll.UseVisualStyleBackColor = true;
this.btnStoreAll.Click += new System.EventHandler(this.btnStoreAll_Click);
//
// btnRegisterToFile
//
this.btnRegisterToFile.Location = new System.Drawing.Point(251, 50);
this.btnRegisterToFile.Name = "btnRegisterToFile";
this.btnRegisterToFile.Size = new System.Drawing.Size(110, 30);
this.btnRegisterToFile.TabIndex = 63;
this.btnRegisterToFile.Text = "RegisterToFile";
this.btnRegisterToFile.UseVisualStyleBackColor = true;
this.btnRegisterToFile.Click += new System.EventHandler(this.btnRegisterToFile_Click);
//
// timer1
//
this.timer1.Interval = 5000;
this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
//
// btnBatLife
//
this.btnBatLife.Location = new System.Drawing.Point(399, 123);
this.btnBatLife.Name = "btnBatLife";
this.btnBatLife.Size = new System.Drawing.Size(110, 30);
this.btnBatLife.TabIndex = 71;
this.btnBatLife.Text = "Lifetime";
this.btnBatLife.UseVisualStyleBackColor = true;
this.btnBatLife.Click += new System.EventHandler(this.btnBatLife_Click);
//
// btnRadioPressure
//
this.btnRadioPressure.Location = new System.Drawing.Point(560, 123);
this.btnRadioPressure.Name = "btnRadioPressure";
this.btnRadioPressure.Size = new System.Drawing.Size(110, 30);
this.btnRadioPressure.TabIndex = 72;
this.btnRadioPressure.Text = "Activate Radio";
this.btnRadioPressure.UseVisualStyleBackColor = true;
this.btnRadioPressure.Click += new System.EventHandler(this.btnRadioPressure_Click);
//
// nundCalResultID
//
this.nundCalResultID.Location = new System.Drawing.Point(562, 58);
this.nundCalResultID.Maximum = new decimal(new int[] {
999999,
0,
0,
0});
this.nundCalResultID.Name = "nundCalResultID";
this.nundCalResultID.Size = new System.Drawing.Size(110, 20);
this.nundCalResultID.TabIndex = 73;
this.nundCalResultID.Visible = false;
//
// lblGtbVersion
//
this.lblGtbVersion.AutoSize = true;
this.lblGtbVersion.Location = new System.Drawing.Point(10, 10);
this.lblGtbVersion.Name = "lblGtbVersion";
this.lblGtbVersion.Size = new System.Drawing.Size(79, 13);
this.lblGtbVersion.TabIndex = 75;
this.lblGtbVersion.Text = "GTB Version: ?";
//
// lblConfigVersion
//
this.lblConfigVersion.AutoSize = true;
this.lblConfigVersion.Location = new System.Drawing.Point(10, 33);
this.lblConfigVersion.Name = "lblConfigVersion";
this.lblConfigVersion.Size = new System.Drawing.Size(119, 13);
this.lblConfigVersion.TabIndex = 76;
this.lblConfigVersion.Text = "Configuration Version: ?";
//
// btnFileToRegister
//
this.btnFileToRegister.Location = new System.Drawing.Point(251, 87);
this.btnFileToRegister.Name = "btnFileToRegister";
this.btnFileToRegister.Size = new System.Drawing.Size(110, 30);
this.btnFileToRegister.TabIndex = 77;
this.btnFileToRegister.Text = "FileToRegister";
this.btnFileToRegister.UseVisualStyleBackColor = true;
this.btnFileToRegister.Click += new System.EventHandler(this.btnFileToRegister_Click);
//
// cbxUseOfflinePwds
//
this.cbxUseOfflinePwds.AutoSize = true;
this.cbxUseOfflinePwds.Location = new System.Drawing.Point(12, 59);
this.cbxUseOfflinePwds.Name = "cbxUseOfflinePwds";
this.cbxUseOfflinePwds.Size = new System.Drawing.Size(132, 17);
this.cbxUseOfflinePwds.TabIndex = 78;
this.cbxUseOfflinePwds.Text = "Use Offline _externPasswords";
this.cbxUseOfflinePwds.UseVisualStyleBackColor = true;
this.cbxUseOfflinePwds.CheckedChanged += new System.EventHandler(this.cbxUseOfflinePwds_CheckedChanged);
//
// FrmRegisterStore
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(803, 553);
this.Controls.Add(this.cbxUseOfflinePwds);
this.Controls.Add(this.btnFileToRegister);
this.Controls.Add(this.lblConfigVersion);
this.Controls.Add(this.lblGtbVersion);
this.Controls.Add(this.nundCalResultID);
this.Controls.Add(this.btnRadioPressure);
this.Controls.Add(this.btnBatLife);
this.Controls.Add(this.btnRegisterToFile);
this.Controls.Add(this.btnStoreAll);
this.Controls.Add(this.btnSetDefaultPulse);
this.Controls.Add(this.btnBatteryIdle);
this.Controls.Add(this.btnCalibrationRestore);
this.Controls.Add(this.btnReadFwVersions);
this.Controls.Add(this.pnlBussy);
this.Controls.Add(this.btnGetPCbID);
this.Controls.Add(this.lblState);
this.Controls.Add(this.btnConnect);
this.Controls.Add(this.registerGridView);
this.Controls.Add(this.btnReadRegister);
this.Controls.Add(this.label1);
this.Controls.Add(this.cbComSlot);
this.Name = "FrmRegisterStore";
this.Text = "frmRegisterStore";
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.frmRegisterStore_FormClosing);
this.Load += new System.EventHandler(this.frmRegisterStore_Load);
((System.ComponentModel.ISupportInitialize)(this.registerGridView)).EndInit();
this.pnlBussy.ResumeLayout(false);
this.pnlBussy.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.nundCalResultID)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.ComboBox cbComSlot;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Button btnReadRegister;
private System.Windows.Forms.DataGridView registerGridView;
private System.Windows.Forms.Button btnConnect;
private System.Windows.Forms.Label lblState;
private System.Windows.Forms.Timer timProgress;
private System.Windows.Forms.Button btnGetPCbID;
private System.Windows.Forms.Panel pnlBussy;
private System.Windows.Forms.Label lblProgress;
private System.Windows.Forms.Label lblAction;
private System.Windows.Forms.ProgressBar probarBusy;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Button btnReadFwVersions;
private System.Windows.Forms.Button btnCalibrationRestore;
private System.Windows.Forms.Button btnBatteryIdle;
private System.Windows.Forms.Button btnSetDefaultPulse;
private System.Windows.Forms.Button btnStoreAll;
private System.Windows.Forms.Button btnRegisterToFile;
private System.Windows.Forms.Timer timer1;
private System.Windows.Forms.Button btnBatLife;
private System.Windows.Forms.Button btnRadioPressure;
private System.Windows.Forms.NumericUpDown nundCalResultID;
private System.Windows.Forms.Label lblGtbVersion;
private System.Windows.Forms.Label lblConfigVersion;
private System.Windows.Forms.Button btnFileToRegister;
private System.Windows.Forms.CheckBox cbxUseOfflinePwds;
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,705 @@
namespace GenesisCordonelInterface.UI.LaatzenAPI_GenesisToolBox
{
partial class FrmSetup
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.btnReload = new System.Windows.Forms.Button();
this.btnStore = new System.Windows.Forms.Button();
this.tabControl1 = new System.Windows.Forms.TabControl();
this.tabPage1 = new System.Windows.Forms.TabPage();
this.btnAddRow = new System.Windows.Forms.Button();
this.dgvConfig = new System.Windows.Forms.DataGridView();
this.tbcSlot = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.cbcRequestPort = new System.Windows.Forms.DataGridViewComboBoxColumn();
this.cbcRequestType = new System.Windows.Forms.DataGridViewComboBoxColumn();
this.cbcStreamingPort = new System.Windows.Forms.DataGridViewComboBoxColumn();
this.cbcSlotType = new System.Windows.Forms.DataGridViewCheckBoxColumn();
this.btcDetectRequest = new System.Windows.Forms.DataGridViewButtonColumn();
this.btcDetectStreaming = new System.Windows.Forms.DataGridViewButtonColumn();
this.tabPage2 = new System.Windows.Forms.TabPage();
this.cbxProductionMode = new System.Windows.Forms.CheckBox();
this.cbUpdateFiles = new System.Windows.Forms.CheckBox();
this.cbUseMinMaxCheck = new System.Windows.Forms.CheckBox();
this.label1 = new System.Windows.Forms.Label();
this.txtWachSeriveUrl = new System.Windows.Forms.TextBox();
this.cbUseRegisterWatch = new System.Windows.Forms.CheckBox();
this.tabPage3 = new System.Windows.Forms.TabPage();
this.cmdAddOffline = new System.Windows.Forms.Button();
this.dgvofflinePw = new System.Windows.Forms.DataGridView();
this.dataGridViewTextBoxColumn1 = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.dataGridViewTextBoxColumn2 = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.offlinePaswordItemBindingSource = new System.Windows.Forms.BindingSource(this.components);
this.tabPage4 = new System.Windows.Forms.TabPage();
this.lblGlobalCurrentPath = new System.Windows.Forms.Label();
this.btnGlobalSearch = new System.Windows.Forms.Button();
this.btnGlobalDefaultLan = new System.Windows.Forms.Button();
this.btnGlobalDefaultLocal = new System.Windows.Forms.Button();
this.label6 = new System.Windows.Forms.Label();
this.lblLocalCurrentPath = new System.Windows.Forms.Label();
this.btnLocalSearch = new System.Windows.Forms.Button();
this.btnLocalDefaultLan = new System.Windows.Forms.Button();
this.btnLocalDefaultLocal = new System.Windows.Forms.Button();
this.lblLocalPath = new System.Windows.Forms.Label();
this.label4 = new System.Windows.Forms.Label();
this.label3 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.tabPage5 = new System.Windows.Forms.TabPage();
this.cbxSirtService868MHz = new System.Windows.Forms.ComboBox();
this.cbxSirtService433MHz = new System.Windows.Forms.ComboBox();
this.label5 = new System.Windows.Forms.Label();
this.label7 = new System.Windows.Forms.Label();
this.cbxSirtComport868MHz = new System.Windows.Forms.ComboBox();
this.cbxSirtComport433MHz = new System.Windows.Forms.ComboBox();
this.tbxSirtBoxNo = new System.Windows.Forms.TextBox();
this.tbxSirtStationId = new System.Windows.Forms.TextBox();
this.lblSirtComport868MHz = new System.Windows.Forms.Label();
this.lblSirtComport433MHz = new System.Windows.Forms.Label();
this.lblSirtBoxNo = new System.Windows.Forms.Label();
this.lblSirtStation = new System.Windows.Forms.Label();
this.tabControl1.SuspendLayout();
this.tabPage1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.dgvConfig)).BeginInit();
this.tabPage2.SuspendLayout();
this.tabPage3.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.dgvofflinePw)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.offlinePaswordItemBindingSource)).BeginInit();
this.tabPage4.SuspendLayout();
this.tabPage5.SuspendLayout();
this.SuspendLayout();
//
// btnReload
//
this.btnReload.Location = new System.Drawing.Point(12, 12);
this.btnReload.Name = "btnReload";
this.btnReload.Size = new System.Drawing.Size(140, 43);
this.btnReload.TabIndex = 1;
this.btnReload.Text = "Reload Setup";
this.btnReload.UseVisualStyleBackColor = true;
this.btnReload.Click += new System.EventHandler(this.BtnReload_Click);
//
// btnStore
//
this.btnStore.Location = new System.Drawing.Point(158, 12);
this.btnStore.Name = "btnStore";
this.btnStore.Size = new System.Drawing.Size(140, 43);
this.btnStore.TabIndex = 2;
this.btnStore.Text = "Save Setup";
this.btnStore.UseVisualStyleBackColor = true;
this.btnStore.Click += new System.EventHandler(this.BtnStore_Click);
//
// tabControl1
//
this.tabControl1.Controls.Add(this.tabPage1);
this.tabControl1.Controls.Add(this.tabPage2);
this.tabControl1.Controls.Add(this.tabPage3);
this.tabControl1.Controls.Add(this.tabPage4);
this.tabControl1.Controls.Add(this.tabPage5);
this.tabControl1.Location = new System.Drawing.Point(12, 74);
this.tabControl1.Name = "tabControl1";
this.tabControl1.SelectedIndex = 0;
this.tabControl1.Size = new System.Drawing.Size(768, 387);
this.tabControl1.TabIndex = 17;
//
// tabPage1
//
this.tabPage1.Controls.Add(this.btnAddRow);
this.tabPage1.Controls.Add(this.dgvConfig);
this.tabPage1.Location = new System.Drawing.Point(4, 22);
this.tabPage1.Name = "tabPage1";
this.tabPage1.Padding = new System.Windows.Forms.Padding(3);
this.tabPage1.Size = new System.Drawing.Size(760, 361);
this.tabPage1.TabIndex = 0;
this.tabPage1.Text = "Slots";
this.tabPage1.UseVisualStyleBackColor = true;
//
// btnAddRow
//
this.btnAddRow.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.btnAddRow.Location = new System.Drawing.Point(6, 255);
this.btnAddRow.Name = "btnAddRow";
this.btnAddRow.Size = new System.Drawing.Size(199, 29);
this.btnAddRow.TabIndex = 5;
this.btnAddRow.Text = "Add Slot";
this.btnAddRow.UseVisualStyleBackColor = true;
this.btnAddRow.Click += new System.EventHandler(this.btnAddRow_Click);
//
// dgvConfig
//
this.dgvConfig.AllowUserToAddRows = false;
this.dgvConfig.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.dgvConfig.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.dgvConfig.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
this.tbcSlot,
this.cbcRequestPort,
this.cbcRequestType,
this.cbcStreamingPort,
this.cbcSlotType,
this.btcDetectRequest,
this.btcDetectStreaming});
this.dgvConfig.Location = new System.Drawing.Point(6, 6);
this.dgvConfig.Name = "dgvConfig";
this.dgvConfig.Size = new System.Drawing.Size(746, 243);
this.dgvConfig.TabIndex = 4;
this.dgvConfig.CellContentClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.DgvConfig_CellContentClick);
this.dgvConfig.DataError += new System.Windows.Forms.DataGridViewDataErrorEventHandler(this.dgvConfig_DataError);
//
// tbcSlot
//
this.tbcSlot.HeaderText = "tbcSlot";
this.tbcSlot.Name = "tbcSlot";
//
// cbcRequestPort
//
this.cbcRequestPort.HeaderText = "cbcRequestPort";
this.cbcRequestPort.Name = "cbcRequestPort";
//
// cbcRequestType
//
this.cbcRequestType.HeaderText = "cbcRequestType";
this.cbcRequestType.Name = "cbcRequestType";
//
// cbcStreamingPort
//
this.cbcStreamingPort.HeaderText = "cbcStreamingPort";
this.cbcStreamingPort.Name = "cbcStreamingPort";
//
// cbcSlotType
//
this.cbcSlotType.HeaderText = "TempretureMeter";
this.cbcSlotType.Name = "cbcSlotType";
this.cbcSlotType.Resizable = System.Windows.Forms.DataGridViewTriState.True;
//
// btcDetectRequest
//
this.btcDetectRequest.HeaderText = "btcDetectRequest";
this.btcDetectRequest.Name = "btcDetectRequest";
//
// btcDetectStreaming
//
this.btcDetectStreaming.HeaderText = "btcDetectStreaming";
this.btcDetectStreaming.Name = "btcDetectStreaming";
//
// tabPage2
//
this.tabPage2.Controls.Add(this.cbxProductionMode);
this.tabPage2.Controls.Add(this.cbUpdateFiles);
this.tabPage2.Controls.Add(this.cbUseMinMaxCheck);
this.tabPage2.Controls.Add(this.label1);
this.tabPage2.Controls.Add(this.txtWachSeriveUrl);
this.tabPage2.Controls.Add(this.cbUseRegisterWatch);
this.tabPage2.Location = new System.Drawing.Point(4, 22);
this.tabPage2.Name = "tabPage2";
this.tabPage2.Padding = new System.Windows.Forms.Padding(3);
this.tabPage2.Size = new System.Drawing.Size(760, 361);
this.tabPage2.TabIndex = 1;
this.tabPage2.Text = "General";
this.tabPage2.UseVisualStyleBackColor = true;
//
// cbxProductionMode
//
this.cbxProductionMode.AutoSize = true;
this.cbxProductionMode.Location = new System.Drawing.Point(25, 19);
this.cbxProductionMode.Name = "cbxProductionMode";
this.cbxProductionMode.Size = new System.Drawing.Size(104, 17);
this.cbxProductionMode.TabIndex = 22;
this.cbxProductionMode.Text = "ProductionMode";
this.cbxProductionMode.UseVisualStyleBackColor = true;
//
// cbUpdateFiles
//
this.cbUpdateFiles.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.cbUpdateFiles.AutoSize = true;
this.cbUpdateFiles.Location = new System.Drawing.Point(25, 42);
this.cbUpdateFiles.Name = "cbUpdateFiles";
this.cbUpdateFiles.Size = new System.Drawing.Size(199, 17);
this.cbUpdateFiles.TabIndex = 21;
this.cbUpdateFiles.Text = "Auto Update files (configuration.json)";
this.cbUpdateFiles.UseVisualStyleBackColor = true;
this.cbUpdateFiles.CheckedChanged += new System.EventHandler(this.cbUpdateFiles_CheckedChanged);
//
// cbUseMinMaxCheck
//
this.cbUseMinMaxCheck.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.cbUseMinMaxCheck.AutoSize = true;
this.cbUseMinMaxCheck.Location = new System.Drawing.Point(25, 88);
this.cbUseMinMaxCheck.Name = "cbUseMinMaxCheck";
this.cbUseMinMaxCheck.Size = new System.Drawing.Size(113, 17);
this.cbUseMinMaxCheck.TabIndex = 20;
this.cbUseMinMaxCheck.Text = "UseMinMaxCheck";
this.cbUseMinMaxCheck.UseVisualStyleBackColor = true;
this.cbUseMinMaxCheck.CheckedChanged += new System.EventHandler(this.cbUseMinMaxCheck_CheckedChanged);
//
// label1
//
this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(147, 65);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(136, 13);
this.label1.TabIndex = 19;
this.label1.Text = "RegisterWatchServiceURL";
//
// txtWachSeriveUrl
//
this.txtWachSeriveUrl.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.txtWachSeriveUrl.Location = new System.Drawing.Point(288, 60);
this.txtWachSeriveUrl.Name = "txtWachSeriveUrl";
this.txtWachSeriveUrl.Size = new System.Drawing.Size(439, 20);
this.txtWachSeriveUrl.TabIndex = 18;
this.txtWachSeriveUrl.TextChanged += new System.EventHandler(this.textBox1_TextChanged);
//
// cbUseRegisterWatch
//
this.cbUseRegisterWatch.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.cbUseRegisterWatch.AutoSize = true;
this.cbUseRegisterWatch.Location = new System.Drawing.Point(25, 65);
this.cbUseRegisterWatch.Name = "cbUseRegisterWatch";
this.cbUseRegisterWatch.Size = new System.Drawing.Size(116, 17);
this.cbUseRegisterWatch.TabIndex = 17;
this.cbUseRegisterWatch.Text = "UseRegisterWatch";
this.cbUseRegisterWatch.UseVisualStyleBackColor = true;
this.cbUseRegisterWatch.CheckedChanged += new System.EventHandler(this.cbUseRegisterWatch_CheckedChanged);
//
// tabPage3
//
this.tabPage3.Controls.Add(this.cmdAddOffline);
this.tabPage3.Controls.Add(this.dgvofflinePw);
this.tabPage3.Location = new System.Drawing.Point(4, 22);
this.tabPage3.Name = "tabPage3";
this.tabPage3.Size = new System.Drawing.Size(760, 361);
this.tabPage3.TabIndex = 2;
this.tabPage3.Text = "OfflinePasswords";
this.tabPage3.UseVisualStyleBackColor = true;
//
// cmdAddOffline
//
this.cmdAddOffline.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.cmdAddOffline.Location = new System.Drawing.Point(3, 195);
this.cmdAddOffline.Name = "cmdAddOffline";
this.cmdAddOffline.Size = new System.Drawing.Size(257, 43);
this.cmdAddOffline.TabIndex = 17;
this.cmdAddOffline.Text = "Add Item";
this.cmdAddOffline.UseVisualStyleBackColor = true;
this.cmdAddOffline.Click += new System.EventHandler(this.cmdAddOffline_Click);
//
// dgvofflinePw
//
this.dgvofflinePw.AutoGenerateColumns = false;
this.dgvofflinePw.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.dgvofflinePw.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
this.dataGridViewTextBoxColumn1,
this.dataGridViewTextBoxColumn2});
this.dgvofflinePw.DataSource = this.offlinePaswordItemBindingSource;
this.dgvofflinePw.Location = new System.Drawing.Point(3, 19);
this.dgvofflinePw.Name = "dgvofflinePw";
this.dgvofflinePw.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect;
this.dgvofflinePw.Size = new System.Drawing.Size(345, 170);
this.dgvofflinePw.TabIndex = 16;
//
// dataGridViewTextBoxColumn1
//
this.dataGridViewTextBoxColumn1.DataPropertyName = "PcbID";
this.dataGridViewTextBoxColumn1.HeaderText = "PcbID";
this.dataGridViewTextBoxColumn1.Name = "dataGridViewTextBoxColumn1";
//
// dataGridViewTextBoxColumn2
//
this.dataGridViewTextBoxColumn2.DataPropertyName = "Password";
this.dataGridViewTextBoxColumn2.HeaderText = "Password";
this.dataGridViewTextBoxColumn2.Name = "dataGridViewTextBoxColumn2";
//
// offlinePaswordItemBindingSource
//
this.offlinePaswordItemBindingSource.DataSource = typeof(OfflinePasswordItem);
//
// tabPage4
//
this.tabPage4.Controls.Add(this.lblGlobalCurrentPath);
this.tabPage4.Controls.Add(this.btnGlobalSearch);
this.tabPage4.Controls.Add(this.btnGlobalDefaultLan);
this.tabPage4.Controls.Add(this.btnGlobalDefaultLocal);
this.tabPage4.Controls.Add(this.label6);
this.tabPage4.Controls.Add(this.lblLocalCurrentPath);
this.tabPage4.Controls.Add(this.btnLocalSearch);
this.tabPage4.Controls.Add(this.btnLocalDefaultLan);
this.tabPage4.Controls.Add(this.btnLocalDefaultLocal);
this.tabPage4.Controls.Add(this.lblLocalPath);
this.tabPage4.Controls.Add(this.label4);
this.tabPage4.Controls.Add(this.label3);
this.tabPage4.Controls.Add(this.label2);
this.tabPage4.Location = new System.Drawing.Point(4, 22);
this.tabPage4.Name = "tabPage4";
this.tabPage4.Size = new System.Drawing.Size(760, 361);
this.tabPage4.TabIndex = 3;
this.tabPage4.Text = "Logging";
this.tabPage4.UseVisualStyleBackColor = true;
this.tabPage4.Enter += new System.EventHandler(this.tabPage4_Click);
//
// lblGlobalCurrentPath
//
this.lblGlobalCurrentPath.AutoSize = true;
this.lblGlobalCurrentPath.Location = new System.Drawing.Point(132, 211);
this.lblGlobalCurrentPath.Name = "lblGlobalCurrentPath";
this.lblGlobalCurrentPath.Size = new System.Drawing.Size(10, 13);
this.lblGlobalCurrentPath.TabIndex = 12;
this.lblGlobalCurrentPath.Text = "-";
//
// btnGlobalSearch
//
this.btnGlobalSearch.Location = new System.Drawing.Point(52, 307);
this.btnGlobalSearch.Name = "btnGlobalSearch";
this.btnGlobalSearch.Size = new System.Drawing.Size(314, 29);
this.btnGlobalSearch.TabIndex = 11;
this.btnGlobalSearch.Text = "Search";
this.btnGlobalSearch.UseVisualStyleBackColor = true;
this.btnGlobalSearch.Click += new System.EventHandler(this.btnGlobalSearch_Click);
//
// btnGlobalDefaultLan
//
this.btnGlobalDefaultLan.Location = new System.Drawing.Point(52, 272);
this.btnGlobalDefaultLan.Name = "btnGlobalDefaultLan";
this.btnGlobalDefaultLan.Size = new System.Drawing.Size(314, 29);
this.btnGlobalDefaultLan.TabIndex = 10;
this.btnGlobalDefaultLan.Text = "Use \\\\sla12buma\\cordonelds$\\${machinename}";
this.btnGlobalDefaultLan.UseVisualStyleBackColor = true;
this.btnGlobalDefaultLan.Click += new System.EventHandler(this.btnGlobalDefaultLan_Click);
//
// btnGlobalDefaultLocal
//
this.btnGlobalDefaultLocal.Location = new System.Drawing.Point(52, 237);
this.btnGlobalDefaultLocal.Name = "btnGlobalDefaultLocal";
this.btnGlobalDefaultLocal.Size = new System.Drawing.Size(314, 29);
this.btnGlobalDefaultLocal.TabIndex = 9;
this.btnGlobalDefaultLocal.Text = "Use C:\\GenesisLog\\";
this.btnGlobalDefaultLocal.UseVisualStyleBackColor = true;
this.btnGlobalDefaultLocal.Click += new System.EventHandler(this.btnGlobalDefaultLocal_Click);
//
// label6
//
this.label6.AutoSize = true;
this.label6.Location = new System.Drawing.Point(49, 211);
this.label6.Name = "label6";
this.label6.Size = new System.Drawing.Size(66, 13);
this.label6.TabIndex = 8;
this.label6.Text = "CurrentPath:";
//
// lblLocalCurrentPath
//
this.lblLocalCurrentPath.AutoSize = true;
this.lblLocalCurrentPath.Location = new System.Drawing.Point(132, 57);
this.lblLocalCurrentPath.Name = "lblLocalCurrentPath";
this.lblLocalCurrentPath.Size = new System.Drawing.Size(10, 13);
this.lblLocalCurrentPath.TabIndex = 7;
this.lblLocalCurrentPath.Text = "-";
//
// btnLocalSearch
//
this.btnLocalSearch.Location = new System.Drawing.Point(52, 153);
this.btnLocalSearch.Name = "btnLocalSearch";
this.btnLocalSearch.Size = new System.Drawing.Size(314, 29);
this.btnLocalSearch.TabIndex = 6;
this.btnLocalSearch.Text = "Search";
this.btnLocalSearch.UseVisualStyleBackColor = true;
this.btnLocalSearch.Click += new System.EventHandler(this.btnLocalSearch_Click);
//
// btnLocalDefaultLan
//
this.btnLocalDefaultLan.Location = new System.Drawing.Point(52, 118);
this.btnLocalDefaultLan.Name = "btnLocalDefaultLan";
this.btnLocalDefaultLan.Size = new System.Drawing.Size(314, 29);
this.btnLocalDefaultLan.TabIndex = 5;
this.btnLocalDefaultLan.Text = "Use \\\\sla12buma\\cordonelds$\\${machinename}";
this.btnLocalDefaultLan.UseVisualStyleBackColor = true;
this.btnLocalDefaultLan.Click += new System.EventHandler(this.btnLocalDefaultLan_Click);
//
// btnLocalDefaultLocal
//
this.btnLocalDefaultLocal.Location = new System.Drawing.Point(52, 83);
this.btnLocalDefaultLocal.Name = "btnLocalDefaultLocal";
this.btnLocalDefaultLocal.Size = new System.Drawing.Size(314, 29);
this.btnLocalDefaultLocal.TabIndex = 4;
this.btnLocalDefaultLocal.Text = "Use C:\\GenesisLog\\";
this.btnLocalDefaultLocal.UseVisualStyleBackColor = true;
this.btnLocalDefaultLocal.Click += new System.EventHandler(this.btnLocalDefaultLocal_Click);
//
// lblLocalPath
//
this.lblLocalPath.AutoSize = true;
this.lblLocalPath.Location = new System.Drawing.Point(121, 57);
this.lblLocalPath.Name = "lblLocalPath";
this.lblLocalPath.Size = new System.Drawing.Size(0, 13);
this.lblLocalPath.TabIndex = 3;
//
// label4
//
this.label4.AutoSize = true;
this.label4.Location = new System.Drawing.Point(49, 57);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(66, 13);
this.label4.TabIndex = 2;
this.label4.Text = "CurrentPath:";
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(13, 190);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(37, 13);
this.label3.TabIndex = 1;
this.label3.Text = "Global";
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(13, 32);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(103, 13);
this.label2.TabIndex = 0;
this.label2.Text = "Local (only ToolBox)";
//
// tabPage5
//
this.tabPage5.Controls.Add(this.cbxSirtService868MHz);
this.tabPage5.Controls.Add(this.cbxSirtService433MHz);
this.tabPage5.Controls.Add(this.label5);
this.tabPage5.Controls.Add(this.label7);
this.tabPage5.Controls.Add(this.cbxSirtComport868MHz);
this.tabPage5.Controls.Add(this.cbxSirtComport433MHz);
this.tabPage5.Controls.Add(this.tbxSirtBoxNo);
this.tabPage5.Controls.Add(this.tbxSirtStationId);
this.tabPage5.Controls.Add(this.lblSirtComport868MHz);
this.tabPage5.Controls.Add(this.lblSirtComport433MHz);
this.tabPage5.Controls.Add(this.lblSirtBoxNo);
this.tabPage5.Controls.Add(this.lblSirtStation);
this.tabPage5.Location = new System.Drawing.Point(4, 22);
this.tabPage5.Name = "tabPage5";
this.tabPage5.Size = new System.Drawing.Size(760, 361);
this.tabPage5.TabIndex = 4;
this.tabPage5.Text = "SIRT";
this.tabPage5.UseVisualStyleBackColor = true;
//
// cbxSirtService868MHz
//
this.cbxSirtService868MHz.FormattingEnabled = true;
this.cbxSirtService868MHz.Location = new System.Drawing.Point(142, 164);
this.cbxSirtService868MHz.Name = "cbxSirtService868MHz";
this.cbxSirtService868MHz.Size = new System.Drawing.Size(121, 21);
this.cbxSirtService868MHz.TabIndex = 13;
//
// cbxSirtService433MHz
//
this.cbxSirtService433MHz.FormattingEnabled = true;
this.cbxSirtService433MHz.Location = new System.Drawing.Point(142, 137);
this.cbxSirtService433MHz.Name = "cbxSirtService433MHz";
this.cbxSirtService433MHz.Size = new System.Drawing.Size(121, 21);
this.cbxSirtService433MHz.TabIndex = 12;
//
// label5
//
this.label5.AutoSize = true;
this.label5.Location = new System.Drawing.Point(22, 168);
this.label5.Name = "label5";
this.label5.Size = new System.Drawing.Size(114, 13);
this.label5.TabIndex = 11;
this.label5.Text = "Service Port 868 MHz:";
//
// label7
//
this.label7.AutoSize = true;
this.label7.Location = new System.Drawing.Point(22, 140);
this.label7.Name = "label7";
this.label7.Size = new System.Drawing.Size(114, 13);
this.label7.TabIndex = 10;
this.label7.Text = "Service Port 433 MHz:";
//
// cbxSirtComport868MHz
//
this.cbxSirtComport868MHz.FormattingEnabled = true;
this.cbxSirtComport868MHz.Location = new System.Drawing.Point(142, 102);
this.cbxSirtComport868MHz.Name = "cbxSirtComport868MHz";
this.cbxSirtComport868MHz.Size = new System.Drawing.Size(121, 21);
this.cbxSirtComport868MHz.TabIndex = 9;
//
// cbxSirtComport433MHz
//
this.cbxSirtComport433MHz.FormattingEnabled = true;
this.cbxSirtComport433MHz.Location = new System.Drawing.Point(142, 75);
this.cbxSirtComport433MHz.Name = "cbxSirtComport433MHz";
this.cbxSirtComport433MHz.Size = new System.Drawing.Size(121, 21);
this.cbxSirtComport433MHz.TabIndex = 8;
//
// tbxSirtBoxNo
//
this.tbxSirtBoxNo.Location = new System.Drawing.Point(142, 44);
this.tbxSirtBoxNo.Name = "tbxSirtBoxNo";
this.tbxSirtBoxNo.Size = new System.Drawing.Size(100, 20);
this.tbxSirtBoxNo.TabIndex = 7;
//
// tbxSirtStationId
//
this.tbxSirtStationId.Location = new System.Drawing.Point(142, 17);
this.tbxSirtStationId.Name = "tbxSirtStationId";
this.tbxSirtStationId.Size = new System.Drawing.Size(100, 20);
this.tbxSirtStationId.TabIndex = 6;
//
// lblSirtComport868MHz
//
this.lblSirtComport868MHz.AutoSize = true;
this.lblSirtComport868MHz.Location = new System.Drawing.Point(22, 106);
this.lblSirtComport868MHz.Name = "lblSirtComport868MHz";
this.lblSirtComport868MHz.Size = new System.Drawing.Size(103, 13);
this.lblSirtComport868MHz.TabIndex = 5;
this.lblSirtComport868MHz.Text = "RSSI Port 868 MHz:";
//
// lblSirtComport433MHz
//
this.lblSirtComport433MHz.AutoSize = true;
this.lblSirtComport433MHz.Location = new System.Drawing.Point(22, 78);
this.lblSirtComport433MHz.Name = "lblSirtComport433MHz";
this.lblSirtComport433MHz.Size = new System.Drawing.Size(103, 13);
this.lblSirtComport433MHz.TabIndex = 4;
this.lblSirtComport433MHz.Text = "RSSI Port 433 MHz:";
//
// lblSirtBoxNo
//
this.lblSirtBoxNo.AutoSize = true;
this.lblSirtBoxNo.Location = new System.Drawing.Point(22, 51);
this.lblSirtBoxNo.Name = "lblSirtBoxNo";
this.lblSirtBoxNo.Size = new System.Drawing.Size(45, 13);
this.lblSirtBoxNo.TabIndex = 3;
this.lblSirtBoxNo.Text = "Box No:";
//
// lblSirtStation
//
this.lblSirtStation.AutoSize = true;
this.lblSirtStation.Location = new System.Drawing.Point(22, 24);
this.lblSirtStation.Name = "lblSirtStation";
this.lblSirtStation.Size = new System.Drawing.Size(57, 13);
this.lblSirtStation.TabIndex = 2;
this.lblSirtStation.Text = "Station ID:";
//
// FrmSetup
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(780, 671);
this.Controls.Add(this.tabControl1);
this.Controls.Add(this.btnStore);
this.Controls.Add(this.btnReload);
this.MinimumSize = new System.Drawing.Size(755, 410);
this.Name = "FrmSetup";
this.Text = "Setup";
this.Load += new System.EventHandler(this.FrmSetup_Load);
this.tabControl1.ResumeLayout(false);
this.tabPage1.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.dgvConfig)).EndInit();
this.tabPage2.ResumeLayout(false);
this.tabPage2.PerformLayout();
this.tabPage3.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.dgvofflinePw)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.offlinePaswordItemBindingSource)).EndInit();
this.tabPage4.ResumeLayout(false);
this.tabPage4.PerformLayout();
this.tabPage5.ResumeLayout(false);
this.tabPage5.PerformLayout();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Button btnReload;
private System.Windows.Forms.Button btnStore;
private System.Windows.Forms.DataGridViewTextBoxColumn pcbIDDataGridViewTextBoxColumn;
private System.Windows.Forms.DataGridViewTextBoxColumn passwordDataGridViewTextBoxColumn;
private System.Windows.Forms.BindingSource offlinePaswordItemBindingSource;
private System.Windows.Forms.TabControl tabControl1;
private System.Windows.Forms.TabPage tabPage1;
private System.Windows.Forms.Button btnAddRow;
private System.Windows.Forms.DataGridView dgvConfig;
private System.Windows.Forms.DataGridViewTextBoxColumn tbcSlot;
private System.Windows.Forms.DataGridViewComboBoxColumn cbcRequestPort;
private System.Windows.Forms.DataGridViewComboBoxColumn cbcRequestType;
private System.Windows.Forms.DataGridViewComboBoxColumn cbcStreamingPort;
private System.Windows.Forms.DataGridViewCheckBoxColumn cbcSlotType;
private System.Windows.Forms.DataGridViewButtonColumn btcDetectRequest;
private System.Windows.Forms.DataGridViewButtonColumn btcDetectStreaming;
private System.Windows.Forms.TabPage tabPage2;
private System.Windows.Forms.CheckBox cbxProductionMode;
private System.Windows.Forms.CheckBox cbUpdateFiles;
private System.Windows.Forms.CheckBox cbUseMinMaxCheck;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.TextBox txtWachSeriveUrl;
private System.Windows.Forms.CheckBox cbUseRegisterWatch;
private System.Windows.Forms.TabPage tabPage3;
private System.Windows.Forms.Button cmdAddOffline;
private System.Windows.Forms.DataGridView dgvofflinePw;
private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn1;
private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn2;
private System.Windows.Forms.TabPage tabPage4;
private System.Windows.Forms.Button btnLocalDefaultLocal;
private System.Windows.Forms.Label lblLocalPath;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Button btnLocalSearch;
private System.Windows.Forms.Button btnLocalDefaultLan;
private System.Windows.Forms.Label lblLocalCurrentPath;
private System.Windows.Forms.Label lblGlobalCurrentPath;
private System.Windows.Forms.Button btnGlobalSearch;
private System.Windows.Forms.Button btnGlobalDefaultLan;
private System.Windows.Forms.Button btnGlobalDefaultLocal;
private System.Windows.Forms.Label label6;
private System.Windows.Forms.TabPage tabPage5;
private System.Windows.Forms.Label lblSirtComport868MHz;
private System.Windows.Forms.Label lblSirtComport433MHz;
private System.Windows.Forms.Label lblSirtBoxNo;
private System.Windows.Forms.Label lblSirtStation;
private System.Windows.Forms.TextBox tbxSirtBoxNo;
private System.Windows.Forms.TextBox tbxSirtStationId;
private System.Windows.Forms.ComboBox cbxSirtComport868MHz;
private System.Windows.Forms.ComboBox cbxSirtComport433MHz;
private System.Windows.Forms.ComboBox cbxSirtService868MHz;
private System.Windows.Forms.ComboBox cbxSirtService433MHz;
private System.Windows.Forms.Label label5;
private System.Windows.Forms.Label label7;
}
}
@@ -0,0 +1,861 @@
using Newtonsoft.Json;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Threading;
using System.Windows.Forms;
using System.Xml.Linq;
using Xylem.Common.CommonCore.Consts;
using Xylem.Common.Hardware.Interfaces.Ports.PortCore;
using Xylem.Common.Hardware.Interfaces.Ports.PortCore.EventArguments;
using Xylem.Common.Hardware.Interfaces.Ports.SerialPorts;
using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore;
using Xylem.Common.Hardware.WaterMeter.WaterMeterCore;
using Xylem.Common.Utils.Logging;
using GenesisCordonelInterface.API;
using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisConfig;
namespace GenesisCordonelInterface.UI.LaatzenAPI_GenesisToolBox
{
/// <summary>
/// Setup of GTB
/// </summary>
public partial class FrmSetup : Form
{
private static readonly NLog.ILogger Logger = NLog.LogManager.GetLogger("GenesisCordonelInterface");
private readonly InterfaceGCIToLaatzen interfaceToLaatzen = new InterfaceGCIToLaatzen();
private const String RequestPortString = "RequestPort";
private const String RequestTypeString = "RequestType";
private const String StreamingPortString = "StreamingPort";
private const String SlotTypeString = "RefTemperature";
private const String SlotString = "Slot";
private const String StreamingDetectString = "DetectStreaming";
private const String RequestDetectString = "DetectRequest";
private const String ValueString = "Value";
private const String TextString = "Text";
private String _fileString;
private readonly String _serialConfigFilePathName;
private readonly String _offlinePwdPathName;
private readonly DataTable _slotConfigDataTable = new DataTable();
private readonly SirtConfig _sirtConfig = new SirtConfig();
private readonly ProcessConfig _configuration = new ProcessConfig();
private ConcurrentBag<String> _countRawData = new ConcurrentBag<String>();
private List<OfflinePasswordItem> _listOfOfflinePasswords = new List<OfflinePasswordItem>();
/// <summary>
/// Ctor
/// </summary>
public FrmSetup()
{
_serialConfigFilePathName = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
"Genesis",
ProgramConfig.SerialConfigFileName);
_offlinePwdPathName = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
"Genesis",
ProgramConfig.OfflineInfoFile);
if (!File.Exists(_offlinePwdPathName))
{
_listOfOfflinePasswords.Add(new OfflinePasswordItem("", ""));
File.WriteAllText(_offlinePwdPathName, JsonConvert.SerializeObject(_listOfOfflinePasswords));
}
_slotConfigDataTable.Columns.Add(SlotString, typeof(String));
_slotConfigDataTable.Columns.Add(StreamingPortString, typeof(String));
_slotConfigDataTable.Columns.Add(RequestPortString, typeof(String));
_slotConfigDataTable.Columns.Add(RequestTypeString, typeof(String));
_slotConfigDataTable.Columns.Add(SlotTypeString, typeof(String));
InitializeComponent();
tbcSlot.Name = SlotString;
cbcRequestPort.Name = RequestPortString;
cbcRequestType.Name = RequestTypeString;
cbcStreamingPort.Name = StreamingPortString;
cbcSlotType.Name = SlotTypeString;
btcDetectStreaming.Name = StreamingDetectString;
btcDetectRequest.Name = RequestDetectString;
btcDetectStreaming.Name = StreamingDetectString;
tbcSlot.HeaderText = SlotString;
cbcRequestPort.HeaderText = RequestPortString;
cbcRequestType.HeaderText = RequestTypeString;
cbcStreamingPort.HeaderText = StreamingPortString;
btcDetectRequest.HeaderText = RequestDetectString;
btcDetectStreaming.HeaderText = StreamingDetectString;
cbcSlotType.HeaderText = SlotTypeString;
LoadFromFile();
_configuration.ReadProcessConfig();
cbUseMinMaxCheck.Checked = _configuration.UseMinMaxCheck;
cbUseRegisterWatch.Checked = _configuration.UseRegisterWatchService;
txtWachSeriveUrl.Text = _configuration.RegisterWatchServiceUrl;
cbUpdateFiles.Checked = _configuration.AutoUpdateFiles;
cbxProductionMode.Checked = _configuration.ProductionMode;
_sirtConfig.ReadSirtConfig();
tbxSirtStationId.Text = _sirtConfig.StationId?.ToString();
tbxSirtBoxNo.Text = _sirtConfig.SirtBoxNo?.ToString();
if (_sirtConfig.SirtComport433MHz != null)
cbxSirtComport433MHz.Items.Add(_sirtConfig.SirtComport433MHz);
if (_sirtConfig.SirtComport868MHz != null)
cbxSirtComport868MHz.Items.Add(_sirtConfig.SirtComport868MHz);
var comPorts = SerialPort.GetPortNames().ToList();
foreach (var comPort in comPorts.Where(comPort => !cbxSirtComport433MHz.Items.Contains(comPort)))
{
cbxSirtComport433MHz.Items.Add(comPort);
}
foreach (var comPort in comPorts.Where(comPort => !cbxSirtComport868MHz.Items.Contains(comPort)))
{
cbxSirtComport868MHz.Items.Add(comPort);
}
if (cbxSirtComport433MHz.Items.Count > 0)
cbxSirtComport433MHz.Text = cbxSirtComport433MHz.Items[0].ToString();
if (cbxSirtComport868MHz.Items.Count > 0)
cbxSirtComport868MHz.Text = cbxSirtComport868MHz.Items[0].ToString();
if (_sirtConfig.ServiceSirtComport433MHz != null)
cbxSirtService433MHz.Items.Add(_sirtConfig.ServiceSirtComport433MHz);
if (_sirtConfig.ServiceSirtComport868MHz != null)
cbxSirtService868MHz.Items.Add(_sirtConfig.ServiceSirtComport868MHz);
foreach (var comPort in comPorts.Where(comPort => !cbxSirtService433MHz.Items.Contains(comPort)))
{
cbxSirtService433MHz.Items.Add(comPort);
}
foreach (var comPort in comPorts.Where(comPort => !cbxSirtService868MHz.Items.Contains(comPort)))
{
cbxSirtService868MHz.Items.Add(comPort);
}
if (cbxSirtService433MHz.Items.Count > 0)
cbxSirtService433MHz.Text = cbxSirtService433MHz.Items[0].ToString();
if (cbxSirtService868MHz.Items.Count > 0)
cbxSirtService868MHz.Text = cbxSirtService868MHz.Items[0].ToString();
Logger.Trace("CONFIG: Setup loaded.");
}
private void BtnReload_Click(Object sender, EventArgs e)
{
Logger.Trace("CONFIG: Reload setup requested.");
LoadFromFile();
LoadOfflineFile();
Logger.Trace("CONFIG: Setup reloaded.");
}
private void BtnStore_Click(Object sender, EventArgs e)
{
Logger.Trace("CONFIG: Save setup requested.");
StoreToPc();
StoreOfflineFile();
StoreSirtSettings();
Logger.Trace("CONFIG: Setup saved.");
}
private void StoreSirtSettings()
{
if (int.TryParse(tbxSirtStationId.Text, out var intNo))
{
_sirtConfig.StationId = intNo;
}
if (int.TryParse(tbxSirtBoxNo.Text, out intNo))
{
_sirtConfig.SirtBoxNo = intNo;
}
_sirtConfig.SirtComport433MHz = cbxSirtComport433MHz.Text;
_sirtConfig.SirtComport868MHz = cbxSirtComport868MHz.Text;
_sirtConfig.ServiceSirtComport433MHz = cbxSirtService433MHz.Text;
_sirtConfig.ServiceSirtComport868MHz = cbxSirtService868MHz.Text;
_sirtConfig.Update();
Logger.Trace("CONFIG: SIRT settings stored.");
}
private void StoreToPc()
{
Logger.Trace("CONFIG: Storing slot configuration to PC.");
var newFileContent = new List<SlotConfig>();
for (var row = 0; row < dgvConfig.Rows.Count; row++)
{
var slotStr = (String)dgvConfig.Rows[row].Cells[SlotString].Value;
int.TryParse(slotStr, out var slot);
var irdaType = typeof(IrdaSerialPort).FullName;
if (dgvConfig.Rows[row].Cells[RequestTypeString].Value != null)
{
irdaType = (String)dgvConfig.Rows[row].Cells[RequestTypeString].Value;
}
var requestPort = new PortConfig()
{
PortName = (String)dgvConfig.Rows[row].Cells[RequestPortString].Value,
Type = irdaType
};
var streamingPort = new PortConfig()
{
PortName = (String)dgvConfig.Rows[row].Cells[StreamingPortString].Value,
Type = typeof(UartSerialPort).FullName
};
var slotType = SlotType.DutMeter;
if (dgvConfig.Rows[row].Cells[SlotTypeString].Value != null)
{
var isChecked = dgvConfig.Rows[row].Cells[SlotTypeString].Value.ToString();
if (bool.TrueString == isChecked)
{
slotType = SlotType.TemperatureMeter;
}
}
if (!string.IsNullOrEmpty(slotStr))
{
newFileContent.Add(new SlotConfig()
{
Slot = slot,
Request = requestPort,
Streaming = streamingPort,
Type = slotType
});
}
}
var text = JsonConvert.SerializeObject(newFileContent);
if (text == _fileString)
{
Logger.Trace("CONFIG: No setup changes detected.");
LoadFromFile();
return;
}
if (File.Exists(_serialConfigFilePathName))
{
var backupSerialConfigFile =
$"{Path.GetDirectoryName(_serialConfigFilePathName)}\\Backup_{DateTime.Now:yyyyMMdd}_{DateTime.Now:HHmmss}_{ProgramConfig.SerialConfigFileName}";
File.Move(_serialConfigFilePathName, backupSerialConfigFile);
}
File.WriteAllText(_serialConfigFilePathName, text);
LoadFromFile();
LoadOfflineFile();
Logger.Trace("CONFIG: Slot configuration stored.");
}
private void LoadFromFile()
{
Logger.Trace("CONFIG: Loading slot configuration from file.");
_slotConfigDataTable.Clear();
dgvConfig.Rows.Clear();
if (!File.Exists(_serialConfigFilePathName))
{
Logger.Trace("CONFIG: Serial configuration file not found.");
return;
}
SlotConfig[] meterConfigList;
using (var tr = new StreamReader(_serialConfigFilePathName))
{
_fileString = tr.ReadToEnd();
meterConfigList = JsonConvert.DeserializeObject<SlotConfig[]>(_fileString);
}
foreach (var item in meterConfigList)
{
var row = _slotConfigDataTable.NewRow();
row[SlotString] = item.Slot;
row[RequestPortString] = item.Request.PortName;
row[RequestTypeString] = item.Request.Type;
row[StreamingPortString] = item.Streaming.PortName;
row[SlotTypeString] = item.Type == SlotType.TemperatureMeter;
_slotConfigDataTable.Rows.Add(row);
}
foreach (DataRow row in _slotConfigDataTable.Rows)
{
dgvConfig.Rows.Add(AddRowToGrid(row));
}
Logger.Trace("CONFIG: Slot configuration loaded.");
}
private DataGridViewRow AddRowToGrid(DataRow row = null)
{
var newRow = new DataGridViewRow();
var slotCell = new DataGridViewTextBoxCell();
newRow.Cells.Add(slotCell);
var requestPortCell = new DataGridViewComboBoxCell
{
DataSource = GetPorts(),
DisplayMember = TextString,
ValueMember = ValueString
};
newRow.Cells.Add(requestPortCell);
var requestTypeCell = new DataGridViewComboBoxCell
{
DataSource = GetTypes(),
DisplayMember = TextString,
ValueMember = ValueString
};
newRow.Cells.Add(requestTypeCell);
var streamingPortCell = new DataGridViewComboBoxCell
{
DataSource = GetPorts(),
DisplayMember = TextString,
ValueMember = ValueString
};
newRow.Cells.Add(streamingPortCell);
var slotTypeCell = new DataGridViewCheckBoxCell();
slotTypeCell.Value = false;
if (row == null)
{
return newRow;
}
slotCell.Value = row[SlotString];
streamingPortCell.Value = row[StreamingPortString];
requestPortCell.Value = row[RequestPortString];
try
{
requestTypeCell.Value = row[RequestTypeString];
}
catch (Exception ex)
{
Logger.Error("Failed to set request type in grid: " + ex.Message);
}
slotTypeCell.Value = row[SlotTypeString];
newRow.Cells.Add(slotTypeCell);
return newRow;
}
private DataTable GetSlotTypes()
{
var ret = new DataTable();
ret.Columns.Add(TextString);
ret.Columns.Add(ValueString, typeof(Int32));
ret.Rows.Add("DutMeter", SlotType.DutMeter.GetHashCode());
ret.Rows.Add("TemperatureMeter", SlotType.TemperatureMeter.GetHashCode());
return ret;
}
private DataTable GetPorts()
{
var ret = new DataTable();
ret.Columns.Add(ValueString);
ret.Columns.Add(TextString);
var portList = SerialPort.GetPortNames().ToList();
foreach (var item in portList)
{
ret.Rows.Add(item, item);
}
foreach (DataRow row in _slotConfigDataTable.Rows)
{
if (portList.All(pl => pl != (String)row[StreamingPortString]))
{
ret.Rows.Add(row[StreamingPortString].ToString(), BaseSerialPort.PortNotAssigned);
}
if (portList.All(pl => pl != (String)row[RequestPortString]))
{
ret.Rows.Add(row[RequestPortString].ToString(), BaseSerialPort.PortNotAssigned);
}
}
return ret;
}
private static DataTable GetTypes()
{
var ret = new DataTable();
ret.Columns.Add(ValueString);
ret.Columns.Add(TextString);
ret.Rows.Add(typeof(UartSerialPort).FullName, nameof(UartSerialPort));
ret.Rows.Add(typeof(RfidSerialPort).FullName, nameof(RfidSerialPort));
ret.Rows.Add(typeof(IrdaSerialPort).FullName, nameof(IrdaSerialPort));
return ret;
}
private void __DgvConfig_CellContentClick(Object sender, DataGridViewCellEventArgs e)
{
Logger.Trace("UI-CLICK: FrmSetup: DgvConfig_CellContentClick() use APILaatzen");
if (e.RowIndex < 0 || e.ColumnIndex < 0)
{
return;
}
if (!dgvConfig.Columns[e.ColumnIndex].Name.Contains(StreamingDetectString) &&
!dgvConfig.Columns[e.ColumnIndex].Name.Contains(RequestDetectString))
{
return;
}
StoreToPc();
var slotString = (String)dgvConfig.Rows[e.RowIndex].Cells[SlotString].Value;
int.TryParse(slotString, out var slot);
using (var mb = new MeterBatch())
{
using (var meter = new GenesisMeter())
{
meter.SetupFromConfigFile(slot, false);
mb.AddMeter(meter);
const String checkMark = "\u2714";
if (dgvConfig.Columns[e.ColumnIndex].Name.Contains(StreamingDetectString))
{
Logger.Trace("COM: Detecting streaming port for slot " + slot + "...");
_countRawData = new ConcurrentBag<String>();
meter.StreamingPort.OnRawRecordReceived += delegate (Object o, BasePortDataEventArgs rawMsg)
{
var data = (String)rawMsg.GetData();
_countRawData.Add(data);
};
Thread.Sleep(500);
if (_countRawData.Any())
{
var text = $"SUCCESS\nSlot: {slot}\nStreaming port: {meter.StreamingPort.GetPortName()}\n\n{checkMark}";
MessageBox.Show(text, @"SUCCESS", MessageBoxButtons.OK);
dgvConfig.Rows[e.RowIndex].Cells[StreamingDetectString].Style.BackColor = Color.Green;
Logger.Info("COM: Streaming detection SUCCESS for slot " + slot + ", port " + meter.StreamingPort.GetPortName() + ".");
}
else
{
var text = $"FAILED\nSlot: {slot}\nStreaming port: {meter.StreamingPort.GetPortName()}";
MessageBox.Show(text, @"FAILED", MessageBoxButtons.OK, MessageBoxIcon.Error);
dgvConfig.Rows[e.RowIndex].Cells[StreamingDetectString].Style.BackColor = Color.Red;
Logger.Error("COM: Streaming detection FAILED for slot " + slot + ", port " + meter.StreamingPort.GetPortName() + ".");
}
_countRawData = new ConcurrentBag<String>();
}
else
{
meter.Logout();
var pcbId = meter.GetPcbId();
if (string.IsNullOrEmpty(pcbId))
{
var text = $"FAILED\nSlot: {slot}\nRequest port: {meter.RequestPort.GetPortName()}";
MessageBox.Show(text, @"FAILED", MessageBoxButtons.OK, MessageBoxIcon.Error);
dgvConfig.Rows[e.RowIndex].Cells[RequestDetectString].Style.BackColor = Color.Red;
Logger.Info("COM: Streaming detection SUCCESS for slot " + slot + ", port " + meter.StreamingPort.GetPortName() + ".");
}
else
{
var text = $"SUCCESS\nSlot: {slot}\nRequest port: {meter.RequestPort.GetPortName()}\n\n{checkMark}";
MessageBox.Show(text, @"SUCCESS", MessageBoxButtons.OK);
dgvConfig.Rows[e.RowIndex].Cells[RequestDetectString].Style.BackColor = Color.Green;
Logger.Error("COM: Streaming detection FAILED for slot " + slot + ", port " + meter.StreamingPort.GetPortName() + ".");
}
}
}
}
}
private void DgvConfig_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
Logger.Trace("UI-CLICK: FrmSetup: DgvConfig_CellContentClick() use API2");
if (e.RowIndex < 0 || e.ColumnIndex < 0)
return;
var columnName = dgvConfig.Columns[e.ColumnIndex].Name;
if (!columnName.Contains(StreamingDetectString) &&
!columnName.Contains(RequestDetectString))
{
return;
}
StoreToPc();
var slotString = (string)dgvConfig.Rows[e.RowIndex].Cells[SlotString].Value;
if (!int.TryParse(slotString, out var slot))
return;
const string checkMark = "\u2714";
try
{
if (columnName.Contains(StreamingDetectString))
{
Logger.Trace("COM: Detecting streaming port for slot " + slot + "...");
var result = interfaceToLaatzen.DetectStreamingPort(slot);
if (result.Success)
{
var text = $"SUCCESS\nSlot: {result.Slot}\nStreaming port: {result.PortName}\n\n{checkMark}";
MessageBox.Show(text, @"SUCCESS", MessageBoxButtons.OK);
dgvConfig.Rows[e.RowIndex].Cells[StreamingDetectString].Style.BackColor = Color.Green;
Logger.Info("COM: Streaming detection SUCCESS for slot " + result.Slot + ", port " + result.PortName + ".");
}
else
{
var text = $"FAILED\nSlot: {result.Slot}\nStreaming port: {result.PortName}";
MessageBox.Show(text, @"FAILED", MessageBoxButtons.OK, MessageBoxIcon.Error);
dgvConfig.Rows[e.RowIndex].Cells[StreamingDetectString].Style.BackColor = Color.Red;
Logger.Error("COM: Streaming detection FAILED for slot " + result.Slot + ", port " + result.PortName + ".");
}
}
else
{
var result = interfaceToLaatzen.DetectRequestPort(slot);
if (result.Success)
{
var text = $"SUCCESS\nSlot: {result.Slot}\nRequest port: {result.PortName}\n\n{checkMark}";
MessageBox.Show(text, @"SUCCESS", MessageBoxButtons.OK);
dgvConfig.Rows[e.RowIndex].Cells[RequestDetectString].Style.BackColor = Color.Green;
Logger.Info("COM: Request detection SUCCESS for slot " + result.Slot + ", port " + result.PortName + ".");
}
else
{
var text = $"FAILED\nSlot: {result.Slot}\nRequest port: {result.PortName}";
MessageBox.Show(text, @"FAILED", MessageBoxButtons.OK, MessageBoxIcon.Error);
dgvConfig.Rows[e.RowIndex].Cells[RequestDetectString].Style.BackColor = Color.Red;
Logger.Error("COM: Request detection FAILED for slot " + result.Slot + ", port " + result.PortName + ".");
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, @"ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
Logger.Error(ex);
}
}
private void dgvConfig_DataError(Object sender, DataGridViewDataErrorEventArgs e)
{
Logger.Error("CONFIG: DataGridView data error.");
}
private void cbUseRegisterWatch_CheckedChanged(Object sender, EventArgs e)
{
_configuration.UseRegisterWatchService = cbUseRegisterWatch.Checked;
_configuration.Update();
StoreToPc();
Logger.Trace("UseRegisterWatchService changed to " + cbUseRegisterWatch.Checked);
}
private void cbUseMinMaxCheck_CheckedChanged(Object sender, EventArgs e)
{
_configuration.UseMinMaxCheck = cbUseMinMaxCheck.Checked;
_configuration.Update();
StoreToPc();
Logger.Trace("UseMinMaxCheck changed to " + cbUseMinMaxCheck.Checked);
}
private void textBox1_TextChanged(Object sender, EventArgs e)
{
_configuration.RegisterWatchServiceUrl = txtWachSeriveUrl.Text;
_configuration.Update();
StoreToPc();
Logger.Trace("RegisterWatchServiceUrl changed.");
}
private void cbUpdateFiles_CheckedChanged(Object sender, EventArgs e)
{
_configuration.AutoUpdateFiles = cbUpdateFiles.Checked;
_configuration.Update();
StoreToPc();
Logger.Trace("CONFIG: AutoUpdateFiles changed to " + cbUpdateFiles.Checked);
}
private void FrmSetup_Load(Object sender, EventArgs e)
{
LoadOfflineFile();
cbxProductionMode.CheckedChanged += cbxProductionMode_CheckedChanged;
Logger.Trace("FORM: FrmSetup loaded.");
}
private void StoreOfflineFile()
{
try
{
var listToRemove = _listOfOfflinePasswords.Where(offlinePwd => string.IsNullOrEmpty(offlinePwd.PcbID)).ToList();
foreach (var itemToRemove in listToRemove)
{
_listOfOfflinePasswords.Remove(itemToRemove);
}
_listOfOfflinePasswords.Add(new OfflinePasswordItem("", ""));
File.WriteAllText(_offlinePwdPathName, JsonConvert.SerializeObject(_listOfOfflinePasswords));
dgvofflinePw.CellValidated -= dgvofflinePw_CellValidated;
dgvofflinePw.DataSource = null;
dgvofflinePw.DataSource = _listOfOfflinePasswords;
dgvofflinePw.CellValidated += dgvofflinePw_CellValidated;
Logger.Trace("CONFIG: Offline password file stored.");
}
catch (Exception ex)
{
Logger.Error("CONFIG: Failed to store offline password file: " + ex.Message);
}
}
private void LoadOfflineFile()
{
try
{
_listOfOfflinePasswords = JsonConvert.DeserializeObject<List<OfflinePasswordItem>>(File.ReadAllText(_offlinePwdPathName));
}
catch (Exception ex)
{
_listOfOfflinePasswords = new List<OfflinePasswordItem>();
Logger.Error("CONFIG: Failed to load offline password file. New empty list created. " + ex.Message);
}
finally
{
if (!_listOfOfflinePasswords.Any())
{
_listOfOfflinePasswords.Add(new OfflinePasswordItem("", ""));
}
dgvofflinePw.CellValidated -= dgvofflinePw_CellValidated;
dgvofflinePw.DataSource = null;
dgvofflinePw.DataSource = _listOfOfflinePasswords;
dgvofflinePw.CellValidated += dgvofflinePw_CellValidated;
Logger.Trace("CONFIG: Offline password file loaded.");
}
}
private void dgvofflinePw_CellValidated(Object sender, DataGridViewCellEventArgs e)
{
StoreOfflineFile();
}
private void cmdAddOffline_Click(Object sender, EventArgs e)
{
_listOfOfflinePasswords.Add(new OfflinePasswordItem("", ""));
dgvofflinePw.DataSource = null;
dgvofflinePw.DataSource = _listOfOfflinePasswords;
Logger.Trace("TABLE: Offline password row added.");
}
private void cbxProductionMode_CheckedChanged(Object sender, EventArgs e)
{
if (cbxProductionMode.Checked)
{
MessageBox.Show(@"Production mode! Configuration.json has to be the latest! ");
}
else
{
MessageBox.Show("Developer mode! Configuration.json can be exchanged on individual requirements.\n" +
"\nRISK:\n" +
"- Register ranges cannot be checked\n" +
"- Register may not be able to access");
}
_configuration.ProductionMode = cbxProductionMode.Checked;
_configuration.Update();
StoreToPc();
Logger.Trace("CHECKBOX: ProductionMode changed to " + cbxProductionMode.Checked);
}
private void tabPage4_Click(Object sender, EventArgs e)
{
Logger.Trace("TABPAGE4: Logging tab opened.");
try
{
var path = NLogHelper.GetCurrentApplicationFolder();
var a = XElement.Load(path);
lblLocalCurrentPath.Text = a.Elements()
.First(s => s.Name.LocalName == "variable")
.Attributes()
.First(s => s.Value == "BasePath")
.NextAttribute.Value;
}
catch (Exception ex)
{
lblLocalCurrentPath.Text = ex.Message;
Logger.Error("TABPAGE4: Failed to read local NLog path: " + ex.Message);
}
try
{
var path = NLogHelper.GetApplicationDataPath();
var b = XElement.Load(path);
lblGlobalCurrentPath.Text = b.Elements()
.First(s => s.Name.LocalName == "variable")
.Attributes()
.First(s => s.Value == "BasePath")
.NextAttribute.Value;
}
catch (Exception ex)
{
lblGlobalCurrentPath.Text = ex.Message;
Logger.Error("TABPAGE4: Failed to read global NLog path: " + ex.Message);
}
}
private void Add(String path, String newDest)
{
try
{
var a = XElement.Load(path);
var firstIsVariable = a.Elements().First();
if (firstIsVariable.Name.LocalName != "variable")
{
var newElm = new XElement("variable", null);
newElm.SetAttributeValue("name", "BasePath");
newElm.SetAttributeValue("value", newDest);
a.AddFirst(newElm);
}
else if (a.Elements().First(b => b.Name.LocalName == "variable").Attributes()
.All(s => s.Value != "BasePath"))
{
var newElm = new XElement("variable", null);
newElm.SetAttributeValue("name", "BasePath");
newElm.SetAttributeValue("value", newDest);
a.AddFirst(newElm);
}
else
{
a.Elements().First(b => b.Name.LocalName == "variable").Attributes()
.First(s => s.Value == "BasePath").NextAttribute.Value = newDest;
}
a.Save(path);
tabPage4_Click(this, null);
Logger.Trace("Log path updated to: " + newDest);
}
catch (Exception ex)
{
Logger.Trace("Failed to update log path: " + ex.Message);
}
}
private void btnLocalDefaultLocal_Click(Object sender, EventArgs e)
{
Add(NLogHelper.GetCurrentApplicationFolder(), "C:\\GenesisLog\\");
Logger.Trace("Local log path set to default local.");
}
private void btnLocalDefaultLan_Click(Object sender, EventArgs e)
{
Add(NLogHelper.GetCurrentApplicationFolder(), "\\\\sla12buma\\cordonelds$\\${machinename}");
Logger.Trace("Local log path set to default LAN.");
}
private void btnGlobalDefaultLocal_Click(Object sender, EventArgs e)
{
Add(NLogHelper.GetApplicationDataPath(), "C:\\GenesisLog\\");
Logger.Trace("Global log path set to default local.");
}
private void btnGlobalDefaultLan_Click(Object sender, EventArgs e)
{
Add(NLogHelper.GetApplicationDataPath(), "\\\\sla12buma\\cordonelds$\\${{machinename}}");
Logger.Trace("Global log path set to default LAN.");
}
private void btnGlobalSearch_Click(Object sender, EventArgs e)
{
var dia = new FolderBrowserDialog();
dia.ShowDialog();
Add(NLogHelper.GetApplicationDataPath(), dia.SelectedPath);
Logger.Trace("Global log path selected by search dialog.");
}
private void btnLocalSearch_Click(Object sender, EventArgs e)
{
var dia = new FolderBrowserDialog();
dia.ShowDialog();
Add(NLogHelper.GetCurrentApplicationFolder(), dia.SelectedPath);
Logger.Trace("Local log path selected by search dialog.");
}
private void btnAddRow_Click(Object sender, EventArgs e)
{
dgvConfig.Rows.Add(AddRowToGrid());
Logger.Trace("TABLE: New slot row added.");
}
public class OfflinePasswordItem
{
public OfflinePasswordItem()
{
}
public OfflinePasswordItem(String pcbID, String password)
{
PcbID = pcbID;
Password = password;
}
public String PcbID { get; set; }
public String Password { get; set; }
}
}
}
+166
View File
@@ -0,0 +1,166 @@
namespace GenesisCordonelInterface.UI
{
partial class MainForm
{
private System.ComponentModel.IContainer components = null;
private System.Windows.Forms.MenuStrip menuStrip1;
private System.Windows.Forms.ToolStripMenuItem miFile;
private System.Windows.Forms.ToolStripMenuItem miExit;
private System.Windows.Forms.ToolStripMenuItem miView;
private System.Windows.Forms.ToolStripMenuItem miClearLog;
private System.Windows.Forms.ToolStripMenuItem miHelp;
private System.Windows.Forms.ToolStripMenuItem miHelpAbout;
private System.Windows.Forms.Panel mainHostPanel;
private System.Windows.Forms.StatusStrip statusStrip1;
private System.Windows.Forms.ToolStripStatusLabel tslStatus;
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
components.Dispose();
base.Dispose(disposing);
}
private void InitializeComponent()
{
this.menuStrip1 = new System.Windows.Forms.MenuStrip();
this.miFile = new System.Windows.Forms.ToolStripMenuItem();
this.miExit = new System.Windows.Forms.ToolStripMenuItem();
this.miView = new System.Windows.Forms.ToolStripMenuItem();
this.miClearLog = new System.Windows.Forms.ToolStripMenuItem();
this.miHelp = new System.Windows.Forms.ToolStripMenuItem();
this.miHelpAbout = new System.Windows.Forms.ToolStripMenuItem();
this.mainHostPanel = new System.Windows.Forms.Panel();
this.statusStrip1 = new System.Windows.Forms.StatusStrip();
this.tslStatus = new System.Windows.Forms.ToolStripStatusLabel();
this.menuStrip1.SuspendLayout();
this.statusStrip1.SuspendLayout();
this.SuspendLayout();
//
// menuStrip1
//
this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.miFile,
this.miView,
this.miHelp
});
this.menuStrip1.Location = new System.Drawing.Point(0, 0);
this.menuStrip1.Name = "menuStrip1";
this.menuStrip1.Padding = new System.Windows.Forms.Padding(5, 2, 0, 2);
this.menuStrip1.Size = new System.Drawing.Size(1309, 24);
this.menuStrip1.TabIndex = 0;
this.menuStrip1.Text = "menuStrip1";
//
// miFile
//
this.miFile.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.miExit
});
this.miFile.Name = "miFile";
this.miFile.Size = new System.Drawing.Size(37, 20);
this.miFile.Text = "FileConfig";
//
// miExit
//
this.miExit.Name = "miExit";
this.miExit.Size = new System.Drawing.Size(92, 22);
this.miExit.Text = "Exit";
this.miExit.Click += new System.EventHandler(this.miExit_Click);
//
// miView
//
this.miView.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.miClearLog
});
this.miView.Name = "miView";
this.miView.Size = new System.Drawing.Size(44, 20);
this.miView.Text = "View";
//
// miClearLog
//
this.miClearLog.Name = "miClearLog";
this.miClearLog.Size = new System.Drawing.Size(124, 22);
this.miClearLog.Text = "Clear Log";
this.miClearLog.Click += new System.EventHandler(this.miClearLog_Click);
//
// miHelp
//
this.miHelp.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.miHelpAbout
});
this.miHelp.Name = "miHelp";
this.miHelp.Size = new System.Drawing.Size(44, 20);
this.miHelp.Text = "Help";
//
// miHelpAbout
//
this.miHelpAbout.Name = "miHelpAbout";
this.miHelpAbout.Size = new System.Drawing.Size(107, 22);
this.miHelpAbout.Text = "About";
this.miHelpAbout.Click += new System.EventHandler(this.miHelpAbout_Click);
//
// mainHostPanel
//
this.mainHostPanel.Dock = System.Windows.Forms.DockStyle.Fill;
this.mainHostPanel.Location = new System.Drawing.Point(0, 24);
this.mainHostPanel.Name = "mainHostPanel";
this.mainHostPanel.Padding = new System.Windows.Forms.Padding(0);
this.mainHostPanel.Size = new System.Drawing.Size(1309, 474);
this.mainHostPanel.TabIndex = 1;
//
// statusStrip1
//
this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.tslStatus
});
this.statusStrip1.Location = new System.Drawing.Point(0, 498);
this.statusStrip1.Name = "statusStrip1";
this.statusStrip1.Padding = new System.Windows.Forms.Padding(1, 0, 12, 0);
this.statusStrip1.Size = new System.Drawing.Size(1309, 22);
this.statusStrip1.TabIndex = 2;
this.statusStrip1.Text = "statusStrip1";
//
// tslStatus
//
this.tslStatus.Name = "tslStatus";
this.tslStatus.Size = new System.Drawing.Size(39, 17);
this.tslStatus.Text = "Ready";
//
// MainForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(1309, 520);
this.Controls.Add(this.mainHostPanel);
this.Controls.Add(this.statusStrip1);
this.Controls.Add(this.menuStrip1);
this.MainMenuStrip = this.menuStrip1;
this.MinimumSize = new System.Drawing.Size(774, 439);
this.Name = "MainForm";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "Genesis Cordonel Interface";
this.Load += new System.EventHandler(this.MainForm_Load);
this.menuStrip1.ResumeLayout(false);
this.menuStrip1.PerformLayout();
this.statusStrip1.ResumeLayout(false);
this.statusStrip1.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
}
}
+51
View File
@@ -0,0 +1,51 @@
using System;
using System.Drawing;
using System.Windows.Forms;
namespace GenesisCordonelInterface.UI
{
public partial class MainForm : Form
{
private MainView mainView;
public MainForm()
{
InitializeComponent();
StartPosition = FormStartPosition.Manual;
Location = new Point(Screen.PrimaryScreen.WorkingArea.Width - Width, 0);
StartPosition = FormStartPosition.CenterScreen;
WindowState = FormWindowState.Maximized;
}
private void MainForm_Load(object sender, EventArgs e)
{
mainView = new MainView();
mainView.Dock = DockStyle.Fill;
Controls.Add(mainView);
mainView.BringToFront();
this.WindowState = FormWindowState.Maximized;
}
private void miExit_Click(object sender, EventArgs e)
{
Close();
}
private void miClearLog_Click(object sender, EventArgs e)
{
if (mainView != null)
mainView.ClearLog();
}
private void miHelpAbout_Click(object sender, EventArgs e)
{
MessageBox.Show(
"Genesis Cordonel Tester",
"About",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
}
}
}
+129
View File
@@ -0,0 +1,129 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="menuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="statusStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>132, 17</value>
</metadata>
<metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>65</value>
</metadata>
</root>
+310
View File
@@ -0,0 +1,310 @@
namespace GenesisCordonelInterface.UI
{
partial class MainView
{
private System.ComponentModel.IContainer components = null;
private System.Windows.Forms.Panel pnlLeftMenu;
private System.Windows.Forms.Panel pnlMain;
private System.Windows.Forms.SplitContainer splitMain;
private System.Windows.Forms.SplitContainer splitBottom;
private System.Windows.Forms.RichTextBox rtbMainLog;
private System.Windows.Forms.Panel pnlSlotConfig;
private System.Windows.Forms.Panel pnlWorkerDebug;
private System.Windows.Forms.TabControl tabControl1;
private System.Windows.Forms.TabPage tabPage1;
private System.Windows.Forms.TabPage tabPage2;
private System.Windows.Forms.GroupBox groupBox1;
private System.Windows.Forms.GroupBox groupBox2;
private System.Windows.Forms.GroupBox groupBox3;
private System.Windows.Forms.Button btnSetup;
private System.Windows.Forms.Button btnRegisterStore;
private System.Windows.Forms.Button btnPulseSetup;
private System.Windows.Forms.Button preadjustmentButton;
private System.Windows.Forms.Button btnMeterInit;
private System.Windows.Forms.Button btnMetersAction;
private System.Windows.Forms.SplitContainer splitWorkArea;
private System.Windows.Forms.Panel pnlGciViewHost;
private void InitializeComponent()
{
this.pnlLeftMenu = new System.Windows.Forms.Panel();
this.tabControl1 = new System.Windows.Forms.TabControl();
this.tabPage1 = new System.Windows.Forms.TabPage();
this.groupBox2 = new System.Windows.Forms.GroupBox();
this.preadjustmentButton = new System.Windows.Forms.Button();
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.btnPulseSetup = new System.Windows.Forms.Button();
this.btnSetup = new System.Windows.Forms.Button();
this.btnRegisterStore = new System.Windows.Forms.Button();
this.tabPage2 = new System.Windows.Forms.TabPage();
this.groupBox3 = new System.Windows.Forms.GroupBox();
this.btnMeterInit = new System.Windows.Forms.Button();
this.btnMetersAction = new System.Windows.Forms.Button();
this.pnlMain = new System.Windows.Forms.Panel();
this.splitMain = new System.Windows.Forms.SplitContainer();
this.splitBottom = new System.Windows.Forms.SplitContainer();
this.rtbMainLog = new System.Windows.Forms.RichTextBox();
this.pnlSlotConfig = new System.Windows.Forms.Panel();
this.pnlWorkerDebug = new System.Windows.Forms.Panel();
this.splitWorkArea = new System.Windows.Forms.SplitContainer();
this.pnlGciViewHost = new System.Windows.Forms.Panel();
this.pnlLeftMenu.SuspendLayout();
this.tabControl1.SuspendLayout();
this.tabPage1.SuspendLayout();
this.groupBox2.SuspendLayout();
this.groupBox1.SuspendLayout();
this.tabPage2.SuspendLayout();
this.groupBox3.SuspendLayout();
this.pnlMain.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.splitMain)).BeginInit();
this.splitMain.Panel1.SuspendLayout();
this.splitMain.Panel2.SuspendLayout();
this.splitMain.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.splitBottom)).BeginInit();
this.splitBottom.Panel1.SuspendLayout();
this.splitBottom.Panel2.SuspendLayout();
this.splitBottom.SuspendLayout();
this.SuspendLayout();
// pnlLeftMenu
this.pnlLeftMenu.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.pnlLeftMenu.Controls.Add(this.tabControl1);
this.pnlLeftMenu.Dock = System.Windows.Forms.DockStyle.Left;
this.pnlLeftMenu.Location = new System.Drawing.Point(0, 0);
this.pnlLeftMenu.Name = "pnlLeftMenu";
this.pnlLeftMenu.Size = new System.Drawing.Size(190, 500);
this.pnlLeftMenu.TabIndex = 0;
// tabControl1
this.tabControl1.Controls.Add(this.tabPage1);
this.tabControl1.Controls.Add(this.tabPage2);
this.tabControl1.Dock = System.Windows.Forms.DockStyle.Fill;
this.tabControl1.Location = new System.Drawing.Point(0, 0);
this.tabControl1.Name = "tabControl1";
this.tabControl1.SelectedIndex = 0;
this.tabControl1.Size = new System.Drawing.Size(188, 498);
this.tabControl1.TabIndex = 0;
// tabPage1
this.tabPage1.Controls.Add(this.groupBox2);
this.tabPage1.Controls.Add(this.groupBox1);
this.tabPage1.Location = new System.Drawing.Point(4, 22);
this.tabPage1.Name = "tabPage1";
this.tabPage1.Padding = new System.Windows.Forms.Padding(3);
this.tabPage1.Size = new System.Drawing.Size(180, 472);
this.tabPage1.TabIndex = 0;
this.tabPage1.Text = "Laatzen API";
this.tabPage1.UseVisualStyleBackColor = true;
// groupBox1
this.groupBox1.Controls.Add(this.btnPulseSetup);
this.groupBox1.Controls.Add(this.btnSetup);
this.groupBox1.Controls.Add(this.btnRegisterStore);
this.groupBox1.Location = new System.Drawing.Point(6, 10);
this.groupBox1.Name = "groupBox1";
this.groupBox1.Size = new System.Drawing.Size(166, 150);
this.groupBox1.TabIndex = 0;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "GenesisToolBox";
// btnSetup
this.btnSetup.Location = new System.Drawing.Point(7, 20);
this.btnSetup.Name = "btnSetup";
this.btnSetup.Size = new System.Drawing.Size(150, 30);
this.btnSetup.TabIndex = 0;
this.btnSetup.Text = "Setup";
this.btnSetup.UseVisualStyleBackColor = true;
this.btnSetup.Click += new System.EventHandler(this.btnSetup_Click);
// btnRegisterStore
this.btnRegisterStore.Location = new System.Drawing.Point(7, 55);
this.btnRegisterStore.Name = "btnRegisterStore";
this.btnRegisterStore.Size = new System.Drawing.Size(150, 30);
this.btnRegisterStore.TabIndex = 1;
this.btnRegisterStore.Text = "Register Store";
this.btnRegisterStore.UseVisualStyleBackColor = true;
this.btnRegisterStore.Click += new System.EventHandler(this.btnRegisterStore_Click);
// btnPulseSetup
this.btnPulseSetup.Location = new System.Drawing.Point(7, 90);
this.btnPulseSetup.Name = "btnPulseSetup";
this.btnPulseSetup.Size = new System.Drawing.Size(150, 30);
this.btnPulseSetup.TabIndex = 2;
this.btnPulseSetup.Text = "Pulse Setup";
this.btnPulseSetup.UseVisualStyleBackColor = true;
this.btnPulseSetup.Click += new System.EventHandler(this.btnPulseSetup_Click);
// groupBox2
this.groupBox2.Controls.Add(this.preadjustmentButton);
this.groupBox2.Location = new System.Drawing.Point(6, 170);
this.groupBox2.Name = "groupBox2";
this.groupBox2.Size = new System.Drawing.Size(166, 70);
this.groupBox2.TabIndex = 1;
this.groupBox2.TabStop = false;
this.groupBox2.Text = "CordonelPreadjustmentUI";
// preadjustmentButton
this.preadjustmentButton.Location = new System.Drawing.Point(6, 20);
this.preadjustmentButton.Name = "preadjustmentButton";
this.preadjustmentButton.Size = new System.Drawing.Size(150, 30);
this.preadjustmentButton.TabIndex = 0;
this.preadjustmentButton.Text = "Preadjustment";
this.preadjustmentButton.UseVisualStyleBackColor = true;
this.preadjustmentButton.Click += new System.EventHandler(this.preadjustmentButton_Click);
// tabPage2
this.tabPage2.Controls.Add(this.groupBox3);
this.tabPage2.Location = new System.Drawing.Point(4, 22);
this.tabPage2.Name = "tabPage2";
this.tabPage2.Padding = new System.Windows.Forms.Padding(3);
this.tabPage2.Size = new System.Drawing.Size(180, 472);
this.tabPage2.TabIndex = 1;
this.tabPage2.Text = "GCI API";
this.tabPage2.UseVisualStyleBackColor = true;
// groupBox3
this.groupBox3.Controls.Add(this.btnMeterInit);
this.groupBox3.Controls.Add(this.btnMetersAction);
this.groupBox3.Size = new System.Drawing.Size(166, 105);
this.groupBox3.Location = new System.Drawing.Point(6, 10);
this.groupBox3.Name = "groupBox3";
this.groupBox3.TabIndex = 0;
this.groupBox3.TabStop = false;
this.groupBox3.Text = "GenesisCordonelInterface";
// btnMeterInit
this.btnMeterInit.Location = new System.Drawing.Point(6, 20);
this.btnMeterInit.Name = "btnMeterInit";
this.btnMeterInit.Size = new System.Drawing.Size(150, 30);
this.btnMeterInit.Text = "Meter Init";
this.btnMeterInit.UseVisualStyleBackColor = true;
// btnMetersAction
this.btnMetersAction.Location = new System.Drawing.Point(6, 58);
this.btnMetersAction.Name = "btnMetersAction";
this.btnMetersAction.Size = new System.Drawing.Size(150, 30);
this.btnMetersAction.Text = "Meters Action";
this.btnMetersAction.UseVisualStyleBackColor = true;
this.btnMetersAction.Click += new System.EventHandler(this.btnMetersAction_Click);
// pnlMain
this.pnlMain.Controls.Add(this.splitMain);
this.pnlMain.Dock = System.Windows.Forms.DockStyle.Fill;
this.pnlMain.Location = new System.Drawing.Point(190, 0);
this.pnlMain.Name = "pnlMain";
this.pnlMain.Padding = new System.Windows.Forms.Padding(5);
this.pnlMain.Size = new System.Drawing.Size(710, 500);
this.pnlMain.TabIndex = 1;
// splitMain
this.splitMain.Dock = System.Windows.Forms.DockStyle.Fill;
this.splitMain.Location = new System.Drawing.Point(5, 5);
this.splitMain.Name = "splitMain";
this.splitMain.Orientation = System.Windows.Forms.Orientation.Horizontal;
this.splitMain.Panel1.Controls.Add(this.splitWorkArea);
this.splitMain.Panel1MinSize = 100;
this.splitMain.Panel2.Controls.Add(this.splitBottom);
this.splitMain.Panel2MinSize = 100;
this.splitMain.Size = new System.Drawing.Size(700, 490);
this.splitMain.SplitterDistance = 320;
this.splitMain.SplitterWidth = 6;
this.splitMain.TabIndex = 0;
// rtbMainLog
this.rtbMainLog.Dock = System.Windows.Forms.DockStyle.Fill;
this.rtbMainLog.Font = new System.Drawing.Font("Consolas", 10F);
this.rtbMainLog.Name = "rtbMainLog";
this.rtbMainLog.ReadOnly = true;
this.rtbMainLog.Size = new System.Drawing.Size(700, 320);
this.rtbMainLog.TabIndex = 0;
this.rtbMainLog.Text = "";
// splitBottom
this.splitBottom.Dock = System.Windows.Forms.DockStyle.Fill;
this.splitBottom.Location = new System.Drawing.Point(0, 0);
this.splitBottom.Name = "splitBottom";
this.splitBottom.Orientation = System.Windows.Forms.Orientation.Vertical;
this.splitBottom.Panel1.Controls.Add(this.pnlSlotConfig);
this.splitBottom.Panel1MinSize = 250;
this.splitBottom.Panel2.Controls.Add(this.pnlWorkerDebug);
this.splitBottom.Panel2MinSize = 250;
this.splitBottom.Size = new System.Drawing.Size(700, 164);
this.splitBottom.SplitterDistance = 320;
this.splitBottom.SplitterWidth = 6;
this.splitBottom.TabIndex = 0;
// pnlSlotConfig
this.pnlSlotConfig.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.pnlSlotConfig.Dock = System.Windows.Forms.DockStyle.Fill;
this.pnlSlotConfig.Location = new System.Drawing.Point(0, 0);
this.pnlSlotConfig.Name = "pnlSlotConfig";
this.pnlSlotConfig.Size = new System.Drawing.Size(320, 164);
this.pnlSlotConfig.TabIndex = 0;
// pnlWorkerDebug
this.pnlWorkerDebug.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.pnlWorkerDebug.Dock = System.Windows.Forms.DockStyle.Fill;
this.pnlWorkerDebug.Location = new System.Drawing.Point(0, 0);
this.pnlWorkerDebug.Name = "pnlWorkerDebug";
this.pnlWorkerDebug.Size = new System.Drawing.Size(374, 164);
this.pnlWorkerDebug.TabIndex = 0;
// splitWorkArea
this.splitWorkArea.Dock = System.Windows.Forms.DockStyle.Fill;
this.splitWorkArea.Orientation = System.Windows.Forms.Orientation.Vertical;
this.splitWorkArea.Panel1MinSize = 25;
this.splitWorkArea.Panel2MinSize = 25;
this.splitWorkArea.SplitterWidth = 6;
// left = active GCI view
this.splitWorkArea.Panel1.Controls.Add(this.pnlGciViewHost);
// right = black memo/log
this.splitWorkArea.Panel2.Controls.Add(this.rtbMainLog);
// pnlGciViewHost
this.pnlGciViewHost.Dock = System.Windows.Forms.DockStyle.Fill;
this.pnlGciViewHost.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
// rtbMainLog
this.rtbMainLog.Dock = System.Windows.Forms.DockStyle.Fill;
// MainView
this.Controls.Add(this.pnlMain);
this.Controls.Add(this.pnlLeftMenu);
this.Name = "MainView";
this.Size = new System.Drawing.Size(900, 500);
this.pnlLeftMenu.ResumeLayout(false);
this.tabControl1.ResumeLayout(false);
this.tabPage1.ResumeLayout(false);
this.groupBox2.ResumeLayout(false);
this.groupBox1.ResumeLayout(false);
this.tabPage2.ResumeLayout(false);
this.groupBox3.ResumeLayout(false);
this.pnlMain.ResumeLayout(false);
this.splitMain.Panel1.ResumeLayout(false);
this.splitMain.Panel2.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.splitMain)).EndInit();
this.splitMain.ResumeLayout(false);
this.splitBottom.Panel1.ResumeLayout(false);
this.splitBottom.Panel2.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.splitBottom)).EndInit();
this.splitBottom.ResumeLayout(false);
this.ResumeLayout(false);
}
}
}
+326
View File
@@ -0,0 +1,326 @@
using GenesisCordonelInterface.UI.LaatzenAPI_CordonelPreadjustmentUI;
using GenesisCordonelInterface.UI.StaraTuraAPI_GenesisCordonelInterface;
using System;
using System.Drawing;
using System.Linq;
using System.Net.NetworkInformation;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using Xylem.Common.Ui.GenesisToolBox;
using Xylem.Common.Utils.Logging;
using GenesisCordonelInterface.API;
using GenesisCordonelInterface.UI.Debug;
namespace GenesisCordonelInterface.UI
{
public partial class MainView : UserControl
{
private static readonly NLog.ILogger Logger = NLog.LogManager.GetLogger("GenesisCordonelInterface");
private static readonly Regex LogLevelRegex = new Regex(@"\|\s*(TRACE|DEBUG|INFO|WARN|ERROR|FATAL)\s*\|", RegexOptions.Compiled | RegexOptions.IgnoreCase);
private readonly InterfaceOutsideToGCI _api = new InterfaceOutsideToGCI();
private MeterBatchConfigPanel _batchPanel;
public MainView()
{
InitializeComponent();
InitializeDebugPanels();
//InitializeWorkerDebugPanel();
UiLogBus.MessageReceived += UiLogBus_MessageReceived;
rtbMainLog.BackColor = Color.Black;
rtbMainLog.ForeColor = Color.Gainsboro;
rtbMainLog.Font = new Font("Consolas", 9f);
rtbMainLog.ReadOnly = true;
rtbMainLog.HideSelection = false;
}
private void InitializeWorkerDebugPanel()
{
pnlWorkerDebug.Controls.Clear();
var debugPanel = new WorkerDebugPanel(_api)
{
Dock = DockStyle.Fill
};
pnlWorkerDebug.Controls.Add(debugPanel);
}
private void InitializeDebugPanels()
{
_batchPanel = new MeterBatchConfigPanel(_api)
{
Dock = DockStyle.Fill
};
pnlSlotConfig.Controls.Add(_batchPanel);
pnlWorkerDebug.Controls.Add(new WorkerDebugPanel(_api)
{
Dock = DockStyle.Fill
});
}
public void AddSlotRow()
{
_batchPanel?.AddEmptySlotRow();
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
BeginInvoke(new Action(() =>
{
SetSafeSplitterDistance(splitWorkArea, 420);
}));
}
private void SetSafeSplitterDistance(SplitContainer split, int desired)
{
int width = split.ClientSize.Width;
int min1 = split.Panel1MinSize;
int min2 = split.Panel2MinSize;
int splitter = split.SplitterWidth;
int max = width - min2 - splitter;
if (width <= min1 + min2 + splitter)
return;
if (desired < min1)
desired = min1;
if (desired > max)
desired = max;
split.SplitterDistance = desired;
}
protected override void Dispose(bool disposing)
{
UiLogBus.MessageReceived -= UiLogBus_MessageReceived;
base.Dispose(disposing);
}
private IWin32Window DialogOwner
{
get
{
Form owner = FindForm();
return owner ?? (IWin32Window)this;
}
}
private void btnSetup_Click(object sender, EventArgs e)
{
Logger.Trace("FORM: ---------------------------------");
Logger.Trace("FORM: Setup open");
using (FrmSetup frm = new FrmSetup())
{
frm.ShowDialog(DialogOwner);
}
Logger.Trace("FORM: Setup closed.");
}
private void btnRegisterStore_Click(object sender, EventArgs e)
{
Logger.Trace("FORM: ---------------------------------");
Logger.Trace("FORM: Register Store open.");
using (FrmRegisterStore frm = new FrmRegisterStore())
{
frm.ShowDialog(DialogOwner);
}
Logger.Trace("FORM: Register Store closed.");
}
private void btnPulseSetup_Click(object sender, EventArgs e)
{
Logger.Trace("FORM: ---------------------------------");
Logger.Trace("FORM: Pulse Setup open.");
using (FrmConfigurations frm = new FrmConfigurations())
{
frm.ShowDialog(DialogOwner);
}
Logger.Trace("FORM: Pulse Setup closed.");
}
private void preadjustmentButton_Click(object sender, EventArgs e)
{
Logger.Trace("FORM: ---------------------------------");
Logger.Trace("FORM: Preadjustment open.");
using (FrmCordonelPreadjustmentUI frm = new FrmCordonelPreadjustmentUI())
{
frm.ShowDialog(DialogOwner);
}
Logger.Trace("FORM: Preadjustment closed.");
}
private void button1_Click(object sender, EventArgs e)
{
Logger.Trace("FORM: ---------------------------------");
Logger.Trace("FORM: GCI GUI interface open.");
using (var frm = new FrmGCIAPI(_api))
{
frm.ShowDialog(this);
}
Logger.Trace("FORM: GCI GUI interface closed.");
}
private void SwitchGciView(string name, Control view)
{
Logger.Trace("FORM: ---------------------------------");
Logger.Trace($"FORM: GCI VIEW -> {name} OPEN");
pnlGciViewHost.Controls.Clear();
view.Dock = DockStyle.Fill;
pnlGciViewHost.Controls.Add(view);
view.BringToFront();
Logger.Trace($"FORM: GCI VIEW -> {name} LOADED");
}
private void btnMetersAction_Click(object sender, EventArgs e)
{
SwitchGciView(
"MetersAction",
new MetersActionView(_api));
}
public void ClearLog()
{
rtbMainLog.Clear();
Logger.Trace("Log cleared.");
}
private void UiLogBus_MessageReceived(string loggerName, string msg)
{
if (loggerName != "GenesisCordonelInterface")
return;
if (IsDisposed || !IsHandleCreated)
return;
if (InvokeRequired)
{
BeginInvoke(new Action<string, string>(UiLogBus_MessageReceived), loggerName, msg);
return;
}
string[] lines = msg.Replace("\r\n", "\n").Split('\n');
foreach (string originalLine in lines)
{
if (string.IsNullOrWhiteSpace(originalLine))
continue;
string line = originalLine;
Match m = LogLevelRegex.Match(line);
string indent = "";
if (m.Success)
{
int indentLength = m.Index + m.Length;
indent = new string(' ', indentLength);
}
string[] subLines = line.Split(new[] { " - " }, 2, StringSplitOptions.None);
string firstLine = line;
string rest = null;
if (subLines.Length == 2 && subLines[1].Length > 120)
{
firstLine = subLines[0] + " - " + subLines[1].Substring(0, 120);
rest = subLines[1].Substring(120);
}
AppendStyledLine(firstLine);
if (!string.IsNullOrEmpty(rest))
AppendStyledLine(indent + rest);
}
}
private void AppendStyledLine(string line)
{
int start = rtbMainLog.TextLength;
rtbMainLog.SelectionStart = start;
rtbMainLog.SelectionLength = 0;
rtbMainLog.SelectionColor = Color.Gainsboro;
rtbMainLog.AppendText(line + Environment.NewLine);
Match m = LogLevelRegex.Match(line);
if (m.Success)
{
rtbMainLog.SelectionStart = start + m.Index;
rtbMainLog.SelectionLength = m.Length;
rtbMainLog.SelectionColor = GetLogLevelColor(m.Groups[1].Value);
}
HighlightKeywordsInLine(line, start);
}
private Color GetLogLevelColor(string level)
{
switch (level.Trim().ToUpperInvariant())
{
case "TRACE": return Color.Gray;
case "DEBUG": return Color.DeepSkyBlue;
case "INFO": return Color.LimeGreen;
case "WARN": return Color.Orange;
case "ERROR": return Color.Red;
case "FATAL": return Color.Magenta;
default: return Color.Gainsboro;
}
}
private static readonly Tuple<Color, string[]>[] KeywordGroups =
{
Tuple.Create(Color.DeepSkyBlue, new[] { "REQUEST" }),
Tuple.Create(Color.Lime, new[] { "RESPONSE" }),
Tuple.Create(Color.Gold, new[] { "READ-REGISTER-SESSION", "UI-CLICK" })
};
private void HighlightKeywordsInLine(string line, int lineStartIndex)
{
foreach (var group in KeywordGroups)
{
foreach (var keyword in group.Item2)
{
int index = 0;
while ((index = line.IndexOf(keyword, index, StringComparison.Ordinal)) >= 0)
{
rtbMainLog.SelectionStart = lineStartIndex + index;
rtbMainLog.SelectionLength = keyword.Length;
rtbMainLog.SelectionColor = group.Item1;
index += keyword.Length;
}
}
}
}
private void ShowGciView(Control view)
{
pnlGciViewHost.Controls.Clear();
view.Dock = DockStyle.Fill;
pnlGciViewHost.Controls.Add(view);
}
}
}
@@ -0,0 +1,383 @@
namespace GenesisCordonelInterface.UI.StaraTuraAPI_GenesisCordonelInterface
{
partial class FrmGCIAPI
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support.
/// </summary>
private void InitializeComponent()
{
this.lblSlot = new System.Windows.Forms.Label();
this.txtSlot = new System.Windows.Forms.TextBox();
this.lblConfigSource = new System.Windows.Forms.Label();
this.cmbConfigSource = new System.Windows.Forms.ComboBox();
this.lblPasswordSource = new System.Windows.Forms.Label();
this.cmbPasswordSource = new System.Windows.Forms.ComboBox();
this.lblRequestPort = new System.Windows.Forms.Label();
this.txtRequestPort = new System.Windows.Forms.TextBox();
this.lblRequestBaudRate = new System.Windows.Forms.Label();
this.txtRequestBaudRate = new System.Windows.Forms.TextBox();
this.lblStreamingPort = new System.Windows.Forms.Label();
this.txtStreamingPort = new System.Windows.Forms.TextBox();
this.lblStreamingBaudRate = new System.Windows.Forms.Label();
this.txtStreamingBaudRate = new System.Windows.Forms.TextBox();
this.lblRegister = new System.Windows.Forms.Label();
this.txtRegister = new System.Windows.Forms.TextBox();
this.lblValue = new System.Windows.Forms.Label();
this.txtValue = new System.Windows.Forms.TextBox();
this.lblPassword = new System.Windows.Forms.Label();
this.txtPassword = new System.Windows.Forms.TextBox();
this.btnInit = new System.Windows.Forms.Button();
this.btnConnectOne = new System.Windows.Forms.Button();
this.btnConnectAll = new System.Windows.Forms.Button();
this.btnDisconnect = new System.Windows.Forms.Button();
this.btnGetPcbId = new System.Windows.Forms.Button();
this.btnReadRegister = new System.Windows.Forms.Button();
this.btnWriteRegister = new System.Windows.Forms.Button();
this.btnSetPassword = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// lblSlot
//
this.lblSlot.AutoSize = true;
this.lblSlot.Location = new System.Drawing.Point(20, 20);
this.lblSlot.Name = "lblSlot";
this.lblSlot.Size = new System.Drawing.Size(28, 13);
this.lblSlot.TabIndex = 0;
this.lblSlot.Text = "Slot:";
//
// txtSlot
//
this.txtSlot.Location = new System.Drawing.Point(150, 17);
this.txtSlot.Name = "txtSlot";
this.txtSlot.Size = new System.Drawing.Size(120, 20);
this.txtSlot.TabIndex = 1;
this.txtSlot.Text = "1";
//
// lblConfigSource
//
this.lblConfigSource.AutoSize = true;
this.lblConfigSource.Location = new System.Drawing.Point(20, 55);
this.lblConfigSource.Name = "lblConfigSource";
this.lblConfigSource.Size = new System.Drawing.Size(75, 13);
this.lblConfigSource.TabIndex = 2;
this.lblConfigSource.Text = "GciConfigSource:";
//
// cmbConfigSource
//
this.cmbConfigSource.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.cmbConfigSource.FormattingEnabled = true;
this.cmbConfigSource.Location = new System.Drawing.Point(150, 52);
this.cmbConfigSource.Name = "cmbConfigSource";
this.cmbConfigSource.Size = new System.Drawing.Size(180, 21);
this.cmbConfigSource.TabIndex = 3;
//
// lblPasswordSource
//
this.lblPasswordSource.AutoSize = true;
this.lblPasswordSource.Location = new System.Drawing.Point(20, 90);
this.lblPasswordSource.Name = "lblPasswordSource";
this.lblPasswordSource.Size = new System.Drawing.Size(88, 13);
this.lblPasswordSource.TabIndex = 4;
this.lblPasswordSource.Text = "PasswordSource:";
//
// cmbPasswordSource
//
this.cmbPasswordSource.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.cmbPasswordSource.FormattingEnabled = true;
this.cmbPasswordSource.Location = new System.Drawing.Point(150, 87);
this.cmbPasswordSource.Name = "cmbPasswordSource";
this.cmbPasswordSource.Size = new System.Drawing.Size(180, 21);
this.cmbPasswordSource.TabIndex = 5;
//
// lblRequestPort
//
this.lblRequestPort.AutoSize = true;
this.lblRequestPort.Location = new System.Drawing.Point(20, 125);
this.lblRequestPort.Name = "lblRequestPort";
this.lblRequestPort.Size = new System.Drawing.Size(67, 13);
this.lblRequestPort.TabIndex = 6;
this.lblRequestPort.Text = "RequestPort:";
//
// txtRequestPort
//
this.txtRequestPort.Location = new System.Drawing.Point(150, 122);
this.txtRequestPort.Name = "txtRequestPort";
this.txtRequestPort.Size = new System.Drawing.Size(180, 20);
this.txtRequestPort.TabIndex = 7;
this.txtRequestPort.Text = "COM1";
//
// lblRequestBaudRate
//
this.lblRequestBaudRate.AutoSize = true;
this.lblRequestBaudRate.Location = new System.Drawing.Point(360, 125);
this.lblRequestBaudRate.Name = "lblRequestBaudRate";
this.lblRequestBaudRate.Size = new System.Drawing.Size(94, 13);
this.lblRequestBaudRate.TabIndex = 8;
this.lblRequestBaudRate.Text = "RequestBaudRate:";
//
// txtRequestBaudRate
//
this.txtRequestBaudRate.Location = new System.Drawing.Point(480, 122);
this.txtRequestBaudRate.Name = "txtRequestBaudRate";
this.txtRequestBaudRate.Size = new System.Drawing.Size(120, 20);
this.txtRequestBaudRate.TabIndex = 9;
this.txtRequestBaudRate.Text = "115200";
//
// lblStreamingPort
//
this.lblStreamingPort.AutoSize = true;
this.lblStreamingPort.Location = new System.Drawing.Point(20, 160);
this.lblStreamingPort.Name = "lblStreamingPort";
this.lblStreamingPort.Size = new System.Drawing.Size(74, 13);
this.lblStreamingPort.TabIndex = 10;
this.lblStreamingPort.Text = "StreamingPort:";
//
// txtStreamingPort
//
this.txtStreamingPort.Location = new System.Drawing.Point(150, 157);
this.txtStreamingPort.Name = "txtStreamingPort";
this.txtStreamingPort.Size = new System.Drawing.Size(180, 20);
this.txtStreamingPort.TabIndex = 11;
this.txtStreamingPort.Text = "COM2";
//
// lblStreamingBaudRate
//
this.lblStreamingBaudRate.AutoSize = true;
this.lblStreamingBaudRate.Location = new System.Drawing.Point(360, 160);
this.lblStreamingBaudRate.Name = "lblStreamingBaudRate";
this.lblStreamingBaudRate.Size = new System.Drawing.Size(101, 13);
this.lblStreamingBaudRate.TabIndex = 12;
this.lblStreamingBaudRate.Text = "StreamingBaudRate:";
//
// txtStreamingBaudRate
//
this.txtStreamingBaudRate.Location = new System.Drawing.Point(480, 157);
this.txtStreamingBaudRate.Name = "txtStreamingBaudRate";
this.txtStreamingBaudRate.Size = new System.Drawing.Size(120, 20);
this.txtStreamingBaudRate.TabIndex = 13;
this.txtStreamingBaudRate.Text = "115200";
//
// lblRegister
//
this.lblRegister.AutoSize = true;
this.lblRegister.Location = new System.Drawing.Point(20, 195);
this.lblRegister.Name = "lblRegister";
this.lblRegister.Size = new System.Drawing.Size(49, 13);
this.lblRegister.TabIndex = 14;
this.lblRegister.Text = "Register:";
//
// txtRegister
//
this.txtRegister.Location = new System.Drawing.Point(150, 192);
this.txtRegister.Name = "txtRegister";
this.txtRegister.Size = new System.Drawing.Size(450, 20);
this.txtRegister.TabIndex = 15;
this.txtRegister.Text = "GENESISFLOW_TriggerTest";
//
// lblValue
//
this.lblValue.AutoSize = true;
this.lblValue.Location = new System.Drawing.Point(20, 230);
this.lblValue.Name = "lblValue";
this.lblValue.Size = new System.Drawing.Size(37, 13);
this.lblValue.TabIndex = 16;
this.lblValue.Text = "Value:";
//
// txtValue
//
this.txtValue.Location = new System.Drawing.Point(150, 227);
this.txtValue.Name = "txtValue";
this.txtValue.Size = new System.Drawing.Size(450, 20);
this.txtValue.TabIndex = 17;
this.txtValue.Text = "1";
//
// lblPassword
//
this.lblPassword.AutoSize = true;
this.lblPassword.Location = new System.Drawing.Point(20, 265);
this.lblPassword.Name = "lblPassword";
this.lblPassword.Size = new System.Drawing.Size(56, 13);
this.lblPassword.TabIndex = 18;
this.lblPassword.Text = "Password:";
//
// txtPassword
//
this.txtPassword.Location = new System.Drawing.Point(150, 262);
this.txtPassword.Name = "txtPassword";
this.txtPassword.Size = new System.Drawing.Size(450, 20);
this.txtPassword.TabIndex = 19;
this.txtPassword.Text = "1234";
//
// btnInit
//
this.btnInit.Location = new System.Drawing.Point(23, 310);
this.btnInit.Name = "btnInit";
this.btnInit.Size = new System.Drawing.Size(180, 32);
this.btnInit.TabIndex = 20;
this.btnInit.Text = "Init One Meter From Extern";
this.btnInit.UseVisualStyleBackColor = true;
this.btnInit.Click += new System.EventHandler(this.btnInit_Click);
//
// btnConnectOne
//
this.btnConnectOne.Location = new System.Drawing.Point(220, 310);
this.btnConnectOne.Name = "btnConnectOne";
this.btnConnectOne.Size = new System.Drawing.Size(180, 32);
this.btnConnectOne.TabIndex = 21;
this.btnConnectOne.Text = "Connect One Meter";
this.btnConnectOne.UseVisualStyleBackColor = true;
this.btnConnectOne.Click += new System.EventHandler(this.btnConnectOne_Click);
//
// btnConnectAll
//
this.btnConnectAll.Location = new System.Drawing.Point(417, 310);
this.btnConnectAll.Name = "btnConnectAll";
this.btnConnectAll.Size = new System.Drawing.Size(180, 32);
this.btnConnectAll.TabIndex = 22;
this.btnConnectAll.Text = "Connect All Meters";
this.btnConnectAll.UseVisualStyleBackColor = true;
this.btnConnectAll.Click += new System.EventHandler(this.btnConnectAll_Click);
//
// btnDisconnect
//
this.btnDisconnect.Location = new System.Drawing.Point(23, 355);
this.btnDisconnect.Name = "btnDisconnect";
this.btnDisconnect.Size = new System.Drawing.Size(180, 32);
this.btnDisconnect.TabIndex = 23;
this.btnDisconnect.Text = "Disconnect";
this.btnDisconnect.UseVisualStyleBackColor = true;
this.btnDisconnect.Click += new System.EventHandler(this.btnDisconnect_Click);
//
// btnGetPcbId
//
this.btnGetPcbId.Location = new System.Drawing.Point(220, 355);
this.btnGetPcbId.Name = "btnGetPcbId";
this.btnGetPcbId.Size = new System.Drawing.Size(180, 32);
this.btnGetPcbId.TabIndex = 24;
this.btnGetPcbId.Text = "Get PCB ID";
this.btnGetPcbId.UseVisualStyleBackColor = true;
this.btnGetPcbId.Click += new System.EventHandler(this.btnGetPcbId_Click);
//
// btnReadRegister
//
this.btnReadRegister.Location = new System.Drawing.Point(417, 355);
this.btnReadRegister.Name = "btnReadRegister";
this.btnReadRegister.Size = new System.Drawing.Size(180, 32);
this.btnReadRegister.TabIndex = 25;
this.btnReadRegister.Text = "Read Register";
this.btnReadRegister.UseVisualStyleBackColor = true;
this.btnReadRegister.Click += new System.EventHandler(this.btnReadRegister_Click);
//
// btnWriteRegister
//
this.btnWriteRegister.Location = new System.Drawing.Point(23, 400);
this.btnWriteRegister.Name = "btnWriteRegister";
this.btnWriteRegister.Size = new System.Drawing.Size(180, 32);
this.btnWriteRegister.TabIndex = 26;
this.btnWriteRegister.Text = "Write Register";
this.btnWriteRegister.UseVisualStyleBackColor = true;
this.btnWriteRegister.Click += new System.EventHandler(this.btnWriteRegister_Click);
//
// btnSetPassword
//
this.btnSetPassword.Location = new System.Drawing.Point(220, 400);
this.btnSetPassword.Name = "btnSetPassword";
this.btnSetPassword.Size = new System.Drawing.Size(180, 32);
this.btnSetPassword.TabIndex = 27;
this.btnSetPassword.Text = "Set Meter Password";
this.btnSetPassword.UseVisualStyleBackColor = true;
this.btnSetPassword.Click += new System.EventHandler(this.btnSetPassword_Click);
//
// FrmGCIAPI
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(624, 650);
this.Controls.Add(this.btnSetPassword);
this.Controls.Add(this.btnWriteRegister);
this.Controls.Add(this.btnReadRegister);
this.Controls.Add(this.btnGetPcbId);
this.Controls.Add(this.btnDisconnect);
this.Controls.Add(this.btnConnectAll);
this.Controls.Add(this.btnConnectOne);
this.Controls.Add(this.btnInit);
this.Controls.Add(this.txtPassword);
this.Controls.Add(this.lblPassword);
this.Controls.Add(this.txtValue);
this.Controls.Add(this.lblValue);
this.Controls.Add(this.txtRegister);
this.Controls.Add(this.lblRegister);
this.Controls.Add(this.txtStreamingBaudRate);
this.Controls.Add(this.lblStreamingBaudRate);
this.Controls.Add(this.txtStreamingPort);
this.Controls.Add(this.lblStreamingPort);
this.Controls.Add(this.txtRequestBaudRate);
this.Controls.Add(this.lblRequestBaudRate);
this.Controls.Add(this.txtRequestPort);
this.Controls.Add(this.lblRequestPort);
this.Controls.Add(this.cmbPasswordSource);
this.Controls.Add(this.lblPasswordSource);
this.Controls.Add(this.cmbConfigSource);
this.Controls.Add(this.lblConfigSource);
this.Controls.Add(this.txtSlot);
this.Controls.Add(this.lblSlot);
this.Name = "FrmGCIAPI";
this.Text = "GCI API Test Panel";
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Label lblSlot;
private System.Windows.Forms.TextBox txtSlot;
private System.Windows.Forms.Label lblConfigSource;
private System.Windows.Forms.ComboBox cmbConfigSource;
private System.Windows.Forms.Label lblPasswordSource;
private System.Windows.Forms.ComboBox cmbPasswordSource;
private System.Windows.Forms.Label lblRequestPort;
private System.Windows.Forms.TextBox txtRequestPort;
private System.Windows.Forms.Label lblRequestBaudRate;
private System.Windows.Forms.TextBox txtRequestBaudRate;
private System.Windows.Forms.Label lblStreamingPort;
private System.Windows.Forms.TextBox txtStreamingPort;
private System.Windows.Forms.Label lblStreamingBaudRate;
private System.Windows.Forms.TextBox txtStreamingBaudRate;
private System.Windows.Forms.Label lblRegister;
private System.Windows.Forms.TextBox txtRegister;
private System.Windows.Forms.Label lblValue;
private System.Windows.Forms.TextBox txtValue;
private System.Windows.Forms.Label lblPassword;
private System.Windows.Forms.TextBox txtPassword;
private System.Windows.Forms.Button btnInit;
private System.Windows.Forms.Button btnConnectOne;
private System.Windows.Forms.Button btnConnectAll;
private System.Windows.Forms.Button btnDisconnect;
private System.Windows.Forms.Button btnGetPcbId;
private System.Windows.Forms.Button btnReadRegister;
private System.Windows.Forms.Button btnWriteRegister;
private System.Windows.Forms.Button btnSetPassword;
}
}
@@ -0,0 +1,442 @@
using System;
using System.Threading.Tasks;
using System.Windows.Forms;
using GenesisCordonelInterface.API;
using Xylem.Common.Hardware.Interfaces.Ports.PortCore;
using static Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore.GenesisMeter;
namespace GenesisCordonelInterface.UI.StaraTuraAPI_GenesisCordonelInterface
{
public partial class FrmGCIAPI : Form
{
/*
GCI UI async execution model
The UI thread must never execute long-running meter communication directly.
When the user clicks a button, the UI only reads input values from controls
(for example slot number) and then delegates the real work to the GCI API.
The API call is executed by a per-slot worker queue:
- one slot / one meter / one communication port has its own worker
- commands for the same meter are executed sequentially
- commands for different meters can run in parallel
- after await completes, execution returns back to the UI thread safely
This prevents the WinForms UI from freezing while keeping meter communication
safe and ordered.
workflow:
User clicks button
|
v
WinForms UI thread
(read textbox values only)
|
v
await _api.GetPcbIdAsync(slot)
|
v
InterfaceOutsideToGCI
(clean public facade)
|
v
InterfaceGCIToLaatzen
(API/business logic)
|
v
Per-slot ApiWorker queue
(slot 1 / slot 2 / slot 3 ...)
|
v
GenesisMeter communication
(blocking HW operation)
|
v
Result returned
|
v
UI thread continues after await
(update labels / show MessageBox)
The UI does not freeze because hardware communication is not executed directly inside the event handler.
The event handler only calls an async method and waits using await. While waiting, the UI thread remains free.
The actual work is executed on a worker thread assigned to a specific slot/meter.
For a single meter, requests are queued, so they are executed sequentially and do not run at the same time,
which prevents communication conflicts.
*/
private readonly InterfaceOutsideToGCI _api;
public FrmGCIAPI() : this(new InterfaceOutsideToGCI())
{
}
/// <summary>
/// Initializes the form and default UI values.
/// </summary>
public FrmGCIAPI(InterfaceOutsideToGCI api)
{
_api = api ?? throw new ArgumentNullException(nameof(api));
InitializeComponent();
InitializeDefaults();
}
/// <summary>
/// Sets default values for combo boxes.
/// </summary>
private void InitializeDefaults()
{
cmbConfigSource.DataSource = Enum.GetValues(typeof(ConfigSource));
cmbPasswordSource.DataSource = Enum.GetValues(typeof(PasswordSource));
cmbConfigSource.SelectedItem = ConfigSource.InterfaceInputConfig;
cmbPasswordSource.SelectedItem = PasswordSource.OfflineFile;
}
#region UI Helpers
/// <summary>
/// Executes an async API action with UI busy state and centralized error handling.
/// </summary>
private async Task ExecuteApiActionAsync(Func<Task> action)
{
try
{
SetBusy(true);
await action();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "API call failed", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
finally
{
SetBusy(false);
}
}
/// <summary>
/// Enables/disables UI controls and updates cursor to indicate busy state.
/// </summary>
private void SetBusy(bool busy)
{
Cursor = busy ? Cursors.WaitCursor : Cursors.Default;
btnInit.Enabled = !busy;
btnConnectOne.Enabled = !busy;
btnConnectAll.Enabled = !busy;
btnDisconnect.Enabled = !busy;
btnGetPcbId.Enabled = !busy;
btnReadRegister.Enabled = !busy;
btnWriteRegister.Enabled = !busy;
btnSetPassword.Enabled = !busy;
}
/// <summary>
/// Safely parses slot number from UI textbox.
/// </summary>
private int GetSlotSafe()
{
if (!int.TryParse(txtSlot.Text, out int slot))
throw new Exception("Invalid slot number.");
return slot;
}
/// <summary>
/// Converts string input to best matching primitive type.
/// </summary>
private object ParseValue(string input)
{
if (int.TryParse(input, out int i)) return i;
if (uint.TryParse(input, out uint ui)) return ui;
if (bool.TryParse(input, out bool b)) return b;
return input;
}
/// <summary>
/// Creates a public GCI port configuration object from UI input values.
/// </summary>
/// <param name="portName">Name of the port (e.g. COM3).</param>
/// <param name="baudRateText">Baud rate entered in the UI.</param>
/// <returns>
/// Instance of <see cref="PublicModels.GciPortConfig"/> or null if port name is empty.
/// </returns>
/// <exception cref="Exception">Thrown when baud rate is invalid.</exception>
private PublicModels.GciPortConfig CreateGciPortConfig(string portName, string baudRateText)
{
if (string.IsNullOrWhiteSpace(portName))
return null;
if (!int.TryParse(baudRateText, out int baudRate))
throw new Exception($"Invalid baud rate for port {portName}.");
return new PublicModels.GciPortConfig
{
PortName = portName,
Type = "Serial",
};
}
/// <summary>
/// Gets selected configuration source from UI and maps it to public GCI model.
/// </summary>
/// <returns>Selected <see cref="PublicModels.GciConfigSource"/>.</returns>
/// <exception cref="Exception">Thrown when no value is selected.</exception>
private PublicModels.GciConfigSource GetConfigSource()
{
if (cmbConfigSource.SelectedItem == null)
throw new Exception("Config source is not selected.");
return (PublicModels.GciConfigSource)cmbConfigSource.SelectedItem;
}
/// <summary>
/// Gets selected password source from UI and maps it to public GCI model.
/// </summary>
/// <returns>Selected <see cref="PublicModels.GciPasswordSource"/>.</returns>
/// <exception cref="Exception">Thrown when no value is selected.</exception>
private PublicModels.GciPasswordSource GetPasswordSource()
{
if (cmbPasswordSource.SelectedItem == null)
throw new Exception("Password source is not selected.");
return (PublicModels.GciPasswordSource)cmbPasswordSource.SelectedItem;
}
#endregion
#region Buttons
/// <summary>
/// Initializes meter using external configuration.
/// </summary>
private async void btnInit_Click(object sender, EventArgs e)
{
int slot;
try { slot = GetSlotSafe(); }
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Invalid input");
return;
}
await ExecuteApiActionAsync(async () =>
{
var request = new PublicModels.GciInitSlotRequest
{
SlotId = slot,
ConfigSource = GetConfigSource(),
PasswordSource = GetPasswordSource(),
RequestPort = CreateGciPortConfig(txtRequestPort.Text, txtRequestBaudRate.Text),
StreamingPort = CreateGciPortConfig(txtStreamingPort.Text, txtStreamingBaudRate.Text)
};
var result = await _api.InitSlotAsync(request);
if (!result.Success)
throw new Exception(result.Message);
MessageBox.Show("Meter initialized.");
});
}
/// <summary>
/// Connects to one meter.
/// </summary>
private async void btnConnectOne_Click(object sender, EventArgs e)
{
int slot;
try { slot = GetSlotSafe(); }
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Invalid input");
return;
}
await ExecuteApiActionAsync(async () =>
{
var result = await _api.ConnectOneSlotAsync(slot);
if (!result.Success)
throw new Exception(result.Message);
MessageBox.Show($"Connected.\r\n");
});
}
/// <summary>
/// Disconnects from current meter.
/// </summary>
private async void btnDisconnect_Click(object sender, EventArgs e)
{
int slot;
try { slot = GetSlotSafe(); }
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Invalid input");
return;
}
await ExecuteApiActionAsync(async () =>
{
await _api.DisconnectAsync(slot);
MessageBox.Show("Disconnected.");
});
}
/// <summary>
/// Reads PCB ID asynchronously.
/// </summary>
private async void btnGetPcbId_Click(object sender, EventArgs e)
{
int slot;
try { slot = GetSlotSafe(); }
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Invalid input");
return;
}
await ExecuteApiActionAsync(async () =>
{
PublicModels.GciGetPcbIdResult result =
await _api.GetPcbIdAsync(slot);
if (!result.Success)
throw new Exception(result.Message);
MessageBox.Show($"PCB ID: {result.PcbId}");
});
}
/// <summary>
/// Reads register value.
/// </summary>
private async void btnReadRegister_Click(object sender, EventArgs e)
{
int slot;
string registerName = txtRegister.Text;
try
{
slot = GetSlotSafe();
if (string.IsNullOrWhiteSpace(registerName))
throw new Exception("Register name is empty.");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Invalid input");
return;
}
await ExecuteApiActionAsync(async () =>
{
var result = await _api.ReadRegisterAsync(slot, registerName);
if (!result.Success)
throw new Exception(result.ErrorMessage);
MessageBox.Show($"Register: {result.RegisterName}\r\nRaw: {result.RawHex}");
});
}
private async void btnConnectAll_Click(object sender, EventArgs e)
{
await ExecuteApiActionAsync(async () =>
{
var slots = _api.GetSelectedSlots();
if (slots.Count == 0)
throw new Exception("No slots selected.");
foreach (int slot in slots)
{
var result = await _api.ConnectOneSlotAsync(slot);
if (!result.Success)
throw new Exception($"Slot {slot}: {result.Message}");
}
MessageBox.Show("Selected meters connected.");
});
}
private async void btnWriteRegister_Click(object sender, EventArgs e)
{
int slot;
string registerName = txtRegister.Text;
string valueText = txtValue.Text;
try
{
slot = GetSlotSafe();
if (string.IsNullOrWhiteSpace(registerName))
throw new Exception("Register name is empty.");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Invalid input");
return;
}
await ExecuteApiActionAsync(async () =>
{
object value = ParseValue(valueText);
var result = await _api.WriteRegisterAsync(
slot,
registerName,
value,
false,
false);
if (!result.Success)
throw new Exception(result.ErrorMessage);
MessageBox.Show($"Write OK: {registerName} = {value}");
});
}
private async void btnSetPassword_Click(object sender, EventArgs e)
{
int slot;
string password = txtPassword.Text;
try
{
slot = GetSlotSafe();
if (string.IsNullOrWhiteSpace(password))
throw new Exception("Password is empty.");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Invalid input");
return;
}
await ExecuteApiActionAsync(async () =>
{
PublicModels.GciSetPasswordResult result = await _api.SetMeterPasswordAsync(slot, password);
if (!result.Success)
throw new Exception("Set password failed.");
MessageBox.Show("Password set successfully.");
});
}
#endregion
}
}
@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
@@ -0,0 +1,48 @@
namespace GenesisCordonelInterface.UI.StaraTuraAPI_GenesisCordonelInterface
{
partial class MeterInitView
{
private System.ComponentModel.IContainer components = null;
private System.Windows.Forms.Button btnReloadSetup;
private System.Windows.Forms.Button btnSaveSetup;
private System.Windows.Forms.Button btnAddSlot;
protected override void Dispose(bool disposing)
{
if (disposing && components != null)
components.Dispose();
base.Dispose(disposing);
}
private void InitializeComponent()
{
this.btnReloadSetup = new System.Windows.Forms.Button();
this.btnSaveSetup = new System.Windows.Forms.Button();
this.btnAddSlot = new System.Windows.Forms.Button();
this.SuspendLayout();
this.btnReloadSetup.SetBounds(20, 20, 140, 32);
this.btnReloadSetup.Text = "Reload Setup";
this.btnSaveSetup.SetBounds(170, 20, 140, 32);
this.btnSaveSetup.Text = "Save Setup";
this.btnSaveSetup.Click += new System.EventHandler(this.btnSaveSetup_Click);
this.btnAddSlot.SetBounds(20, 65, 290, 32);
this.btnAddSlot.Text = "Add Slot";
this.btnAddSlot.Click += new System.EventHandler(this.btnAddSlot_Click);
this.Controls.Add(this.btnReloadSetup);
this.Controls.Add(this.btnSaveSetup);
this.Controls.Add(this.btnAddSlot);
this.Name = "MeterInitView";
this.Size = new System.Drawing.Size(340, 130);
this.ResumeLayout(false);
}
}
}
@@ -0,0 +1,65 @@
using System;
using System.Windows.Forms;
using GenesisCordonelInterface.API;
namespace GenesisCordonelInterface.UI.StaraTuraAPI_GenesisCordonelInterface
{
public partial class MeterInitView : UserControl
{
private readonly InterfaceOutsideToGCI _api;
private readonly Action _addSlotAction;
private readonly Action _saveAction;
public MeterInitView(InterfaceOutsideToGCI api, Action addSlotAction, Action saveAction)
{
_api = api;
_addSlotAction = addSlotAction;
_saveAction = saveAction;
InitializeComponent();
}
#region BUTTONS
// ----------------------------------------------------
private void btnSaveSetup_Click(object sender, EventArgs e)
{
_saveAction?.Invoke();
}
private void btnAddSlot_Click(object sender, EventArgs e)
{
_addSlotAction?.Invoke();
}
// ----------------------------------------------------
#endregion
private void ExecuteApiAction(Action action)
{
try
{
SetBusy(true);
action();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "API call failed", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
finally
{
SetBusy(false);
}
}
private void SetBusy(bool busy)
{
Cursor = busy ? Cursors.WaitCursor : Cursors.Default;
btnReloadSetup.Enabled = !busy;
btnSaveSetup.Enabled = !busy;
btnAddSlot.Enabled = !busy;
}
}
}
@@ -0,0 +1,99 @@
namespace GenesisCordonelInterface.UI.StaraTuraAPI_GenesisCordonelInterface
{
partial class MetersActionView
{
private System.ComponentModel.IContainer components = null;
private System.Windows.Forms.Label lblRegister;
private System.Windows.Forms.TextBox txtRegister;
private System.Windows.Forms.Label lblValue;
private System.Windows.Forms.TextBox txtValue;
private System.Windows.Forms.Label lblPassword;
private System.Windows.Forms.TextBox txtPassword;
private System.Windows.Forms.Button btnConnectSelected;
private System.Windows.Forms.Button btnReadRegister;
private System.Windows.Forms.Button btnWriteRegister;
private System.Windows.Forms.Button btnSetPassword;
private System.Windows.Forms.Button btnDisconnectSelected;
protected override void Dispose(bool disposing)
{
if (disposing && components != null)
components.Dispose();
base.Dispose(disposing);
}
private void InitializeComponent()
{
this.lblRegister = new System.Windows.Forms.Label();
this.txtRegister = new System.Windows.Forms.TextBox();
this.lblValue = new System.Windows.Forms.Label();
this.txtValue = new System.Windows.Forms.TextBox();
this.lblPassword = new System.Windows.Forms.Label();
this.txtPassword = new System.Windows.Forms.TextBox();
this.btnConnectSelected = new System.Windows.Forms.Button();
this.btnReadRegister = new System.Windows.Forms.Button();
this.btnWriteRegister = new System.Windows.Forms.Button();
this.btnSetPassword = new System.Windows.Forms.Button();
this.btnDisconnectSelected = new System.Windows.Forms.Button();
this.SuspendLayout();
this.lblRegister.SetBounds(20, 20, 100, 20);
this.lblRegister.Text = "Register:";
this.txtRegister.SetBounds(130, 17, 250, 20);
this.txtRegister.Text = "GENESISFLOW_TriggerTest";
this.lblValue.SetBounds(20, 55, 100, 20);
this.lblValue.Text = "Value:";
this.txtValue.SetBounds(130, 52, 250, 20);
this.txtValue.Text = "1";
this.lblPassword.SetBounds(20, 90, 100, 20);
this.lblPassword.Text = "Password:";
this.txtPassword.SetBounds(130, 87, 250, 20);
this.txtPassword.Text = "1234";
this.btnConnectSelected.SetBounds(20, 140, 170, 32);
this.btnConnectSelected.Text = "Connect Selected";
this.btnConnectSelected.Click += new System.EventHandler(this.btnConnectSelected_Click);
this.btnDisconnectSelected.SetBounds(210, 140, 170, 32);
this.btnDisconnectSelected.Text = "Disconnect Selected";
this.btnDisconnectSelected.Click += new System.EventHandler(this.btnDisconnectSelected_Click);
this.btnReadRegister.SetBounds(20, 185, 170, 32);
this.btnReadRegister.Text = "Read Register";
this.btnReadRegister.Click += new System.EventHandler(this.btnReadRegister_Click);
this.btnWriteRegister.SetBounds(210, 185, 170, 32);
this.btnWriteRegister.Text = "Write Register";
this.btnWriteRegister.Click += new System.EventHandler(this.btnWriteRegister_Click);
this.btnSetPassword.SetBounds(20, 230, 170, 32);
this.btnSetPassword.Text = "Set Password";
this.btnSetPassword.Click += new System.EventHandler(this.btnSetPassword_Click);
this.Controls.Add(this.lblRegister);
this.Controls.Add(this.txtRegister);
this.Controls.Add(this.lblValue);
this.Controls.Add(this.txtValue);
this.Controls.Add(this.lblPassword);
this.Controls.Add(this.txtPassword);
this.Controls.Add(this.btnConnectSelected);
this.Controls.Add(this.btnDisconnectSelected);
this.Controls.Add(this.btnReadRegister);
this.Controls.Add(this.btnWriteRegister);
this.Controls.Add(this.btnSetPassword);
this.Name = "MetersActionView";
this.Size = new System.Drawing.Size(420, 320);
this.ResumeLayout(false);
this.PerformLayout();
}
}
}
@@ -0,0 +1,180 @@
using System;
using System.Threading.Tasks;
using System.Windows.Forms;
using GenesisCordonelInterface.API;
namespace GenesisCordonelInterface.UI.StaraTuraAPI_GenesisCordonelInterface
{
public partial class MetersActionView : UserControl
{
private readonly InterfaceOutsideToGCI _api;
public MetersActionView(InterfaceOutsideToGCI api)
{
_api = api ?? throw new ArgumentNullException(nameof(api));
InitializeComponent();
}
private async Task ExecuteApiActionAsync(Func<Task> action)
{
try
{
SetBusy(true);
await action();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "API call failed", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
finally
{
SetBusy(false);
}
}
private void SetBusy(bool busy)
{
Cursor = busy ? Cursors.WaitCursor : Cursors.Default;
btnConnectSelected.Enabled = !busy;
btnReadRegister.Enabled = !busy;
btnWriteRegister.Enabled = !busy;
btnSetPassword.Enabled = !busy;
btnDisconnectSelected.Enabled = !busy;
}
private object ParseValue(string input)
{
if (int.TryParse(input, out int i)) return i;
if (uint.TryParse(input, out uint ui)) return ui;
if (bool.TryParse(input, out bool b)) return b;
return input;
}
private void ValidateSelectedSlots()
{
if (_api.GetSelectedSlots().Count == 0)
throw new Exception("No slots selected.");
}
private async void btnConnectSelected_Click(object sender, EventArgs e)
{
await ExecuteApiActionAsync(async () =>
{
ValidateSelectedSlots();
foreach (int slot in _api.GetSelectedSlots())
{
var result = await _api.ConnectOneSlotAsync(slot);
if (!result.Success)
throw new Exception($"Slot {slot}: {result.Message}");
}
MessageBox.Show("Selected meters connected.");
});
}
private async void btnReadRegister_Click(object sender, EventArgs e)
{
string registerName = txtRegister.Text;
if (string.IsNullOrWhiteSpace(registerName))
{
MessageBox.Show("Register name is empty.", "Invalid input");
return;
}
await ExecuteApiActionAsync(async () =>
{
ValidateSelectedSlots();
foreach (int slot in _api.GetSelectedSlots())
{
var result = await _api.ReadRegisterAsync(slot, registerName);
if (!result.Success)
throw new Exception($"Slot {slot}: {result.ErrorMessage}");
}
MessageBox.Show("Read register finished.");
});
}
private async void btnWriteRegister_Click(object sender, EventArgs e)
{
string registerName = txtRegister.Text;
string valueText = txtValue.Text;
if (string.IsNullOrWhiteSpace(registerName))
{
MessageBox.Show("Register name is empty.", "Invalid input");
return;
}
await ExecuteApiActionAsync(async () =>
{
ValidateSelectedSlots();
object value = ParseValue(valueText);
foreach (int slot in _api.GetSelectedSlots())
{
var result = await _api.WriteRegisterAsync(
slot,
registerName,
value,
false,
false);
if (!result.Success)
throw new Exception($"Slot {slot}: {result.ErrorMessage}");
}
MessageBox.Show("Write register finished.");
});
}
private async void btnSetPassword_Click(object sender, EventArgs e)
{
string password = txtPassword.Text;
if (string.IsNullOrWhiteSpace(password))
{
MessageBox.Show("Password is empty.", "Invalid input");
return;
}
await ExecuteApiActionAsync(async () =>
{
ValidateSelectedSlots();
foreach (int slot in _api.GetSelectedSlots())
{
PublicModels.GciSetPasswordResult result = await _api.SetMeterPasswordAsync(slot, password);
if (!result.Success)
throw new Exception($"Slot {slot}: Set password failed.");
}
MessageBox.Show("Password set for selected meters.");
});
}
private async void btnDisconnectSelected_Click(object sender, EventArgs e)
{
await ExecuteApiActionAsync(async () =>
{
ValidateSelectedSlots();
foreach (int slot in _api.GetSelectedSlots())
{
await _api.DisconnectAsync(slot);
}
MessageBox.Show("Selected meters disconnected.");
});
}
}
}
+25
View File
@@ -0,0 +1,25 @@
<?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">
<extensions>
<add assembly="Xylem.Common.Utils.Logging" />
</extensions>
<targets>
<target name="uiTrace"
xsi:type="UiTarget"
layout="${time}|${level:uppercase=true:padding=-5}|${message}" />
<target name="logfile"
xsi:type="File"
fileName="${basedir}/GenesisCordonelInterfaceLogger.log"
layout="${longdate}|${level:uppercase=true:padding=-5}|${logger}|${message}|${exception:format=tostring}" />
</targets>
<rules>
<logger name="GenesisCordonelInterface*" minlevel="Trace" writeTo="uiTrace" />
<logger name="GenesisCordonelInterface*" minlevel="Trace" writeTo="logfile" />
</rules>
</nlog>
+5
View File
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Newtonsoft.Json" version="13.0.3" targetFramework="net48" />
<package id="NLog" version="5.2.2" targetFramework="net48" />
</packages>

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