From 175a92f633d0217d25b697c83d9be65ca9130c10 Mon Sep 17 00:00:00 2001 From: Milan Hanajik Date: Mon, 28 Jul 2014 09:54:35 +0200 Subject: [PATCH] Initial commit almost identical to SVN-repo rev.340 --- TestBenchFramework.sln | 33 + TestBenchFramework/AboutDlg.Designer.cs | 117 + TestBenchFramework/AboutDlg.cs | 28 + TestBenchFramework/AboutDlg.resx | 123 + TestBenchFramework/AttachedTextBoxes.cs | 173 + TestBenchFramework/BarGraph.cs | 72 + .../BenchControl/BenchId/Component.cs | 25 + .../BenchControl/BenchId/ComponentCfg.cs | 55 + .../BenchControl/BenchId/ComponentCfgCtrl.cs | 63 + .../BenchId/ComponentCfgCtrl.designer.cs | 106 + .../BenchId/ComponentCfgCtrl.resx | 120 + .../BenchControl/BenchId/ComponentFactory.cs | 40 + TestBenchFramework/BenchControl/BenchPath.cs | 48 + .../Cameras/CameraRoi/CameraRoi.cs | 108 + .../Cameras/CameraRoi/CameraRoiCfg.cs | 54 + .../Cameras/CameraRoi/CameraRoiCfgCtrl.cs | 94 + .../CameraRoi/CameraRoiCfgCtrl.designer.cs | 130 + .../Cameras/CameraRoi/CameraRoiCfgCtrl.resx | 120 + .../Cameras/CameraRoi/CameraRoiFactory.cs | 46 + .../Cameras/CameraRoi/ReadRegisterOp.cs | 74 + .../Cameras/CameraRoi/RoiProcedureParams.cs | 313 + .../Cameras/IdcCamera/Command/Connect.cs | 15 + .../Cameras/IdcCamera/Command/Detect.cs | 60 + .../Cameras/IdcCamera/Command/Disconnect.cs | 13 + .../Cameras/IdcCamera/Command/Grab.cs | 31 + .../Cameras/IdcCamera/Command/Measure.cs | 44 + .../Cameras/IdcCamera/Command/Other.cs | 15 + .../Cameras/IdcCamera/Command/Save.cs | 21 + .../IdcCamera/Command/SetBrightness.cs | 15 + .../Cameras/IdcCamera/Command/StartNew.cs | 13 + .../Cameras/IdcCamera/Command/StopOp.cs | 13 + .../Cameras/IdcCamera/Command/StopStream.cs | 13 + .../Cameras/IdcCamera/Command/Stream.cs | 19 + .../Cameras/IdcCamera/IWorkerCmd.cs | 8 + .../BenchControl/Cameras/IdcCamera/Idc100.cs | 1441 + .../Cameras/IdcCamera/IdcCamera.cs | 297 + .../Cameras/IdcCamera/IdcCameraCfg.cs | 57 + .../Cameras/IdcCamera/IdcCameraCfgCtrl.cs | 88 + .../IdcCamera/IdcCameraCfgCtrl.designer.cs | 176 + .../Cameras/IdcCamera/IdcCameraCfgCtrl.resx | 120 + .../Cameras/IdcCamera/IdcCameraFactory.cs | 41 + .../Cameras/IdcCamera/IdcEnums.cs | 65 + .../Cameras/IdcCamera/SerialFileIO.cs | 227 + .../Cameras/IdcCamera/SerialLayer.cs | 619 + .../BenchControl/ComponentBase.cs | 46 + .../BenchControl/ComponentCfgBase.cs | 87 + TestBenchFramework/BenchControl/Constants.cs | 12 + TestBenchFramework/BenchControl/Current.cs | 48 + .../Munich/CycleBeginningForm.Designer.cs | 193 + .../DataEntry/Munich/CycleBeginningForm.cs | 36 + .../DataEntry/Munich/CycleBeginningForm.resx | 120 + .../DataEntry/Munich/CycleEndForm.Designer.cs | 264 + .../DataEntry/Munich/CycleEndForm.cs | 55 + .../DataEntry/Munich/CycleEndForm.resx | 120 + .../DataEntry/Munich/EntryForm.cs | 140 + .../DataEntry/Munich/EntryFormCfg.cs | 62 + .../DataEntry/Munich/EntryFormCfgCtrl.cs | 67 + .../Munich/EntryFormCfgCtrl.designer.cs | 152 + .../DataEntry/Munich/EntryFormCfgCtrl.resx | 120 + .../DataEntry/Munich/EntryFormFactory.cs | 40 + .../BenchControl/Elde/Common.cs | 71 + .../BenchControl/Elde/ControlBoardCfg.cs | 52 + .../Elde/ControlBoardCfgCtrl.Designer.cs | 106 + .../BenchControl/Elde/ControlBoardCfgCtrl.cs | 75 + .../Elde/ControlBoardCfgCtrl.resx | 120 + .../BenchControl/Elde/ControlBoardDev.cs | 334 + .../BenchControl/Elde/ControlBoardFactory.cs | 40 + .../BenchControl/Elde/ControlComSim.cs | 293 + .../BenchControl/Elde/ControlComWrap.cs | 265 + .../BenchControl/Elde/Diverter/Diverter.cs | 50 + .../BenchControl/Elde/Diverter/DiverterCfg.cs | 51 + .../Elde/Diverter/DiverterCfgCtrl.Designer.cs | 130 + .../Elde/Diverter/DiverterCfgCtrl.cs | 89 + .../Elde/Diverter/DiverterCfgCtrl.resx | 120 + .../Elde/Diverter/DiverterFactory.cs | 42 + .../BenchControl/Elde/FlowMeter/FlowMeter.cs | 73 + .../Elde/FlowMeter/FlowMeterCfg.cs | 61 + .../FlowMeter/FlowMeterCfgCtrl.Designer.cs | 153 + .../Elde/FlowMeter/FlowMeterCfgCtrl.cs | 102 + .../Elde/FlowMeter/FlowMeterCfgCtrl.resx | 120 + .../Elde/FlowMeter/FlowMeterFactory.cs | 43 + .../BenchControl/Elde/FlowMeter/ReadFlowOp.cs | 65 + .../BenchControl/Elde/IControlCom.cs | 69 + .../Elde/PressureMeter/PressureMeter.cs | 71 + .../Elde/PressureMeter/PressureMeterCfg.cs | 63 + .../PressureMeterCfgCtrl.Designer.cs | 153 + .../PressureMeter/PressureMeterCfgCtrl.cs | 100 + .../PressureMeter/PressureMeterCfgCtrl.resx | 120 + .../PressureMeter/PressureMeterFactory.cs | 42 + .../Elde/PressureMeter/ReadPressureOp.cs | 58 + .../BenchControl/Elde/Pump/Pump.cs | 56 + .../BenchControl/Elde/Pump/PumpCfg.cs | 52 + .../Elde/Pump/PumpCfgCtrl.Designer.cs | 130 + .../BenchControl/Elde/Pump/PumpCfgCtrl.cs | 92 + .../BenchControl/Elde/Pump/PumpCfgCtrl.resx | 120 + .../BenchControl/Elde/Pump/PumpFactory.cs | 39 + .../Elde/PumpWithFM/FMPumpTestParams.cs | 151 + .../BenchControl/Elde/PumpWithFM/Pump.cs | 117 + .../BenchControl/Elde/PumpWithFM/PumpCfg.cs | 53 + .../Elde/PumpWithFM/PumpCfgCtrl.Designer.cs | 153 + .../Elde/PumpWithFM/PumpCfgCtrl.cs | 100 + .../Elde/PumpWithFM/PumpCfgCtrl.resx | 120 + .../Elde/PumpWithFM/PumpFactory.cs | 42 + .../Elde/QueryMeasurementEndOp.cs | 59 + .../Elde/RegisterReader/RRProcedureParams.cs | 155 + .../ReadReferenceForRegisterOp.cs | 58 + .../Elde/RegisterReader/ReadRegisterOp.cs | 71 + .../Elde/RegisterReader/RegisterReader.cs | 82 + .../Elde/RegisterReader/RegisterReaderCfg.cs | 60 + .../RegisterReaderCfgCtrl.Designer.cs | 130 + .../RegisterReader/RegisterReaderCfgCtrl.cs | 92 + .../RegisterReader/RegisterReaderCfgCtrl.resx | 120 + .../RegisterReader/RegisterReaderFactory.cs | 46 + .../Elde/RegulValve/ChangeValvePositionOp.cs | 78 + .../Elde/RegulValve/RegulValve.cs | 102 + .../Elde/RegulValve/RegulValveCfg.cs | 73 + .../RegulValve/RegulValveCfgCtrl.Designer.cs | 213 + .../Elde/RegulValve/RegulValveCfgCtrl.cs | 120 + .../Elde/RegulValve/RegulValveCfgCtrl.resx | 120 + .../Elde/RegulValve/RegulValveFactory.cs | 39 + .../BenchControl/Elde/RegulValve/SetFlowOp.cs | 269 + .../RegulValve/SetRegulValvePositionOp.cs | 127 + .../BenchControl/Elde/StartMeasurementOp.cs | 68 + .../BenchControl/Elde/StopPreviousOp.cs | 63 + .../BenchControl/Elde/TempMeter/ReadTempOp.cs | 57 + .../BenchControl/Elde/TempMeter/TempMeter.cs | 82 + .../Elde/TempMeter/TempMeterCfg.cs | 78 + .../TempMeter/TempMeterCfgCtrl.Designer.cs | 245 + .../Elde/TempMeter/TempMeterCfgCtrl.cs | 140 + .../Elde/TempMeter/TempMeterCfgCtrl.resx | 120 + .../Elde/TempMeter/TempMeterFactory.cs | 39 + .../BenchControl/Elde/UpdateTankWeightOp.cs | 48 + .../BenchControl/Elde/Valve/SetValvesOp.cs | 195 + .../BenchControl/Elde/Valve/Valve.cs | 63 + .../BenchControl/Elde/Valve/ValveCfg.cs | 67 + .../Elde/Valve/ValveCfgCtrl.Designer.cs | 214 + .../BenchControl/Elde/Valve/ValveCfgCtrl.cs | 125 + .../BenchControl/Elde/Valve/ValveCfgCtrl.resx | 120 + .../BenchControl/Elde/Valve/ValveFactory.cs | 39 + TestBenchFramework/BenchControl/Events.cs | 97 + .../BenchControl/FeedingPath.cs | 42 + TestBenchFramework/BenchControl/FloatBox.cs | 22 + TestBenchFramework/BenchControl/Formulas.cs | 133 + .../Generic/IChildComponentCfg.cs | 8 + .../BenchControl/Generic/IComponent.cs | 8 + .../BenchControl/Generic/IComponentCfg.cs | 47 + .../BenchControl/Generic/IComponentCfgCtrl.cs | 28 + .../BenchControl/Generic/IComponentFactory.cs | 42 + .../BenchControl/Generic/IDevice.cs | 35 + .../BenchControl/Generic/IParamsProvider.cs | 43 + .../BenchControl/Generic/IProcedureParams.cs | 9 + .../BenchControl/Generic/ITestParams.cs | 9 + .../BenchControl/GenericDevices/IAmbient.cs | 16 + .../BenchControl/GenericDevices/IBalance.cs | 48 + .../BenchControl/GenericDevices/IBalance2.cs | 14 + .../BenchControl/GenericDevices/ICamera.cs | 46 + .../BenchControl/GenericDevices/ICameraRoi.cs | 23 + .../BenchControl/GenericDevices/IDataEntry.cs | 11 + .../BenchControl/GenericDevices/IDiverter.cs | 12 + .../BenchControl/GenericDevices/IFlowMeter.cs | 36 + .../GenericDevices/IHasCompleted.cs | 8 + .../GenericDevices/IHasProtocolTitle.cs | 8 + .../GenericDevices/IPressureMeter.cs | 31 + .../BenchControl/GenericDevices/IPump.cs | 12 + .../BenchControl/GenericDevices/IPumpFM.cs | 21 + .../GenericDevices/IRegisterReader.cs | 12 + .../GenericDevices/IRegulValve.cs | 51 + .../GenericDevices/IResultsPrinter.cs | 18 + .../GenericDevices/IResultsWriter.cs | 15 + .../BenchControl/GenericDevices/ITempMeter.cs | 24 + .../GenericDevices/ITestMethod.cs | 9 + .../BenchControl/GenericDevices/IValve.cs | 37 + .../GenericDevices/IValveControl.cs | 25 + .../GenericDevices/IWaterMeter.cs | 14 + .../BenchControl/GenericDevices/ValveBase.cs | 72 + .../BenchControl/Greco/Ambient.cs | 186 + .../BenchControl/Greco/AmbientCfg.cs | 62 + .../Greco/AmbientCfgCtrl.Designer.cs | 226 + .../BenchControl/Greco/AmbientCfgCtrl.cs | 156 + .../BenchControl/Greco/AmbientCfgCtrl.resx | 120 + .../BenchControl/Greco/AmbientFactory.cs | 40 + TestBenchFramework/BenchControl/IOperation.cs | 44 + TestBenchFramework/BenchControl/ISequence.cs | 10 + TestBenchFramework/BenchControl/IntBox.cs | 22 + TestBenchFramework/BenchControl/MetersPath.cs | 33 + .../BenchControl/MettlerToledo/BalanceCfg.cs | 66 + .../MettlerToledo/BalanceCfgCtrl.Designer.cs | 259 + .../MettlerToledo/BalanceCfgCtrl.cs | 167 + .../MettlerToledo/BalanceCfgCtrl.resx | 120 + .../BenchControl/MettlerToledo/BalanceDev.cs | 423 + .../MettlerToledo/BalanceFactory.cs | 41 + .../MettlerToledo/BalanceNewDev.cs | 264 + .../MettlerToledo/BalanceNewFactory.cs | 41 + .../MettlerToledo/GetBalanceSNOp.cs | 59 + .../BenchControl/MettlerToledo/ReadMassOp.cs | 68 + .../MettlerToledo/ReadMassesOp.cs | 60 + .../MettlerToledo/ReadStableMassOp.cs | 88 + .../BenchControl/MettlerToledo/SetUnitsOp.cs | 58 + .../BenchControl/MettlerToledo/TaringOp.cs | 74 + .../Operations/AskYesNoForm.Designer.cs | 94 + .../BenchControl/Operations/AskYesNoForm.cs | 38 + .../BenchControl/Operations/AskYesNoForm.resx | 120 + .../BenchControl/Operations/AskYesNoOp.cs | 53 + .../BenchControl/Operations/CheckUIOp.cs | 109 + .../BenchControl/Operations/ClearResultsOp.cs | 25 + .../Operations/EmptyBalanceTankOp.cs | 51 + .../Operations/LoadProcedureOp.cs | 75 + .../BenchControl/Operations/OpTemplate.cs | 61 + .../Operations/ReadMoreRegistersOp.cs | 134 + .../Operations/SetAllRegulValvesOp.cs | 76 + .../BenchControl/Operations/TimerOp.cs | 72 + TestBenchFramework/BenchControl/OutputPath.cs | 52 + .../Basic/BasicPrintDocument.cs | 111 + .../ResultsPrinters/Basic/Printer.cs | 67 + .../ResultsPrinters/Basic/PrinterCfg.cs | 54 + .../Basic/PrinterCfgCtrl.Designer.cs | 83 + .../ResultsPrinters/Basic/PrinterCfgCtrl.cs | 58 + .../ResultsPrinters/Basic/PrinterCfgCtrl.resx | 120 + .../ResultsPrinters/Basic/PrinterFactory.cs | 40 + .../Munich/MunichPrintDocument.cs | 325 + .../ResultsPrinters/Munich/Printer.cs | 86 + .../ResultsPrinters/Munich/PrinterCfg.cs | 54 + .../ResultsPrinters/Munich/PrinterCfgCtrl.cs | 58 + .../Munich/PrinterCfgCtrl.designer.cs | 83 + .../Munich/PrinterCfgCtrl.resx | 120 + .../ResultsPrinters/Munich/PrinterFactory.cs | 43 + .../ResultsPrinters/Munich/ProcParams.cs | 163 + .../ResultsWriters/Basic/Writer.cs | 140 + .../ResultsWriters/Basic/WriterCfg.cs | 54 + .../ResultsWriters/Basic/WriterCfgCtrl.cs | 58 + .../Basic/WriterCfgCtrl.designer.cs | 83 + .../ResultsWriters/Basic/WriterCfgCtrl.resx | 120 + .../ResultsWriters/Basic/WriterFactory.cs | 40 + .../BenchControl/Sequences/MainSeq.cs | 533 + .../BenchControl/Sequences/SequenceBase.cs | 589 + TestBenchFramework/BenchControl/State.cs | 199 + .../BenchControl/StateMachine.cs | 513 + .../BenchControl/TbfComponents.cs | 150 + .../BenchControl/TestBenchSim.cs | 377 + .../CameraRoiDetection/RoiDetection.cs | 27 + .../CameraRoiDetection/RoiDetectionCfg.cs | 54 + .../CameraRoiDetection/RoiDetectionCfgCtrl.cs | 58 + .../RoiDetectionCfgCtrl.designer.cs | 79 + .../RoiDetectionCfgCtrl.resx | 120 + .../CameraRoiDetection/RoiDetectionFactory.cs | 40 + .../CameraRoiDetection/RoiDetectionSeq.cs | 245 + .../CombinedMeters/CombinedMetersSeq.cs | 483 + .../TestMethods/CombinedMeters/TestMethod.cs | 27 + .../CombinedMeters/TestMethodCfg.cs | 54 + .../CombinedMeters/TestMethodCfgCtrl.cs | 58 + .../TestMethodCfgCtrl.designer.cs | 83 + .../CombinedMeters/TestMethodCfgCtrl.resx | 120 + .../CombinedMeters/TestMethodFactory.cs | 41 + .../CombinedWithDetTestParams.cs | 177 + .../CombinedWithDetectionSeq.cs | 668 + .../CombinedWithDetection/TestMethod.cs | 29 + .../CombinedWithDetection/TestMethodCfg.cs | 54 + .../TestMethodCfgCtrl.cs | 58 + .../TestMethodCfgCtrl.designer.cs | 83 + .../TestMethodCfgCtrl.resx | 120 + .../TestMethodFactory.cs | 45 + .../FlyingStartCollectionMethodSeq.cs | 466 + .../FlyingStartCollectionMethod/TestMethod.cs | 27 + .../TestMethodCfg.cs | 54 + .../TestMethodCfgCtrl.cs | 58 + .../TestMethodCfgCtrl.designer.cs | 83 + .../TestMethodCfgCtrl.resx | 120 + .../TestMethodFactory.cs | 40 + TestBenchFramework/BenchControl/Transition.cs | 32 + .../BenchControl/WaterMeter/ProcParams.cs | 170 + .../BenchControl/WaterMeter/WaterMeter.cs | 69 + .../BenchControl/WaterMeter/WaterMeterCfg.cs | 66 + .../WaterMeter/WaterMeterCfgCtrl.cs | 60 + .../WaterMeter/WaterMeterCfgCtrl.designer.cs | 83 + .../WaterMeter/WaterMeterCfgCtrl.resx | 120 + .../WaterMeter/WaterMeterFactory.cs | 43 + TestBenchFramework/BenchesDlg.Designer.cs | 137 + TestBenchFramework/BenchesDlg.cs | 199 + TestBenchFramework/BenchesDlg.de.resx | 148 + TestBenchFramework/BenchesDlg.resx | 339 + .../ComponentParametersDlg.Designer.cs | 86 + TestBenchFramework/ComponentParametersDlg.cs | 87 + .../ComponentParametersDlg.de.resx | 130 + .../ComponentParametersDlg.resx | 120 + .../ComponentsManagerDlg.Designer.cs | 95 + TestBenchFramework/ComponentsManagerDlg.cs | 313 + TestBenchFramework/ComponentsManagerDlg.resx | 243 + TestBenchFramework/CustomStyle.cs | 83 + TestBenchFramework/DBSettings.cs | 28 + TestBenchFramework/DatabaseSettings.cs | 48 + .../DatabaseSettingsDlg.Designer.cs | 370 + TestBenchFramework/DatabaseSettingsDlg.cs | 261 + TestBenchFramework/DatabaseSettingsDlg.resx | 930 + TestBenchFramework/Entities/BenchPath.cs | 78 + TestBenchFramework/Entities/Component.cs | 71 + .../Entities/ComponentProcedure.cs | 19 + TestBenchFramework/Entities/ComponentTest.cs | 19 + TestBenchFramework/Entities/Enums.cs | 78 + TestBenchFramework/Entities/FeedingPath.cs | 69 + TestBenchFramework/Entities/Group.cs | 12 + TestBenchFramework/Entities/IHasItemNr.cs | 9 + TestBenchFramework/Entities/IHasValves.cs | 9 + .../Entities/MeasurementCorrection.cs | 11 + .../Entities/MeterTestResult.cs | 48 + TestBenchFramework/Entities/MetersPath.cs | 157 + TestBenchFramework/Entities/OutputPath.cs | 85 + TestBenchFramework/Entities/Procedure.cs | 78 + .../Entities/ProcedureHistory.cs | 28 + TestBenchFramework/Entities/Test.cs | 78 + TestBenchFramework/Entities/TestResult.cs | 142 + .../Entities/TransitionSequence.cs | 37 + TestBenchFramework/Entities/TransitionStep.cs | 52 + TestBenchFramework/Entities/User.cs | 226 + TestBenchFramework/Entities/WMType.cs | 75 + TestBenchFramework/Entities/Watermeter.cs | 38 + TestBenchFramework/ErrorHandler.cs | 31 + TestBenchFramework/FluentCommon.cs | 317 + TestBenchFramework/Forms/AboutDlg.Designer.cs | 100 + TestBenchFramework/Forms/AboutDlg.cs | 28 + TestBenchFramework/Forms/AboutDlg.de.resx | 136 + TestBenchFramework/Forms/AboutDlg.resx | 279 + .../Forms/ClosingProgram.Designer.cs | 66 + TestBenchFramework/Forms/ClosingProgram.cs | 31 + TestBenchFramework/Forms/ClosingProgram.resx | 120 + .../Forms/EditSelectedUser.Designer.cs | 145 + TestBenchFramework/Forms/EditSelectedUser.cs | 175 + .../Forms/EditSelectedUser.de.resx | 181 + .../Forms/EditSelectedUser.resx | 398 + .../Forms/EditUsers.Designer.cs | 125 + TestBenchFramework/Forms/EditUsers.cs | 120 + TestBenchFramework/Forms/EditUsers.de.resx | 132 + TestBenchFramework/Forms/EditUsers.resx | 308 + TestBenchFramework/Forms/EmergencyStopForm.cs | 56 + .../Forms/EmergencyStopForm.designer.cs | 73 + .../Forms/EmergencyStopForm.resx | 120 + .../Forms/EnterPasswordDlg.Designer.cs | 106 + TestBenchFramework/Forms/EnterPasswordDlg.cs | 48 + .../Forms/EnterPasswordDlg.resx | 120 + TestBenchFramework/Forms/ErrorDlg.Designer.cs | 106 + TestBenchFramework/Forms/ErrorDlg.cs | 53 + TestBenchFramework/Forms/ErrorDlg.de.resx | 126 + TestBenchFramework/Forms/ErrorDlg.resx | 243 + .../Forms/NoBenchOrDatabaseDlg.Designer.cs | 120 + .../Forms/NoBenchOrDatabaseDlg.cs | 48 + .../Forms/NoBenchOrDatabaseDlg.resx | 272 + .../Forms/ResultsConfig.Designer.cs | 254 + TestBenchFramework/Forms/ResultsConfig.cs | 195 + TestBenchFramework/Forms/ResultsConfig.resx | 120 + .../Forms/TabNameDlg.Designer.cs | 73 + TestBenchFramework/Forms/TabNameDlg.cs | 31 + TestBenchFramework/Forms/TabNameDlg.resx | 120 + TestBenchFramework/Grp.cs | 98 + TestBenchFramework/LocalSettings.cs | 135 + TestBenchFramework/LoginDlg.Designer.cs | 107 + TestBenchFramework/LoginDlg.cs | 124 + TestBenchFramework/LoginDlg.de.resx | 142 + TestBenchFramework/LoginDlg.resx | 291 + .../LoginDlgWithBenchSelection.cs | 111 + .../LoginDlgWithBenchSelection.de.resx | 145 + .../LoginDlgWithBenchSelection.designer.cs | 130 + .../LoginDlgWithBenchSelection.resx | 339 + .../LoginDlgWithBenchSelection.sk.resx | 157 + TestBenchFramework/MainWnd.Designer.cs | 578 + TestBenchFramework/MainWnd.cs | 408 + TestBenchFramework/MainWnd.de.resx | 314 + TestBenchFramework/MainWnd.resx | 1203 + TestBenchFramework/Mappings/BenchPathMap.cs | 27 + TestBenchFramework/Mappings/ComponentMap.cs | 25 + .../Mappings/ComponentProcedureMap.cs | 19 + .../Mappings/ComponentTestMap.cs | 19 + TestBenchFramework/Mappings/FeedingPathMap.cs | 24 + TestBenchFramework/Mappings/GroupMap.cs | 14 + .../Mappings/MeasurementCorrectionMap.cs | 15 + .../Mappings/MeterTestResultMap.cs | 23 + TestBenchFramework/Mappings/MetersPathMap.cs | 39 + TestBenchFramework/Mappings/OutputPathMap.cs | 29 + TestBenchFramework/Mappings/ProcedureMap.cs | 34 + TestBenchFramework/Mappings/TestMap.cs | 36 + TestBenchFramework/Mappings/TestResultMap.cs | 93 + .../Mappings/TransitionSequenceMap.cs | 19 + .../Mappings/TransitionStepMap.cs | 24 + TestBenchFramework/Mappings/UserMap.cs | 18 + TestBenchFramework/Mappings/WMTypeMap.cs | 17 + TestBenchFramework/Mappings/WatermeterMap.cs | 16 + TestBenchFramework/MetrologyDlg.Designer.cs | 100 + TestBenchFramework/MetrologyDlg.cs | 145 + TestBenchFramework/MetrologyDlg.resx | 120 + TestBenchFramework/PathsDlg.Designer.cs | 190 + TestBenchFramework/PathsDlg.cs | 178 + TestBenchFramework/PathsDlg.de.resx | 135 + TestBenchFramework/PathsDlg.resx | 450 + TestBenchFramework/PreferencesDlg.Designer.cs | 90 + TestBenchFramework/PreferencesDlg.cs | 71 + TestBenchFramework/PreferencesDlg.de.resx | 148 + TestBenchFramework/PreferencesDlg.resx | 243 + TestBenchFramework/ProcedureDlg.Designer.cs | 464 + TestBenchFramework/ProcedureDlg.cs | 1084 + TestBenchFramework/ProcedureDlg.de.resx | 311 + TestBenchFramework/ProcedureDlg.resx | 1176 + TestBenchFramework/ProceduresDlg.Designer.cs | 103 + TestBenchFramework/ProceduresDlg.cs | 153 + TestBenchFramework/ProceduresDlg.resx | 120 + TestBenchFramework/Program.cs | 247 + TestBenchFramework/Properties/AssemblyInfo.cs | 33 + ...enchFramework.Entities.Pressure.datasource | 10 + .../Properties/Resources.Designer.cs | 113 + TestBenchFramework/Properties/Resources.resx | 136 + .../Properties/Settings.Designer.cs | 26 + .../Properties/Settings.settings | 7 + TestBenchFramework/Resources/Headpic.png | Bin 0 -> 21028 bytes .../Resources/Strings.Designer.cs | 2145 + .../Resources/Strings.de.Designer.cs | 0 TestBenchFramework/Resources/Strings.de.resx | 738 + TestBenchFramework/Resources/Strings.resx | 814 + TestBenchFramework/Resources/Strings.sk.resx | 288 + .../Resources/TestFailedImage.png | Bin 0 -> 263 bytes .../Resources/TestNotDoneImage.png | Bin 0 -> 317 bytes .../Resources/TestPassedImage.png | Bin 0 -> 250 bytes TestBenchFramework/Resources/sensus-logo.png | Bin 0 -> 21342 bytes TestBenchFramework/SampleConfig/SQLite.db | Bin 0 -> 45056 bytes TestBenchFramework/SampleConfig/config.xml | 55 + TestBenchFramework/SampleConfig/fuzhou150.sql | 742 + TestBenchFramework/SampleConfig/gwz-1-new.sql | 1754 + .../SampleConfig/log4netConfig.xml | 67 + .../SampleConfig/munich-gwz-1.sql | 1166 + TestBenchFramework/SampleConfig/sensus.sql | 1147 + .../Screens/LogsTabPageCtrl.Designer.cs | 100 + TestBenchFramework/Screens/LogsTabPageCtrl.cs | 35 + .../Screens/LogsTabPageCtrl.resx | 291 + .../MeasurementTabPageCtrl.Designer.cs | 205 + .../Screens/MeasurementTabPageCtrl.cs | 178 + .../Screens/MeasurementTabPageCtrl.resx | 120 + .../Screens/PicturesTabPageCtrl.Designer.cs | 174 + .../Screens/PicturesTabPageCtrl.cs | 82 + .../Screens/PicturesTabPageCtrl.resx | 462 + .../Screens/ProcessTabPageCtrl.Designer.cs | 1081 + .../Screens/ProcessTabPageCtrl.cs | 280 + .../Screens/ProcessTabPageCtrl.resx | 120 + .../Screens/ResultsTabPageCtrl.Designer.cs | 118 + .../Screens/ResultsTabPageCtrl.cs | 421 + .../Screens/ResultsTabPageCtrl.resx | 120 + .../SelectComponentClassDlg.Designer.cs | 95 + TestBenchFramework/SelectComponentClassDlg.cs | 63 + .../SelectComponentClassDlg.de.resx | 133 + .../SelectComponentClassDlg.resx | 240 + TestBenchFramework/TBF.csproj | 1176 + TestBenchFramework/TestProgressControls.cs | 136 + .../TestWizard/FlowSelection.Designer.cs | 192 + .../TestWizard/FlowSelection.cs | 98 + .../TestWizard/FlowSelection.resx | 120 + .../TestWizard/MethodSelection.Designer.cs | 170 + .../TestWizard/MethodSelection.cs | 111 + .../TestWizard/MethodSelection.resx | 120 + .../TestWizard/SensorsSelection.Designer.cs | 116 + .../TestWizard/SensorsSelection.cs | 80 + .../TestWizard/SensorsSelection.resx | 120 + .../VolumeAndErrorSelection.Designer.cs | 214 + .../TestWizard/VolumeAndErrorSelection.cs | 129 + .../TestWizard/VolumeAndErrorSelection.resx | 120 + TestBenchFramework/Tools/ByteFormatter.cs | 59 + TestBenchFramework/Tools/IniUtil.cs | 105 + TestBenchFramework/Tools/XmlTools.cs | 27 + TestBenchFramework/TransitionsDlg.Designer.cs | 88 + TestBenchFramework/TransitionsDlg.cs | 276 + TestBenchFramework/TransitionsDlg.de.resx | 321 + TestBenchFramework/TransitionsDlg.resx | 249 + .../UiBridge/ActivityEventArgs.cs | 14 + TestBenchFramework/UiBridge/Bridge.cs | 188 + .../UiBridge/ButtonsEtcEventArgs.cs | 17 + .../UiBridge/CameraStateChangedEventArgs.cs | 17 + .../UiBridge/EmergencyStopEventArgs.cs | 22 + TestBenchFramework/UiBridge/Enums.cs | 52 + .../UiBridge/ImageUpdatedEventArgs.cs | 17 + TestBenchFramework/UiBridge/LogEventArgs.cs | 14 + .../UiBridge/ProcedureCompletedEventArgs.cs | 15 + .../UiBridge/ProcedureSelectedEventArgs.cs | 15 + .../UiBridge/StateChangedEventArgs.cs | 14 + .../UiBridge/TestCompletedEventArgs.cs | 14 + .../UiBridge/TestProgressEventArgs.cs | 30 + .../UiBridge/TestSelectedEventArgs.cs | 27 + .../UiControls/BaseWithListViewEx.cs | 203 + .../UiControls/BenchControlPanel.Designer.cs | 289 + .../UiControls/BenchControlPanel.cs | 271 + .../UiControls/BenchControlPanel.de.resx | 295 + .../UiControls/BenchControlPanel.resx | 786 + .../UiControls/CameraPictureCtrl.Designer.cs | 141 + .../UiControls/CameraPictureCtrl.cs | 63 + .../UiControls/CameraPictureCtrl.resx | 120 + .../UiControls/IMetrologyDlgTab.cs | 18 + .../UiControls/IParentOfListViewEx.cs | 8 + .../UiControls/ITabWithListViewEx.cs | 18 + TestBenchFramework/UiControls/ListViewEx.cs | 451 + TestBenchFramework/UiControls/ListViewEx.resx | 42 + .../MetrologyDlgBalanceTab.Designer.cs | 179 + .../UiControls/MetrologyDlgBalanceTab.cs | 234 + .../UiControls/MetrologyDlgBalanceTab.resx | 120 + .../MetrologyDlgFlowMeterTab.Designer.cs | 180 + .../UiControls/MetrologyDlgFlowMeterTab.cs | 233 + .../UiControls/MetrologyDlgFlowMeterTab.resx | 120 + .../MetrologyDlgPressMeterTab.Designer.cs | 180 + .../UiControls/MetrologyDlgPressMeterTab.cs | 233 + .../UiControls/MetrologyDlgPressMeterTab.resx | 120 + .../UiControls/PathsBenchCtrl.cs | 247 + .../UiControls/PathsFeedingCtrl.cs | 225 + .../UiControls/PathsMetersCtrl.cs | 179 + .../UiControls/PathsOutputCtrl.cs | 255 + .../ProcedureParamsCtrl.Designer.cs | 62 + .../UiControls/ProcedureParamsCtrl.cs | 165 + .../UiControls/ProcedureParamsCtrl.resx | 120 + .../UiControls/ProceduresCtrl.cs | 204 + .../UiControls/SharedButtons.Designer.cs | 215 + .../UiControls/SharedButtons.cs | 251 + .../UiControls/SharedButtons.resx | 120 + .../UiControls/TestParamsCtrl.Designer.cs | 62 + .../UiControls/TestParamsCtrl.cs | 193 + .../UiControls/TestParamsCtrl.resx | 120 + .../UiControls/TestProgressCtrl.Designer.cs | 73 + .../UiControls/TestProgressCtrl.cs | 77 + .../UiControls/TestProgressCtrl.resx | 120 + .../UiControls/TransitionStepsCtrl.cs | 219 + TestBenchFramework/Utils.cs | 136 + TestBenchFramework/app.config | 6 + TestBenchFramework/packages.config | 9 + TestBenchFramework/x64/SQLite.Interop.dll | Bin 0 -> 1123840 bytes TestBenchFramework/x86/SQLite.Interop.dll | Bin 0 -> 867328 bytes packages/ControlBoard/ControlCom2VB.dll | Bin 0 -> 175616 bytes .../ControlBoard/ControlComponent3Munich.dll | Bin 0 -> 264704 bytes packages/ControlBoard/ControlComponent3U.dll | Bin 0 -> 341504 bytes packages/ControlBoard/GaugeIndicator.dll | Bin 0 -> 15872 bytes packages/ControlBoard/procedure.txt | 0 packages/ControlBoard/readme.txt | 3 + .../FluentNHibernate.1.3.0.733.nupkg | Bin 0 -> 298273 bytes .../FluentNHibernate.1.3.0.733.nuspec | 21 + .../lib/FluentNHibernate.XML | 5766 ++ .../lib/FluentNHibernate.dll | Bin 0 -> 512000 bytes .../Iesi.Collections.3.2.0.4000.nupkg | Bin 0 -> 28356 bytes .../Iesi.Collections.3.2.0.4000.nuspec | 16 + .../lib/Net35/Iesi.Collections.dll | Bin 0 -> 32768 bytes .../lib/Net35/Iesi.Collections.xml | 1903 + .../lib/net40/Microsoft.VisualBasic.dll | Bin 0 -> 152424 bytes .../lib/net40/Microsoft.VisualBasic.xml | 10708 ++++ .../MySql.Data.6.6.5/MySql.Data.6.6.5.nupkg | Bin 0 -> 460360 bytes .../MySql.Data.6.6.5/MySql.Data.6.6.5.nuspec | 19 + .../MySql.Data.6.6.5/lib/net20/MySql.Data.dll | Bin 0 -> 392704 bytes .../MySql.Data.6.6.5/lib/net40/MySql.Data.dll | Bin 0 -> 391680 bytes .../ConfigurationTemplates/FireBird.cfg.xml | 30 + .../ConfigurationTemplates/MSSQL.cfg.xml | 16 + .../ConfigurationTemplates/MySql.cfg.xml | 16 + .../ConfigurationTemplates/Oracle.cfg.xml | 18 + .../ConfigurationTemplates/PostgreSQL.cfg.xml | 15 + .../ConfigurationTemplates/SQLite.cfg.xml | 15 + .../ConfigurationTemplates/SybaseASE.cfg.xml | 16 + .../SybaseSQLAnywhere.cfg.xml | 16 + .../NHibernate.3.3.3.4001.nupkg | Bin 0 -> 1944056 bytes .../NHibernate.3.3.3.4001.nuspec | 20 + .../NHibernate.license.txt | 460 + .../NHibernate.readme.html | 54 + .../NHibernate.releasenotes.txt | 2637 + .../lib/Net35/NHibernate.dll | Bin 0 -> 3599360 bytes .../lib/Net35/NHibernate.xml | 44178 ++++++++++++++++ .../nhibernate-configuration.xsd | 226 + .../nhibernate-mapping.xsd | 1699 + .../System.Data.SQLite.1.0.90.0.nupkg | Bin 0 -> 5153838 bytes .../System.Data.SQLite.1.0.90.0.nuspec | 19 + .../content/net40/x64/SQLite.Interop.dll | Bin 0 -> 1123840 bytes .../content/net40/x86/SQLite.Interop.dll | Bin 0 -> 867328 bytes .../lib/net40/System.Data.SQLite.Linq.dll | Bin 0 -> 183296 bytes .../lib/net40/System.Data.SQLite.dll | Bin 0 -> 261120 bytes .../lib/net40/System.Data.SQLite.xml | 12758 +++++ .../tools/install.ps1 | 36 + .../log4net.2.0.2/lib/net40-full/log4net.dll | Bin 0 -> 298496 bytes .../log4net.2.0.2/lib/net40-full/log4net.xml | 31809 +++++++++++ packages/log4net.2.0.2/log4net.2.0.2.nupkg | Bin 0 -> 1921263 bytes packages/log4net.2.0.2/log4net.2.0.2.nuspec | 23 + packages/repositories.config | 4 + 575 files changed, 186534 insertions(+) create mode 100644 TestBenchFramework.sln create mode 100644 TestBenchFramework/AboutDlg.Designer.cs create mode 100644 TestBenchFramework/AboutDlg.cs create mode 100644 TestBenchFramework/AboutDlg.resx create mode 100644 TestBenchFramework/AttachedTextBoxes.cs create mode 100644 TestBenchFramework/BarGraph.cs create mode 100644 TestBenchFramework/BenchControl/BenchId/Component.cs create mode 100644 TestBenchFramework/BenchControl/BenchId/ComponentCfg.cs create mode 100644 TestBenchFramework/BenchControl/BenchId/ComponentCfgCtrl.cs create mode 100644 TestBenchFramework/BenchControl/BenchId/ComponentCfgCtrl.designer.cs create mode 100644 TestBenchFramework/BenchControl/BenchId/ComponentCfgCtrl.resx create mode 100644 TestBenchFramework/BenchControl/BenchId/ComponentFactory.cs create mode 100644 TestBenchFramework/BenchControl/BenchPath.cs create mode 100644 TestBenchFramework/BenchControl/Cameras/CameraRoi/CameraRoi.cs create mode 100644 TestBenchFramework/BenchControl/Cameras/CameraRoi/CameraRoiCfg.cs create mode 100644 TestBenchFramework/BenchControl/Cameras/CameraRoi/CameraRoiCfgCtrl.cs create mode 100644 TestBenchFramework/BenchControl/Cameras/CameraRoi/CameraRoiCfgCtrl.designer.cs create mode 100644 TestBenchFramework/BenchControl/Cameras/CameraRoi/CameraRoiCfgCtrl.resx create mode 100644 TestBenchFramework/BenchControl/Cameras/CameraRoi/CameraRoiFactory.cs create mode 100644 TestBenchFramework/BenchControl/Cameras/CameraRoi/ReadRegisterOp.cs create mode 100644 TestBenchFramework/BenchControl/Cameras/CameraRoi/RoiProcedureParams.cs create mode 100644 TestBenchFramework/BenchControl/Cameras/IdcCamera/Command/Connect.cs create mode 100644 TestBenchFramework/BenchControl/Cameras/IdcCamera/Command/Detect.cs create mode 100644 TestBenchFramework/BenchControl/Cameras/IdcCamera/Command/Disconnect.cs create mode 100644 TestBenchFramework/BenchControl/Cameras/IdcCamera/Command/Grab.cs create mode 100644 TestBenchFramework/BenchControl/Cameras/IdcCamera/Command/Measure.cs create mode 100644 TestBenchFramework/BenchControl/Cameras/IdcCamera/Command/Other.cs create mode 100644 TestBenchFramework/BenchControl/Cameras/IdcCamera/Command/Save.cs create mode 100644 TestBenchFramework/BenchControl/Cameras/IdcCamera/Command/SetBrightness.cs create mode 100644 TestBenchFramework/BenchControl/Cameras/IdcCamera/Command/StartNew.cs create mode 100644 TestBenchFramework/BenchControl/Cameras/IdcCamera/Command/StopOp.cs create mode 100644 TestBenchFramework/BenchControl/Cameras/IdcCamera/Command/StopStream.cs create mode 100644 TestBenchFramework/BenchControl/Cameras/IdcCamera/Command/Stream.cs create mode 100644 TestBenchFramework/BenchControl/Cameras/IdcCamera/IWorkerCmd.cs create mode 100644 TestBenchFramework/BenchControl/Cameras/IdcCamera/Idc100.cs create mode 100644 TestBenchFramework/BenchControl/Cameras/IdcCamera/IdcCamera.cs create mode 100644 TestBenchFramework/BenchControl/Cameras/IdcCamera/IdcCameraCfg.cs create mode 100644 TestBenchFramework/BenchControl/Cameras/IdcCamera/IdcCameraCfgCtrl.cs create mode 100644 TestBenchFramework/BenchControl/Cameras/IdcCamera/IdcCameraCfgCtrl.designer.cs create mode 100644 TestBenchFramework/BenchControl/Cameras/IdcCamera/IdcCameraCfgCtrl.resx create mode 100644 TestBenchFramework/BenchControl/Cameras/IdcCamera/IdcCameraFactory.cs create mode 100644 TestBenchFramework/BenchControl/Cameras/IdcCamera/IdcEnums.cs create mode 100644 TestBenchFramework/BenchControl/Cameras/IdcCamera/SerialFileIO.cs create mode 100644 TestBenchFramework/BenchControl/Cameras/IdcCamera/SerialLayer.cs create mode 100644 TestBenchFramework/BenchControl/ComponentBase.cs create mode 100644 TestBenchFramework/BenchControl/ComponentCfgBase.cs create mode 100644 TestBenchFramework/BenchControl/Constants.cs create mode 100644 TestBenchFramework/BenchControl/Current.cs create mode 100644 TestBenchFramework/BenchControl/DataEntry/Munich/CycleBeginningForm.Designer.cs create mode 100644 TestBenchFramework/BenchControl/DataEntry/Munich/CycleBeginningForm.cs create mode 100644 TestBenchFramework/BenchControl/DataEntry/Munich/CycleBeginningForm.resx create mode 100644 TestBenchFramework/BenchControl/DataEntry/Munich/CycleEndForm.Designer.cs create mode 100644 TestBenchFramework/BenchControl/DataEntry/Munich/CycleEndForm.cs create mode 100644 TestBenchFramework/BenchControl/DataEntry/Munich/CycleEndForm.resx create mode 100644 TestBenchFramework/BenchControl/DataEntry/Munich/EntryForm.cs create mode 100644 TestBenchFramework/BenchControl/DataEntry/Munich/EntryFormCfg.cs create mode 100644 TestBenchFramework/BenchControl/DataEntry/Munich/EntryFormCfgCtrl.cs create mode 100644 TestBenchFramework/BenchControl/DataEntry/Munich/EntryFormCfgCtrl.designer.cs create mode 100644 TestBenchFramework/BenchControl/DataEntry/Munich/EntryFormCfgCtrl.resx create mode 100644 TestBenchFramework/BenchControl/DataEntry/Munich/EntryFormFactory.cs create mode 100644 TestBenchFramework/BenchControl/Elde/Common.cs create mode 100644 TestBenchFramework/BenchControl/Elde/ControlBoardCfg.cs create mode 100644 TestBenchFramework/BenchControl/Elde/ControlBoardCfgCtrl.Designer.cs create mode 100644 TestBenchFramework/BenchControl/Elde/ControlBoardCfgCtrl.cs create mode 100644 TestBenchFramework/BenchControl/Elde/ControlBoardCfgCtrl.resx create mode 100644 TestBenchFramework/BenchControl/Elde/ControlBoardDev.cs create mode 100644 TestBenchFramework/BenchControl/Elde/ControlBoardFactory.cs create mode 100644 TestBenchFramework/BenchControl/Elde/ControlComSim.cs create mode 100644 TestBenchFramework/BenchControl/Elde/ControlComWrap.cs create mode 100644 TestBenchFramework/BenchControl/Elde/Diverter/Diverter.cs create mode 100644 TestBenchFramework/BenchControl/Elde/Diverter/DiverterCfg.cs create mode 100644 TestBenchFramework/BenchControl/Elde/Diverter/DiverterCfgCtrl.Designer.cs create mode 100644 TestBenchFramework/BenchControl/Elde/Diverter/DiverterCfgCtrl.cs create mode 100644 TestBenchFramework/BenchControl/Elde/Diverter/DiverterCfgCtrl.resx create mode 100644 TestBenchFramework/BenchControl/Elde/Diverter/DiverterFactory.cs create mode 100644 TestBenchFramework/BenchControl/Elde/FlowMeter/FlowMeter.cs create mode 100644 TestBenchFramework/BenchControl/Elde/FlowMeter/FlowMeterCfg.cs create mode 100644 TestBenchFramework/BenchControl/Elde/FlowMeter/FlowMeterCfgCtrl.Designer.cs create mode 100644 TestBenchFramework/BenchControl/Elde/FlowMeter/FlowMeterCfgCtrl.cs create mode 100644 TestBenchFramework/BenchControl/Elde/FlowMeter/FlowMeterCfgCtrl.resx create mode 100644 TestBenchFramework/BenchControl/Elde/FlowMeter/FlowMeterFactory.cs create mode 100644 TestBenchFramework/BenchControl/Elde/FlowMeter/ReadFlowOp.cs create mode 100644 TestBenchFramework/BenchControl/Elde/IControlCom.cs create mode 100644 TestBenchFramework/BenchControl/Elde/PressureMeter/PressureMeter.cs create mode 100644 TestBenchFramework/BenchControl/Elde/PressureMeter/PressureMeterCfg.cs create mode 100644 TestBenchFramework/BenchControl/Elde/PressureMeter/PressureMeterCfgCtrl.Designer.cs create mode 100644 TestBenchFramework/BenchControl/Elde/PressureMeter/PressureMeterCfgCtrl.cs create mode 100644 TestBenchFramework/BenchControl/Elde/PressureMeter/PressureMeterCfgCtrl.resx create mode 100644 TestBenchFramework/BenchControl/Elde/PressureMeter/PressureMeterFactory.cs create mode 100644 TestBenchFramework/BenchControl/Elde/PressureMeter/ReadPressureOp.cs create mode 100644 TestBenchFramework/BenchControl/Elde/Pump/Pump.cs create mode 100644 TestBenchFramework/BenchControl/Elde/Pump/PumpCfg.cs create mode 100644 TestBenchFramework/BenchControl/Elde/Pump/PumpCfgCtrl.Designer.cs create mode 100644 TestBenchFramework/BenchControl/Elde/Pump/PumpCfgCtrl.cs create mode 100644 TestBenchFramework/BenchControl/Elde/Pump/PumpCfgCtrl.resx create mode 100644 TestBenchFramework/BenchControl/Elde/Pump/PumpFactory.cs create mode 100644 TestBenchFramework/BenchControl/Elde/PumpWithFM/FMPumpTestParams.cs create mode 100644 TestBenchFramework/BenchControl/Elde/PumpWithFM/Pump.cs create mode 100644 TestBenchFramework/BenchControl/Elde/PumpWithFM/PumpCfg.cs create mode 100644 TestBenchFramework/BenchControl/Elde/PumpWithFM/PumpCfgCtrl.Designer.cs create mode 100644 TestBenchFramework/BenchControl/Elde/PumpWithFM/PumpCfgCtrl.cs create mode 100644 TestBenchFramework/BenchControl/Elde/PumpWithFM/PumpCfgCtrl.resx create mode 100644 TestBenchFramework/BenchControl/Elde/PumpWithFM/PumpFactory.cs create mode 100644 TestBenchFramework/BenchControl/Elde/QueryMeasurementEndOp.cs create mode 100644 TestBenchFramework/BenchControl/Elde/RegisterReader/RRProcedureParams.cs create mode 100644 TestBenchFramework/BenchControl/Elde/RegisterReader/ReadReferenceForRegisterOp.cs create mode 100644 TestBenchFramework/BenchControl/Elde/RegisterReader/ReadRegisterOp.cs create mode 100644 TestBenchFramework/BenchControl/Elde/RegisterReader/RegisterReader.cs create mode 100644 TestBenchFramework/BenchControl/Elde/RegisterReader/RegisterReaderCfg.cs create mode 100644 TestBenchFramework/BenchControl/Elde/RegisterReader/RegisterReaderCfgCtrl.Designer.cs create mode 100644 TestBenchFramework/BenchControl/Elde/RegisterReader/RegisterReaderCfgCtrl.cs create mode 100644 TestBenchFramework/BenchControl/Elde/RegisterReader/RegisterReaderCfgCtrl.resx create mode 100644 TestBenchFramework/BenchControl/Elde/RegisterReader/RegisterReaderFactory.cs create mode 100644 TestBenchFramework/BenchControl/Elde/RegulValve/ChangeValvePositionOp.cs create mode 100644 TestBenchFramework/BenchControl/Elde/RegulValve/RegulValve.cs create mode 100644 TestBenchFramework/BenchControl/Elde/RegulValve/RegulValveCfg.cs create mode 100644 TestBenchFramework/BenchControl/Elde/RegulValve/RegulValveCfgCtrl.Designer.cs create mode 100644 TestBenchFramework/BenchControl/Elde/RegulValve/RegulValveCfgCtrl.cs create mode 100644 TestBenchFramework/BenchControl/Elde/RegulValve/RegulValveCfgCtrl.resx create mode 100644 TestBenchFramework/BenchControl/Elde/RegulValve/RegulValveFactory.cs create mode 100644 TestBenchFramework/BenchControl/Elde/RegulValve/SetFlowOp.cs create mode 100644 TestBenchFramework/BenchControl/Elde/RegulValve/SetRegulValvePositionOp.cs create mode 100644 TestBenchFramework/BenchControl/Elde/StartMeasurementOp.cs create mode 100644 TestBenchFramework/BenchControl/Elde/StopPreviousOp.cs create mode 100644 TestBenchFramework/BenchControl/Elde/TempMeter/ReadTempOp.cs create mode 100644 TestBenchFramework/BenchControl/Elde/TempMeter/TempMeter.cs create mode 100644 TestBenchFramework/BenchControl/Elde/TempMeter/TempMeterCfg.cs create mode 100644 TestBenchFramework/BenchControl/Elde/TempMeter/TempMeterCfgCtrl.Designer.cs create mode 100644 TestBenchFramework/BenchControl/Elde/TempMeter/TempMeterCfgCtrl.cs create mode 100644 TestBenchFramework/BenchControl/Elde/TempMeter/TempMeterCfgCtrl.resx create mode 100644 TestBenchFramework/BenchControl/Elde/TempMeter/TempMeterFactory.cs create mode 100644 TestBenchFramework/BenchControl/Elde/UpdateTankWeightOp.cs create mode 100644 TestBenchFramework/BenchControl/Elde/Valve/SetValvesOp.cs create mode 100644 TestBenchFramework/BenchControl/Elde/Valve/Valve.cs create mode 100644 TestBenchFramework/BenchControl/Elde/Valve/ValveCfg.cs create mode 100644 TestBenchFramework/BenchControl/Elde/Valve/ValveCfgCtrl.Designer.cs create mode 100644 TestBenchFramework/BenchControl/Elde/Valve/ValveCfgCtrl.cs create mode 100644 TestBenchFramework/BenchControl/Elde/Valve/ValveCfgCtrl.resx create mode 100644 TestBenchFramework/BenchControl/Elde/Valve/ValveFactory.cs create mode 100644 TestBenchFramework/BenchControl/Events.cs create mode 100644 TestBenchFramework/BenchControl/FeedingPath.cs create mode 100644 TestBenchFramework/BenchControl/FloatBox.cs create mode 100644 TestBenchFramework/BenchControl/Formulas.cs create mode 100644 TestBenchFramework/BenchControl/Generic/IChildComponentCfg.cs create mode 100644 TestBenchFramework/BenchControl/Generic/IComponent.cs create mode 100644 TestBenchFramework/BenchControl/Generic/IComponentCfg.cs create mode 100644 TestBenchFramework/BenchControl/Generic/IComponentCfgCtrl.cs create mode 100644 TestBenchFramework/BenchControl/Generic/IComponentFactory.cs create mode 100644 TestBenchFramework/BenchControl/Generic/IDevice.cs create mode 100644 TestBenchFramework/BenchControl/Generic/IParamsProvider.cs create mode 100644 TestBenchFramework/BenchControl/Generic/IProcedureParams.cs create mode 100644 TestBenchFramework/BenchControl/Generic/ITestParams.cs create mode 100644 TestBenchFramework/BenchControl/GenericDevices/IAmbient.cs create mode 100644 TestBenchFramework/BenchControl/GenericDevices/IBalance.cs create mode 100644 TestBenchFramework/BenchControl/GenericDevices/IBalance2.cs create mode 100644 TestBenchFramework/BenchControl/GenericDevices/ICamera.cs create mode 100644 TestBenchFramework/BenchControl/GenericDevices/ICameraRoi.cs create mode 100644 TestBenchFramework/BenchControl/GenericDevices/IDataEntry.cs create mode 100644 TestBenchFramework/BenchControl/GenericDevices/IDiverter.cs create mode 100644 TestBenchFramework/BenchControl/GenericDevices/IFlowMeter.cs create mode 100644 TestBenchFramework/BenchControl/GenericDevices/IHasCompleted.cs create mode 100644 TestBenchFramework/BenchControl/GenericDevices/IHasProtocolTitle.cs create mode 100644 TestBenchFramework/BenchControl/GenericDevices/IPressureMeter.cs create mode 100644 TestBenchFramework/BenchControl/GenericDevices/IPump.cs create mode 100644 TestBenchFramework/BenchControl/GenericDevices/IPumpFM.cs create mode 100644 TestBenchFramework/BenchControl/GenericDevices/IRegisterReader.cs create mode 100644 TestBenchFramework/BenchControl/GenericDevices/IRegulValve.cs create mode 100644 TestBenchFramework/BenchControl/GenericDevices/IResultsPrinter.cs create mode 100644 TestBenchFramework/BenchControl/GenericDevices/IResultsWriter.cs create mode 100644 TestBenchFramework/BenchControl/GenericDevices/ITempMeter.cs create mode 100644 TestBenchFramework/BenchControl/GenericDevices/ITestMethod.cs create mode 100644 TestBenchFramework/BenchControl/GenericDevices/IValve.cs create mode 100644 TestBenchFramework/BenchControl/GenericDevices/IValveControl.cs create mode 100644 TestBenchFramework/BenchControl/GenericDevices/IWaterMeter.cs create mode 100644 TestBenchFramework/BenchControl/GenericDevices/ValveBase.cs create mode 100644 TestBenchFramework/BenchControl/Greco/Ambient.cs create mode 100644 TestBenchFramework/BenchControl/Greco/AmbientCfg.cs create mode 100644 TestBenchFramework/BenchControl/Greco/AmbientCfgCtrl.Designer.cs create mode 100644 TestBenchFramework/BenchControl/Greco/AmbientCfgCtrl.cs create mode 100644 TestBenchFramework/BenchControl/Greco/AmbientCfgCtrl.resx create mode 100644 TestBenchFramework/BenchControl/Greco/AmbientFactory.cs create mode 100644 TestBenchFramework/BenchControl/IOperation.cs create mode 100644 TestBenchFramework/BenchControl/ISequence.cs create mode 100644 TestBenchFramework/BenchControl/IntBox.cs create mode 100644 TestBenchFramework/BenchControl/MetersPath.cs create mode 100644 TestBenchFramework/BenchControl/MettlerToledo/BalanceCfg.cs create mode 100644 TestBenchFramework/BenchControl/MettlerToledo/BalanceCfgCtrl.Designer.cs create mode 100644 TestBenchFramework/BenchControl/MettlerToledo/BalanceCfgCtrl.cs create mode 100644 TestBenchFramework/BenchControl/MettlerToledo/BalanceCfgCtrl.resx create mode 100644 TestBenchFramework/BenchControl/MettlerToledo/BalanceDev.cs create mode 100644 TestBenchFramework/BenchControl/MettlerToledo/BalanceFactory.cs create mode 100644 TestBenchFramework/BenchControl/MettlerToledo/BalanceNewDev.cs create mode 100644 TestBenchFramework/BenchControl/MettlerToledo/BalanceNewFactory.cs create mode 100644 TestBenchFramework/BenchControl/MettlerToledo/GetBalanceSNOp.cs create mode 100644 TestBenchFramework/BenchControl/MettlerToledo/ReadMassOp.cs create mode 100644 TestBenchFramework/BenchControl/MettlerToledo/ReadMassesOp.cs create mode 100644 TestBenchFramework/BenchControl/MettlerToledo/ReadStableMassOp.cs create mode 100644 TestBenchFramework/BenchControl/MettlerToledo/SetUnitsOp.cs create mode 100644 TestBenchFramework/BenchControl/MettlerToledo/TaringOp.cs create mode 100644 TestBenchFramework/BenchControl/Operations/AskYesNoForm.Designer.cs create mode 100644 TestBenchFramework/BenchControl/Operations/AskYesNoForm.cs create mode 100644 TestBenchFramework/BenchControl/Operations/AskYesNoForm.resx create mode 100644 TestBenchFramework/BenchControl/Operations/AskYesNoOp.cs create mode 100644 TestBenchFramework/BenchControl/Operations/CheckUIOp.cs create mode 100644 TestBenchFramework/BenchControl/Operations/ClearResultsOp.cs create mode 100644 TestBenchFramework/BenchControl/Operations/EmptyBalanceTankOp.cs create mode 100644 TestBenchFramework/BenchControl/Operations/LoadProcedureOp.cs create mode 100644 TestBenchFramework/BenchControl/Operations/OpTemplate.cs create mode 100644 TestBenchFramework/BenchControl/Operations/ReadMoreRegistersOp.cs create mode 100644 TestBenchFramework/BenchControl/Operations/SetAllRegulValvesOp.cs create mode 100644 TestBenchFramework/BenchControl/Operations/TimerOp.cs create mode 100644 TestBenchFramework/BenchControl/OutputPath.cs create mode 100644 TestBenchFramework/BenchControl/ResultsPrinters/Basic/BasicPrintDocument.cs create mode 100644 TestBenchFramework/BenchControl/ResultsPrinters/Basic/Printer.cs create mode 100644 TestBenchFramework/BenchControl/ResultsPrinters/Basic/PrinterCfg.cs create mode 100644 TestBenchFramework/BenchControl/ResultsPrinters/Basic/PrinterCfgCtrl.Designer.cs create mode 100644 TestBenchFramework/BenchControl/ResultsPrinters/Basic/PrinterCfgCtrl.cs create mode 100644 TestBenchFramework/BenchControl/ResultsPrinters/Basic/PrinterCfgCtrl.resx create mode 100644 TestBenchFramework/BenchControl/ResultsPrinters/Basic/PrinterFactory.cs create mode 100644 TestBenchFramework/BenchControl/ResultsPrinters/Munich/MunichPrintDocument.cs create mode 100644 TestBenchFramework/BenchControl/ResultsPrinters/Munich/Printer.cs create mode 100644 TestBenchFramework/BenchControl/ResultsPrinters/Munich/PrinterCfg.cs create mode 100644 TestBenchFramework/BenchControl/ResultsPrinters/Munich/PrinterCfgCtrl.cs create mode 100644 TestBenchFramework/BenchControl/ResultsPrinters/Munich/PrinterCfgCtrl.designer.cs create mode 100644 TestBenchFramework/BenchControl/ResultsPrinters/Munich/PrinterCfgCtrl.resx create mode 100644 TestBenchFramework/BenchControl/ResultsPrinters/Munich/PrinterFactory.cs create mode 100644 TestBenchFramework/BenchControl/ResultsPrinters/Munich/ProcParams.cs create mode 100644 TestBenchFramework/BenchControl/ResultsWriters/Basic/Writer.cs create mode 100644 TestBenchFramework/BenchControl/ResultsWriters/Basic/WriterCfg.cs create mode 100644 TestBenchFramework/BenchControl/ResultsWriters/Basic/WriterCfgCtrl.cs create mode 100644 TestBenchFramework/BenchControl/ResultsWriters/Basic/WriterCfgCtrl.designer.cs create mode 100644 TestBenchFramework/BenchControl/ResultsWriters/Basic/WriterCfgCtrl.resx create mode 100644 TestBenchFramework/BenchControl/ResultsWriters/Basic/WriterFactory.cs create mode 100644 TestBenchFramework/BenchControl/Sequences/MainSeq.cs create mode 100644 TestBenchFramework/BenchControl/Sequences/SequenceBase.cs create mode 100644 TestBenchFramework/BenchControl/State.cs create mode 100644 TestBenchFramework/BenchControl/StateMachine.cs create mode 100644 TestBenchFramework/BenchControl/TbfComponents.cs create mode 100644 TestBenchFramework/BenchControl/TestBenchSim.cs create mode 100644 TestBenchFramework/BenchControl/TestMethods/CameraRoiDetection/RoiDetection.cs create mode 100644 TestBenchFramework/BenchControl/TestMethods/CameraRoiDetection/RoiDetectionCfg.cs create mode 100644 TestBenchFramework/BenchControl/TestMethods/CameraRoiDetection/RoiDetectionCfgCtrl.cs create mode 100644 TestBenchFramework/BenchControl/TestMethods/CameraRoiDetection/RoiDetectionCfgCtrl.designer.cs create mode 100644 TestBenchFramework/BenchControl/TestMethods/CameraRoiDetection/RoiDetectionCfgCtrl.resx create mode 100644 TestBenchFramework/BenchControl/TestMethods/CameraRoiDetection/RoiDetectionFactory.cs create mode 100644 TestBenchFramework/BenchControl/TestMethods/CameraRoiDetection/RoiDetectionSeq.cs create mode 100644 TestBenchFramework/BenchControl/TestMethods/CombinedMeters/CombinedMetersSeq.cs create mode 100644 TestBenchFramework/BenchControl/TestMethods/CombinedMeters/TestMethod.cs create mode 100644 TestBenchFramework/BenchControl/TestMethods/CombinedMeters/TestMethodCfg.cs create mode 100644 TestBenchFramework/BenchControl/TestMethods/CombinedMeters/TestMethodCfgCtrl.cs create mode 100644 TestBenchFramework/BenchControl/TestMethods/CombinedMeters/TestMethodCfgCtrl.designer.cs create mode 100644 TestBenchFramework/BenchControl/TestMethods/CombinedMeters/TestMethodCfgCtrl.resx create mode 100644 TestBenchFramework/BenchControl/TestMethods/CombinedMeters/TestMethodFactory.cs create mode 100644 TestBenchFramework/BenchControl/TestMethods/CombinedWithDetection/CombinedWithDetTestParams.cs create mode 100644 TestBenchFramework/BenchControl/TestMethods/CombinedWithDetection/CombinedWithDetectionSeq.cs create mode 100644 TestBenchFramework/BenchControl/TestMethods/CombinedWithDetection/TestMethod.cs create mode 100644 TestBenchFramework/BenchControl/TestMethods/CombinedWithDetection/TestMethodCfg.cs create mode 100644 TestBenchFramework/BenchControl/TestMethods/CombinedWithDetection/TestMethodCfgCtrl.cs create mode 100644 TestBenchFramework/BenchControl/TestMethods/CombinedWithDetection/TestMethodCfgCtrl.designer.cs create mode 100644 TestBenchFramework/BenchControl/TestMethods/CombinedWithDetection/TestMethodCfgCtrl.resx create mode 100644 TestBenchFramework/BenchControl/TestMethods/CombinedWithDetection/TestMethodFactory.cs create mode 100644 TestBenchFramework/BenchControl/TestMethods/FlyingStartCollectionMethod/FlyingStartCollectionMethodSeq.cs create mode 100644 TestBenchFramework/BenchControl/TestMethods/FlyingStartCollectionMethod/TestMethod.cs create mode 100644 TestBenchFramework/BenchControl/TestMethods/FlyingStartCollectionMethod/TestMethodCfg.cs create mode 100644 TestBenchFramework/BenchControl/TestMethods/FlyingStartCollectionMethod/TestMethodCfgCtrl.cs create mode 100644 TestBenchFramework/BenchControl/TestMethods/FlyingStartCollectionMethod/TestMethodCfgCtrl.designer.cs create mode 100644 TestBenchFramework/BenchControl/TestMethods/FlyingStartCollectionMethod/TestMethodCfgCtrl.resx create mode 100644 TestBenchFramework/BenchControl/TestMethods/FlyingStartCollectionMethod/TestMethodFactory.cs create mode 100644 TestBenchFramework/BenchControl/Transition.cs create mode 100644 TestBenchFramework/BenchControl/WaterMeter/ProcParams.cs create mode 100644 TestBenchFramework/BenchControl/WaterMeter/WaterMeter.cs create mode 100644 TestBenchFramework/BenchControl/WaterMeter/WaterMeterCfg.cs create mode 100644 TestBenchFramework/BenchControl/WaterMeter/WaterMeterCfgCtrl.cs create mode 100644 TestBenchFramework/BenchControl/WaterMeter/WaterMeterCfgCtrl.designer.cs create mode 100644 TestBenchFramework/BenchControl/WaterMeter/WaterMeterCfgCtrl.resx create mode 100644 TestBenchFramework/BenchControl/WaterMeter/WaterMeterFactory.cs create mode 100644 TestBenchFramework/BenchesDlg.Designer.cs create mode 100644 TestBenchFramework/BenchesDlg.cs create mode 100644 TestBenchFramework/BenchesDlg.de.resx create mode 100644 TestBenchFramework/BenchesDlg.resx create mode 100644 TestBenchFramework/ComponentParametersDlg.Designer.cs create mode 100644 TestBenchFramework/ComponentParametersDlg.cs create mode 100644 TestBenchFramework/ComponentParametersDlg.de.resx create mode 100644 TestBenchFramework/ComponentParametersDlg.resx create mode 100644 TestBenchFramework/ComponentsManagerDlg.Designer.cs create mode 100644 TestBenchFramework/ComponentsManagerDlg.cs create mode 100644 TestBenchFramework/ComponentsManagerDlg.resx create mode 100644 TestBenchFramework/CustomStyle.cs create mode 100644 TestBenchFramework/DBSettings.cs create mode 100644 TestBenchFramework/DatabaseSettings.cs create mode 100644 TestBenchFramework/DatabaseSettingsDlg.Designer.cs create mode 100644 TestBenchFramework/DatabaseSettingsDlg.cs create mode 100644 TestBenchFramework/DatabaseSettingsDlg.resx create mode 100644 TestBenchFramework/Entities/BenchPath.cs create mode 100644 TestBenchFramework/Entities/Component.cs create mode 100644 TestBenchFramework/Entities/ComponentProcedure.cs create mode 100644 TestBenchFramework/Entities/ComponentTest.cs create mode 100644 TestBenchFramework/Entities/Enums.cs create mode 100644 TestBenchFramework/Entities/FeedingPath.cs create mode 100644 TestBenchFramework/Entities/Group.cs create mode 100644 TestBenchFramework/Entities/IHasItemNr.cs create mode 100644 TestBenchFramework/Entities/IHasValves.cs create mode 100644 TestBenchFramework/Entities/MeasurementCorrection.cs create mode 100644 TestBenchFramework/Entities/MeterTestResult.cs create mode 100644 TestBenchFramework/Entities/MetersPath.cs create mode 100644 TestBenchFramework/Entities/OutputPath.cs create mode 100644 TestBenchFramework/Entities/Procedure.cs create mode 100644 TestBenchFramework/Entities/ProcedureHistory.cs create mode 100644 TestBenchFramework/Entities/Test.cs create mode 100644 TestBenchFramework/Entities/TestResult.cs create mode 100644 TestBenchFramework/Entities/TransitionSequence.cs create mode 100644 TestBenchFramework/Entities/TransitionStep.cs create mode 100644 TestBenchFramework/Entities/User.cs create mode 100644 TestBenchFramework/Entities/WMType.cs create mode 100644 TestBenchFramework/Entities/Watermeter.cs create mode 100644 TestBenchFramework/ErrorHandler.cs create mode 100644 TestBenchFramework/FluentCommon.cs create mode 100644 TestBenchFramework/Forms/AboutDlg.Designer.cs create mode 100644 TestBenchFramework/Forms/AboutDlg.cs create mode 100644 TestBenchFramework/Forms/AboutDlg.de.resx create mode 100644 TestBenchFramework/Forms/AboutDlg.resx create mode 100644 TestBenchFramework/Forms/ClosingProgram.Designer.cs create mode 100644 TestBenchFramework/Forms/ClosingProgram.cs create mode 100644 TestBenchFramework/Forms/ClosingProgram.resx create mode 100644 TestBenchFramework/Forms/EditSelectedUser.Designer.cs create mode 100644 TestBenchFramework/Forms/EditSelectedUser.cs create mode 100644 TestBenchFramework/Forms/EditSelectedUser.de.resx create mode 100644 TestBenchFramework/Forms/EditSelectedUser.resx create mode 100644 TestBenchFramework/Forms/EditUsers.Designer.cs create mode 100644 TestBenchFramework/Forms/EditUsers.cs create mode 100644 TestBenchFramework/Forms/EditUsers.de.resx create mode 100644 TestBenchFramework/Forms/EditUsers.resx create mode 100644 TestBenchFramework/Forms/EmergencyStopForm.cs create mode 100644 TestBenchFramework/Forms/EmergencyStopForm.designer.cs create mode 100644 TestBenchFramework/Forms/EmergencyStopForm.resx create mode 100644 TestBenchFramework/Forms/EnterPasswordDlg.Designer.cs create mode 100644 TestBenchFramework/Forms/EnterPasswordDlg.cs create mode 100644 TestBenchFramework/Forms/EnterPasswordDlg.resx create mode 100644 TestBenchFramework/Forms/ErrorDlg.Designer.cs create mode 100644 TestBenchFramework/Forms/ErrorDlg.cs create mode 100644 TestBenchFramework/Forms/ErrorDlg.de.resx create mode 100644 TestBenchFramework/Forms/ErrorDlg.resx create mode 100644 TestBenchFramework/Forms/NoBenchOrDatabaseDlg.Designer.cs create mode 100644 TestBenchFramework/Forms/NoBenchOrDatabaseDlg.cs create mode 100644 TestBenchFramework/Forms/NoBenchOrDatabaseDlg.resx create mode 100644 TestBenchFramework/Forms/ResultsConfig.Designer.cs create mode 100644 TestBenchFramework/Forms/ResultsConfig.cs create mode 100644 TestBenchFramework/Forms/ResultsConfig.resx create mode 100644 TestBenchFramework/Forms/TabNameDlg.Designer.cs create mode 100644 TestBenchFramework/Forms/TabNameDlg.cs create mode 100644 TestBenchFramework/Forms/TabNameDlg.resx create mode 100644 TestBenchFramework/Grp.cs create mode 100644 TestBenchFramework/LocalSettings.cs create mode 100644 TestBenchFramework/LoginDlg.Designer.cs create mode 100644 TestBenchFramework/LoginDlg.cs create mode 100644 TestBenchFramework/LoginDlg.de.resx create mode 100644 TestBenchFramework/LoginDlg.resx create mode 100644 TestBenchFramework/LoginDlgWithBenchSelection.cs create mode 100644 TestBenchFramework/LoginDlgWithBenchSelection.de.resx create mode 100644 TestBenchFramework/LoginDlgWithBenchSelection.designer.cs create mode 100644 TestBenchFramework/LoginDlgWithBenchSelection.resx create mode 100644 TestBenchFramework/LoginDlgWithBenchSelection.sk.resx create mode 100644 TestBenchFramework/MainWnd.Designer.cs create mode 100644 TestBenchFramework/MainWnd.cs create mode 100644 TestBenchFramework/MainWnd.de.resx create mode 100644 TestBenchFramework/MainWnd.resx create mode 100644 TestBenchFramework/Mappings/BenchPathMap.cs create mode 100644 TestBenchFramework/Mappings/ComponentMap.cs create mode 100644 TestBenchFramework/Mappings/ComponentProcedureMap.cs create mode 100644 TestBenchFramework/Mappings/ComponentTestMap.cs create mode 100644 TestBenchFramework/Mappings/FeedingPathMap.cs create mode 100644 TestBenchFramework/Mappings/GroupMap.cs create mode 100644 TestBenchFramework/Mappings/MeasurementCorrectionMap.cs create mode 100644 TestBenchFramework/Mappings/MeterTestResultMap.cs create mode 100644 TestBenchFramework/Mappings/MetersPathMap.cs create mode 100644 TestBenchFramework/Mappings/OutputPathMap.cs create mode 100644 TestBenchFramework/Mappings/ProcedureMap.cs create mode 100644 TestBenchFramework/Mappings/TestMap.cs create mode 100644 TestBenchFramework/Mappings/TestResultMap.cs create mode 100644 TestBenchFramework/Mappings/TransitionSequenceMap.cs create mode 100644 TestBenchFramework/Mappings/TransitionStepMap.cs create mode 100644 TestBenchFramework/Mappings/UserMap.cs create mode 100644 TestBenchFramework/Mappings/WMTypeMap.cs create mode 100644 TestBenchFramework/Mappings/WatermeterMap.cs create mode 100644 TestBenchFramework/MetrologyDlg.Designer.cs create mode 100644 TestBenchFramework/MetrologyDlg.cs create mode 100644 TestBenchFramework/MetrologyDlg.resx create mode 100644 TestBenchFramework/PathsDlg.Designer.cs create mode 100644 TestBenchFramework/PathsDlg.cs create mode 100644 TestBenchFramework/PathsDlg.de.resx create mode 100644 TestBenchFramework/PathsDlg.resx create mode 100644 TestBenchFramework/PreferencesDlg.Designer.cs create mode 100644 TestBenchFramework/PreferencesDlg.cs create mode 100644 TestBenchFramework/PreferencesDlg.de.resx create mode 100644 TestBenchFramework/PreferencesDlg.resx create mode 100644 TestBenchFramework/ProcedureDlg.Designer.cs create mode 100644 TestBenchFramework/ProcedureDlg.cs create mode 100644 TestBenchFramework/ProcedureDlg.de.resx create mode 100644 TestBenchFramework/ProcedureDlg.resx create mode 100644 TestBenchFramework/ProceduresDlg.Designer.cs create mode 100644 TestBenchFramework/ProceduresDlg.cs create mode 100644 TestBenchFramework/ProceduresDlg.resx create mode 100644 TestBenchFramework/Program.cs create mode 100644 TestBenchFramework/Properties/AssemblyInfo.cs create mode 100644 TestBenchFramework/Properties/DataSources/TestBenchFramework.Entities.Pressure.datasource create mode 100644 TestBenchFramework/Properties/Resources.Designer.cs create mode 100644 TestBenchFramework/Properties/Resources.resx create mode 100644 TestBenchFramework/Properties/Settings.Designer.cs create mode 100644 TestBenchFramework/Properties/Settings.settings create mode 100644 TestBenchFramework/Resources/Headpic.png create mode 100644 TestBenchFramework/Resources/Strings.Designer.cs create mode 100644 TestBenchFramework/Resources/Strings.de.Designer.cs create mode 100644 TestBenchFramework/Resources/Strings.de.resx create mode 100644 TestBenchFramework/Resources/Strings.resx create mode 100644 TestBenchFramework/Resources/Strings.sk.resx create mode 100644 TestBenchFramework/Resources/TestFailedImage.png create mode 100644 TestBenchFramework/Resources/TestNotDoneImage.png create mode 100644 TestBenchFramework/Resources/TestPassedImage.png create mode 100644 TestBenchFramework/Resources/sensus-logo.png create mode 100644 TestBenchFramework/SampleConfig/SQLite.db create mode 100644 TestBenchFramework/SampleConfig/config.xml create mode 100644 TestBenchFramework/SampleConfig/fuzhou150.sql create mode 100644 TestBenchFramework/SampleConfig/gwz-1-new.sql create mode 100644 TestBenchFramework/SampleConfig/log4netConfig.xml create mode 100644 TestBenchFramework/SampleConfig/munich-gwz-1.sql create mode 100644 TestBenchFramework/SampleConfig/sensus.sql create mode 100644 TestBenchFramework/Screens/LogsTabPageCtrl.Designer.cs create mode 100644 TestBenchFramework/Screens/LogsTabPageCtrl.cs create mode 100644 TestBenchFramework/Screens/LogsTabPageCtrl.resx create mode 100644 TestBenchFramework/Screens/MeasurementTabPageCtrl.Designer.cs create mode 100644 TestBenchFramework/Screens/MeasurementTabPageCtrl.cs create mode 100644 TestBenchFramework/Screens/MeasurementTabPageCtrl.resx create mode 100644 TestBenchFramework/Screens/PicturesTabPageCtrl.Designer.cs create mode 100644 TestBenchFramework/Screens/PicturesTabPageCtrl.cs create mode 100644 TestBenchFramework/Screens/PicturesTabPageCtrl.resx create mode 100644 TestBenchFramework/Screens/ProcessTabPageCtrl.Designer.cs create mode 100644 TestBenchFramework/Screens/ProcessTabPageCtrl.cs create mode 100644 TestBenchFramework/Screens/ProcessTabPageCtrl.resx create mode 100644 TestBenchFramework/Screens/ResultsTabPageCtrl.Designer.cs create mode 100644 TestBenchFramework/Screens/ResultsTabPageCtrl.cs create mode 100644 TestBenchFramework/Screens/ResultsTabPageCtrl.resx create mode 100644 TestBenchFramework/SelectComponentClassDlg.Designer.cs create mode 100644 TestBenchFramework/SelectComponentClassDlg.cs create mode 100644 TestBenchFramework/SelectComponentClassDlg.de.resx create mode 100644 TestBenchFramework/SelectComponentClassDlg.resx create mode 100644 TestBenchFramework/TBF.csproj create mode 100644 TestBenchFramework/TestProgressControls.cs create mode 100644 TestBenchFramework/TestWizard/FlowSelection.Designer.cs create mode 100644 TestBenchFramework/TestWizard/FlowSelection.cs create mode 100644 TestBenchFramework/TestWizard/FlowSelection.resx create mode 100644 TestBenchFramework/TestWizard/MethodSelection.Designer.cs create mode 100644 TestBenchFramework/TestWizard/MethodSelection.cs create mode 100644 TestBenchFramework/TestWizard/MethodSelection.resx create mode 100644 TestBenchFramework/TestWizard/SensorsSelection.Designer.cs create mode 100644 TestBenchFramework/TestWizard/SensorsSelection.cs create mode 100644 TestBenchFramework/TestWizard/SensorsSelection.resx create mode 100644 TestBenchFramework/TestWizard/VolumeAndErrorSelection.Designer.cs create mode 100644 TestBenchFramework/TestWizard/VolumeAndErrorSelection.cs create mode 100644 TestBenchFramework/TestWizard/VolumeAndErrorSelection.resx create mode 100644 TestBenchFramework/Tools/ByteFormatter.cs create mode 100644 TestBenchFramework/Tools/IniUtil.cs create mode 100644 TestBenchFramework/Tools/XmlTools.cs create mode 100644 TestBenchFramework/TransitionsDlg.Designer.cs create mode 100644 TestBenchFramework/TransitionsDlg.cs create mode 100644 TestBenchFramework/TransitionsDlg.de.resx create mode 100644 TestBenchFramework/TransitionsDlg.resx create mode 100644 TestBenchFramework/UiBridge/ActivityEventArgs.cs create mode 100644 TestBenchFramework/UiBridge/Bridge.cs create mode 100644 TestBenchFramework/UiBridge/ButtonsEtcEventArgs.cs create mode 100644 TestBenchFramework/UiBridge/CameraStateChangedEventArgs.cs create mode 100644 TestBenchFramework/UiBridge/EmergencyStopEventArgs.cs create mode 100644 TestBenchFramework/UiBridge/Enums.cs create mode 100644 TestBenchFramework/UiBridge/ImageUpdatedEventArgs.cs create mode 100644 TestBenchFramework/UiBridge/LogEventArgs.cs create mode 100644 TestBenchFramework/UiBridge/ProcedureCompletedEventArgs.cs create mode 100644 TestBenchFramework/UiBridge/ProcedureSelectedEventArgs.cs create mode 100644 TestBenchFramework/UiBridge/StateChangedEventArgs.cs create mode 100644 TestBenchFramework/UiBridge/TestCompletedEventArgs.cs create mode 100644 TestBenchFramework/UiBridge/TestProgressEventArgs.cs create mode 100644 TestBenchFramework/UiBridge/TestSelectedEventArgs.cs create mode 100644 TestBenchFramework/UiControls/BaseWithListViewEx.cs create mode 100644 TestBenchFramework/UiControls/BenchControlPanel.Designer.cs create mode 100644 TestBenchFramework/UiControls/BenchControlPanel.cs create mode 100644 TestBenchFramework/UiControls/BenchControlPanel.de.resx create mode 100644 TestBenchFramework/UiControls/BenchControlPanel.resx create mode 100644 TestBenchFramework/UiControls/CameraPictureCtrl.Designer.cs create mode 100644 TestBenchFramework/UiControls/CameraPictureCtrl.cs create mode 100644 TestBenchFramework/UiControls/CameraPictureCtrl.resx create mode 100644 TestBenchFramework/UiControls/IMetrologyDlgTab.cs create mode 100644 TestBenchFramework/UiControls/IParentOfListViewEx.cs create mode 100644 TestBenchFramework/UiControls/ITabWithListViewEx.cs create mode 100644 TestBenchFramework/UiControls/ListViewEx.cs create mode 100644 TestBenchFramework/UiControls/ListViewEx.resx create mode 100644 TestBenchFramework/UiControls/MetrologyDlgBalanceTab.Designer.cs create mode 100644 TestBenchFramework/UiControls/MetrologyDlgBalanceTab.cs create mode 100644 TestBenchFramework/UiControls/MetrologyDlgBalanceTab.resx create mode 100644 TestBenchFramework/UiControls/MetrologyDlgFlowMeterTab.Designer.cs create mode 100644 TestBenchFramework/UiControls/MetrologyDlgFlowMeterTab.cs create mode 100644 TestBenchFramework/UiControls/MetrologyDlgFlowMeterTab.resx create mode 100644 TestBenchFramework/UiControls/MetrologyDlgPressMeterTab.Designer.cs create mode 100644 TestBenchFramework/UiControls/MetrologyDlgPressMeterTab.cs create mode 100644 TestBenchFramework/UiControls/MetrologyDlgPressMeterTab.resx create mode 100644 TestBenchFramework/UiControls/PathsBenchCtrl.cs create mode 100644 TestBenchFramework/UiControls/PathsFeedingCtrl.cs create mode 100644 TestBenchFramework/UiControls/PathsMetersCtrl.cs create mode 100644 TestBenchFramework/UiControls/PathsOutputCtrl.cs create mode 100644 TestBenchFramework/UiControls/ProcedureParamsCtrl.Designer.cs create mode 100644 TestBenchFramework/UiControls/ProcedureParamsCtrl.cs create mode 100644 TestBenchFramework/UiControls/ProcedureParamsCtrl.resx create mode 100644 TestBenchFramework/UiControls/ProceduresCtrl.cs create mode 100644 TestBenchFramework/UiControls/SharedButtons.Designer.cs create mode 100644 TestBenchFramework/UiControls/SharedButtons.cs create mode 100644 TestBenchFramework/UiControls/SharedButtons.resx create mode 100644 TestBenchFramework/UiControls/TestParamsCtrl.Designer.cs create mode 100644 TestBenchFramework/UiControls/TestParamsCtrl.cs create mode 100644 TestBenchFramework/UiControls/TestParamsCtrl.resx create mode 100644 TestBenchFramework/UiControls/TestProgressCtrl.Designer.cs create mode 100644 TestBenchFramework/UiControls/TestProgressCtrl.cs create mode 100644 TestBenchFramework/UiControls/TestProgressCtrl.resx create mode 100644 TestBenchFramework/UiControls/TransitionStepsCtrl.cs create mode 100644 TestBenchFramework/Utils.cs create mode 100644 TestBenchFramework/app.config create mode 100644 TestBenchFramework/packages.config create mode 100644 TestBenchFramework/x64/SQLite.Interop.dll create mode 100644 TestBenchFramework/x86/SQLite.Interop.dll create mode 100644 packages/ControlBoard/ControlCom2VB.dll create mode 100644 packages/ControlBoard/ControlComponent3Munich.dll create mode 100644 packages/ControlBoard/ControlComponent3U.dll create mode 100644 packages/ControlBoard/GaugeIndicator.dll create mode 100644 packages/ControlBoard/procedure.txt create mode 100644 packages/ControlBoard/readme.txt create mode 100644 packages/FluentNHibernate.1.3.0.733/FluentNHibernate.1.3.0.733.nupkg create mode 100644 packages/FluentNHibernate.1.3.0.733/FluentNHibernate.1.3.0.733.nuspec create mode 100644 packages/FluentNHibernate.1.3.0.733/lib/FluentNHibernate.XML create mode 100644 packages/FluentNHibernate.1.3.0.733/lib/FluentNHibernate.dll create mode 100644 packages/Iesi.Collections.3.2.0.4000/Iesi.Collections.3.2.0.4000.nupkg create mode 100644 packages/Iesi.Collections.3.2.0.4000/Iesi.Collections.3.2.0.4000.nuspec create mode 100644 packages/Iesi.Collections.3.2.0.4000/lib/Net35/Iesi.Collections.dll create mode 100644 packages/Iesi.Collections.3.2.0.4000/lib/Net35/Iesi.Collections.xml create mode 100644 packages/MSVisualBasic/lib/net40/Microsoft.VisualBasic.dll create mode 100644 packages/MSVisualBasic/lib/net40/Microsoft.VisualBasic.xml create mode 100644 packages/MySql.Data.6.6.5/MySql.Data.6.6.5.nupkg create mode 100644 packages/MySql.Data.6.6.5/MySql.Data.6.6.5.nuspec create mode 100644 packages/MySql.Data.6.6.5/lib/net20/MySql.Data.dll create mode 100644 packages/MySql.Data.6.6.5/lib/net40/MySql.Data.dll create mode 100644 packages/NHibernate.3.3.3.4001/ConfigurationTemplates/FireBird.cfg.xml create mode 100644 packages/NHibernate.3.3.3.4001/ConfigurationTemplates/MSSQL.cfg.xml create mode 100644 packages/NHibernate.3.3.3.4001/ConfigurationTemplates/MySql.cfg.xml create mode 100644 packages/NHibernate.3.3.3.4001/ConfigurationTemplates/Oracle.cfg.xml create mode 100644 packages/NHibernate.3.3.3.4001/ConfigurationTemplates/PostgreSQL.cfg.xml create mode 100644 packages/NHibernate.3.3.3.4001/ConfigurationTemplates/SQLite.cfg.xml create mode 100644 packages/NHibernate.3.3.3.4001/ConfigurationTemplates/SybaseASE.cfg.xml create mode 100644 packages/NHibernate.3.3.3.4001/ConfigurationTemplates/SybaseSQLAnywhere.cfg.xml create mode 100644 packages/NHibernate.3.3.3.4001/NHibernate.3.3.3.4001.nupkg create mode 100644 packages/NHibernate.3.3.3.4001/NHibernate.3.3.3.4001.nuspec create mode 100644 packages/NHibernate.3.3.3.4001/NHibernate.license.txt create mode 100644 packages/NHibernate.3.3.3.4001/NHibernate.readme.html create mode 100644 packages/NHibernate.3.3.3.4001/NHibernate.releasenotes.txt create mode 100644 packages/NHibernate.3.3.3.4001/lib/Net35/NHibernate.dll create mode 100644 packages/NHibernate.3.3.3.4001/lib/Net35/NHibernate.xml create mode 100644 packages/NHibernate.3.3.3.4001/nhibernate-configuration.xsd create mode 100644 packages/NHibernate.3.3.3.4001/nhibernate-mapping.xsd create mode 100644 packages/System.Data.SQLite.1.0.90.0/System.Data.SQLite.1.0.90.0.nupkg create mode 100644 packages/System.Data.SQLite.1.0.90.0/System.Data.SQLite.1.0.90.0.nuspec create mode 100644 packages/System.Data.SQLite.1.0.90.0/content/net40/x64/SQLite.Interop.dll create mode 100644 packages/System.Data.SQLite.1.0.90.0/content/net40/x86/SQLite.Interop.dll create mode 100644 packages/System.Data.SQLite.1.0.90.0/lib/net40/System.Data.SQLite.Linq.dll create mode 100644 packages/System.Data.SQLite.1.0.90.0/lib/net40/System.Data.SQLite.dll create mode 100644 packages/System.Data.SQLite.1.0.90.0/lib/net40/System.Data.SQLite.xml create mode 100644 packages/System.Data.SQLite.1.0.90.0/tools/install.ps1 create mode 100644 packages/log4net.2.0.2/lib/net40-full/log4net.dll create mode 100644 packages/log4net.2.0.2/lib/net40-full/log4net.xml create mode 100644 packages/log4net.2.0.2/log4net.2.0.2.nupkg create mode 100644 packages/log4net.2.0.2/log4net.2.0.2.nuspec create mode 100644 packages/repositories.config diff --git a/TestBenchFramework.sln b/TestBenchFramework.sln new file mode 100644 index 000000000..71d82d668 --- /dev/null +++ b/TestBenchFramework.sln @@ -0,0 +1,33 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TBF", "TestBenchFramework\TBF.csproj", "{8648FD92-CDA1-4C3A-B5F9-FE547CE1FA48}" +EndProject +Project("{54435603-DBB4-11D2-8724-00A0C9A8B90C}") = "TBFSetup", "TBFSetup\TBFSetup.vdproj", "{4890DE5C-9F68-40D7-B075-92C8EAB79833}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8648FD92-CDA1-4C3A-B5F9-FE547CE1FA48}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8648FD92-CDA1-4C3A-B5F9-FE547CE1FA48}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8648FD92-CDA1-4C3A-B5F9-FE547CE1FA48}.Debug|x86.ActiveCfg = Debug|x86 + {8648FD92-CDA1-4C3A-B5F9-FE547CE1FA48}.Debug|x86.Build.0 = Debug|x86 + {8648FD92-CDA1-4C3A-B5F9-FE547CE1FA48}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8648FD92-CDA1-4C3A-B5F9-FE547CE1FA48}.Release|Any CPU.Build.0 = Release|Any CPU + {8648FD92-CDA1-4C3A-B5F9-FE547CE1FA48}.Release|x86.ActiveCfg = Release|x86 + {8648FD92-CDA1-4C3A-B5F9-FE547CE1FA48}.Release|x86.Build.0 = Release|x86 + {4890DE5C-9F68-40D7-B075-92C8EAB79833}.Debug|Any CPU.ActiveCfg = Debug + {4890DE5C-9F68-40D7-B075-92C8EAB79833}.Debug|x86.ActiveCfg = Debug + {4890DE5C-9F68-40D7-B075-92C8EAB79833}.Release|Any CPU.ActiveCfg = Release + {4890DE5C-9F68-40D7-B075-92C8EAB79833}.Release|Any CPU.Build.0 = Release + {4890DE5C-9F68-40D7-B075-92C8EAB79833}.Release|x86.ActiveCfg = Release + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/TestBenchFramework/AboutDlg.Designer.cs b/TestBenchFramework/AboutDlg.Designer.cs new file mode 100644 index 000000000..376976216 --- /dev/null +++ b/TestBenchFramework/AboutDlg.Designer.cs @@ -0,0 +1,117 @@ +namespace TestBenchFramework +{ + partial class AboutDlg + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.copyrightLabel = new System.Windows.Forms.Label(); + this.versionLabel = new System.Windows.Forms.Label(); + this.buildDateLabel = new System.Windows.Forms.Label(); + this.closeButton = new System.Windows.Forms.Button(); + this.logoPictureBox = new System.Windows.Forms.PictureBox(); + ((System.ComponentModel.ISupportInitialize)(this.logoPictureBox)).BeginInit(); + this.SuspendLayout(); + // + // copyrightLabel + // + this.copyrightLabel.AutoSize = true; + this.copyrightLabel.Location = new System.Drawing.Point(145, 19); + this.copyrightLabel.Name = "copyrightLabel"; + this.copyrightLabel.Size = new System.Drawing.Size(90, 13); + this.copyrightLabel.TabIndex = 4; + this.copyrightLabel.Text = "Copyright 2013"; + // + // versionLabel + // + this.versionLabel.AutoSize = true; + this.versionLabel.Location = new System.Drawing.Point(145, 41); + this.versionLabel.Name = "versionLabel"; + this.versionLabel.Size = new System.Drawing.Size(105, 13); + this.versionLabel.TabIndex = 5; + this.versionLabel.Text = "Version _VERSION_"; + // + // buildDateLabel + // + this.buildDateLabel.AutoSize = true; + this.buildDateLabel.Location = new System.Drawing.Point(145, 64); + this.buildDateLabel.Name = "buildDateLabel"; + this.buildDateLabel.Size = new System.Drawing.Size(136, 13); + this.buildDateLabel.TabIndex = 6; + this.buildDateLabel.Text = "Build date _BUILD_DATE_"; + // + // closeButton + // + this.closeButton.DialogResult = System.Windows.Forms.DialogResult.OK; + this.closeButton.Location = new System.Drawing.Point(341, 36); + this.closeButton.Name = "closeButton"; + this.closeButton.Size = new System.Drawing.Size(105, 28); + this.closeButton.TabIndex = 11; + this.closeButton.Text = "&Close"; + this.closeButton.UseVisualStyleBackColor = true; + // + // logoPictureBox + // + this.logoPictureBox.BackgroundImage = global::TestBenchFramework.Properties.Resources.sensus_logo; + this.logoPictureBox.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch; + this.logoPictureBox.InitialImage = null; + this.logoPictureBox.Location = new System.Drawing.Point(12, 34); + this.logoPictureBox.Name = "logoPictureBox"; + this.logoPictureBox.Size = new System.Drawing.Size(103, 30); + this.logoPictureBox.TabIndex = 12; + this.logoPictureBox.TabStop = false; + // + // AboutDlg + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.BackColor = System.Drawing.SystemColors.Window; + this.ClientSize = new System.Drawing.Size(458, 99); + this.Controls.Add(this.logoPictureBox); + this.Controls.Add(this.closeButton); + this.Controls.Add(this.buildDateLabel); + this.Controls.Add(this.versionLabel); + this.Controls.Add(this.copyrightLabel); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.Name = "AboutDlg"; + this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "About Test Bench Framework"; + ((System.ComponentModel.ISupportInitialize)(this.logoPictureBox)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label copyrightLabel; + private System.Windows.Forms.Label versionLabel; + private System.Windows.Forms.Label buildDateLabel; + private System.Windows.Forms.Button closeButton; + private System.Windows.Forms.PictureBox logoPictureBox; + } +} \ No newline at end of file diff --git a/TestBenchFramework/AboutDlg.cs b/TestBenchFramework/AboutDlg.cs new file mode 100644 index 000000000..9400162a8 --- /dev/null +++ b/TestBenchFramework/AboutDlg.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Windows.Forms; + +namespace TestBenchFramework +{ + /// + /// About dialog + /// + public partial class AboutDlg : Form + { + /// + /// Contsructor + /// + /// Language neutral version string + /// Regionally formated build date string + public AboutDlg(string version, string buildDate) + { + InitializeComponent(); + versionLabel.Text = versionLabel.Text.Replace("_VERSION_", version); + buildDateLabel.Text = buildDateLabel.Text.Replace("_BUILD_DATE_", buildDate); + } + } +} \ No newline at end of file diff --git a/TestBenchFramework/AboutDlg.resx b/TestBenchFramework/AboutDlg.resx new file mode 100644 index 000000000..62664e0db --- /dev/null +++ b/TestBenchFramework/AboutDlg.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + True + + \ No newline at end of file diff --git a/TestBenchFramework/AttachedTextBoxes.cs b/TestBenchFramework/AttachedTextBoxes.cs new file mode 100644 index 000000000..54f206dc8 --- /dev/null +++ b/TestBenchFramework/AttachedTextBoxes.cs @@ -0,0 +1,173 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows.Forms; + +namespace TBF +{ + /// + /// Data types and orientation of the table layout panel attached data. + /// + public enum Arrangement + { + RowOfIntegers, + RowOfDoubles, + RowOfStrings, + ColumnOfIntegers, + ColumnOfDoubles, + ColumnOfStrings, + } + + /// + /// This class represents TextBox controls and data modified by them + /// that are attached to (=displayed inside) a TableLayoutPanel control. + /// + public class AttachedTextBoxes + { + /// + /// Private fields + /// + int count; /// Number of attached TextBoxes / cells + Arrangement arngmnt; /// Type of attachemnt (see above) + bool isRow; /// true if it is a row + TextBox[] textBoxes; /// TextBox controls to be aded to TableLayoutPanel + int[] intData; /// integer data | + double[] doubleData; /// double data |-> one of these three arrays is used + string[] stringData; /// string data | + + /// + /// Constructor, which creates TextBox controls and adds them to the table layout panel. + /// + public AttachedTextBoxes(TableLayoutPanel tblLtPnl, Arrangement arngmnt, int firstColumn, int firstRow, int size) + { + this.count = size; + this.arngmnt = arngmnt; + isRow = (arngmnt == Arrangement.RowOfIntegers || arngmnt == Arrangement.RowOfDoubles || arngmnt == Arrangement.RowOfStrings); + + textBoxes = new TextBox[count]; + intData = new int[count]; + doubleData = new double[count]; + stringData = new string[count]; + + for (int i = 0; i < count; i++) + { + textBoxes[i] = new TextBox(); /// Crete a new TextBox control + + if (isRow) + { + tblLtPnl.Controls.Add(textBoxes[i], firstColumn + i, firstRow); + } + else + { + tblLtPnl.Controls.Add(textBoxes[i], firstColumn, firstRow + i); + } + } + } + + /// + /// Attached data array size + /// + public int Count { get { return count; } } + + /// + /// Indexer returning a TextBox + /// + /// Index + /// TextBox object reference + public TextBox this[int index] + { + get + { + if (index < 0 || index >= count) + { + return null; + } + else + { + return textBoxes[index]; + } + } + } + + /// + /// Retrieves data from the controls or detects a format error. + /// Wrong format in a cell interrupts data retrieving, so when the first control + /// contains data with wrong format, no data are retrieved at all. + /// + /// true if all data have correct format + public bool ValidateData() + { + switch (arngmnt) + { + case Arrangement.RowOfIntegers: + case Arrangement.ColumnOfIntegers: + for (int i = 0; i < count; i++) + { + if (!Int32.TryParse(textBoxes[i].Text, out intData[i])) return false; + } + return true; + + case Arrangement.RowOfDoubles: + case Arrangement.ColumnOfDoubles: + for (int i = 0; i < count; i++) + { + if (!Double.TryParse(textBoxes[i].Text, out doubleData[i])) return false; + } + return true; + + case Arrangement.RowOfStrings: + case Arrangement.ColumnOfStrings: + default: + return true; + } + } + + /// + /// The following three methods provide initialization of controls with original data. + /// + + public void SetData(int index, int value) + { + if (index < 0 || index >= count) return; + intData[index] = value; + textBoxes[index].Text = value.ToString(); + } + + public void SetData(int index, double value) + { + if (index < 0 || index >= count) return; + doubleData[index] = value; + textBoxes[index].Text = value.ToString(); + } + + public void SetData(int index, string value) + { + if (index < 0 || index >= count) return; + stringData[index] = value; + textBoxes[index].Text = value; + } + + /// + /// The following three methods provide retrieving data from controls. + /// ValidateData() must be called first. The return value must be true. + /// + + public int GetIntData(int index) + { + if (index < 0 || index >= count) return 0; + return intData[index]; + } + + public double GetDoubleData(int index) + { + if (index < 0 || index >= count) return 0; + return doubleData[index]; + } + + public string GetStringData(int index) + { + if (index < 0 || index >= count) return null; + return textBoxes[index].Text; + } + } +} diff --git a/TestBenchFramework/BarGraph.cs b/TestBenchFramework/BarGraph.cs new file mode 100644 index 000000000..197e199f7 --- /dev/null +++ b/TestBenchFramework/BarGraph.cs @@ -0,0 +1,72 @@ +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace TBF +{ + public class BarGraph + { + int originX; /// Left coordinate of the bar + int originY; /// Top coordinate of the bar + int barWidth; /// Bar width, the bar is actualy 1 pixel wider + int barHeight; /// Bar height the bat is actualy 1 pixel higher + Color barColor; /// Bar color + Color backColor; /// Background color (above the bar) + /// Bar border is always black, 1 pixel wide + int barValue; /// The actual bar size (the bar is drawn from bottom) + + System.Windows.Forms.Control control; + Rectangle rect; + + + /// Use this setter to update the bar size + public float FValue + { + get { return (float)barValue/(float)barHeight; } + set + { + Value = (int)(value * (float)barHeight); + control.Invalidate(); + } + } + + /// Use this setter to update the bar size + public int Value + { + get { return barValue; } + set + { + if (value < 0) barValue = 0; + else if (value >= barHeight) barValue = barHeight; + else barValue = value; + control.Invalidate(); + } + } + + /// + /// Constructor + /// + public BarGraph(System.Windows.Forms.Control control, int originX, int originY, int barWidth, int barHeight, Color barColor, Color backColor) + { + this.control = control; + this.originX = originX; + this.originY = originY; + this.barWidth = barWidth; + this.barHeight = barHeight; + this.barColor = barColor; + this.backColor = backColor; + rect = new Rectangle(originX, originY, barWidth + 1, barHeight + 1); + barValue = 0; + } + + /// + /// Call this function in Form1_Paint(..), pass the arguments without any modifications + /// + public void Paint(Graphics g) + { + g.FillRectangle(new SolidBrush(backColor), originX + 1, originY + 1, barWidth, barHeight - barValue); + g.FillRectangle(new SolidBrush(barColor), originX + 1, originY + barHeight + 1 - barValue, barWidth, barValue); + g.DrawRectangle(new Pen(Color.Black, 2.0F), originX, originY, barWidth + 1, barHeight + 1); + } + } +} diff --git a/TestBenchFramework/BenchControl/BenchId/Component.cs b/TestBenchFramework/BenchControl/BenchId/Component.cs new file mode 100644 index 000000000..6bb7a8c92 --- /dev/null +++ b/TestBenchFramework/BenchControl/BenchId/Component.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using TBF.BenchControl; + +namespace TBF.BenchControl.BenchId +{ + /// + /// Holds information identifying the test bench. + /// + public class Component : ComponentBase, Generic.IComponent + { + readonly ComponentCfg benchIdCfg; + + public static void ResetStaticProperties() { } + + public int TestBenchNr { get { return benchIdCfg.TestBenchNr; } } + + public Component(ComponentCfg cfg) + : base(cfg) + { + if (cfg == null) throw new ArgumentNullException("cfg"); + this.benchIdCfg = cfg; + } + } +} diff --git a/TestBenchFramework/BenchControl/BenchId/ComponentCfg.cs b/TestBenchFramework/BenchControl/BenchId/ComponentCfg.cs new file mode 100644 index 000000000..039c80393 --- /dev/null +++ b/TestBenchFramework/BenchControl/BenchId/ComponentCfg.cs @@ -0,0 +1,55 @@ +using System; +using System.IO; +using System.Xml.Serialization; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.BenchId +{ + /// + /// Holds information identifying the test bench - serializable configuration. + /// + public class ComponentCfg : ComponentCfgBase, Generic.IComponentCfg + { + public int TestBenchNr; + + /// Parameterless constructor + public ComponentCfg() + { + } + + public ComponentCfg(IComponentFactory factory, string name, int testBenchNr) + : base(factory, name) + { + TestBenchNr = testBenchNr; + } + + public IComponentCfg Clone() + { + return new ComponentCfg(Factory, Name, TestBenchNr); + } + + public string ToString(int i) + { + return string.Format("TestBenchNr = {0}", TestBenchNr); + } + + public TBF.Entities.Component CreateDbEntity() + { + using (var writer = new StringWriter()) + { + (new XmlSerializer(GetType())).Serialize(writer, this); + return Entities.Component.CreateFromCfg(Name, Factory.ClassName, ParentName, ItemNr, DebugLevel, LogLevel, writer.ToString()); + } + } + + public static IComponentCfg CreateFromDbEntity(Entities.Component component, IComponentFactory factory) + { + using (var reader = new StringReader(component.Parameters)) + { + ComponentCfg config = (ComponentCfg)(new XmlSerializer(typeof(ComponentCfg))).Deserialize(reader); + config.InitCfgBaseFromEntity(component, factory); + return config; + } + } + } +} diff --git a/TestBenchFramework/BenchControl/BenchId/ComponentCfgCtrl.cs b/TestBenchFramework/BenchControl/BenchId/ComponentCfgCtrl.cs new file mode 100644 index 000000000..bc8d040a1 --- /dev/null +++ b/TestBenchFramework/BenchControl/BenchId/ComponentCfgCtrl.cs @@ -0,0 +1,63 @@ +using System; +using System.Windows.Forms; +using TBF.BenchControl.Generic; +using TBF.Resources; + +namespace TBF.BenchControl.BenchId +{ + public partial class ComponentCfgCtrl : UserControl, IComponentCfgCtrl + { + ComponentCfg config; + + public IComponentCfg Config + { + get { return config as IComponentCfg; } + set + { + config = value as ComponentCfg; + Redraw(); + } + } + + public ComponentCfgCtrl() + { + InitializeComponent(); + } + + private void EntryFormCfgCtrl_Load(object sender, EventArgs e) + { + nameLabel.Text = Strings.Name; + numberLabel.Text = Strings.Test_bench_number; + Redraw(); + } + + void Redraw() + { + if (config == null) return; /// Control was not loaded, settings were not changed + classNameLabel.Text = config.Factory.ClassName; + nameTextBox.Text = config.Name; + numberTextBox.Text = config.TestBenchNr.ToString(); + } + + public void Unlock() + { + nameTextBox.Enabled = true; + numberTextBox.Enabled = true; + } + + public CfgVerifyFlags VerifyCfg(ref string message) + { + CfgVerifyFlags flags = CfgVerifyFlags.None; + return flags; + } + + public void UpdateCfg() + { + if (config == null) return; /// Control was not loaded, settings were not changed + config.Name = nameTextBox.Text; + + try { config.TestBenchNr = int.Parse(numberTextBox.Text); } + catch { config.TestBenchNr = 1; } + } + } +} diff --git a/TestBenchFramework/BenchControl/BenchId/ComponentCfgCtrl.designer.cs b/TestBenchFramework/BenchControl/BenchId/ComponentCfgCtrl.designer.cs new file mode 100644 index 000000000..69cbd9119 --- /dev/null +++ b/TestBenchFramework/BenchControl/BenchId/ComponentCfgCtrl.designer.cs @@ -0,0 +1,106 @@ +namespace TBF.BenchControl.BenchId +{ + partial class ComponentCfgCtrl + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.nameTextBox = new System.Windows.Forms.TextBox(); + this.nameLabel = new System.Windows.Forms.Label(); + this.classNameLabel = new System.Windows.Forms.Label(); + this.numberLabel = new System.Windows.Forms.Label(); + this.numberTextBox = new System.Windows.Forms.TextBox(); + this.SuspendLayout(); + // + // nameTextBox + // + this.nameTextBox.Enabled = false; + this.nameTextBox.Location = new System.Drawing.Point(135, 55); + this.nameTextBox.Name = "nameTextBox"; + this.nameTextBox.Size = new System.Drawing.Size(130, 20); + this.nameTextBox.TabIndex = 5; + // + // nameLabel + // + this.nameLabel.AutoSize = true; + this.nameLabel.Location = new System.Drawing.Point(25, 58); + this.nameLabel.Name = "nameLabel"; + this.nameLabel.Size = new System.Drawing.Size(35, 13); + this.nameLabel.TabIndex = 4; + this.nameLabel.Text = "Name"; + // + // classNameLabel + // + this.classNameLabel.AutoSize = true; + this.classNameLabel.Location = new System.Drawing.Point(132, 31); + this.classNameLabel.Name = "classNameLabel"; + this.classNameLabel.Size = new System.Drawing.Size(60, 13); + this.classNameLabel.TabIndex = 3; + this.classNameLabel.Text = "ClassName"; + // + // numberLabel + // + this.numberLabel.AutoSize = true; + this.numberLabel.Location = new System.Drawing.Point(25, 86); + this.numberLabel.Name = "numberLabel"; + this.numberLabel.Size = new System.Drawing.Size(44, 13); + this.numberLabel.TabIndex = 6; + this.numberLabel.Text = "Number"; + // + // numberTextBox + // + this.numberTextBox.Enabled = false; + this.numberTextBox.Location = new System.Drawing.Point(135, 83); + this.numberTextBox.Name = "numberTextBox"; + this.numberTextBox.Size = new System.Drawing.Size(57, 20); + this.numberTextBox.TabIndex = 7; + // + // ComponentCfgCtrl + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.numberTextBox); + this.Controls.Add(this.numberLabel); + this.Controls.Add(this.nameTextBox); + this.Controls.Add(this.nameLabel); + this.Controls.Add(this.classNameLabel); + this.Name = "ComponentCfgCtrl"; + this.Size = new System.Drawing.Size(300, 200); + this.Load += new System.EventHandler(this.EntryFormCfgCtrl_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TextBox nameTextBox; + private System.Windows.Forms.Label nameLabel; + private System.Windows.Forms.Label classNameLabel; + private System.Windows.Forms.Label numberLabel; + private System.Windows.Forms.TextBox numberTextBox; + } +} diff --git a/TestBenchFramework/BenchControl/BenchId/ComponentCfgCtrl.resx b/TestBenchFramework/BenchControl/BenchId/ComponentCfgCtrl.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/TestBenchFramework/BenchControl/BenchId/ComponentCfgCtrl.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/BenchControl/BenchId/ComponentFactory.cs b/TestBenchFramework/BenchControl/BenchId/ComponentFactory.cs new file mode 100644 index 000000000..2a3a1839f --- /dev/null +++ b/TestBenchFramework/BenchControl/BenchId/ComponentFactory.cs @@ -0,0 +1,40 @@ +using System.Collections.Generic; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.BenchId +{ + public class ComponentFactory : IComponentFactory + { + public string ClassName { get { return "Bench-ID"; } } + public bool HasProcedureParams { get { return false; } } + public bool HasTestParams { get { return false; } } + public IParamsProvider GetTestParams(Entities.ComponentTest testParams) { return null; } + public IParamsProvider GetProcedureParams(Entities.ComponentProcedure procedureParams) { return null; } + + /// Max. number of components of this class in the system + public int MaxCount { get { return int.MaxValue; } } + + + public IComponentCfg DefaultConfig(IList components) + { + return new ComponentCfg(this, "Bench-ID", 1); + } + + public IComponentCfgCtrl CreateCfgCtrl() + { + return new ComponentCfgCtrl(); + } + + public IComponent ComponentFromCmpntCfg(IComponentCfg config, IList components) + { + return new Component((ComponentCfg)config); + } + + public IComponentCfg CmpntCfgFromCmpntEntity(Entities.Component component) + { + return ComponentCfg.CreateFromDbEntity(component, this); + } + + public void ResetStaticProperties() { Component.ResetStaticProperties(); } + } +} diff --git a/TestBenchFramework/BenchControl/BenchPath.cs b/TestBenchFramework/BenchControl/BenchPath.cs new file mode 100644 index 000000000..4bbe79ca6 --- /dev/null +++ b/TestBenchFramework/BenchControl/BenchPath.cs @@ -0,0 +1,48 @@ +using System.Collections.Generic; +using TBF.BenchControl.GenericDevices; + +namespace TBF.BenchControl +{ + public class BenchPath + { + public int ItemNr; + public string Name; + public float Qfrom; + public float Qto; + public ITempMeter TempIn; + public ITempMeter TempOut; + public IPressureMeter PressIn; + public IPressureMeter PressOut; + public IList ValvesOpen; + public IList ValvesClose; + + /// Constructor from name, the rest is empty + public BenchPath(string name, int itemNr) + { + ItemNr = itemNr; + Name = name; + ValvesOpen = new List(); + ValvesClose = new List(); + } + + /// Constructor from data entity + public BenchPath(Entities.BenchPath entity, IList components) + : this(entity.Name, entity.ItemNr) + { + Qfrom = entity.Qfrom; + Qto = entity.Qto; + TempIn = (ITempMeter)TbfComponents.FindComponent(entity.TempIn, components); + TempOut = (ITempMeter)TbfComponents.FindComponent(entity.TempOut, components); + PressIn = (IPressureMeter)TbfComponents.FindComponent(entity.PressIn, components); + PressOut = (IPressureMeter)TbfComponents.FindComponent(entity.PressOut, components); + + string[] vOpen = entity.ValvesOpen.Split(new char[] { ';' }); + ValvesOpen = new List(); + foreach (var vName in vOpen) ValvesOpen.Add((IValve)TbfComponents.FindComponent(vName, components)); + + string[] vClose = entity.ValvesClose.Split(new char[] { ';' }); + ValvesClose = new List(); + foreach (var vName in vClose) ValvesClose.Add((IValve)TbfComponents.FindComponent(vName, components)); + } + } +} diff --git a/TestBenchFramework/BenchControl/Cameras/CameraRoi/CameraRoi.cs b/TestBenchFramework/BenchControl/Cameras/CameraRoi/CameraRoi.cs new file mode 100644 index 000000000..bdd06397e --- /dev/null +++ b/TestBenchFramework/BenchControl/Cameras/CameraRoi/CameraRoi.cs @@ -0,0 +1,108 @@ +using System; +using System.Diagnostics; +using System.Collections.Generic; +using System.Threading; +using TBF.BenchControl; +using TBF.BenchControl.Generic; +using log4net; + +namespace TBF.BenchControl.Cameras.CameraRoi +{ + /// + /// IdcCamera object represents all IDC cameras. + /// Camera ID is an argument of most methods. + /// + public class CameraRoi : ComponentBase, IComponent, GenericDevices.ICameraRoi, GenericDevices.IRegisterReader + { + private static readonly ILog log = LogManager.GetLogger(typeof(CameraRoi)); + public override string ToString() { return string.Format("{0}, roi{1}, parent={2}", + cameraRoiCfg.Name, cameraRoiCfg.RoiNr, Cfg.ParentName); } + + public static void ResetStaticProperties() + { + } + + readonly CameraRoiCfg cameraRoiCfg; + + readonly GenericDevices.ICamera camera; + public GenericDevices.ICamera Camera { get { return camera; } } + + public float PulsesPerLtr + { + get { return (ProcedureParams as RoiProcedureParams).GradPerLtr; } + } + + public CameraRoi(CameraRoiCfg cfg, IList components) + : base(cfg) + { + if (cfg == null) throw new ArgumentNullException("cfg"); + this.cameraRoiCfg = cfg; + if (cfg.DebugLevel != Entities.DebugMode.Off) + { + camera = TbfComponents.FindComponent(cfg.ParentName, components) as GenericDevices.ICamera; + if (camera == null) throw new Exception("Cannot find " + Name + " parent"); + } + } + + /// + /// Events: Event.ReadRegisterDone, Event.Error + /// + /// Reference to a variable for the water meter pulses + /// ReadWaterMeter instance reference casted to IOperaton + public IOperation ReadRegisterOp(ref IntBox pulses) + { + return new ReadRegisterOp(this, ref pulses); + } + + /// + /// Events: Event.ReadRegisterDone, Event.Error + /// + /// Reference to a variable for the water meter pulses + /// Reference to a variable for the related reference flow meter pulses + /// ReadWaterMeter instance reference casted to IOperaton + public IOperation ReadRegisterOp(ref IntBox pulses, ref IntBox refPulses) + { + return new ReadRegisterOp(this, ref pulses, ref refPulses); + } + + /// + /// Events: ReadReferenceDone, Error + /// + /// Reference to a variable for the water meter pulses + /// ReadWaterMeter instance reference casted to IOperaton + public IOperation ReadReferenceForRegisterOp(ref IntBox pulses, ref IntBox refPulses) + { + return null; /// not implemented + } + + /// + /// Watermeter wheel/arrow detection process. + /// + /// Region of interest (1..4) + /// Reference to operation object instance + public IOperation DetectOp() + { + RoiProcedureParams pp = ProcedureParams as RoiProcedureParams; + return camera.DetectOp(cameraRoiCfg.RoiNr, + new Cameras.IdcCamera.Command.Detect(cameraRoiCfg.RoiNr, 0, pp.IRoiX, pp.IRoiY, pp.IRoiW, pp.IRoiH, + pp.CX, pp.CY, pp.ORoiW, pp.ORoiH, pp.R1, pp.R2, pp.R3, + pp.Ang1, pp.Ang2, pp.AngStep, pp.CCW, (pp.CCW ? -30 : 30), + pp.SequenceLen, pp.SequenceTiming, pp.BackgroundCorr, + pp.BrightnessRoi * camera.Brightness)); + } + + /// + /// Watermeter wheel/arrow angle measurement process. + /// + /// Region of interest (1..4) + /// Reference to operation object instance + public IOperation MeasureOp() + { + RoiProcedureParams pp = ProcedureParams as RoiProcedureParams; + return camera.MeasureOp(cameraRoiCfg.RoiNr, + new Cameras.IdcCamera.Command.Measure(cameraRoiCfg.RoiNr, true, 0, pp.IRoiX, pp.IRoiY, pp.IRoiW, pp.IRoiH, + pp.CX, pp.CY, pp.ORoiW, pp.ORoiH, pp.MinMvmt, pp.MaxMvmt, + pp.BrightnessRoi * camera.Brightness)); + } + } +} diff --git a/TestBenchFramework/BenchControl/Cameras/CameraRoi/CameraRoiCfg.cs b/TestBenchFramework/BenchControl/Cameras/CameraRoi/CameraRoiCfg.cs new file mode 100644 index 000000000..b07307fc0 --- /dev/null +++ b/TestBenchFramework/BenchControl/Cameras/CameraRoi/CameraRoiCfg.cs @@ -0,0 +1,54 @@ +using System.IO; +using System.IO.Ports; +using System.Xml.Serialization; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.Cameras.CameraRoi +{ + public class CameraRoiCfg : ComponentCfgBase, IChildComponentCfg + { + public int RoiNr; /// ROI number 1..4 + + /// Parameterless constructor + public CameraRoiCfg() + { + } + + /// Constructor + public CameraRoiCfg(IComponentFactory factory, string name, string parentName, int roiNr) + : base(factory, name, parentName) + { + this.RoiNr = roiNr; + } + + public IComponentCfg Clone() + { + return new CameraRoiCfg(Factory, Name, ParentName, RoiNr); + } + + public string ToString(int i) + { + return string.Format("roi{0}, parent={1}", RoiNr, ParentName); + } + + public TBF.Entities.Component CreateDbEntity() + { + using (var writer = new StringWriter()) + { + (new XmlSerializer(GetType())).Serialize(writer, this); + return Entities.Component.CreateFromCfg(Name, Factory.ClassName, ParentName, ItemNr, + DebugLevel, LogLevel, writer.ToString()); + } + } + + public static IComponentCfg CreateFromDbEntity(Entities.Component component, IComponentFactory factory) + { + using (var reader = new StringReader(component.Parameters)) + { + CameraRoiCfg config = (CameraRoiCfg)(new XmlSerializer(typeof(CameraRoiCfg))).Deserialize(reader); + config.InitCfgBaseFromEntity(component, factory); + return config; + } + } + } +} diff --git a/TestBenchFramework/BenchControl/Cameras/CameraRoi/CameraRoiCfgCtrl.cs b/TestBenchFramework/BenchControl/Cameras/CameraRoi/CameraRoiCfgCtrl.cs new file mode 100644 index 000000000..be098693f --- /dev/null +++ b/TestBenchFramework/BenchControl/Cameras/CameraRoi/CameraRoiCfgCtrl.cs @@ -0,0 +1,94 @@ +using System; +using System.Windows.Forms; +using System.IO.Ports; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.Cameras.CameraRoi +{ + public partial class CameraRoiCfgCtrl : UserControl, IComponentCfgCtrl + { + ComponentParametersDlg parent; + + CameraRoiCfg config; + public IComponentCfg Config + { + get { return config as IComponentCfg; } + set + { + config = value as CameraRoiCfg; + Redraw(); + } + } + + public CameraRoiCfgCtrl() + { + InitializeComponent(); + } + + private void IdcCameraCfgCtrl_Load(object sender, EventArgs e) + { + parent = ParentForm as ComponentParametersDlg; + if (parent == null) return; + + if (parent.TbfComponents != null) + { + parentNameComboBox.Items.Add("---"); + foreach (var cmpnt in parent.TbfComponents) + { + if (TbfComponents.CmpntFactoryFromClassName(cmpnt.ClassName) is BenchControl.Cameras.IdcCamera.IdcCameraFactory) + { + parentNameComboBox.Items.Add(cmpnt.Name); + } + } + } + + Redraw(); + } + + void Redraw() + { + if (config == null) return; /// Control was not loaded, settings were not changed + + classNameLabel.Text = config.Factory.ClassName; + nameTextBox.Text = config.Name; + parentNameComboBox.Text = string.IsNullOrEmpty(config.ParentName) ? "---" : config.ParentName; + roiTextBox.Text = config.RoiNr.ToString(); + } + + public void Unlock() + { + nameTextBox.Enabled = true; + parentNameComboBox.Enabled = true; + roiTextBox.Enabled = true; + } + + public CfgVerifyFlags VerifyCfg(ref string message) + { + CfgVerifyFlags flags = CfgVerifyFlags.None; + + if (!parentNameComboBox.Items.Contains(parentNameComboBox.Text)) + { + flags |= CfgVerifyFlags.Error; + message += Environment.NewLine + "Invalid 'Parent Name'"; + } + + int dummy; + if (!int.TryParse(roiTextBox.Text, out dummy) || dummy < 1 || dummy > 4) + { + flags |= CfgVerifyFlags.Error; + message += Environment.NewLine + "'Region of Interest' is not valid"; + } + + return flags; + } + + public void UpdateCfg() + { + if (config == null) return; /// Control was not loaded, settings were not changed + + config.Name = nameTextBox.Text; + config.ParentName = parentNameComboBox.Text.Equals("---") ? string.Empty : parentNameComboBox.Text; + config.RoiNr = int.Parse(roiTextBox.Text); + } + } +} diff --git a/TestBenchFramework/BenchControl/Cameras/CameraRoi/CameraRoiCfgCtrl.designer.cs b/TestBenchFramework/BenchControl/Cameras/CameraRoi/CameraRoiCfgCtrl.designer.cs new file mode 100644 index 000000000..74d10a5e7 --- /dev/null +++ b/TestBenchFramework/BenchControl/Cameras/CameraRoi/CameraRoiCfgCtrl.designer.cs @@ -0,0 +1,130 @@ +namespace TBF.BenchControl.Cameras.CameraRoi +{ + partial class CameraRoiCfgCtrl + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.nameTextBox = new System.Windows.Forms.TextBox(); + this.nameLabel = new System.Windows.Forms.Label(); + this.classNameLabel = new System.Windows.Forms.Label(); + this.roiTextBox = new System.Windows.Forms.TextBox(); + this.roiLabel = new System.Windows.Forms.Label(); + this.parentNameComboBox = new System.Windows.Forms.ComboBox(); + this.parentNameLabel = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // nameTextBox + // + this.nameTextBox.Enabled = false; + this.nameTextBox.Location = new System.Drawing.Point(138, 72); + this.nameTextBox.Name = "nameTextBox"; + this.nameTextBox.Size = new System.Drawing.Size(130, 20); + this.nameTextBox.TabIndex = 2; + // + // nameLabel + // + this.nameLabel.AutoSize = true; + this.nameLabel.Location = new System.Drawing.Point(28, 75); + this.nameLabel.Name = "nameLabel"; + this.nameLabel.Size = new System.Drawing.Size(35, 13); + this.nameLabel.TabIndex = 1; + this.nameLabel.Text = "Name"; + // + // classNameLabel + // + this.classNameLabel.AutoSize = true; + this.classNameLabel.Location = new System.Drawing.Point(135, 46); + this.classNameLabel.Name = "classNameLabel"; + this.classNameLabel.Size = new System.Drawing.Size(89, 13); + this.classNameLabel.TabIndex = 0; + this.classNameLabel.Text = "ComponentName"; + // + // roiTextBox + // + this.roiTextBox.Enabled = false; + this.roiTextBox.Location = new System.Drawing.Point(138, 121); + this.roiTextBox.Name = "roiTextBox"; + this.roiTextBox.Size = new System.Drawing.Size(80, 20); + this.roiTextBox.TabIndex = 4; + // + // roiLabel + // + this.roiLabel.AutoSize = true; + this.roiLabel.Location = new System.Drawing.Point(28, 124); + this.roiLabel.Name = "roiLabel"; + this.roiLabel.Size = new System.Drawing.Size(94, 13); + this.roiLabel.TabIndex = 3; + this.roiLabel.Text = "Region of Interest:"; + // + // parentNameComboBox + // + this.parentNameComboBox.Enabled = false; + this.parentNameComboBox.FormattingEnabled = true; + this.parentNameComboBox.Location = new System.Drawing.Point(138, 96); + this.parentNameComboBox.Name = "parentNameComboBox"; + this.parentNameComboBox.Size = new System.Drawing.Size(130, 21); + this.parentNameComboBox.TabIndex = 6; + // + // parentNameLabel + // + this.parentNameLabel.AutoSize = true; + this.parentNameLabel.Location = new System.Drawing.Point(28, 99); + this.parentNameLabel.Name = "parentNameLabel"; + this.parentNameLabel.Size = new System.Drawing.Size(69, 13); + this.parentNameLabel.TabIndex = 5; + this.parentNameLabel.Text = "Parent Name"; + // + // CameraRoiCfgCtrl + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.parentNameComboBox); + this.Controls.Add(this.parentNameLabel); + this.Controls.Add(this.nameTextBox); + this.Controls.Add(this.nameLabel); + this.Controls.Add(this.classNameLabel); + this.Controls.Add(this.roiTextBox); + this.Controls.Add(this.roiLabel); + this.Name = "CameraRoiCfgCtrl"; + this.Size = new System.Drawing.Size(300, 240); + this.Load += new System.EventHandler(this.IdcCameraCfgCtrl_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TextBox nameTextBox; + private System.Windows.Forms.Label nameLabel; + private System.Windows.Forms.Label classNameLabel; + private System.Windows.Forms.TextBox roiTextBox; + private System.Windows.Forms.Label roiLabel; + private System.Windows.Forms.ComboBox parentNameComboBox; + private System.Windows.Forms.Label parentNameLabel; + } +} diff --git a/TestBenchFramework/BenchControl/Cameras/CameraRoi/CameraRoiCfgCtrl.resx b/TestBenchFramework/BenchControl/Cameras/CameraRoi/CameraRoiCfgCtrl.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/TestBenchFramework/BenchControl/Cameras/CameraRoi/CameraRoiCfgCtrl.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/BenchControl/Cameras/CameraRoi/CameraRoiFactory.cs b/TestBenchFramework/BenchControl/Cameras/CameraRoi/CameraRoiFactory.cs new file mode 100644 index 000000000..58b7802bf --- /dev/null +++ b/TestBenchFramework/BenchControl/Cameras/CameraRoi/CameraRoiFactory.cs @@ -0,0 +1,46 @@ +using System.Collections.Generic; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.Cameras.CameraRoi +{ + public class CameraRoiFactory : IComponentFactory + { + public string ClassName { get { return "CameraROI"; } } + + /// Max. number of components of this class in the system + public int MaxCount { get { return 20; } } + + public IComponentCfg DefaultConfig(IList components) + { + return new CameraRoiCfg(this, "ROI", "", 1); + } + + public IComponentCfgCtrl CreateCfgCtrl() + { + return new CameraRoiCfgCtrl(); + } + + public IComponent ComponentFromCmpntCfg(IComponentCfg config, IList components) + { + return new CameraRoi((CameraRoiCfg)config, components); + } + + public IComponentCfg CmpntCfgFromCmpntEntity(Entities.Component component) + { + return CameraRoiCfg.CreateFromDbEntity(component, this); + } + + public bool HasProcedureParams { get { return true; } } + // + public IParamsProvider GetProcedureParams(Entities.ComponentProcedure procedureParams) + { + return RoiProcedureParams.GetProcedureParams(procedureParams); + } + + public bool HasTestParams { get { return false; } } + // + public IParamsProvider GetTestParams(Entities.ComponentTest testParams) { return null; } + + public void ResetStaticProperties() { CameraRoi.ResetStaticProperties(); } + } +} diff --git a/TestBenchFramework/BenchControl/Cameras/CameraRoi/ReadRegisterOp.cs b/TestBenchFramework/BenchControl/Cameras/CameraRoi/ReadRegisterOp.cs new file mode 100644 index 000000000..f43ef4bab --- /dev/null +++ b/TestBenchFramework/BenchControl/Cameras/CameraRoi/ReadRegisterOp.cs @@ -0,0 +1,74 @@ +using System; +using log4net; + +namespace TBF.BenchControl.Cameras.CameraRoi +{ + public class ReadRegisterOp : IOperation + { + private static readonly ILog log = LogManager.GetLogger(typeof(ReadRegisterOp)); + public override string ToString() { return string.Format("ReadRegisterOp({0})", cameraRoi.Cfg.Name); } + + /// Set by the constructor + readonly GenericDevices.ICameraRoi cameraRoi; + readonly BenchControl.Cameras.IdcCamera.IdcCamera camera; + IntBox pulses; + IntBox refPulses; + + /// + /// Events: Event.ReadRegisterDone or Event.Error + /// + /// Register reader reference + /// Reference to a field with the water meter pulses + public ReadRegisterOp(GenericDevices.ICameraRoi cameraRoi, ref IntBox pulses) + { + this.cameraRoi = cameraRoi; + if (cameraRoi == null) throw new ArgumentNullException("reader is null or it is not IdcCamera"); + + camera = cameraRoi.Camera as BenchControl.Cameras.IdcCamera.IdcCamera; + + this.pulses = pulses; + log.Debug(this.ToString()); + } + + /// + /// Events: Event.ReadRegisterDone or Event.Error + /// + /// Register reader reference + /// Reference to a Box with the water meter pulses + /// Reference to a Box with the reference flow meter pulses synchronized with the water meter + public ReadRegisterOp(GenericDevices.ICameraRoi cameraRoi, ref IntBox pulses, ref IntBox refPulses) + : this(cameraRoi, ref pulses) + { + this.refPulses = refPulses; + log.Debug(this.ToString()); + } + + private void ReadPulses() + { + pulses.N = camera.Idc100.Pulses; + if (refPulses != null) + { + refPulses.N = 0; + } + } + + /// Start this operation + public void Start() + { + ReadPulses(); + } + + /// Run this operation + /// eventDone + public Event Run() + { + ReadPulses(); + return Event.ReadRegisterDone; + } + + /// Stop this operation + public void Stop() + { + } + } +} diff --git a/TestBenchFramework/BenchControl/Cameras/CameraRoi/RoiProcedureParams.cs b/TestBenchFramework/BenchControl/Cameras/CameraRoi/RoiProcedureParams.cs new file mode 100644 index 000000000..7c1db8ca6 --- /dev/null +++ b/TestBenchFramework/BenchControl/Cameras/CameraRoi/RoiProcedureParams.cs @@ -0,0 +1,313 @@ +using System; +using System.IO; +using System.Text; +using System.Xml.Serialization; +using TBF.BenchControl.Generic; +using TBF.Resources; + +namespace TBF.BenchControl.Cameras.CameraRoi +{ + public class RoiProcedureParams : IParamsProvider, IProcedureParams + { + public int IRoiX; + public int IRoiY; + public int IRoiW; + public int IRoiH; + + public float GradPerLtr; + public bool CCW; /// Clockwise = false, Counter clockwise = true + public float ORoiW; + public float ORoiH; + public float CX; + public float CY; + + public float R1; + public float R2; + public float R3; + public float Ang1; + public float Ang2; + public float AngStep; + public int MinMvmt; + public int MaxMvmt; + + public int SequenceLen; + public int SequenceTiming; + public int BackgroundCorr; + public float BrightnessRoi; + + string[] paramNames = new string[] + { + "IRoiX", + "IRoiY", + "IRoiW", + "IRoiH", + + "Grad per liter", + "CW/CCW", + "ORoiW", + "ORoiH", + "CX", + "CY", + + "R1", + "R2", + "R3", + "Ang1", + "Ang2", + "AngStep", + "Min.Mvmt.", + "Max.Mvmt.", + + "Det.Seq.Len", + "Det.Seq.Timing", + "Background", + "Brightness", + }; + public string ParamName(int i) { return paramNames[i]; } + + public string ToString(int i) + { + switch (i) + { + case 0: return IRoiX.ToString(); + case 1: return IRoiY.ToString(); + case 2: return IRoiW.ToString(); + case 3: return IRoiH.ToString(); + + case 4: return GradPerLtr.ToString(); + case 5: return (CCW ? "ccw" : "cw"); + case 6: return ORoiW.ToString(); + case 7: return ORoiH.ToString(); + case 8: return CX.ToString(); + case 9: return CY.ToString(); + + case 10: return R1.ToString(); + case 11: return R2.ToString(); + case 12: return R3.ToString(); + case 13: return Ang1.ToString(); + case 14: return Ang2.ToString(); + case 15: return AngStep.ToString(); + case 16: return MinMvmt.ToString(); + case 17: return MaxMvmt.ToString(); + + case 18: return SequenceLen.ToString(); + case 19: return SequenceTiming.ToString(); + case 20: return BackgroundCorr.ToString(); + case 21: return ((int)(100.0f * BrightnessRoi)).ToString(); + + default: return string.Empty; + } + } + + /// + /// Parameterless constructor - sets default values of parameters. + /// + public RoiProcedureParams() + { + IRoiX = 60; + IRoiY = 1; + IRoiW = 520; + IRoiH = 478; + + GradPerLtr = 40; + CCW = true; + ORoiW = 64.0f; + ORoiH = 64.0f; + CX = 31.0f; + CY = 31.0f; + + R1 = 21.0f; + R2 = 31.0f; + R3 = 0; + Ang1 = 0; + Ang2 = 400.0f; + AngStep = 40.0f; + MinMvmt = 0; + MaxMvmt = 0; + + SequenceLen = 8; + SequenceTiming = 1; + BackgroundCorr = 0; + BrightnessRoi = 1.0f; + } + + public void UpdateParam(int i, string strValue) + { + switch (i) + { + case 0: IRoiX = int.Parse(strValue); return; + case 1: IRoiY = int.Parse(strValue); return; + case 2: IRoiW = int.Parse(strValue); return; + case 3: IRoiH = int.Parse(strValue); return; + + case 4: GradPerLtr = Utils.ParseUFloat(strValue); return; + case 5: CCW = strValue.ToLower().Equals("ccw"); return; + case 6: ORoiW = Utils.ParseUFloat(strValue); return; + case 7: ORoiH = Utils.ParseUFloat(strValue); return; + case 8: CX = Utils.ParseUFloat(strValue); return; + case 9: CY = Utils.ParseUFloat(strValue); return; + + case 10: R1 = Utils.ParseUFloat(strValue); return; + case 11: R2 = Utils.ParseUFloat(strValue); return; + case 12: R3 = Utils.ParseSFloat(strValue); return; + case 13: Ang1 = Utils.ParseSFloat(strValue); return; + case 14: Ang2 = Utils.ParseSFloat(strValue); return; + case 15: AngStep = Utils.ParseUFloat(strValue); return; + case 16: MinMvmt = int.Parse(strValue); return; + case 17: MaxMvmt = int.Parse(strValue); return; + + case 18: SequenceLen = int.Parse(strValue); return; + case 19: SequenceTiming = int.Parse(strValue); return; + case 20: BackgroundCorr = int.Parse(strValue); return; + case 21: BrightnessRoi = ((float)int.Parse(strValue) / 100.0f); return; + default: return; + } + } + + /// + /// Parses the text in the control to verify whether it represents a valid parameter. + /// + /// Parameter nr. + /// String to be verified + /// Message to be shown when verification fails + /// 'true' if parameter string is valid, 'false' otherwise + public bool ValidateParam(int i, string strValue, out string message) + { + message = string.Empty; + + int iDummy; + float dummy; + switch (i) + { + case 0: + case 1: + case 2: + case 3: + case 16: + case 17: + case 18: + case 19: + case 20: + if (int.TryParse(strValue, out iDummy)) return true; + break; + + case 4: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 15: + case 21: + if (Utils.TryParseUFloat(strValue, out dummy)) return true; + break; + + case 12: + case 13: + case 14: + if (Utils.TryParseSFloat(strValue, out dummy)) return true; + break; + + case 5: + if (strValue.ToLower().Equals("cw") || strValue.ToLower().Equals("ccw")) return true; + break; + + default: + message = "Invalid index"; + return false; + } + + message = ParamName(i) + " is invalid"; + return false; + } + + #region Boilerplate code + + public int ParamsCount() { return paramNames.Length; } + + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < ParamsCount(); i++) + { + if (i != 0) sb.Append("; "); + sb.Append(ParamName(i)); + sb.Append("="); + sb.Append(ToString(i)); + } + return sb.ToString(); + } + + [XmlIgnore] + public Entities.ComponentProcedure ProcedureParamsEntity { get { return procedureParamsEntity; } } + Entities.ComponentProcedure procedureParamsEntity; + + [XmlIgnore] + public string ComponentName { get { return componentName; } } + string componentName; + + [XmlIgnore] + public Entities.Procedure Procedure { get { return procedure; } } + Entities.Procedure procedure; + + public RoiProcedureParams(Entities.ComponentProcedure procedureParamsEntity, string componentName, Entities.Procedure procedure) + : this() + { + this.procedureParamsEntity = procedureParamsEntity; + this.componentName = componentName; + this.procedure = procedure; + } + + public TBF.Entities.ComponentProcedure ToDbEntity(IComponent component, Entities.Procedure procedure) + { + using (var writer = new StringWriter()) + { + /// Serialize this class with parameters + (new XmlSerializer(GetType())).Serialize(writer, this); + + /// Create and return the ComponentProcedure entity + TBF.Entities.ComponentProcedure entity = new TBF.Entities.ComponentProcedure(); + entity.CmpntName = component.Cfg.Name; + entity.Parameters = writer.ToString(); + entity.Procedure = procedure; + return entity; + } + } + + public void UpdateDbEntity() + { + using (var writer = new StringWriter()) + { + /// Serialize this class and update the entity + (new XmlSerializer(GetType())).Serialize(writer, this); + procedureParamsEntity.Parameters = writer.ToString(); + procedureParamsEntity.CmpntName = componentName; + procedureParamsEntity.Procedure = procedure; + + } + } + + public static IParamsProvider GetProcedureParams(Entities.ComponentProcedure procedureParamsEntity) + { + if (procedureParamsEntity == null) return new RoiProcedureParams(); + + RoiProcedureParams procedureParams; + try + { + procedureParams = (RoiProcedureParams)(new XmlSerializer(typeof(RoiProcedureParams))) + .Deserialize(new StringReader(procedureParamsEntity.Parameters)); + } + catch + { + procedureParams = new RoiProcedureParams(); + } + procedureParams.procedureParamsEntity = procedureParamsEntity; + procedureParams.componentName = procedureParamsEntity.CmpntName; + procedureParams.procedure = procedureParamsEntity.Procedure; + return procedureParams; + } + + #endregion + } +} diff --git a/TestBenchFramework/BenchControl/Cameras/IdcCamera/Command/Connect.cs b/TestBenchFramework/BenchControl/Cameras/IdcCamera/Command/Connect.cs new file mode 100644 index 000000000..e9fbbb987 --- /dev/null +++ b/TestBenchFramework/BenchControl/Cameras/IdcCamera/Command/Connect.cs @@ -0,0 +1,15 @@ +using System; + +namespace TBF.BenchControl.Cameras.IdcCamera.Command +{ + public class Connect : IWorkerCmd + { + public string CmdName { get { return "Connect"; } } + public int TimeoutMs; + + public Connect(int timeoutMs) + { + this.TimeoutMs = timeoutMs; + } + } +} diff --git a/TestBenchFramework/BenchControl/Cameras/IdcCamera/Command/Detect.cs b/TestBenchFramework/BenchControl/Cameras/IdcCamera/Command/Detect.cs new file mode 100644 index 000000000..a358be799 --- /dev/null +++ b/TestBenchFramework/BenchControl/Cameras/IdcCamera/Command/Detect.cs @@ -0,0 +1,60 @@ +using System; + +namespace TBF.BenchControl.Cameras.IdcCamera.Command +{ + public class Detect : IWorkerCmd + { + public string CmdName { get { return "Detect"; } } + public int RoiNr; + public int WMeterType; + public int IRoiX; + public int IRoiY; + public int IRoiW; + public int IRoiH; + public float CX; + public float CY; + public float ORoiW; + public float ORoiH; + public float R1; + public float R2; + public float R3; + public float Ang1; + public float Ang2; + public float AngStep; + public bool CCW; /// Clockwise = false, Counter clockwise = true + public float NomSpeed; + public int SequenceLen; + public int SequenceTiming; + public int BackgroundCorr; + public float Brightness; /// Overal brightness 0.0 .. 1.0 obtained as a product of the camera and the ROI brightness + + public Detect(int roiNr, int wMeterType, int iRoiX, int iRoiY, int iRoiW, int iRoiH, + float cx, float cy, float oRoiW, float oRoiH, + float r1, float r2, float r3, float ang1, float ang2, float angStep, bool ccw, + float nomSpeed, int sequenceLen, int sequenceTiming, int backgroundCorr, float brightness) + { + this.RoiNr = roiNr; + this.WMeterType = wMeterType; + this.IRoiX = iRoiX; + this.IRoiY = iRoiY; + this.IRoiW = iRoiW; + this.IRoiH = iRoiH; + this.CX = cx; + this.CY = cy; + this.ORoiW = oRoiW; + this.ORoiH = oRoiH; + this.R1 = r1; + this.R2 = r2; + this.R3 = r3; + this.Ang1 = ang1; + this.Ang2 = ang2; + this.AngStep = angStep; + this.CCW = ccw; + this.NomSpeed = nomSpeed; + this.SequenceLen = sequenceLen; + this.SequenceTiming = sequenceTiming; + this.BackgroundCorr = backgroundCorr; + this.Brightness = brightness; + } + } +} diff --git a/TestBenchFramework/BenchControl/Cameras/IdcCamera/Command/Disconnect.cs b/TestBenchFramework/BenchControl/Cameras/IdcCamera/Command/Disconnect.cs new file mode 100644 index 000000000..72b94adcf --- /dev/null +++ b/TestBenchFramework/BenchControl/Cameras/IdcCamera/Command/Disconnect.cs @@ -0,0 +1,13 @@ +using System; + +namespace TBF.BenchControl.Cameras.IdcCamera.Command +{ + public class Disconnect : IWorkerCmd + { + public string CmdName { get { return "Disconnect"; } } + + public Disconnect() + { + } + } +} diff --git a/TestBenchFramework/BenchControl/Cameras/IdcCamera/Command/Grab.cs b/TestBenchFramework/BenchControl/Cameras/IdcCamera/Command/Grab.cs new file mode 100644 index 000000000..faf155674 --- /dev/null +++ b/TestBenchFramework/BenchControl/Cameras/IdcCamera/Command/Grab.cs @@ -0,0 +1,31 @@ +using System; + +namespace TBF.BenchControl.Cameras.IdcCamera.Command +{ + public class Grab : IWorkerCmd + { + public string CmdName { get { return "Grab"; } } + public int X; + public int Y; + public int W; + public int H; + public int Scale; + public string FileName; + public FileFormat Format; + public float Brightness; /// Camera brightness 0.0 .. 1.0 + bool WaitCompleted; + + public Grab(string fileName, FileFormat format, float brihtness, bool waitCompleted) + { + X = 0; + Y = 0; + W = 640; + H = 480; + Scale = 1; + this.FileName = fileName; + this.Format = format; + this.Brightness = brihtness; + this.WaitCompleted = waitCompleted; + } + } +} diff --git a/TestBenchFramework/BenchControl/Cameras/IdcCamera/Command/Measure.cs b/TestBenchFramework/BenchControl/Cameras/IdcCamera/Command/Measure.cs new file mode 100644 index 000000000..50dd8adfc --- /dev/null +++ b/TestBenchFramework/BenchControl/Cameras/IdcCamera/Command/Measure.cs @@ -0,0 +1,44 @@ +using System; + +namespace TBF.BenchControl.Cameras.IdcCamera.Command +{ + public class Measure : IWorkerCmd + { + public string CmdName { get { return "Measure"; } } + public int RoiNr; /// 1 or 2 + public bool Triggered; + public int WMeterType; + public int IRoiX; + public int IRoiY; + public int IRoiW; + public int IRoiH; + public float CX; + public float CY; + public float ORoiW; + public float ORoiH; + public int MinMvmt; + public int MaxMvmt; + public float Brightness; /// Overal brightness 0.0 .. 1.0 obtained as a product of the camera and the ROI brightness + + public Measure(int roiNr, bool triggered, int wMeterType, + int iRoiX, int iRoiY, int iRoiW, int iRoiH, + float cx, float cy, float oRoiW, float oRoiH, + int minMvmt, int maxMvmt, float brightness) + { + this.RoiNr = roiNr; + this.Triggered = triggered; + this.WMeterType = wMeterType; + this.IRoiX = iRoiX; + this.IRoiY = iRoiY; + this.IRoiW = iRoiW; + this.IRoiH = iRoiH; + this.CX = cx; + this.CY = cy; + this.ORoiW = oRoiW; + this.ORoiH = oRoiH; + this.MinMvmt = minMvmt; + this.MaxMvmt = maxMvmt; + this.Brightness = brightness; + } + } +} diff --git a/TestBenchFramework/BenchControl/Cameras/IdcCamera/Command/Other.cs b/TestBenchFramework/BenchControl/Cameras/IdcCamera/Command/Other.cs new file mode 100644 index 000000000..b508a18f7 --- /dev/null +++ b/TestBenchFramework/BenchControl/Cameras/IdcCamera/Command/Other.cs @@ -0,0 +1,15 @@ +using System; + +namespace TBF.BenchControl.Cameras.IdcCamera.Command +{ + public class Other : IWorkerCmd + { + public string CmdName { get { return "Other"; } } + public string Command; + + public Other(string command) + { + this.Command = command; + } + } +} diff --git a/TestBenchFramework/BenchControl/Cameras/IdcCamera/Command/Save.cs b/TestBenchFramework/BenchControl/Cameras/IdcCamera/Command/Save.cs new file mode 100644 index 000000000..bcc5b37eb --- /dev/null +++ b/TestBenchFramework/BenchControl/Cameras/IdcCamera/Command/Save.cs @@ -0,0 +1,21 @@ +using System; + +namespace TBF.BenchControl.Cameras.IdcCamera.Command +{ + class Save : IWorkerCmd + { + public string CmdName { get { return "Save"; } } + public string VariableName; + public string FileName; + public FileFormat Format; + public bool WaitCompleted; + + public Save(string variableName, string fileName, FileFormat format, bool waitCompleted) + { + this.VariableName = variableName; + this.FileName = fileName; + this.Format = format; + this.WaitCompleted = waitCompleted; + } + } +} diff --git a/TestBenchFramework/BenchControl/Cameras/IdcCamera/Command/SetBrightness.cs b/TestBenchFramework/BenchControl/Cameras/IdcCamera/Command/SetBrightness.cs new file mode 100644 index 000000000..d03d80bd0 --- /dev/null +++ b/TestBenchFramework/BenchControl/Cameras/IdcCamera/Command/SetBrightness.cs @@ -0,0 +1,15 @@ +using System; + +namespace TBF.BenchControl.Cameras.IdcCamera.Command +{ + public class SetBrightness : IWorkerCmd + { + public string CmdName { get { return "SetBrightness"; } } + public float Brightness; /// 0.0f .. 1.0f + + public SetBrightness(float brightness) + { + this.Brightness = brightness; + } + } +} diff --git a/TestBenchFramework/BenchControl/Cameras/IdcCamera/Command/StartNew.cs b/TestBenchFramework/BenchControl/Cameras/IdcCamera/Command/StartNew.cs new file mode 100644 index 000000000..ba530e1c3 --- /dev/null +++ b/TestBenchFramework/BenchControl/Cameras/IdcCamera/Command/StartNew.cs @@ -0,0 +1,13 @@ +using System; + +namespace TBF.BenchControl.Cameras.IdcCamera.Command +{ + public class StartNew : IWorkerCmd + { + public string CmdName { get { return "StartNew"; } } + + public StartNew() + { + } + } +} diff --git a/TestBenchFramework/BenchControl/Cameras/IdcCamera/Command/StopOp.cs b/TestBenchFramework/BenchControl/Cameras/IdcCamera/Command/StopOp.cs new file mode 100644 index 000000000..89aa90ff5 --- /dev/null +++ b/TestBenchFramework/BenchControl/Cameras/IdcCamera/Command/StopOp.cs @@ -0,0 +1,13 @@ +using System; + +namespace TBF.BenchControl.Cameras.IdcCamera.Command +{ + public class StopOp : IWorkerCmd + { + public string CmdName { get { return "StopOp"; } } + + public StopOp() + { + } + } +} diff --git a/TestBenchFramework/BenchControl/Cameras/IdcCamera/Command/StopStream.cs b/TestBenchFramework/BenchControl/Cameras/IdcCamera/Command/StopStream.cs new file mode 100644 index 000000000..f977e0ed6 --- /dev/null +++ b/TestBenchFramework/BenchControl/Cameras/IdcCamera/Command/StopStream.cs @@ -0,0 +1,13 @@ +using System; + +namespace TBF.BenchControl.Cameras.IdcCamera.Command +{ + public class StopStream : IWorkerCmd + { + public string CmdName { get { return "StopStream"; } } + + public StopStream() + { + } + } +} diff --git a/TestBenchFramework/BenchControl/Cameras/IdcCamera/Command/Stream.cs b/TestBenchFramework/BenchControl/Cameras/IdcCamera/Command/Stream.cs new file mode 100644 index 000000000..a509ac22c --- /dev/null +++ b/TestBenchFramework/BenchControl/Cameras/IdcCamera/Command/Stream.cs @@ -0,0 +1,19 @@ +using System; + +namespace TBF.BenchControl.Cameras.IdcCamera.Command +{ + public class Stream : IWorkerCmd + { + public string CmdName { get { return "Stream"; } } + public StreamType Type; + public FileFormat Format; + public float Brightness; /// Camera brightness 0.0 .. 1.0 + + public Stream(StreamType type, FileFormat format, float brightness) + { + this.Type = type; + this.Format = format; + this.Brightness = brightness; + } + } +} diff --git a/TestBenchFramework/BenchControl/Cameras/IdcCamera/IWorkerCmd.cs b/TestBenchFramework/BenchControl/Cameras/IdcCamera/IWorkerCmd.cs new file mode 100644 index 000000000..aa3f62c58 --- /dev/null +++ b/TestBenchFramework/BenchControl/Cameras/IdcCamera/IWorkerCmd.cs @@ -0,0 +1,8 @@ + +namespace TBF.BenchControl.Cameras.IdcCamera +{ + public interface IWorkerCmd + { + string CmdName { get; } + } +} diff --git a/TestBenchFramework/BenchControl/Cameras/IdcCamera/Idc100.cs b/TestBenchFramework/BenchControl/Cameras/IdcCamera/Idc100.cs new file mode 100644 index 000000000..9d16555f5 --- /dev/null +++ b/TestBenchFramework/BenchControl/Cameras/IdcCamera/Idc100.cs @@ -0,0 +1,1441 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Threading; +using log4net; + +namespace TBF.BenchControl.Cameras.IdcCamera +{ + public class Idc100 + { + private static readonly ILog log = LogManager.GetLogger(typeof(Idc100)); + + /// + /// Constants + /// + const string IdcHomeDir = Program.HomeDir; /// Contains subdirectory Images/... + const int MesurementPeriod_Frames = 6; + const int ParamsSize = 14; + const int MaxMeasurementsCount = 160000; /// Enough for +/- 3,5h measurement + + /// + /// Data marks identifying events + /// + enum MARK + { + FALLING = 2000000000, /// Marks measurement start + RISING = 2000000001, /// marks measurement end + BEGIN = 2000000002, /// not used + END = 2000000003, /// not used + DUMMY = 2000000004 + } + + /// Version string + public string Version { get { return cameraVersionStr; } } + string cameraVersionStr; /// IDC100 version, valid after 'Connect' + + /// + /// Private fields + /// + int cameraNr; /// 0-based camera number + int comPortNr; /// COM port number + int baudRate; + float brightness; /// Relative brightness 0 .. 1.0f + string imagesPath; + Tools.IniUtil commonIni; + + SerialLayer serial; /// Communications + Thread workerThread; + + struct Measurement + { + public uint timeStamp; + public int angle; + public Measurement(uint timeStamp, int angle) + { + this.timeStamp = timeStamp; + this.angle = angle; + } + } + + IList measurements; /// Raw angle measurements obtained by the camera + + int wm_nrBegin; /// Measuremnt start mark + uint wm_timestampBegin; + + int wm_nrEnd; /// Measurement end mark + uint wm_timestampEnd; + + /// + /// The angle difference since the start of the measurement operation (the start mark) + /// + public int Pulses + { + get + { + if (measurements.Count < 1 || wm_nrBegin >= measurements.Count) return 0; + return measurements[measurements.Count - 1].angle - measurements[wm_nrBegin].angle; + } + } + + /// + /// The angle difference between the end and the start of the measurement operation + /// + public int TotalPulses + { + get + { + if (wm_nrBegin >= measurements.Count || wm_nrEnd > measurements.Count || wm_nrBegin > wm_nrEnd) return 0; + return measurements[wm_nrEnd - 1].angle - measurements[wm_nrBegin].angle; + } + } + + int m_initSpeed; + + + IdcState _idcState; + /// + IdcState idcState + { + get { return _idcState; } + set + { + if (value != _idcState) + { + _idcState = value; + TBF.UiBridge.Bridge.OnCameraStateChanged(this, + new TBF.UiBridge.CameraStateChangedEventArgs(cameraNr, value)); + } + } + } + /// + public IdcState IdcState { get { return _idcState; } } + + + string m_errorStr; /// last camera error string + RetVal m_lastError; /// last error (either host or camera) + + /// On program exit the control sets these events to avoid deadlocks + AutoResetEvent workerCommandEvent; + AutoResetEvent workerEvent; + + IWorkerCmd workerCmd; + RetVal workerResponse; + + + /// + /// Constructor + /// + /// Camera name = 'Images' subdirectory name) + /// Com port number 1..999 + /// Baud rate 57600 or 115200 + /// Relative brightness 0..1.0f + public Idc100(string name, int cameraNr, int comPortNr, int baudRate, float brightness) + { + this.comPortNr = comPortNr; + this.baudRate = baudRate; + this.brightness = brightness; + this.cameraNr = cameraNr; + m_initSpeed = 0; + + /// Read the rest of parameters from INI-files + this.commonIni = new Tools.IniUtil(IdcHomeDir + "config\\common.ini"); + + /// Create SerialLayer instance + imagesPath = string.Format("{0}Images\\{1}\\", IdcHomeDir, name); + Directory.CreateDirectory(imagesPath); + serial = new SerialLayer(cameraNr, comPortNr, baudRate, 2000, imagesPath); + + /// Initialize the rest + measurements = new List(); + + wm_nrBegin = 0; + wm_nrEnd = 0; + wm_timestampBegin = 0; + wm_timestampEnd = 0; + + m_lastError = RetVal.OK; + + idcState = IdcState.NotConnected; + workerCmd = null; + workerResponse = 0; + workerCommandEvent = new AutoResetEvent(false); + workerEvent = new AutoResetEvent(false); + + //ExecuteIdcIniFile(); + } + + + public RetVal StartOp(IWorkerCmd workerCmd) + { + IdcState[] iniStates; + IdcTransition[] sTransTbl; + + ///------------------------------------ Connection state ------------------------------------ + if (workerCmd is Command.Connect) + { + m_lastError = Connect((workerCmd as Command.Connect).TimeoutMs); + return m_lastError; + } + else if (workerCmd is Command.Disconnect) + { + iniStates = new IdcState[] { IdcState.Idle, IdcState.Busy, IdcState.OpCompleted, IdcState.OpFailed }; + sTransTbl = new IdcTransition[] { new IdcTransition(RetVal.SequenceError, IdcState.Unchanged), + new IdcTransition(RetVal.FatalError, IdcState.Unchanged), + new IdcTransition(RetVal.OK, IdcState.NotConnected), }; + serial.m_disconnecting = true; + serial.UnlockLastRead(); /// Quit infinite fifo.Get() waiting for a character in read FIFO + RetVal retv = IssueThreadCmd(workerCmd, iniStates, sTransTbl); + + if (retv == RetVal.SequenceError) + return m_lastError = RetVal.OK; /// Camera was not connected - OK + else + return m_lastError = retv; + } + else if (idcState == IdcState.NotConnected) + { + /// connection must be established for all remaining operations + return (m_lastError = RetVal.CameraNotConnected); + } + + ///------------------------------------ Other operations ------------------------------------ + + if (workerCmd is Command.Detect || workerCmd is Command.Measure || workerCmd is Command.Stream) + { + /// + /// Long lasting (start/stop) operations state transition table + /// + iniStates = new IdcState[] { IdcState.Idle }; + sTransTbl = new IdcTransition[] { new IdcTransition(RetVal.Busy, IdcState.Busy), + new IdcTransition(RetVal.OpFailed, IdcState.OpFailed), + new IdcTransition(RetVal.OK, IdcState.Busy), }; + } + else + { + /// + /// Immediate operations state transition table + /// + iniStates = new IdcState[] { IdcState.Idle }; + sTransTbl = new IdcTransition[] { new IdcTransition(RetVal.Busy, IdcState.Busy), + new IdcTransition(RetVal.OK, IdcState.Idle), }; + } + + m_lastError = IssueThreadCmd(workerCmd, iniStates, sTransTbl); + return m_lastError; + } + + + public RetVal StopOp() + { + IdcState[] iniStates = new IdcState[] { IdcState.Busy, + IdcState.OpCompleted, + IdcState.OpFailed }; + + IdcTransition[] sTransTbl = new IdcTransition[] { new IdcTransition(RetVal.SequenceError, IdcState.Unchanged), + new IdcTransition(RetVal.OK, IdcState.Idle) + }; + + return m_lastError = IssueThreadCmd(new Command.StopOp(), iniStates, sTransTbl); + } + + + //--------------------------------------------------------------------- + // Connect + // Starts the worker thread, opens the COM-port and establishes + // communication with the camera. + // Returns: + // 0 = OK + // RetVal.SEQUENCE_ERROR ....... camera was already connected, etc + // RetVal.INVALID_COMPORT_NR ... invalid COM-port number + // RetVal.CANNOT_INIT_CAMERA ... when worker thread cannot be started + // RetVal.CANNOT_OPEN_COMPORT ... cannot open COM-port + // RetVal.CANNOT_SET_COMPORT_PARAMETERS ... cannot set comm. parameters + // RetVal.COMM_TIMEOUT ... comm. timeout when establishing a connection + // RetVal.UNKNNOWN_COMM_ERROR ... other less common comm. error + //--------------------------------------------------------------------- + RetVal Connect(int timeoutMs) + { + lock (serial) + { + if (idcState != IdcState.NotConnected) return RetVal.SequenceError; /// Command sequence error + if (comPortNr == 0) return RetVal.InvalidComPortNr; + + /// Start the worker thread + workerThread = new Thread(new ThreadStart(Worker)); + workerThread.Start(); + + if (workerEvent.WaitOne(timeoutMs)) + { + if (workerResponse == RetVal.OK) + { + idcState = IdcState.Idle; + return RetVal.OK; /// Intro part completed OK in time, thread is running OK + } + else + { + return workerResponse; /// Return the code from the thread + } + } + + return RetVal.CommTimeout; /// Timeout + } + } + + ///------------------------------------------------------------------------------ + /// Used to issue command to the worker thread + /// Arguments: + /// threadCmd ... thread command (definend in enum in Common.h) + /// expectedStates ... = NULL ... do not check current state + /// = {state1, state2, ..., 0} ... check if current + /// state is one of states in the zero terminated arary + /// stateTransitionTable= {{resp1,state1},{resp2,state2}, ... ,{RetVal.OK,defaultState}} + /// (!!! last item must be {RetVal.OK,defaultState}) + /// Returns: + /// workerResponse (error code in case of an error) + ///------------------------------------------------------------------------------ + RetVal IssueThreadCmd(IWorkerCmd workerCmd, IdcState[] expectedStates, IdcTransition[] stateTransitionTable) + { + lock (serial) + { + /// Check the initial state + if (idcState == IdcState.NotConnected || expectedStates == null) + { + return RetVal.SequenceError; /// Camera is not connected or expexted states missing + } + /// + bool isInExpectedState = false; + foreach (var expextedState in expectedStates) + { + if (idcState == expextedState) isInExpectedState = true; + } + if (!isInExpectedState) + { + return RetVal.SequenceError; /// Camera is not in any of the expected states + } + + /// Issue thread comand and wait for a response + workerResponse = 0; + this.workerCmd = workerCmd; + workerCommandEvent.Set(); + workerEvent.WaitOne(); + + /// Change the state depending on the response + if (stateTransitionTable != null) + { + foreach (var item in stateTransitionTable) + { + if (item.RetVal == workerResponse) + { + if (item.NewState != IdcState.Unchanged) idcState = item.NewState; + break; + } + } + } + + return workerResponse; + } + } + + /// + /// Shut down Idc100 operation, stop the worker thread. + /// + public void ShutDown() + { + if (workerThread != null) workerThread.Join(); + } + + void Worker() + { + //------------------------------------------------------------------- + // Introductory part: 'Connect' operation waits until it is completed + //------------------------------------------------------------------- + + /// Open the COM-port and set communication parameters + workerResponse = serial.OpenPort(); + + /// Verify connection and get version + if (RetVal.OK == workerResponse && RetVal.OK != serial.GetVer(out cameraVersionStr)) + { + serial.ClosePort(); + workerResponse = RetVal.CannotCommWithCamera; + } + + /// Signal intro is finished, return on error + workerEvent.Set(); + + if (workerResponse != RetVal.OK) return; /// Thread halted on error + + //-------------------------------------------------- + // Worker thread loop + //-------------------------------------------------- + string cmd; + RetVal retv; + int iretv; + + while (true) + { + workerCommandEvent.WaitOne(); + + //------------------------------------------------------------------------------------------- + if (workerCmd is Command.Disconnect) + { + // Disconnect camera: close the com-port and exit worker thread + serial.ClosePort(); + workerResponse = RetVal.OK; + workerEvent.Set(); + return; + } + //------------------------------------------------------------------------------------------- + else if (workerCmd is Command.StopOp) + { + // StopOp() when camera is idle -> do nothing + workerResponse = RetVal.OK; + workerEvent.Set(); + } + //------------------------------------------------------------------------------------------- + else if (workerCmd is Command.StartNew) + { + // Format: + // startnew + // Issues command(s): + // startnew + // settime + byte znak; + int[] received = new int[1]; + received[0] = 0; /// OK in debug mode + + serial.WriteString("startnew\r\n"); + + workerResponse = RetVal.Busy; // state -> State.CAMERA_BUSY + workerEvent.Set(); + + // Returns: + // WAIT_OBJECT_0 ... WorkerCommand.STOP_OP received + // WAIT_TIMEOUT .... time expired, no WorkerCommand.STOP_OP received + + while (true) + { + if (workerCommandEvent.WaitOne(6000)) + { + /// Signal received + if (workerCmd is Command.StopOp) + { + workerResponse = RetVal.OpInterrupted; + break; + } + } + else + { + /// Timeout + workerResponse = RetVal.OK; + break; + } + } + + if (workerResponse == RetVal.OK) + { + do { + retv = serial.ReadByte(out znak); + } + while (znak != '$'); // read all characters in the buffer + + serial.WriteString("connect\r\n"); + + if (RetVal.OK != serial.ReadByte(out znak) || znak != 'V') workerResponse = RetVal.OpFailed; + else if (RetVal.OK != serial.ReadByte(out znak) || znak != '\r') workerResponse = RetVal.OpFailed; + else if (RetVal.OK != serial.ReadByte(out znak) || znak != '\n') workerResponse = RetVal.OpFailed; + else if (RetVal.OK != serial.ReadByte(out znak) || znak != '$') workerResponse = RetVal.OpFailed; + else workerResponse = RetVal.OK; + } + + if (workerResponse == RetVal.OK) + { + /// settime + DateTime now = DateTime.Now; + string settimeStr = String.Format("settime {0} {1} {2} {3} {4} {5} {6}\r\n", + now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second, now.Millisecond); + serial.WriteString(settimeStr); + + if (RetVal.OK != serial.ReadByte(out znak) || znak != '>') workerResponse = RetVal.OpFailed; + else if (RetVal.OK != serial.ReadByte(out znak) || znak != ' ') workerResponse = RetVal.OpFailed; + else if (RetVal.OK != serial.ReadByte(out znak) || znak != '0') workerResponse = RetVal.OpFailed; + else if (RetVal.OK != serial.ReadByte(out znak) || znak != ' ') workerResponse = RetVal.OpFailed; + else if (RetVal.OK != serial.ReadByte(out znak) || znak != 'O') workerResponse = RetVal.OpFailed; + else if (RetVal.OK != serial.ReadByte(out znak) || znak != 'K') workerResponse = RetVal.OpFailed; + else if (RetVal.OK != serial.ReadByte(out znak) || znak != '\r') workerResponse = RetVal.OpFailed; + else if (RetVal.OK != serial.ReadByte(out znak) || znak != '\n') workerResponse = RetVal.OpFailed; + else if (RetVal.OK != serial.ReadByte(out znak) || znak != '$') workerResponse = RetVal.OpFailed; + else workerResponse = RetVal.OK; + } + + /// Verify connection and get version + if (RetVal.OK == workerResponse && RetVal.OK != serial.GetVer(out cameraVersionStr)) + { + serial.ClosePort(); + workerResponse = RetVal.CannotCommWithCamera; + workerEvent.Set(); + continue; + } + + WT_SSOp_Complete(workerResponse); + + workerResponse = RetVal.OK; + workerEvent.Set(); + } + //------------------------------------------------------------------------------------------- + else if (workerCmd is Command.SetBrightness) + { + Command.SetBrightness args = workerCmd as Command.SetBrightness; + + /// Set image brightness + /// Format: setbright 0..100 + /// Example: setbright 50 + int[] received = new int[1]; + received[0] = 0; /// OK in debug mode + + iretv = serial.CommandInt(string.Format("setbright {0}\r\n", Math.Max(0, Math.Min((int)(100.0f * args.Brightness), 100))), + out received, 1, out m_errorStr); + + workerResponse = (iretv <= 0 || received[0] < 0) ? RetVal.OpFailed : RetVal.OK; + workerEvent.Set(); + } + //------------------------------------------------------------------------------------------- + else if (workerCmd is Command.Grab) + { + Command.Grab args = workerCmd as Command.Grab; + + int[] received = new int[1]; + received[0] = 0; /// OK in debug mode + + iretv = serial.CommandInt(string.Format("setbright {0}\r\n", Math.Max(0, Math.Min((int)(100.0f * args.Brightness), 100))), + out received, 1, out m_errorStr); + if (iretv <= 0 || received[0] < 0) + { + workerResponse = RetVal.OpFailed; + workerEvent.Set(); + continue; + } + + + iretv = serial.CommandInt(String.Format("new matbyte snap({0},{1}) vecint iroi(5)\r\n", args.W, args.H), + out received, 1, out m_errorStr); + if (iretv<=0 || received[0] < 0) + { + workerResponse = RetVal.OpFailed; + workerEvent.Set(); + continue; + } + + + iretv = serial.CommandInt(String.Format("set iroi {0} {1} {2} {3} {4}\r\n", + args.X, args.Y, args.W, args.H, args.Scale), + out received, 1, out m_errorStr); + if (iretv<=0 || received[0] < 0) + { + workerResponse = RetVal.OpFailed; + workerEvent.Set(); + continue; + } + + // grab + iretv = serial.CommandInt(String.Format("grab snap iroi\r\n"), + out received, 1, out m_errorStr); + if (iretv <= 0 || received[0] < 0) + { + workerResponse = RetVal.OpFailed; + workerEvent.Set(); + continue; + } + + // save + string fmtStr = (args.Format == FileFormat.Bmp) ? "bmp" : ( (args.Format == FileFormat.Jpeg) ? "jpg" : "idc"); + cmd = string.Format("save {0} snap {1}\r\n", fmtStr, args.FileName); + iretv = serial.CommandInt(cmd, out received, 1, out m_errorStr); + workerResponse = (iretv <= 0 || received[0] < 0) ? RetVal.OpFailed : RetVal.OK; + workerEvent.Set(); + } + //------------------------------------------------------------------------------------------- + else if (workerCmd is Command.Save) + { + Command.Save args = workerCmd as Command.Save; + + string fmtStr = (args.Format == FileFormat.Bmp) ? "bmp" : ( (args.Format == FileFormat.Jpeg) ? "jpg" : "idc"); + cmd = string.Format("save {0} {1} {2}\r\n", fmtStr, args.VariableName, args.FileName); + + int[] received = new int[1]; + received[0] = 0; /// OK in debug mode + iretv = serial.CommandInt(cmd, out received, 1, out m_errorStr); + + if (iretv <= 0 || received[0] < 0) + { + // NOK + workerResponse = RetVal.OpFailed; + workerEvent.Set(); + continue; + } + else if (!args.WaitCompleted) + { + // OK and does not wait for completition + workerResponse = RetVal.OK; + workerEvent.Set(); + continue; + } + else + { + // OK, but waits for completition + workerResponse = RetVal.Busy; // state -> State.CAMERA_BUSY + workerEvent.Set(); + + while (true) + { + Thread.Sleep(200); + + iretv = serial.CommandInt("fiostate\r\n", out received, 1, out m_errorStr); + if (iretv <= 0 || received[0] <= 0) + { + //m_pWnd->PostMessage(WM_USER, EVENT_OP_COMPLETED+m_cameraNr, 0); <------- TODO + idcState = IdcState.OpCompleted; + break; + } + } + + WT_SSOp_Wait4StopOp(Timeout.Infinite); + + // OK & completed + workerResponse = RetVal.OK; + workerEvent.Set(); + } + } + //------------------------------------------------------------------------------------------- +/* + ///--------------------------------------- + /// Releases IDC100 memory allocated by created images and variables + /// and deletes oroi1 ... oroi9 (complete detection result) + /// Format: clear + ///--------------------------------------- + case WorkerCommand.NEW_WM: + { + int[] received = new int[1]; + received[0] = 0; /// OK in debug mode + + iretv = serial.CommandInt("delete -all\r\n", out received, 1, out m_errorStr); + if (iretv <= 0 || received[0] < 0) + { + workerResponse = RetVal.OP_FAILED; + workerEvent.Set(); + break; + } + + iretv = serial.CommandInt("new int nrarrows\r\n", out received, 1, out m_errorStr); + if (iretv<=0 || received[0] < 0) + { + workerResponse = RetVal.OP_FAILED; + workerEvent.Set(); + break; + } + + iretv = serial.CommandInt(String.Format("set nrarrows {0}\r\n", arrows.GetLength(0) - 1), out received, 1, out m_errorStr); + if (iretv<=0 || received[0] < 0) + { + workerResponse = RetVal.OP_FAILED; + workerEvent.Set(); + break; + } + + workerResponse = RetVal.OK; /// Eventually overwritten in the for loop + //------ + for (int arwIx = 1; arwIx <= arrows.GetLength(0) - 1; arwIx++) + { + cmd = String.Format("new vecfloat params{0}({1}) vecint oroi{0}(5) matshort bkgnd{0}({2},{3}) matbyte detected{0}({4},{5})\r\n", + arwIx, ParamsSize, (int)(Math.Round(arrows[arwIx].oroi_w)), (int)(Math.Round(arrows[arwIx].oroi_h)), + arrows[arwIx].iroi_w, arrows[arwIx].iroi_h); + iretv = serial.CommandInt(cmd, out received, 1, out m_errorStr); + if (iretv<=0 || received[0] < 0) + { + workerResponse = RetVal.OP_FAILED; + break; + } + + cmd = String.Format("set params{0} {1} {2} {3} {4} {5} {6} {7} {8} {9} {10} {11} {12} {13} {14}\r\n", + arwIx, ParamsSize, + arrows[arwIx].wmType, + arrows[arwIx].cx.ToString("F2", System.Globalization.CultureInfo.InvariantCulture), + arrows[arwIx].cy.ToString("F2", System.Globalization.CultureInfo.InvariantCulture), + arrows[arwIx].oroi_w.ToString("F2", System.Globalization.CultureInfo.InvariantCulture), + arrows[arwIx].oroi_h.ToString("F2", System.Globalization.CultureInfo.InvariantCulture), + arrows[arwIx].r1.ToString("F2", System.Globalization.CultureInfo.InvariantCulture), + arrows[arwIx].r2.ToString("F2", System.Globalization.CultureInfo.InvariantCulture), + arrows[arwIx].r3.ToString("F2", System.Globalization.CultureInfo.InvariantCulture), + arrows[arwIx].a1.ToString("F2", System.Globalization.CultureInfo.InvariantCulture), + arrows[arwIx].a2.ToString("F2", System.Globalization.CultureInfo.InvariantCulture), + arrows[arwIx].step_a.ToString("F2", System.Globalization.CultureInfo.InvariantCulture), + arrows[arwIx].nom_speed.ToString("F2", System.Globalization.CultureInfo.InvariantCulture), + arrows[arwIx].background_corr); + iretv = serial.CommandInt(cmd, out received, 1, out m_errorStr); + if (iretv <= 0 || received[0] < 0) + { + workerResponse = RetVal.OP_FAILED; + break; + } + + cmd = String.Format("set oroi{0} 0 0 {1} {2} 1\r\n", + arwIx, (int)(Math.Round(arrows[arwIx].oroi_w)), (int)(Math.Round(arrows[arwIx].oroi_h))); + iretv = serial.CommandInt(cmd, out received, 1, out m_errorStr); + if (iretv==0 || received[0] < 0) + { + workerResponse = RetVal.OP_FAILED; + break; + } + } //for + + workerEvent.Set(); + break; + } +*/ + //------------------------------------------------------------------------------------------- + else if (workerCmd is Command.Detect) + { + Command.Detect args = workerCmd as Command.Detect; + + int[] received = new int[1]; + received[0] = 0; /// OK in debug mode + + iretv = serial.CommandInt(string.Format("setbright {0}\r\n", Math.Max(0, Math.Min((int)(100.0f * args.Brightness), 100))), + out received, 1, out m_errorStr); + if (iretv <= 0 || received[0] < 0) + { + workerResponse = RetVal.OpFailed; + workerEvent.Set(); + continue; + } + + workerResponse = RetVal.Busy; // state -> State.CAMERA_BUSY + workerEvent.Set(); + + /// Common commands: + cmd = "delete -ex oroi1 oroi2 bkgnd1 bkgnd2 detected1 detected2\r\n"; + if (RetVal.OK == (retv = WT_SSOp_FastCmd(cmd))) + { + if (RetVal.OK == (retv = WT_SSOp_FastCmd("loadflash\r\n"))) + { + cmd = String.Format("new vecfloat params{0}({1}) vecint oroi{0}(5) matshort bkgnd{0}({2},{3}) matbyte detected{0}({4},{5})\r\n", + args.RoiNr, + ParamsSize, + (int)Math.Round(args.ORoiW), + (int)Math.Round(args.ORoiH), + args.IRoiW, + args.IRoiH); + if (RetVal.OK == (retv = WT_SSOp_FastCmd(cmd))) + { + cmd = String.Format("set params{0} {1} {2} {3} {4} {5} {6} {7} {8} {9} {10} {11} {12} {13} {14}\r\n", + args.RoiNr, + ParamsSize, + args.WMeterType, + args.CX.ToString("F2", System.Globalization.CultureInfo.InvariantCulture), + args.CY.ToString("F2", System.Globalization.CultureInfo.InvariantCulture), + args.ORoiW.ToString("F2", System.Globalization.CultureInfo.InvariantCulture), + args.ORoiH.ToString("F2", System.Globalization.CultureInfo.InvariantCulture), + args.R1.ToString("F2", System.Globalization.CultureInfo.InvariantCulture), + args.R2.ToString("F2", System.Globalization.CultureInfo.InvariantCulture), + args.R3.ToString("F2", System.Globalization.CultureInfo.InvariantCulture), + args.Ang1.ToString("F2", System.Globalization.CultureInfo.InvariantCulture), + args.Ang2.ToString("F2", System.Globalization.CultureInfo.InvariantCulture), + args.AngStep.ToString("F2", System.Globalization.CultureInfo.InvariantCulture), + args.NomSpeed.ToString("F2", System.Globalization.CultureInfo.InvariantCulture), + args.BackgroundCorr); + if (RetVal.OK == (retv = WT_SSOp_FastCmd(cmd))) + { + cmd = String.Format("set oroi{0} 0 0 {1} {2} 1\r\n", + args.RoiNr, (int)Math.Round(args.ORoiW), (int)Math.Round(args.ORoiH)); + if (RetVal.OK == (retv = WT_SSOp_FastCmd(cmd))) + { + if (args.WMeterType == 0) + { + /// + /// wmType==0 commands: + /// + cmd = String.Format("new vecint iroi{0}(5) periods timestamps cubbyte seq\r\n", args.RoiNr); + if (RetVal.OK == (retv = WT_SSOp_FastCmd(cmd))) + { + cmd = String.Format("set iroi{0} {1} {2} {3} {4} 1\r\n", + args.RoiNr, args.IRoiX, args.IRoiY, args.IRoiW, args.IRoiH); + if (RetVal.OK == (retv = WT_SSOp_FastCmd(cmd))) + { + StringBuilder sb = new StringBuilder(40); + for (int i = 0; i < args.SequenceLen; i++) + { + sb.Append(" "); + sb.Append((i % 2 == 0) ? "1" : args.SequenceTiming.ToString()); + } + if (RetVal.OK == (retv = WT_SSOp_FastCmd(String.Format("set periods{0}\r\n", sb.ToString())))) + { + cmd = String.Format("grab seq iroi{0} {1} periods timestamps\r\n", + args.RoiNr, args.SequenceLen); + if (RetVal.OK == (retv = WT_SSOp_LongCmd(cmd))) + { + switch (args.RoiNr) + { + default: retv = 0; break; + case 2: retv = WT_SSOp_LongCmd_NoTmOut("mask seq iroi2 oroi1\r\n"); break; + case 3: retv = WT_SSOp_LongCmd_NoTmOut("mask seq iroi3 oroi1 oroi2\r\n"); break; + case 4: retv = WT_SSOp_LongCmd_NoTmOut("mask seq iroi4 oroi1 oroi2 oroi3\r\n"); break; + } + if (RetVal.OK == retv) + { + retv = WT_SSOp_LongCmd(String.Format("detect {0} seq periods detected{0}\r\n", + args.RoiNr)); + + if (retv == RetVal.OK) + { + // save + cmd = string.Format("save jpg detected{0} detected{0}\r\n", args.RoiNr); + iretv = serial.CommandInt(cmd, out received, 1, out m_errorStr); + + RetVal retv2 = (iretv <= 0 || received[0] < 0) ? RetVal.OpFailed : RetVal.OK; + if (retv2 == RetVal.OpInterrupted) retv = RetVal.OpInterrupted; + } + } + } + } + } + } + } + else if (args.WMeterType >= 1) + { // + // wmType==1,2 commands: + // + cmd = String.Format("new matfloat homo vecint iroi{0}(5) cubbyte seq cubshort c1 matshort strip lsdbkg digits0\r\n", args.RoiNr); + if (RetVal.OK == (retv = WT_SSOp_FastCmd(cmd))) + { + cmd = String.Format("set iroi{0} {1} {2} {3} {4} 1\r\n", args.RoiNr, args.IRoiX, args.IRoiY, args.IRoiW, args.IRoiH); + if (RetVal.OK == (retv = WT_SSOp_FastCmd(cmd))) + { + if (RetVal.OK == (retv = WT_SSOp_LongCmd(String.Format("grab seq iroi{0} 20 11\r\n", args.RoiNr)))) + { + if (RetVal.OK == (retv = WT_SSOp_LongCmd(String.Format("detect {0} seq 1 detected{0} homo\r\n", args.RoiNr)))) + { + // time 95s +/- 1.5 turns + if (RetVal.OK == (retv = WT_SSOp_LongCmd(String.Format("grab c1 oroi{0} 300 7\r\n", args.RoiNr)))) + { + if (RetVal.OK == (retv = WT_SSOp_LongCmd_NoTmOut(String.Format("mount c1 oroi{0} homo strip lsdbkg 0\r\n", args.RoiNr)))) + { + retv = WT_SSOp_LongCmd("getdigits strip digits0\r\n"); + } + } + } + } + } + } + } + } + } + } + } + } + WT_SSOp_Complete(retv); + workerResponse = RetVal.OK; + workerEvent.Set(); + } +/* + case WorkerCommand.VERIFY: + { + int[] received = new int[1]; + received[0] = 0; /// OK in debug mode + + iretv = serial.CommandInt("verify\r\n", out received, 1, out m_errorStr); + if (iretv <= 0 || received[0] < 0) + { + workerResponse = RetVal.OP_FAILED; + workerEvent.Set(); + break; + } + + workerResponse = RetVal.BUSY; // state -> State.CAMERA_BUSY + workerEvent.Set(); + + workerResponse = RetVal.OK; + workerEvent.Set(); + break; + } + */ + //------------------------------------------------------------------------------------------- + else if (workerCmd is Command.Measure) + { + Command.Measure args = workerCmd as Command.Measure; + + int[] received = new int[1]; + received[0] = 0; /// OK in debug mode + + iretv = serial.CommandInt(string.Format("setbright {0}\r\n", Math.Max(0, Math.Min((int)(100.0f * args.Brightness), 100))), + out received, 1, out m_errorStr); + if (iretv <= 0 || received[0] < 0) + { + workerResponse = RetVal.OpFailed; + workerEvent.Set(); + continue; + } + + int logLen = 400000 / (int)Math.Round(args.ORoiW) / (int)Math.Round(args.ORoiH); + if (logLen < 2) logLen = 2; + + if (args.WMeterType == 0) + { + cmd = String.Format("new vecint iroi{0}(5) snaptimes(10) cubshort snaps({1},{2},10) log({1},{2},{3}) int shift\r\n", + args.RoiNr, (int)Math.Round(args.ORoiW), (int)Math.Round(args.ORoiH), logLen); + } + else + { + cmd = String.Format("new vecint iroi{0}(5) snaptimes(10) cubshort snaps({1},{2},10) lsdlog int shift\r\n", + args.RoiNr, (int)Math.Round(args.CX), (int)Math.Round(args.CY)); // snaps(cx,cy,10) ... dimensions + } + + iretv = serial.CommandInt(cmd, out received, 1, out m_errorStr); + if (iretv<=0 || received[0] < 0) + { + workerResponse = RetVal.OpFailed; + workerEvent.Set(); + continue; + } + + cmd = String.Format("set iroi{0} {1} {2} {3} {4} 1\r\n", + args.RoiNr, args.IRoiX, args.IRoiY, args.IRoiW, args.IRoiH); + iretv = serial.CommandInt(cmd, out received, 1, out m_errorStr); + if (iretv <= 0 || received[0] < 0) + { + workerResponse = RetVal.OpFailed; + workerEvent.Set(); + continue; + } + + /* + cmd = String.Format("getshift seq iroi{0} shift {1}\r\n", args.RoiNr, 30); + iretv = serial.CommandInt(cmd, out received, 1, out m_errorStr); + if (iretv <= 0 || received[0] < 0) + { + workerResponse = RetVal.OpFailed; + workerEvent.Set(); + continue; + } + */ + + if (args.WMeterType == 0 && args.MaxMvmt == 0 && args.MinMvmt == 0) + { + /// + /// Std: Uses 'initSpeed' + /// + cmd = String.Format("task 1 oroi{0} 1 {1} {2} shift snaps snaptimes log {3} params{0} bkgnd{0}\r\n", + args.RoiNr, + MesurementPeriod_Frames, + (args.Triggered ? "1" : "0"), + logLen); + serial.FifoFlush(); + serial.WriteString(cmd); // send command + } + else if (args.WMeterType == 0) + { + // + // Introduced in ver.7.6.7: + // Uses 'maxMvmt' and 'minMvmt', allows faster movement measurement + // + cmd = String.Format("task 1 oroi{0} 1 {1} {2} shift snaps snaptimes log {3} params{0} bkgnd{0} {4} {5}\r\n", + args.RoiNr, + MesurementPeriod_Frames, + (args.Triggered ? "1" : "0"), + logLen, + args.MaxMvmt, + args.MinMvmt); + serial.FifoFlush(); + serial.WriteString(cmd); // send command + } + else if (args.WMeterType >= 1) + { + // + // Digital counters (Dubai) + // + cmd = String.Format("task {0} oroi{1} 1 {2} {3} shift snaps snaptimes 0 0 homo digits0 params{1} lsdbkg 36 lsdlog\r\n", + args.WMeterType + 1, + args.RoiNr, + MesurementPeriod_Frames, + (args.Triggered ? "1" : "0")); + serial.FifoFlush(); + serial.WriteString(cmd); // send command + } + else + { + // ... + } + + // clear measurement data + measurements.Clear(); + wm_nrBegin = 0; + wm_nrEnd = 0; + wm_timestampBegin = 0; + wm_timestampEnd = 0; + + workerResponse = RetVal.Busy; // state -> State.CAMERA_BUSY + workerEvent.Set(); + + // start reading data + byte znak; + bool stopOpReceived = false; + int angle; + uint time; + while (true) + { + // wait for '>' character, check for WorkerCommand.STOP_OP + do { + if (!stopOpReceived && WorkerCommand.StopOp == WT_SSOp_Wait4StopOp(5)) + { + stopOpReceived = true; + serial.WriteByte((byte)'Q'); + } + if (RetVal.OK != (retv = serial.ReadByte(out znak))) /// if ReadByte_C fails => quit the loop ... + { /// ... and return negative error code + break; + } + } + while (znak != '>'); + + if (retv != RetVal.OK) break; /// communication failed + + /// Read the rest of line + StringBuilder restOfLine = new StringBuilder(); + while (RetVal.OK == (retv = serial.ReadByte(out znak)) && + (znak != (byte)'\r') && (znak != (byte)'\n')) + { + restOfLine.Append((char)znak); + } + if (retv != RetVal.OK) break; + + log.InfoFormat("Received: >{0}", restOfLine); + + /// Parse the line, save and send the result + string[] results = restOfLine.ToString().Split(new char[] { ' ' }); + if ((results.Length >= 3) && results[1].Equals("0") && results[2].Equals("OK")) + { + retv = RetVal.OK; /// Op. successfully completed + break; + } + else if (results.Length < 3 || !UInt32.TryParse(results[1], out time) || !Int32.TryParse(results[2], out angle)) + { + retv = RetVal.OpFailed; /// Op. failed + log.ErrorFormat("RetVal.OpFailed", restOfLine); + break; + } + + if (!stopOpReceived) + { + if ((time > 0) && (measurements.Count < MaxMeasurementsCount)) + { + if (angle == (int)MARK.DUMMY) + { + // do nothing + } + else if (angle == (int)MARK.FALLING) + { + wm_nrBegin = measurements.Count; + wm_timestampBegin = time; + //m_pWnd->PostMessage(WM_USER, EVENT_DATA_READY+m_cameraNr, ID_BEGIN); <------- TODO + } + else if (angle == (int)MARK.RISING) + { + wm_nrEnd = measurements.Count; + wm_timestampEnd = time; + //m_pWnd->PostMessage(WM_USER, EVENT_DATA_READY+m_cameraNr, ID_END); <------- TODO + } + else + { + measurements.Add(new Measurement(time, angle)); + //m_pWnd->PostMessage(WM_USER, EVENT_DATA_READY+m_cameraNr, wm_nrmeasurements); <------- TODO + } + } + } + else if (retv == RetVal.OK && time == 0) + { + /// Wait until '$' + do { + if (RetVal.OK != (retv = serial.ReadByte(out znak))) /// if ReadByte_C fails => quit ... + break; //return -retv; /// ... the loop and return negative ... + } /// ... error code + while (znak != '$'); + break; + } + } + + if (retv != RetVal.OK && !stopOpReceived) + { + //m_pWnd->PostMessage(WM_USER, EVENT_OP_FAILED+m_cameraNr, 0); <------- TODO + idcState = IdcState.OpFailed; + WT_SSOp_Wait4StopOp(Timeout.Infinite); + } + + workerResponse = RetVal.OK; + workerEvent.Set(); + } + //------------------------------------------------------------------------------------------- + else if (workerCmd is Command.Other) + { + Command.Other args = workerCmd as Command.Other; + + int[] received = new int[1]; + received[0] = 0; /// OK in debug mode + + iretv = serial.CommandInt(args.Command + "\r\n", out received, 1, out m_errorStr); + if (iretv < 0) workerResponse = (RetVal)(-iretv); + else if (iretv==0) workerResponse = RetVal.OpFailed; + else if (received[0] < 0) workerResponse = (RetVal)(-received[0]); + else workerResponse = RetVal.OK; + + workerEvent.Set(); + } + //------------------------------------------------------------------------------------------- + else if (workerCmd is Command.Stream) + { + Command.Stream args = workerCmd as Command.Stream; + + int[] received = new int[1]; + received[0] = 0; /// OK in debug mode + + /// Check the camera file I/O state + while (true) + { + iretv = serial.CommandInt("fiostate\r\n", out received, 1, out m_errorStr); + if (iretv <= 0) + { + workerResponse = RetVal.OpFailed; + workerEvent.Set(); + continue; + } + else if (received[0] == 0) + { + break; /// Continue - start a stream operation + } + } + + iretv = serial.CommandInt(string.Format("setbright {0}\r\n", Math.Max(0, Math.Min((int)(100.0f * args.Brightness), 100))), + out received, 1, out m_errorStr); + if (iretv <= 0 || received[0] < 0) + { + workerResponse = RetVal.OpFailed; + workerEvent.Set(); + continue; + } + + /// Grab one image + if (args.Type != StreamType.Full) + { + iretv = serial.CommandInt("acqimage\r\n", out received, 1, out m_errorStr); + if (iretv <= 0 || received[0] < 0) + { + workerResponse = RetVal.OpFailed; + workerEvent.Set(); + continue; + } + } + + /// Prepare the camera command string + if (args.Format == FileFormat.Bmp) + { + if (args.Type == StreamType.SubSampled) cmd = "streamssdbmp\r\n"; + else if (args.Type == StreamType.Focus) cmd = "streamroibmp\r\n"; + else cmd = "streambmp\r\n"; + } + else if (args.Format == FileFormat.Jpeg) + { + if (args.Type == StreamType.SubSampled) cmd = "streamssdjpg\r\n"; + else if (args.Type == StreamType.Focus) cmd = "streamroijpg\r\n"; + else cmd = "streamjpg\r\n"; + } + else + { + workerResponse = RetVal.OK; + workerEvent.Set(); + continue; + } + + /// Start streaming + iretv = serial.CommandInt(cmd, out received, 1, out m_errorStr); + + if (iretv >= 1 && received[0] == 0) + { + workerResponse = RetVal.Busy; // state -> State.CAMERA_BUSY + workerEvent.Set(); + + WorkerCommand wrkCmd = WT_SSOp_Wait4StopOp(Timeout.Infinite); + + /// Stop streaming + iretv = serial.CommandInt("stopstream\r\n", out received, 1, out m_errorStr); + if (iretv >= 1 && received[0] == 0) + { + workerResponse = RetVal.OK; // state -> State.CAMERA_IDLE + workerEvent.Set(); + } + if (wrkCmd != WorkerCommand.StopOp) + { + WT_SSOp_Wait4StopOp(Timeout.Infinite); + workerResponse = RetVal.OK; // state: State.CAMERA_OP_COMPLETED -> State.CAMERA_IDLE or + workerEvent.Set(); + } + } + else + { + /// Streaming was not started, return error and wait for StopOp + workerResponse = RetVal.OpFailed; // state -> State.CAMERA_OP_FAILED + workerEvent.Set(); + + WT_SSOp_Wait4StopOp(Timeout.Infinite); + + workerResponse = RetVal.OK; // state -> State.CAMERA_IDLE + workerEvent.Set(); + } + } + //------------------------------------------------------------------------------------------- + else if (workerCmd is Command.StopStream) + { + Command.StopStream args = workerCmd as Command.StopStream; + } + } // end while (true) + } + + //--------------------------------------------------------------------- + // Sends command and waits for a response. + // + // Arguments: + // cmd ........ command + // Returns: + // long ... 0 = command completed OK, error code=0 + // 1...999 = command completed with an error code + // RetVal.OP_INTERRUPTED = StopOp was received by the OCX component + // 1000... = camera error (communication timeout ?) + //--------------------------------------------------------------------- + RetVal WT_SSOp_FastCmd(string cmd) + { + if (WorkerCommand.StopOp == WT_SSOp_Wait4StopOp(1)) + { + return RetVal.OpInterrupted; /// This error code has the priority to avoid deadlocks + } + + int[] received = new int[1]; + received[0] = 0; /// OK in debug mode + + /// Send a command that cannot be interrupted via 'Q' + int readByteRetv = serial.CommandInt(cmd, out received, 1, out m_errorStr); + + if (readByteRetv<0) return (RetVal)(-readByteRetv); /// possibly a camera timeout + + return (RetVal)(-received[0]); /// <--- normal return from the operation + } + + //--------------------------------------------------------------------- + // Sends command and waits for "> 'received' 'string'" or sends 'Q' + // after CMD_STOP_OP. Then waits for a prompt '$'. + // Waits until '>' is received. + // + // Arguments: + // cmd ........ command + // Returns: + // long ... 0 = command completed OK, error code=0 + // 1...999 = command completed with an error code + // RetVal.OP_INTERRUPTED = StopOp was received by the OCX component + // 1000... = camera error (communication timeout ?) + //--------------------------------------------------------------------- + RetVal WT_SSOp_LongCmd(string cmd) + { + /// Send the command + serial.FifoFlush(); + serial.WriteString(cmd); + + RetVal readByteRetv; + byte znak; + + /// When WorkerCommand.STOP_OP arrives, 'Q' character is sent to abort the operation. + /// Then the loop still waits until '>' is received. + bool stopOpReceived = false; + do { + if (!stopOpReceived && WorkerCommand.StopOp == WT_SSOp_Wait4StopOp(5)) + { + /// send 'Q' if CMD_STOP_OP worker thread command is received + stopOpReceived = true; + serial.WriteByte((byte)'Q'); + } + + if (RetVal.OK != (readByteRetv = serial.ReadByte(out znak))) break; + /// if ReadByte_C fails quit the loop and return negative error code + } + while (znak != (byte)'>'); + + if (stopOpReceived) return RetVal.OpInterrupted; /// StopOp: This error code has the priority to avoid deadlocks + if (readByteRetv != RetVal.OK) return readByteRetv; /// Possibly a camera communication timeout + + /// Read a line of text from IDC terminated by '\r' (and '\n') + StringBuilder tmp = new StringBuilder(); + do + { + if (RetVal.OK != (readByteRetv = serial.ReadByte(out znak))) break; + if (znak == (byte)'\r') break; + tmp.Append((char)znak); + } + while (true); + + log.InfoFormat("{0}: Received: >{1}", cameraNr, tmp); + + if (readByteRetv != RetVal.OK) return readByteRetv; /// Return on error + + /// Parse the line after '>'. + /// Read two fields: Return code and the rest of the line. + const int maxArrayLen = 3; + string[] strArray = tmp.ToString().Split(new char[] {' '}, maxArrayLen); + /// + if (strArray.Length < 3) return RetVal.CommError; /// Unexpected format, there should be at least 2 strings + /// + int negativeIdcReturnCode; + if (!Int32.TryParse(strArray[1], out negativeIdcReturnCode)) + { + return RetVal.CommError; + } + else if (negativeIdcReturnCode < 0) + { + m_errorStr = strArray[2]; + } + + /// Read characters until '$' received + do { + if (0 != (readByteRetv = serial.ReadByte(out znak))) break; + } + while (znak != '$'); + + if (readByteRetv != RetVal.OK) return readByteRetv; /// Possibly a camera communication timeout + + return (RetVal)(-negativeIdcReturnCode); /// Normal return from the operation + } + + //---------------------------------------------------------------------------- + // Sends command and waits for "> 'received' 'string'" or sends 'Q' + // after CMD_STOP_OP. Then waits for a prompt '$'. + // + // Arguments: + // cmd ........ command + // Returns: + // long ... 0 = command completed OK, error code=0 + // 1...999 = command completed with an error code + // RetVal.OP_INTERRUPTED = StopOp was received by the OCX component + // 1000... = camera error (communication timeout ?) + //---------------------------------------------------------------------------- + RetVal WT_SSOp_LongCmd_NoTmOut(string cmd) + { + /// Send the command + serial.FifoFlush(); + serial.WriteString(cmd); + + RetVal readByteRetv; + byte znak; + + /// When WorkerCommand.STOP_OP arrives, 'Q' character is sent to abort the operation. + /// Then the loop still waits until '>' is received. + bool stopOpReceived = false; + do { + if (!stopOpReceived && WorkerCommand.StopOp == WT_SSOp_Wait4StopOp(5)) + { + // send 'Q' if CMD_STOP_OP worker thread command is received + stopOpReceived = true; + serial.WriteByte((byte)'Q'); + } + readByteRetv = serial.ReadByte(out znak); /// Do not quit the loop on timeout (???) + } + while (znak != '>'); + + if (stopOpReceived) return RetVal.OpInterrupted; /// StopOp: This error code has the priority to avoid deadlocks + if (readByteRetv != RetVal.OK) return readByteRetv; /// Possibly a camera communication timeout + + /// Read a line of text from IDC terminated by '\r' (and '\n') + StringBuilder tmp = new StringBuilder(); + do + { + if (RetVal.OK != (readByteRetv = serial.ReadByte(out znak))) break; + if (znak == (byte)'\r') break; + tmp.Append((char)znak); + } + while (true); + + if (readByteRetv != RetVal.OK) return readByteRetv; /// Return on error + + /// Parse the line after '>'. + /// Read two fields: Return code and the rest of the line. + const int maxArrayLen = 2; + string[] strArray = tmp.ToString().Split(new char[] { ' ' }, maxArrayLen); + /// + if (strArray.Length < 2) return RetVal.OpFailed; /// Unexpected format, there should be at least 2 strings + /// + int negativeIdcReturnCode; + Int32.TryParse(strArray[0], out negativeIdcReturnCode); + if (negativeIdcReturnCode < 0) m_errorStr = strArray[1]; + + /// Read characters until '$' received + do + { + if (0 != (readByteRetv = serial.ReadByte(out znak))) break; + } + while (znak != '$'); + + if (readByteRetv != RetVal.OK) return readByteRetv; /// Possibly a camera communication timeout + + return (RetVal)(-negativeIdcReturnCode); /// Normal return from the operation + } + + //--------------------------------------------------------------------- + // Sends OP_COPMPETED / OP_FAILED message and waits for StopOp. + // + // Arguments: + // errorCode ... RetVal.OP_INTERRUPTED, !!!do not issue any message anymore + // < 1000 command line response (number after >), or + // >=1000 error code (camera timeout, etc.) + // Returns: + // long ........ 0 = OK ... 'received' is valid + // RetVal.COMM_TIEMOUT + //--------------------------------------------------------------------- + void WT_SSOp_Complete(RetVal errorCode) + { + if (errorCode == RetVal.OpInterrupted) return; + + // Send an appropriate message to the control + if (errorCode == RetVal.OK) + { + //m_pWnd->PostMessage(WM_USER, EVENT_OP_COMPLETED+m_cameraNr, 0); <------- TODO + idcState = IdcState.OpCompleted; + } + else + { + //m_pWnd->PostMessage(WM_USER, EVENT_OP_FAILED+m_cameraNr, -errorCode); <------- TODO + idcState = IdcState.OpFailed; + } + + // Wait for StopOp + WT_SSOp_Wait4StopOp(Timeout.Infinite); + } + + /** ------------------------------------------------------------------------------ + * Waits for CMD_STOP_OP command. Other commands are ignoerd. + * + * Arguments: + * ms .............. timeout in ms or INFINITE (default) + * Returns: + * WorkerCommand.STOP_OP ... STOP_OP received + * WorkerCommand.Timeout ... time expired, no STOP_OP received + * ------------------------------------------------------------------------------- */ + WorkerCommand WT_SSOp_Wait4StopOp(int timeoutMs) + { + while (true) + { + if (workerCommandEvent.WaitOne(timeoutMs)) + { + if (workerCmd is Command.StopOp) return WorkerCommand.StopOp; + } + else + { + return WorkerCommand.Timeout; + } + } + } + } +} diff --git a/TestBenchFramework/BenchControl/Cameras/IdcCamera/IdcCamera.cs b/TestBenchFramework/BenchControl/Cameras/IdcCamera/IdcCamera.cs new file mode 100644 index 000000000..9eec77e40 --- /dev/null +++ b/TestBenchFramework/BenchControl/Cameras/IdcCamera/IdcCamera.cs @@ -0,0 +1,297 @@ +using System; +using System.Diagnostics; +using System.Collections.Generic; +using System.Threading; +using TBF.BenchControl; +using TBF.BenchControl.Generic; +using log4net; + +namespace TBF.BenchControl.Cameras.IdcCamera +{ + /// + /// IdcCamera object represents all IDC cameras. + /// Camera ID is an argument of most methods. + /// + public class IdcCamera : ComponentBase, IDevice, IOperation, GenericDevices.ICamera + { + private static readonly ILog log = LogManager.GetLogger(typeof(IdcCamera)); + public override string ToString() { return string.Format("{0}, com{1}, {2}, roi{3}", + idcCameraCfg.Name, idcCameraCfg.ComPortNr, + currentOp, currentRoiId); } + + const int MaxRoisCount = 4; + + /// + /// Enumeration of cameras via static fields and methods + /// + static int nextCameraNr = 0; + public static void ResetStaticProperties() + { + nextCameraNr = 0; + } + + int cameraNr; + public int CameraNr { get { return cameraNr; } } + + public float Brightness { get { return idcCameraCfg.BrightnessCam; } } + + private readonly IdcCameraCfg idcCameraCfg; + + /// + /// Currently running camera operation. + /// ReadRegisterOp-s are not included in this list, they are independent. + /// + public enum CurrentOp + { + None, + StartNew, + SetBrightness, + Grab, + Live, + Focus, + Detect, + Measure, + } + + /// Private fields + public Idc100 Idc100; /// Idc100 camera low level implementation + CurrentOp currentOp; + int currentRoiId; + IWorkerCmd detectCmd; + IWorkerCmd measureCmd; + + public IdcCamera(IdcCameraCfg cfg, IList components) + : base(cfg) + { + if (cfg == null) throw new ArgumentNullException("cfg"); + this.idcCameraCfg = cfg; + + cameraNr = nextCameraNr++; + } + + public void Initialize() + { + if (idcCameraCfg.DebugLevel == Entities.DebugMode.Simulate) + { + log.WarnFormat("{0}: in simulation mode", Name); + return; + } + + /// Initialize the camera + Idc100 = new Idc100(Name, cameraNr, idcCameraCfg.ComPortNr, idcCameraCfg.BaudRate, idcCameraCfg.BrightnessCam); + RetVal rVal = Idc100.StartOp(new Command.Connect(3000)); /// timeout in ms + + + if (idcCameraCfg.DebugLevel == Entities.DebugMode.AutoDetect) + { + if (rVal == RetVal.OK) + idcCameraCfg.DebugLevel = Entities.DebugMode.DetectedOn; + else + idcCameraCfg.DebugLevel = Entities.DebugMode.DetectedOff; + } + else if (rVal != RetVal.OK) + { + throw (new Exception(string.Format("Cannot make a connection to {0} on COM{1}", Name, idcCameraCfg.ComPortNr))); + } + + if (idcCameraCfg.DebugLevel != Entities.DebugMode.DetectedOff) + { + log.WarnFormat("Detected: {0} on COM{1} ver. {2}", Name, idcCameraCfg.ComPortNr, Idc100.Version); + } + } + + public void RunDeviceBefore() + { + } + + public void RunDeviceAfter() + { + } + + public void StopDevice() + { + if (Idc100 != null) + { + RetVal rVal = Idc100.StartOp(new Command.Disconnect()); + Idc100.ShutDown(); + } + } + + /// + /// Restart the camera with a new firmware. + /// + /// Reference to operation object instance + public IOperation StartNewOp() + { + if (currentOp != CurrentOp.None) throw new Exception("Sequence error"); + currentOp = CurrentOp.StartNew; + return this; + } + + /// + /// Set camera image brightness (camera aperture). + /// + /// Reference to operation object instance + public IOperation SetBrightnessOp() + { + if (currentOp != CurrentOp.None) throw new Exception("Sequence error"); + currentOp = CurrentOp.SetBrightness; + return this; + } + + /// + /// Grab an image. + /// + /// Reference to operation object instance + public IOperation GrabOp() + { + if (currentOp != CurrentOp.None) throw new Exception("Sequence error"); + currentOp = CurrentOp.Grab; + return this; + } + + /// + /// Display live image. + /// + /// Reference to operation object instance + public IOperation LiveOp() + { + if (currentOp != CurrentOp.None) throw new Exception("Sequence error"); + currentOp = CurrentOp.Live; + return this; + } + + /// + /// Display live detail to focus the camera. + /// + /// Reference to operation object instance + public IOperation FocusOp() + { + if (currentOp != CurrentOp.None) throw new Exception("Sequence error"); + currentOp = CurrentOp.Focus; + return this; + } + + /// + /// Watermeter wheel/arrow detection process. + /// + /// Region of interest (1..MaxRoisCount) + /// Reference to operation object instance + public IOperation DetectOp(int roiId, IWorkerCmd detectCmd) + { + if (currentOp != CurrentOp.None) throw new Exception("Sequence error"); + if (roiId < 1 || roiId > MaxRoisCount) throw new ArgumentOutOfRangeException("roiId"); + currentOp = CurrentOp.Detect; + this.currentRoiId = roiId; + this.detectCmd = detectCmd; + return this; + } + + /// + /// Watermeter wheel/arrow angle measurement process. + /// + /// Region of interest (1..MaxRoisCount) + /// Reference to operation object instance + public IOperation MeasureOp(int roiId, IWorkerCmd measureCmd) + { + if (currentOp != CurrentOp.None) throw new Exception("Sequence error"); + if (roiId < 1 || roiId > MaxRoisCount) throw new ArgumentOutOfRangeException("roiId"); + currentOp = CurrentOp.Measure; + this.currentRoiId = roiId; + this.measureCmd = measureCmd; + return this; + } + + /// Start the operation + public void Start() + { + if (Cfg.DebugLevel == Entities.DebugMode.Normal || Cfg.DebugLevel == Entities.DebugMode.DetectedOn) + { + switch (currentOp) + { + case CurrentOp.StartNew: + Idc100.StartOp(new Command.StartNew()); + return; + case CurrentOp.Grab: + Idc100.StartOp(new Command.Grab("snap1", FileFormat.Jpeg, Brightness, false)); + return; + case CurrentOp.Live: + Idc100.StartOp(new Command.Stream(StreamType.SubSampled, FileFormat.Jpeg, Brightness)); + return; + case CurrentOp.Focus: + Idc100.StartOp(new Command.Stream(StreamType.Focus, FileFormat.Bmp, Brightness)); + return; + case CurrentOp.Detect: + Idc100.StartOp(this.detectCmd); + return; + case CurrentOp.Measure: + Idc100.StartOp(this.measureCmd); + return; + } + } + } + + /// + /// Check the cameraDev state (OP_COMPLETED or OP_FAILED) + /// + /// + public Event Run() + { + if (Cfg.DebugLevel == Entities.DebugMode.Normal || Cfg.DebugLevel == Entities.DebugMode.DetectedOn) + { + switch (currentOp) + { + case CurrentOp.Grab: + if (Idc100.IdcState == IdcState.Idle) return Event.None; + else return Event.Error; + + case CurrentOp.StartNew: + case CurrentOp.Live: + case CurrentOp.Focus: + case CurrentOp.Measure: + case CurrentOp.Detect: + if (Idc100.IdcState == IdcState.Busy) + { + return Event.CameraBusy; + } + else if (Idc100.IdcState == IdcState.OpCompleted) + { + log.InfoFormat("{0}: {1} - OpCompleted", cameraNr, currentOp); + return Event.CameraOpCompleted; + } + else if (Idc100.IdcState == IdcState.OpFailed) + { + log.WarnFormat("{0}: {1} - OpFailed", cameraNr, currentOp); + return Event.CameraOpFailed; + } + else return Event.Error; + + default: + return Event.Error; + } + } + else + { + if (currentOp == CurrentOp.Grab) + { + return Event.None; + } + else + { + return Event.CameraOpCompleted; + } + } + } + + /// Stop the operation + public void Stop() + { + if ((Cfg.DebugLevel == Entities.DebugMode.Normal || Cfg.DebugLevel == Entities.DebugMode.DetectedOn) + && (Idc100.IdcState != IdcState.Idle)) + { + Idc100.StopOp(); + } + currentOp = CurrentOp.None; + } + } +} diff --git a/TestBenchFramework/BenchControl/Cameras/IdcCamera/IdcCameraCfg.cs b/TestBenchFramework/BenchControl/Cameras/IdcCamera/IdcCameraCfg.cs new file mode 100644 index 000000000..87e74f5dd --- /dev/null +++ b/TestBenchFramework/BenchControl/Cameras/IdcCamera/IdcCameraCfg.cs @@ -0,0 +1,57 @@ +using System.IO; +using System.IO.Ports; +using System.Xml.Serialization; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.Cameras.IdcCamera +{ + public class IdcCameraCfg : ComponentCfgBase, Generic.IComponentCfg + { + public int ComPortNr; /// Com port number 1..999 + public int BaudRate; /// Baud rate 57600 or 115200 + public float BrightnessCam; /// Relative brightness 0 .. 1.0f + + /// Parameterless constructor + public IdcCameraCfg() + { + } + + /// Constructor + public IdcCameraCfg(IComponentFactory factory, string name, int comPortNr, int baudRate, float brightnessCam) + : base(factory, name) + { + this.ComPortNr = comPortNr; + this.BaudRate = baudRate; + this.BrightnessCam = brightnessCam; + } + + public IComponentCfg Clone() + { + return new IdcCameraCfg(Factory, Name, ComPortNr, BaudRate, BrightnessCam); + } + + public string ToString(int i) + { + return string.Format("COM{0}, {1}Bd, brightness={2}%", ComPortNr, BaudRate, (int)(100.0f * BrightnessCam)); + } + + public TBF.Entities.Component CreateDbEntity() + { + using (var writer = new StringWriter()) + { + (new XmlSerializer(GetType())).Serialize(writer, this); + return Entities.Component.CreateFromCfg(Name, Factory.ClassName, ParentName, ItemNr, DebugLevel, LogLevel, writer.ToString()); + } + } + + public static IComponentCfg CreateFromDbEntity(Entities.Component component, IComponentFactory factory) + { + using (var reader = new StringReader(component.Parameters)) + { + IdcCameraCfg config = (IdcCameraCfg)(new XmlSerializer(typeof(IdcCameraCfg))).Deserialize(reader); + config.InitCfgBaseFromEntity(component, factory); + return config; + } + } + } +} diff --git a/TestBenchFramework/BenchControl/Cameras/IdcCamera/IdcCameraCfgCtrl.cs b/TestBenchFramework/BenchControl/Cameras/IdcCamera/IdcCameraCfgCtrl.cs new file mode 100644 index 000000000..f15593e63 --- /dev/null +++ b/TestBenchFramework/BenchControl/Cameras/IdcCamera/IdcCameraCfgCtrl.cs @@ -0,0 +1,88 @@ +using System; +using System.Windows.Forms; +using System.IO.Ports; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.Cameras.IdcCamera +{ + public partial class IdcCameraCfgCtrl : UserControl, IComponentCfgCtrl + { + IdcCameraCfg config; + + public IComponentCfg Config + { + get { return config as IComponentCfg; } + set + { + config = value as IdcCameraCfg; + Redraw(); + } + } + + public IdcCameraCfgCtrl() + { + InitializeComponent(); + } + + private void IdcCameraCfgCtrl_Load(object sender, EventArgs e) + { + baudRateComboBox.Items.Add("57600"); + baudRateComboBox.Items.Add("115200"); + + Redraw(); + } + + void Redraw() + { + if (config == null) return; /// Control was not loaded, settings were not changed + + classNameLabel.Text = config.Factory.ClassName; + nameTextBox.Text = config.Name; + comPortNrTextBox.Text = config.ComPortNr.ToString(); + baudRateComboBox.Text = config.BaudRate.ToString(); + brightnessTextBox.Text = (100.0f * config.BrightnessCam).ToString(); + } + + public void Unlock() + { + nameTextBox.Enabled = true; + comPortNrTextBox.Enabled = true; + baudRateComboBox.Enabled = true; + brightnessTextBox.Enabled = true; + } + + public CfgVerifyFlags VerifyCfg(ref string message) + { + CfgVerifyFlags flags = CfgVerifyFlags.None; + + int dummy; + if (!int.TryParse(comPortNrTextBox.Text, out dummy) || dummy < 1 || dummy > 999) + { + flags |= CfgVerifyFlags.Error; + message += Environment.NewLine + "'Serial Port Number' is not valid"; + } + if (!int.TryParse(baudRateComboBox.Text, out dummy) || ((dummy != 57600) && (dummy != 115200))) + { + flags |= CfgVerifyFlags.Error; + message += Environment.NewLine + "'Baud Rate' should be 57600 or 115200 Bd"; + } + if (!int.TryParse(brightnessTextBox.Text, out dummy) || dummy < 0 || dummy > 100) + { + flags |= CfgVerifyFlags.Error; + message += Environment.NewLine + "'Brightness' should be between 0 and 100 %"; + } + + return flags; + } + + public void UpdateCfg() + { + if (config == null) return; /// Control was not loaded, settings were not changed + + config.Name = nameTextBox.Text; + config.ComPortNr = int.Parse(comPortNrTextBox.Text); + config.BaudRate = int.Parse(baudRateComboBox.Text); + config.BrightnessCam = ((float)int.Parse(brightnessTextBox.Text) / 100.0f); + } + } +} diff --git a/TestBenchFramework/BenchControl/Cameras/IdcCamera/IdcCameraCfgCtrl.designer.cs b/TestBenchFramework/BenchControl/Cameras/IdcCamera/IdcCameraCfgCtrl.designer.cs new file mode 100644 index 000000000..5e40a189e --- /dev/null +++ b/TestBenchFramework/BenchControl/Cameras/IdcCamera/IdcCameraCfgCtrl.designer.cs @@ -0,0 +1,176 @@ +namespace TBF.BenchControl.Cameras.IdcCamera +{ + partial class IdcCameraCfgCtrl + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.nameTextBox = new System.Windows.Forms.TextBox(); + this.nameLabel = new System.Windows.Forms.Label(); + this.classNameLabel = new System.Windows.Forms.Label(); + this.baudRateLabel = new System.Windows.Forms.Label(); + this.comPortNrTextBox = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.brightnessTextBox = new System.Windows.Forms.TextBox(); + this.brightnessLabel = new System.Windows.Forms.Label(); + this.baudRateComboBox = new System.Windows.Forms.ComboBox(); + this.label2 = new System.Windows.Forms.Label(); + this.label3 = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // nameTextBox + // + this.nameTextBox.Enabled = false; + this.nameTextBox.Location = new System.Drawing.Point(139, 47); + this.nameTextBox.Name = "nameTextBox"; + this.nameTextBox.Size = new System.Drawing.Size(130, 20); + this.nameTextBox.TabIndex = 2; + // + // nameLabel + // + this.nameLabel.AutoSize = true; + this.nameLabel.Location = new System.Drawing.Point(29, 50); + this.nameLabel.Name = "nameLabel"; + this.nameLabel.Size = new System.Drawing.Size(35, 13); + this.nameLabel.TabIndex = 1; + this.nameLabel.Text = "Name"; + // + // classNameLabel + // + this.classNameLabel.AutoSize = true; + this.classNameLabel.Location = new System.Drawing.Point(136, 21); + this.classNameLabel.Name = "classNameLabel"; + this.classNameLabel.Size = new System.Drawing.Size(83, 13); + this.classNameLabel.TabIndex = 0; + this.classNameLabel.Text = "ComonentName"; + // + // baudRateLabel + // + this.baudRateLabel.AutoSize = true; + this.baudRateLabel.Location = new System.Drawing.Point(28, 102); + this.baudRateLabel.Name = "baudRateLabel"; + this.baudRateLabel.Size = new System.Drawing.Size(58, 13); + this.baudRateLabel.TabIndex = 5; + this.baudRateLabel.Text = "Baud Rate"; + // + // comPortNrTextBox + // + this.comPortNrTextBox.Enabled = false; + this.comPortNrTextBox.Location = new System.Drawing.Point(139, 73); + this.comPortNrTextBox.Name = "comPortNrTextBox"; + this.comPortNrTextBox.Size = new System.Drawing.Size(80, 20); + this.comPortNrTextBox.TabIndex = 4; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(28, 76); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(98, 13); + this.label1.TabIndex = 3; + this.label1.Text = "Serial Port Number:"; + // + // brightnessTextBox + // + this.brightnessTextBox.Enabled = false; + this.brightnessTextBox.Location = new System.Drawing.Point(140, 126); + this.brightnessTextBox.Name = "brightnessTextBox"; + this.brightnessTextBox.Size = new System.Drawing.Size(79, 20); + this.brightnessTextBox.TabIndex = 8; + // + // brightnessLabel + // + this.brightnessLabel.AutoSize = true; + this.brightnessLabel.Location = new System.Drawing.Point(28, 129); + this.brightnessLabel.Name = "brightnessLabel"; + this.brightnessLabel.Size = new System.Drawing.Size(56, 13); + this.brightnessLabel.TabIndex = 7; + this.brightnessLabel.Text = "Brightness"; + // + // baudRateComboBox + // + this.baudRateComboBox.FormattingEnabled = true; + this.baudRateComboBox.Location = new System.Drawing.Point(139, 99); + this.baudRateComboBox.Name = "baudRateComboBox"; + this.baudRateComboBox.Size = new System.Drawing.Size(80, 21); + this.baudRateComboBox.TabIndex = 6; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(226, 129); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(15, 13); + this.label2.TabIndex = 9; + this.label2.Text = "%"; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(226, 102); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(20, 13); + this.label3.TabIndex = 10; + this.label3.Text = "Bd"; + // + // IdcCameraCfgCtrl + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.label3); + this.Controls.Add(this.label2); + this.Controls.Add(this.baudRateComboBox); + this.Controls.Add(this.brightnessTextBox); + this.Controls.Add(this.brightnessLabel); + this.Controls.Add(this.nameTextBox); + this.Controls.Add(this.nameLabel); + this.Controls.Add(this.classNameLabel); + this.Controls.Add(this.baudRateLabel); + this.Controls.Add(this.comPortNrTextBox); + this.Controls.Add(this.label1); + this.Name = "IdcCameraCfgCtrl"; + this.Size = new System.Drawing.Size(300, 240); + this.Load += new System.EventHandler(this.IdcCameraCfgCtrl_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TextBox nameTextBox; + private System.Windows.Forms.Label nameLabel; + private System.Windows.Forms.Label classNameLabel; + private System.Windows.Forms.Label baudRateLabel; + private System.Windows.Forms.TextBox comPortNrTextBox; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox brightnessTextBox; + private System.Windows.Forms.Label brightnessLabel; + private System.Windows.Forms.ComboBox baudRateComboBox; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label3; + } +} diff --git a/TestBenchFramework/BenchControl/Cameras/IdcCamera/IdcCameraCfgCtrl.resx b/TestBenchFramework/BenchControl/Cameras/IdcCamera/IdcCameraCfgCtrl.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/TestBenchFramework/BenchControl/Cameras/IdcCamera/IdcCameraCfgCtrl.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/BenchControl/Cameras/IdcCamera/IdcCameraFactory.cs b/TestBenchFramework/BenchControl/Cameras/IdcCamera/IdcCameraFactory.cs new file mode 100644 index 000000000..6c54cc6a9 --- /dev/null +++ b/TestBenchFramework/BenchControl/Cameras/IdcCamera/IdcCameraFactory.cs @@ -0,0 +1,41 @@ +using System.Collections.Generic; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.Cameras.IdcCamera +{ + public class IdcCameraFactory : IComponentFactory + { + public string ClassName { get { return "IdcCamera"; } } + + /// Max. number of components of this class in the system + public int MaxCount { get { return 20; } } + + public IComponentCfg DefaultConfig(IList components) + { + return new IdcCameraCfg(this, "Idc", 20, 57600, 0.5f); + } + + public IComponentCfgCtrl CreateCfgCtrl() + { + return new IdcCameraCfgCtrl(); + } + + public IComponent ComponentFromCmpntCfg(IComponentCfg config, IList components) + { + return new IdcCamera((IdcCameraCfg)config, components); + } + + public IComponentCfg CmpntCfgFromCmpntEntity(Entities.Component component) + { + return IdcCameraCfg.CreateFromDbEntity(component, this); + } + + public bool HasProcedureParams { get { return false; } } + public bool HasTestParams { get { return false; } } + // + public IParamsProvider GetProcedureParams(Entities.ComponentProcedure procedureParams) { return null; } + public IParamsProvider GetTestParams(Entities.ComponentTest testParams) { return null; } + + public void ResetStaticProperties() { IdcCamera.ResetStaticProperties(); } + } +} diff --git a/TestBenchFramework/BenchControl/Cameras/IdcCamera/IdcEnums.cs b/TestBenchFramework/BenchControl/Cameras/IdcCamera/IdcEnums.cs new file mode 100644 index 000000000..01623d8b8 --- /dev/null +++ b/TestBenchFramework/BenchControl/Cameras/IdcCamera/IdcEnums.cs @@ -0,0 +1,65 @@ +using System; + +namespace TBF.BenchControl.Cameras.IdcCamera +{ + /// IDC camera states + public enum IdcState + { + Unchanged = -1, /// not a state - used in state transition tables + NotConnected = 0, /// 'gray' + Idle, /// 'green' + Busy, /// 'yellow' or 'orange' + OpCompleted, /// 'green' + OpFailed, /// 'red' + Halted, /// 'red' + } + + public enum RetVal + { + OK = 0, + HOST_START = 1000, /// Start of error codes from HOST part of the software + Busy, /// OK - camera operation in progress + OpInterrupted, /// OK - camera operation interrupted + OpFailed, /// RetVal - Camera operation failed + CameraNotConnected, /// RetVal - Camera is not connected + SequenceError, /// RetVal - Invalid sequence of calls + InvalidComPortNr, /// RetVal - Invalid COM-port number + CannotOpenComPort, /// RetVal - Cannot open COM-port + CannotCommWithCamera, /// RetVal - Cannot communicate with the camera + CommTimeout, /// RetVal - Communication timeout + CommError, /// RetVal - Unknown error during communication + ShutdownInProgress, /// RetVal - System is shutting down + FatalError, /// RetVal - Fatal error + } + + public struct IdcTransition + { + public RetVal RetVal; + public IdcState NewState; + + public IdcTransition(RetVal retVal, IdcState newState) + { + this.RetVal = retVal; + this.NewState = newState; + } + } + + public enum FileFormat + { + Bmp, + Jpeg, + } + + public enum StreamType + { + Full, + SubSampled, + Focus, + } + + enum WorkerCommand + { + StopOp, /// Stop the current operation + Timeout, /// The expected WorkerCommand(s) have not arrived in time + } +} diff --git a/TestBenchFramework/BenchControl/Cameras/IdcCamera/SerialFileIO.cs b/TestBenchFramework/BenchControl/Cameras/IdcCamera/SerialFileIO.cs new file mode 100644 index 000000000..de19c33b8 --- /dev/null +++ b/TestBenchFramework/BenchControl/Cameras/IdcCamera/SerialFileIO.cs @@ -0,0 +1,227 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Text; +using log4net; +using TBF.UiBridge; + +namespace TBF.BenchControl.Cameras.IdcCamera +{ + /// + /// File I/O implementation + /// + public class SerialFileIO + { + static readonly ILog log = LogManager.GetLogger(typeof(SerialFileIO)); + + static TBF.Tools.ByteFormatter byteFormatter = new TBF.Tools.ByteFormatter(); + + const int BUFSIZE = 1024; + const int MAXFNAMESIZE = 62; + + int cameraIdx; + string imagesPath; + + StringBuilder fioFilenameBuilder; + string fioFullPathname; + int packetSize; + byte[] fioBuffer; + BinaryWriter fioWriter; + + enum FioState + { + Command, /// 'o', 'c' or 'w' + Open, /// 'p' + Open2, /// 'e' + Open3, /// 'n' + Open4, /// 1 + Filename, + Close, /// 'l' + Close2, /// 'o' + Close3, /// 's' + Close4, /// 'e' + Close5, /// 1 + Write, /// 'r' + Write2, /// 'i' + Write3, /// 't' + Write4, /// 'e' + Write5, /// 1 + PktSize1, + PktSize2, + PktSize3, + Data, + } + + FioState state; + + public string TransferredFile + { + get { return fioFullPathname; } + } + + public SerialFileIO(int cameraIdx, string imagesPath) + { + this.cameraIdx = cameraIdx; + this.imagesPath = imagesPath; + state = FioState.Command; + fioFullPathname = string.Empty; + fioFilenameBuilder = new StringBuilder(16); + fioBuffer = new byte[BUFSIZE]; + } + + public void ProcessByte(byte b) + { + /// + /// Reaching break in any case of the following switch is an error + /// + if (state == FioState.Data) + { + if (packetSize > 0) + { + if (fioWriter != null) + { + fioWriter.Write(b); + } + if (--packetSize == 0) + { + state = FioState.Command; + } + return; + } + + log.ErrorFormat("{0}: FIO error 17", cameraIdx); + } + else + { + switch (state) + { + case FioState.Command: + if ((char)b == 'o') { state = FioState.Open; return; } + if ((char)b == 'c') { state = FioState.Close; return; } + if ((char)b == 'w') { state = FioState.Write; return; } + log.ErrorFormat("{0}: FIO error 1, fullPathName={1}", cameraIdx, fioFullPathname); + break; + case FioState.Open: + if ((char)b == 'p') { state = FioState.Open2; return; } + log.ErrorFormat("{0}: FIO error 2", cameraIdx); + break; + case FioState.Open2: + if ((char)b == 'e') { state = FioState.Open3; return; } + log.ErrorFormat("{0}: FIO error 3", cameraIdx); + break; + case FioState.Open3: + if ((char)b == 'n') { state = FioState.Open4; return; } + log.ErrorFormat("{0}: FIO error 4", cameraIdx); + break; + case FioState.Open4: + if (b == 1) + { + fioFilenameBuilder.Clear(); + state = FioState.Filename; + return; + } + log.ErrorFormat("{0}: FIO error 5", cameraIdx); + break; + case FioState.Filename: + if (b == 0) + { + if (fioWriter != null) + { + fioWriter.Close(); + fioWriter.Dispose(); + } + + try + { + fioFullPathname = imagesPath + fioFilenameBuilder.ToString(); + fioWriter = new BinaryWriter(File.Open(fioFullPathname, FileMode.Create)); + log.DebugFormat("{0}: Open(\"{1}\")", cameraIdx, fioFullPathname); + } + catch + { + fioWriter = null; + log.WarnFormat("{0}: Failed to open(\"{1}\")", cameraIdx, fioFullPathname); + } + state = FioState.Command; + return; + } + else if (fioFilenameBuilder.Length < MAXFNAMESIZE) + { + fioFilenameBuilder.Append((char)b); + return; + } + log.ErrorFormat("{0}: FIO error 6", cameraIdx); + break; + case FioState.Close: + if ((char)b == 'l') { state = FioState.Close2; return; } + log.ErrorFormat("{0}: FIO error 7", cameraIdx); + break; + case FioState.Close2: + if ((char)b == 'o') { state = FioState.Close3; return; } + log.ErrorFormat("{0}: FIO error 8", cameraIdx); + break; + case FioState.Close3: + if ((char)b == 's') { state = FioState.Close4; return; } + log.ErrorFormat("{0}: FIO error 9", cameraIdx); + break; + case FioState.Close4: + if ((char)b == 'e') { state = FioState.Close5; return; } + log.ErrorFormat("{0}: FIO error 10", cameraIdx); + break; + case FioState.Close5: + if ((char)b == '1' && fioWriter != null) + { + log.DebugFormat("{0}: Close()", cameraIdx); + fioWriter.Close(); + fioWriter.Dispose(); + fioWriter = null; + Bridge.OnImageUpdated(this, new ImageUpdatedEventArgs(cameraIdx, fioFullPathname)); + fioFullPathname = String.Empty; + state = FioState.Command; + return; + } + log.ErrorFormat("{0}: FIO error 11", cameraIdx); + break; + case FioState.Write: + if ((char)b == 'r') { state = FioState.Write2; return; } + log.ErrorFormat("{0}: FIO error 12", cameraIdx); + break; + case FioState.Write2: + if ((char)b == 'i') { state = FioState.Write3; return; } + log.ErrorFormat("{0}: FIO error 13", cameraIdx); + break; + case FioState.Write3: + if ((char)b == 't') { state = FioState.Write4; return; } + log.ErrorFormat("{0}: FIO error 14", cameraIdx); + break; + case FioState.Write4: + if ((char)b == 'e') { state = FioState.Write5; return; } + log.ErrorFormat("{0}: FIO error 15", cameraIdx); + break; + case FioState.Write5: + if ((char)b == '1') { state = FioState.PktSize1; return; } + log.ErrorFormat("{0}: FIO error 16", cameraIdx); + break; + case FioState.PktSize1: + packetSize = (int)b; + state = FioState.PktSize2; + return; + case FioState.PktSize2: + packetSize = (256 * packetSize) + (int)b; + state = FioState.PktSize3; + return; + case FioState.PktSize3: + packetSize = (256 * packetSize) + (int)b; + log.DebugFormat("{0}: write(len={1})", cameraIdx, packetSize); + state = FioState.Data; + return; + default: + log.ErrorFormat("{0}: FIO error 18", cameraIdx); + break; + } + } + + state = FioState.Command; + } + } +} diff --git a/TestBenchFramework/BenchControl/Cameras/IdcCamera/SerialLayer.cs b/TestBenchFramework/BenchControl/Cameras/IdcCamera/SerialLayer.cs new file mode 100644 index 000000000..88f53b5d2 --- /dev/null +++ b/TestBenchFramework/BenchControl/Cameras/IdcCamera/SerialLayer.cs @@ -0,0 +1,619 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.IO.Ports; +using System.Text; +using System.Threading; +using log4net; + +namespace TBF.BenchControl.Cameras.IdcCamera +{ + public class SerialLayer + { + static readonly ILog log = LogManager.GetLogger(typeof(SerialLayer)); + + /// + /// Set to true when shut-down is in progress + /// + public static bool g_shutDown = false; + public bool m_disconnecting; + + int cameraNr; + int comPortNr; + int baudRate; + int readTimeout; + string imagesPath; + + Queue readQueue; + ManualResetEvent queueNotEmptyEvent; + + SerialFileIO serialFileIO; + + SerialPort serialPort; + + byte[] singleCharWrBuff; /// predefined serial write buffer for 1 byte + byte[] twoCharsWrBuff; /// predefined serial write buffer for 2 bytes + + #region Content switching, multiplexing + + const byte CTRLZ = 26; + const byte CTRLQ = 17; + const byte XON = 17; + const byte CTRLS = 19; + const byte XOFF = 19; + + /// + /// Multiplexed channel content ID (destination ID) + /// + enum Mux + { + Console, /// Command console, identified by CTRLZ + 'C' byte sequence + File, /// File download (ICD camera -> file), identified by CTRLZ = 'F' byte sequence + } + + Mux lastWriteContentId; + Mux currentReadContentId; + bool lastReadCtrlZ; + + #endregion + + /// + /// Create a SerialLayer instance. + /// + /// 0-based camera number + /// COM port number 1..999 + /// Baud rate 57600 or 115200 + /// Read timeout in ms + /// Path to a folder where received files are stored + public SerialLayer(int cameraNr, int comPortNr, int baudRate, int readTimeout, string imagesPath) + { + log.InfoFormat("new SerialLayer(ix={0}, com{1}, {2}Bd, tmout={3}ms, ipath={4})", cameraNr, comPortNr, baudRate, readTimeout, imagesPath); + + this.cameraNr = cameraNr; + this.comPortNr = comPortNr; + this.baudRate = baudRate; + this.readTimeout = readTimeout; + this.imagesPath = imagesPath; + + singleCharWrBuff = new byte[1]; + twoCharsWrBuff = new byte[2]; + twoCharsWrBuff[0] = CTRLZ; + + m_disconnecting = false; + readQueue = new Queue(); + queueNotEmptyEvent = new ManualResetEvent(false); + + serialPort = new SerialPort(); + serialPort.DataReceived += serialPort_DataReceived; + } + + /// + /// Open the serial port. + /// + /// RetVal.OK or RetVal.CANNOT_OPEN_COMPORT + public RetVal OpenPort() + { + log.Info("OpenPort()"); + + if (serialPort.IsOpen) return RetVal.OK; + + if (comPortNr<1 || comPortNr>999) return RetVal.CannotOpenComPort; + + m_disconnecting = false; + + /// Initialize FIFO, content switching, multiplexing + readQueue.Clear(); + lastWriteContentId = Mux.Console; + currentReadContentId = Mux.Console; + lastReadCtrlZ = false; + + serialFileIO = new SerialFileIO(cameraNr, imagesPath); + + /// Finally open the serial port + try + { + serialPort.PortName = "COM" + comPortNr.ToString(); + serialPort.BaudRate = baudRate; + serialPort.Parity = Parity.None; + serialPort.DataBits = 8; + serialPort.StopBits = StopBits.One; + serialPort.Handshake = Handshake.None; + serialPort.RtsEnable = true; + serialPort.DtrEnable = true; + + serialPort.ReadTimeout = 1000000; /// Sufficiently large, read timeout is applied to FIFO read + serialPort.WriteTimeout = SerialPort.InfiniteTimeout; + + serialPort.Open(); + } + catch (Exception e) + { + log.Error("Cannot open serial port COM" + comPortNr.ToString(), e); + return RetVal.CannotOpenComPort; + } + + return RetVal.OK; + } + + /// + /// Close the serial port. + /// + public void ClosePort() + { + log.InfoFormat("{0}: ClosePort()", cameraNr); + if (!serialPort.IsOpen) return; + m_disconnecting = true; /// Complete any pending I/O operations + serialPort.Close(); + } + + + public void FifoFlush() + { + lock (readQueue) { readQueue.Clear(); } + } + + public void UnlockLastRead() + { + lock (readQueue) { readQueue.Enqueue((byte)' '); } /// quit infinite fifo.Get() waiting + + } + + /// + /// Serial port data received event handler method + /// + /// SerialPort + /// + void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e) + { + byte[] data = new byte[serialPort.BytesToRead]; + serialPort.Read(data, 0, data.Length); + + foreach (byte dat in data) + { + byte b = dat; + + if (lastReadCtrlZ) + { + lastReadCtrlZ = false; + + if (dat == (byte)'C') + { + currentReadContentId = Mux.Console; /// Ctrl-Z + 'C' sequence detected: Mux.Console + continue; + } + if (dat == (byte)'F') + { + currentReadContentId = Mux.File; /// Ctrl-Z + 'F' sequence detected: Mux.File + continue; + } + + if (dat == (byte)'1') b = (byte)XON; /// Ctrl-Z + '1' sequence detected: XON + if (dat == (byte)'2') b = (byte)XOFF; /// Ctrl-Z + '2' sequence detected: XOFF + } + else if (dat == CTRLZ) + { + lastReadCtrlZ = true; + continue; + } + + /// + /// Process demultiplexed data byte b appropriately + /// + if (currentReadContentId == Mux.Console) + { + lock (readQueue) + { + readQueue.Enqueue(b); + queueNotEmptyEvent.Set(); + } + } + else + { + serialFileIO.ProcessByte(b); + } + } + } + + + #region Read from readQueue + + /// + /// Read one byte from the console content FIFO. + /// + /// Received byte + /// RetVal.OK, RetVal.COMM_TIMEOUT or RetVal.SHUTDOWN + public RetVal ReadByte(out byte response) + { + if (g_shutDown || m_disconnecting) + { + response = 0; + log.DebugFormat("{0}: ReadByte() returns RetVal.SHUTDOWN", cameraNr); + return RetVal.ShutdownInProgress; + } + + lock (readQueue) + { + if (readQueue.Count > 0) + { + response = readQueue.Dequeue(); + return RetVal.OK; + } + else + { + queueNotEmptyEvent.Reset(); + } + } + + if (queueNotEmptyEvent.WaitOne(readTimeout)) + { + lock (readQueue) + { + response = readQueue.Dequeue(); + return RetVal.OK; + } + } + else + { + response = 0; + log.ErrorFormat("{0}: ReadByte() returns RetVal.COMM_TIMEOUT", cameraNr); + return RetVal.CommTimeout; + } + } + + /// + /// Read bytes and form the output string until a delimiter character is received. + /// Output string excludes the delimiter. + /// + /// Delimiter character + /// Output string + /// RetVal.OK, RetVal.COMM_TIMEOUT or RetVal.SHUTDOWN + RetVal ReadUntil(char delimiter, out string output) + { + StringBuilder buffer = new StringBuilder(); + + while (true) + { + RetVal retv; + byte znak; + + if (RetVal.OK != (retv = ReadByte(out znak))) + { + output = buffer.ToString(); /// Copy data received so far to the output + log.Error("ReadUntil('" + delimiter.ToString() + "', out \"" + output + "\") returns " + retv.ToString()); + return retv; /// Communication error + } + char c = (char)znak; + if (c == delimiter) break; + buffer.Append(c); + } + + output = buffer.ToString(); + return RetVal.OK; + } + + /// + /// Read bytes and form the output string until "\r\n" is received. + /// Output string excludes "\r\n". + /// + /// Output string + /// RetVal.OK, RetVal.COMM_TIMEOUT, RetVal.COMM_ERROR or RetVal.SHUTDOWN + RetVal ReadLine(out string output) + { + RetVal retv = ReadUntil('\r', out output); + if (retv != RetVal.OK) return retv; + + /// Read the expected '\n' + byte znak; + if (RetVal.OK != (retv = ReadByte(out znak))) return retv; + if (znak != (byte)'\n') + { + log.Error("ReadLine(out \"" + output + "\") returns " + retv.ToString()); + return RetVal.CommError; + } + + return RetVal.OK; + } + + #endregion + + + #region Write to serial port + + /// + /// Write one byte (console content) to the serial port. + /// + /// Byte to send + public void WriteByte(byte b) + { + WriteByte_Mux(b, Mux.Console); + } + + /// + /// Write one byte from any source (either console or file) to the serial port. + /// Perform multiplexing - expansion to escape sequences using CTRLZ. + /// + /// Byte to send + /// Mux.Console or Mux.File + void WriteByte_Mux(byte b, Mux contentId) + { + if (contentId != lastWriteContentId) + { + /// Switching contentId when writing to a camera is not supported yet, + /// therefore this code within { } wont be invoked right now. + + /// Send the content switch command CTRLZ + contentId + twoCharsWrBuff[1] = (contentId == Mux.Console) ? (byte)'C' : (byte)'F'; + serialPort.Write(twoCharsWrBuff, 0, 2); + lastWriteContentId = contentId; + return; + } + + if (b == CTRLZ) + { + /// If 'b'=CTRLZ send CTRLZ + CTRLZ + twoCharsWrBuff[1] = CTRLZ; + serialPort.Write(twoCharsWrBuff, 0, 2); + return; + } + else if (b == XON) + { + /// If 'b'=XON send CTRLZ + '1' + twoCharsWrBuff[1] = (byte)'1'; + serialPort.Write(twoCharsWrBuff, 0, 2); + return; + } + else if (b == XOFF) + { + /// If 'b'=XON send CTRLZ + '2' + twoCharsWrBuff[1] = (byte)'2'; + serialPort.Write(twoCharsWrBuff, 0, 2); + return; + } + else + { + /// Send a single regular byte 'b' + singleCharWrBuff[0] = b; + serialPort.Write(singleCharWrBuff, 0, 1); + return; + } + } + + /// + /// Write a string (console content) to the serial port. + /// + /// String to send + public void WriteString(string str) + { + if (str == null) return; /// There is nothing to send - return + + if (str.EndsWith("\r\n")) + { + log.InfoFormat("{0}: WriteString(\"{1}\\r\\n\")", cameraNr, str.Substring(0, str.Length - 2)); + } + else + { + log.InfoFormat("{0}: WriteString(\"{1}\")", cameraNr, str); + } + + for (int i = 0; i < str.Length; i++) WriteByte((byte)str[i]); + } + + #endregion + + +//------------------------------------------------------------------------------- +///////////////////////// Higher level console commands /////////////////////// +//------------------------------------------------------------------------------- + + //--------------------------------------------------------------------------- + // Sends the specified command and waits for the following response. + // strings separated by spaces and terminated by + // Stores response into an array of CStrings pointed by pStrArray. + // + // Returns: + // positive numbers and 0 + // The number of fields in the response. Returned number may be + // greater then arrayLen. Only the first arrayLen strings are saved. + // negative numbers + // negative error code returned by lower level functions: + // -RetVal.COMM_TIMEOUT = timeout occurred + // -RetVal.COMM_ERROR = all other errors + //--------------------------------------------------------------------------- + public int CommandStr(string cmd, out string[] strArray, int nrFields, out string remaining) + { + StringBuilder tmp = new StringBuilder(); + StringBuilder logStr = new StringBuilder(); + StringBuilder rem = new StringBuilder(); + + lock (readQueue) { readQueue.Clear(); } + WriteString(cmd); /// send + + strArray = null; + remaining = String.Empty; + + string beforeGT; + RetVal retv = ReadUntil('>', out beforeGT); + if (retv != RetVal.OK) return -(int)retv; /// If Read... fails quit the loop ... + /// ... and return negative error code + /// Read the expected ' ' + byte znak; + if (RetVal.OK != (retv = ReadByte(out znak))) return -(int)retv; + if (znak != (byte)' ') return -(int)RetVal.CommError; + + /// Read fields after '>', parse the first field (the return code) + string received; + retv = ReadLine(out received); + if (retv != RetVal.OK) return -(int)retv; + strArray = received.Split(new char[] { ' ' }, nrFields + 1); + + log.InfoFormat("{0}: Received: > {1}", cameraNr, received); + + /// Skip until '$' received + retv = ReadUntil('$', out received); + if (retv != RetVal.OK) return -(int)retv; + + /// Parse the return code (the 1st field) + int returnCode; + if (!int.TryParse(strArray[0], out returnCode) || returnCode < 0) return returnCode; + + if (strArray.GetLength(0) == nrFields + 1) remaining = strArray[nrFields]; + + return Math.Min(strArray.GetLength(0), nrFields); + } + + //--------------------------------------------------------------------------- + // Sends the specified command and waits for the following response. + // integers separated by spaces and terminated by + // Stores response into an integer array pointed by pIntArray; + // + // Returns: + // positive numbers and 0 + // The number of fields in the response. Returned number may be + // greater then arrayLen. Only the first arrayLen strings are saved. + // negative numbers + // negative error code returned by lower level functions + //--------------------------------------------------------------------------- + public int CommandInt(string cmd, out int[] intArray, int nrFields, out string remaining) + { + string[] strArray; + int retv = CommandStr(cmd, out strArray, nrFields, out remaining); + + if (retv <= 0) + { + intArray = null; + return retv; + } + + intArray = new int[retv]; + for (int i = 0; i < retv; i++) + { + int.TryParse(strArray[i], out intArray[i]); + } + + return retv; + } + + //--------------------------------------------------------------------------- + // Sends the specified command and waits for the following response. + // real numbers separated by spaces and terminated by + // Stores response into a double array pointed by pDblArray; + // + // Returns: + // positive numbers and 0 + // The number of fields in the response. Returned number may be + // greater then arrayLen. Only the first arrayLen strings are saved. + // negative numbers + // negative error code returned by lower level functions + //--------------------------------------------------------------------------- + public int CommandDbl(string cmd, out double[] dblArray, int arrayLen, out string remaining) + { + string[] strArray; + int retv = CommandStr(cmd, out strArray, arrayLen, out remaining); + + if (retv <= 0) + { + dblArray = null; + return retv; + } + + dblArray = new double[retv]; + for (int i = 0; i < retv; i++) + { + double.TryParse(strArray[i], out dblArray[i]); + } + + return retv; + } + + /// + /// Get camera version string + /// + /// Version string + /// RetVal.OK, RetVal.COMM_TIMEOUT, RetVal.COMM_ERROR, RetVal.SHUTDOWN or a camera ret.code (1..999) + public RetVal GetVer(out string versionStr) + { + log.DebugFormat("{0}: GetVer()", cameraNr); + + versionStr = String.Empty; + StringBuilder tmp = new StringBuilder(); + const int arrayLen = 1; + string[] strArray = new string[arrayLen]; + + lock (readQueue) { readQueue.Clear(); } + + WriteString("info\r\n"); /// Send + + /// Read info message until '>' + string infoMessage; + RetVal retv = ReadUntil('>', out infoMessage); + if (retv != RetVal.OK) return retv; + log.DebugFormat("{0}: InfoMessage: {1}", cameraNr, infoMessage); + + /// Read the expected ' ' + byte znak; + if (RetVal.OK != (retv = ReadByte(out znak))) return retv; + if (znak != (byte)' ') return RetVal.CommError; + + /// Read fields after '>', parse the first field (the return code) + string tempStr; + retv = ReadLine(out tempStr); + if (retv != RetVal.OK) return retv; + string[] fields = tempStr.Split(new char[] { ' ' }, 2); + int returnCode; + if (!int.TryParse(fields[0], out returnCode) || returnCode < 0) return (RetVal)(-returnCode); + + /// Skip until '$' received + retv = ReadUntil('$', out tempStr); + if (retv != RetVal.OK) return retv; + + /// Parse the infoMessage + int pos1 = infoMessage.IndexOf("version = "); + if (pos1 != -1) + { + pos1 += "version = ".Length; + int pos2 = infoMessage.IndexOf("\r\n", pos1); + versionStr = infoMessage.Substring(pos1, pos2 - pos1); + + log.InfoFormat("{0}: GetVer(out \"" + versionStr + "\")", cameraNr); + return RetVal.OK; + } + + log.ErrorFormat("{0}: GetVer(...) returns RetVal.OP_FAILED", cameraNr); + return RetVal.CommError; /// Cannot read the version string + } + + //---------------------------------------------------------------------------- + // Check if livestream of serial characters is coming. + // + // Returns: + // RetVal.OK ..... not (OK), + // RetVal.BUSY ... yes (camera needs to be restarted) + //---------------------------------------------------------------------------- + RetVal CheckLiveStream() + { + byte znak; + + // 500 characters without timeout = stream + // copyright message is +/-350 characters long + + for (int i=0; i<500; i++) + { + if (RetVal.CommTimeout == ReadByte(out znak)) return RetVal.OK; /// timeout ... no stream (OK) + } + +#if true + // try to stop the stream + lock (readQueue) { readQueue.Clear(); } + + WriteString("\r\nstopstream\r\n"); + while (RetVal.CommTimeout != ReadByte(out znak)) { }; + return RetVal.OK; +#else + // just report a running stream (RetVal.Busy) + return RetVal.Busy; +#endif + } + + } +} diff --git a/TestBenchFramework/BenchControl/ComponentBase.cs b/TestBenchFramework/BenchControl/ComponentBase.cs new file mode 100644 index 000000000..8777eee58 --- /dev/null +++ b/TestBenchFramework/BenchControl/ComponentBase.cs @@ -0,0 +1,46 @@ +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl +{ + public class ComponentBase : IComponent + { + Generic.IComponentCfg cfg; + public Generic.IComponentCfg Cfg { get { return cfg; } } + + /// Constructor + public ComponentBase(Generic.IComponentCfg cfg) + { + this.cfg = cfg; + } + + + public string Name { get { return Cfg.Name; } } + + + /// + /// Reference to an object with procedure parameters + /// + public IParamsProvider ProcedureParams; + /// + public void GetProcedureParams(TBF.Entities.Procedure procedure) + { + if (Cfg.Factory.HasProcedureParams) + { + ProcedureParams = TbfComponents.GetProcedureParams(this, procedure); + } + } + + /// + /// Reference to an object with test parameters + /// + public IParamsProvider TestParams; + /// + public void GetTestParams(TBF.Entities.Test test) + { + if (Cfg.Factory.HasTestParams) + { + TestParams = TbfComponents.GetTestParams(this, test); + } + } + } +} diff --git a/TestBenchFramework/BenchControl/ComponentCfgBase.cs b/TestBenchFramework/BenchControl/ComponentCfgBase.cs new file mode 100644 index 000000000..faa901196 --- /dev/null +++ b/TestBenchFramework/BenchControl/ComponentCfgBase.cs @@ -0,0 +1,87 @@ +using System.Collections.Generic; +using System.Xml.Serialization; + +namespace TBF.BenchControl +{ + public class ComponentCfgBase + { + [XmlIgnore] + public string Name + { + get { return name; } + set { name = value; } + } + string name; + + [XmlIgnore] + public Generic.IComponentFactory Factory + { + get { return factory; } + set { factory = value; } + } + Generic.IComponentFactory factory; + + [XmlIgnore] + public string ParentName + { + get { return parentName; } + set { parentName = value; } + } + string parentName; + + [XmlIgnore] + public int ItemNr + { + get { return itemNr; } + set { itemNr = value; } + } + int itemNr; + + [XmlIgnore] + public Entities.DebugMode DebugLevel + { + get { return debugLevel; } + set { debugLevel = value; } + } + Entities.DebugMode debugLevel; + + [XmlIgnore] + public Entities.LogLevel LogLevel { get { return logLevel; } } + Entities.LogLevel logLevel; + + [XmlIgnore] + public IList Corrections { get { return corrections; } } + IList corrections; + + protected ComponentCfgBase() + { + itemNr = 0; + debugLevel = Entities.DebugMode.Normal; + logLevel = Entities.LogLevel.Off; + } + + protected ComponentCfgBase(Generic.IComponentFactory factory, string name) + : this() + { + this.factory = factory; + this.name = name; + } + + protected ComponentCfgBase(Generic.IComponentFactory factory, string name, string parentName) + : this(factory, name) + { + this.parentName = parentName; + } + + protected void InitCfgBaseFromEntity(Entities.Component cmpntEntity, Generic.IComponentFactory factory) + { + name = cmpntEntity.Name; + parentName = cmpntEntity.ParentName; + itemNr = cmpntEntity.ItemNr; + debugLevel = cmpntEntity.Mode; + logLevel = cmpntEntity.Logging; + corrections = cmpntEntity.Corrections; + this.factory = factory; + } + } +} diff --git a/TestBenchFramework/BenchControl/Constants.cs b/TestBenchFramework/BenchControl/Constants.cs new file mode 100644 index 000000000..5e865ecce --- /dev/null +++ b/TestBenchFramework/BenchControl/Constants.cs @@ -0,0 +1,12 @@ + +namespace TBF.BenchControl +{ + public static class Constants + { + /// + /// A fraction of the tank volume that is considered to be safe. + /// When the estimated test end tank volume exceeds this fraction, tank emptying is forced. + /// + public const float TankFullFactor = 0.9f; + } +} diff --git a/TestBenchFramework/BenchControl/Current.cs b/TestBenchFramework/BenchControl/Current.cs new file mode 100644 index 000000000..c298d3852 --- /dev/null +++ b/TestBenchFramework/BenchControl/Current.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using TBF.Entities; + +namespace TBF.BenchControl +{ + /// + /// This class keeps the current values used or measured by the test bench. + /// + public class Current + { + /// + /// Procedure, Tests and TestResults data + /// + public static Procedure Procedure; + + public static Test Test; + public static int TestId = 0; + + public static TestResult TestResult; + public static int TestResultId = 0; + + /// + /// Measured data + /// + public static double StartMass; + public static double StopMass; + + static Current() + { + } + + /// Constructor + public Current() + { + /// There should always be some raw data + } + + /// + /// Processes current 'tick' data during measurement. + /// + public static void ProcessTickData() + { + } + } +} diff --git a/TestBenchFramework/BenchControl/DataEntry/Munich/CycleBeginningForm.Designer.cs b/TestBenchFramework/BenchControl/DataEntry/Munich/CycleBeginningForm.Designer.cs new file mode 100644 index 000000000..4f767145b --- /dev/null +++ b/TestBenchFramework/BenchControl/DataEntry/Munich/CycleBeginningForm.Designer.cs @@ -0,0 +1,193 @@ +namespace TBF.BenchControl.DataEntry.Munich +{ + partial class CycleBeginningForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.okButton = new System.Windows.Forms.Button(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.mainStateTextBox = new System.Windows.Forms.TextBox(); + this.label2 = new System.Windows.Forms.Label(); + this.mainSnTextBox = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.auxStateTextBox = new System.Windows.Forms.TextBox(); + this.label3 = new System.Windows.Forms.Label(); + this.auxSnTextBox = new System.Windows.Forms.TextBox(); + this.label4 = new System.Windows.Forms.Label(); + this.groupBox1.SuspendLayout(); + this.groupBox2.SuspendLayout(); + this.SuspendLayout(); + // + // okButton + // + this.okButton.Font = new System.Drawing.Font("Verdana", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238))); + this.okButton.ForeColor = System.Drawing.Color.Black; + this.okButton.Location = new System.Drawing.Point(439, 27); + this.okButton.Name = "okButton"; + this.okButton.Size = new System.Drawing.Size(98, 63); + this.okButton.TabIndex = 0; + this.okButton.Text = "OK"; + this.okButton.UseVisualStyleBackColor = true; + this.okButton.Click += new System.EventHandler(this.okButton_Click); + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.mainStateTextBox); + this.groupBox1.Controls.Add(this.label2); + this.groupBox1.Controls.Add(this.mainSnTextBox); + this.groupBox1.Controls.Add(this.label1); + this.groupBox1.Font = new System.Drawing.Font("Verdana", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238))); + this.groupBox1.ForeColor = System.Drawing.Color.Black; + this.groupBox1.Location = new System.Drawing.Point(28, 18); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(376, 92); + this.groupBox1.TabIndex = 1; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Hauptzähler"; + // + // mainStateTextBox + // + this.mainStateTextBox.Location = new System.Drawing.Point(183, 56); + this.mainStateTextBox.Name = "mainStateTextBox"; + this.mainStateTextBox.Size = new System.Drawing.Size(163, 31); + this.mainStateTextBox.TabIndex = 3; + this.mainStateTextBox.Visible = false; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(18, 59); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(74, 23); + this.label2.TabIndex = 2; + this.label2.Text = "Stand:"; + this.label2.Visible = false; + // + // mainSnTextBox + // + this.mainSnTextBox.Location = new System.Drawing.Point(183, 37); + this.mainSnTextBox.Name = "mainSnTextBox"; + this.mainSnTextBox.Size = new System.Drawing.Size(163, 31); + this.mainSnTextBox.TabIndex = 1; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(18, 40); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(159, 23); + this.label1.TabIndex = 0; + this.label1.Text = "Seriennummer:"; + // + // groupBox2 + // + this.groupBox2.Controls.Add(this.auxStateTextBox); + this.groupBox2.Controls.Add(this.label3); + this.groupBox2.Controls.Add(this.auxSnTextBox); + this.groupBox2.Controls.Add(this.label4); + this.groupBox2.Font = new System.Drawing.Font("Verdana", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238))); + this.groupBox2.ForeColor = System.Drawing.Color.Black; + this.groupBox2.Location = new System.Drawing.Point(28, 135); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size(376, 92); + this.groupBox2.TabIndex = 2; + this.groupBox2.TabStop = false; + this.groupBox2.Text = "Nebenzähler"; + // + // auxStateTextBox + // + this.auxStateTextBox.Location = new System.Drawing.Point(183, 54); + this.auxStateTextBox.Name = "auxStateTextBox"; + this.auxStateTextBox.Size = new System.Drawing.Size(163, 31); + this.auxStateTextBox.TabIndex = 3; + this.auxStateTextBox.Visible = false; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(18, 57); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(74, 23); + this.label3.TabIndex = 2; + this.label3.Text = "Stand:"; + this.label3.Visible = false; + // + // auxSnTextBox + // + this.auxSnTextBox.Location = new System.Drawing.Point(183, 37); + this.auxSnTextBox.Name = "auxSnTextBox"; + this.auxSnTextBox.Size = new System.Drawing.Size(163, 31); + this.auxSnTextBox.TabIndex = 1; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(18, 40); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(159, 23); + this.label4.TabIndex = 0; + this.label4.Text = "Seriennummer:"; + // + // CycleBeginningForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.AutoSize = true; + this.BackColor = System.Drawing.Color.DarkGoldenrod; + this.ClientSize = new System.Drawing.Size(569, 255); + this.Controls.Add(this.groupBox2); + this.Controls.Add(this.groupBox1); + this.Controls.Add(this.okButton); + this.ForeColor = System.Drawing.Color.Black; + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow; + this.Name = "CycleBeginningForm"; + this.Text = "Daten"; + this.TopMost = true; + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.groupBox2.ResumeLayout(false); + this.groupBox2.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Button okButton; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox mainStateTextBox; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.TextBox mainSnTextBox; + private System.Windows.Forms.GroupBox groupBox2; + private System.Windows.Forms.TextBox auxStateTextBox; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.TextBox auxSnTextBox; + private System.Windows.Forms.Label label4; + } +} \ No newline at end of file diff --git a/TestBenchFramework/BenchControl/DataEntry/Munich/CycleBeginningForm.cs b/TestBenchFramework/BenchControl/DataEntry/Munich/CycleBeginningForm.cs new file mode 100644 index 000000000..0e95d5c51 --- /dev/null +++ b/TestBenchFramework/BenchControl/DataEntry/Munich/CycleBeginningForm.cs @@ -0,0 +1,36 @@ +using System; +using System.Windows.Forms; + +namespace TBF.BenchControl.DataEntry.Munich +{ + public partial class CycleBeginningForm : Form, GenericDevices.IHasCompleted + { + // To be retrieved after the form closes + public string MainSNText; + public string AuxSNText; + public string MainStateText; + public string AuxStateText; + + // Set to 'true' when the form closes + public bool Completed { get { return completed; } } + bool completed; + + public CycleBeginningForm() + { + InitializeComponent(); + completed = false; + // TODO: localize strings + } + + private void okButton_Click(object sender, EventArgs e) + { + MainSNText = mainSnTextBox.Text; + AuxSNText = auxSnTextBox.Text; + MainStateText = mainStateTextBox.Text; + AuxStateText = auxStateTextBox.Text; + + completed = true; + Close(); + } + } +} diff --git a/TestBenchFramework/BenchControl/DataEntry/Munich/CycleBeginningForm.resx b/TestBenchFramework/BenchControl/DataEntry/Munich/CycleBeginningForm.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/TestBenchFramework/BenchControl/DataEntry/Munich/CycleBeginningForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/BenchControl/DataEntry/Munich/CycleEndForm.Designer.cs b/TestBenchFramework/BenchControl/DataEntry/Munich/CycleEndForm.Designer.cs new file mode 100644 index 000000000..31157a9d4 --- /dev/null +++ b/TestBenchFramework/BenchControl/DataEntry/Munich/CycleEndForm.Designer.cs @@ -0,0 +1,264 @@ +namespace TBF.BenchControl.DataEntry.Munich +{ + partial class CycleEndForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.auxStateTextBox = new System.Windows.Forms.TextBox(); + this.label3 = new System.Windows.Forms.Label(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.mainStateTextBox = new System.Windows.Forms.TextBox(); + this.label2 = new System.Windows.Forms.Label(); + this.okButton = new System.Windows.Forms.Button(); + this.groupBox3 = new System.Windows.Forms.GroupBox(); + this.radioButton3 = new System.Windows.Forms.RadioButton(); + this.radioButton2 = new System.Windows.Forms.RadioButton(); + this.radioButton1 = new System.Windows.Forms.RadioButton(); + this.groupBox4 = new System.Windows.Forms.GroupBox(); + this.label4 = new System.Windows.Forms.Label(); + this.qFallTextBox = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.qRiseTextBox = new System.Windows.Forms.TextBox(); + this.groupBox2.SuspendLayout(); + this.groupBox1.SuspendLayout(); + this.groupBox3.SuspendLayout(); + this.groupBox4.SuspendLayout(); + this.SuspendLayout(); + // + // groupBox2 + // + this.groupBox2.Controls.Add(this.auxStateTextBox); + this.groupBox2.Controls.Add(this.label3); + this.groupBox2.Font = new System.Drawing.Font("Verdana", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238))); + this.groupBox2.ForeColor = System.Drawing.Color.Black; + this.groupBox2.Location = new System.Drawing.Point(25, 123); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size(362, 81); + this.groupBox2.TabIndex = 4; + this.groupBox2.TabStop = false; + this.groupBox2.Text = "Nebenzähler"; + // + // auxStateTextBox + // + this.auxStateTextBox.Location = new System.Drawing.Point(183, 31); + this.auxStateTextBox.Name = "auxStateTextBox"; + this.auxStateTextBox.Size = new System.Drawing.Size(163, 31); + this.auxStateTextBox.TabIndex = 3; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(18, 34); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(74, 23); + this.label3.TabIndex = 2; + this.label3.Text = "Stand:"; + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.mainStateTextBox); + this.groupBox1.Controls.Add(this.label2); + this.groupBox1.Font = new System.Drawing.Font("Verdana", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238))); + this.groupBox1.ForeColor = System.Drawing.Color.Black; + this.groupBox1.Location = new System.Drawing.Point(25, 23); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(362, 81); + this.groupBox1.TabIndex = 3; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Hauptzähler"; + // + // mainStateTextBox + // + this.mainStateTextBox.Location = new System.Drawing.Point(183, 31); + this.mainStateTextBox.Name = "mainStateTextBox"; + this.mainStateTextBox.Size = new System.Drawing.Size(163, 31); + this.mainStateTextBox.TabIndex = 3; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(18, 34); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(74, 23); + this.label2.TabIndex = 2; + this.label2.Text = "Stand:"; + // + // okButton + // + this.okButton.Font = new System.Drawing.Font("Verdana", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238))); + this.okButton.ForeColor = System.Drawing.Color.Black; + this.okButton.Location = new System.Drawing.Point(425, 33); + this.okButton.Name = "okButton"; + this.okButton.Size = new System.Drawing.Size(98, 63); + this.okButton.TabIndex = 5; + this.okButton.Text = "OK"; + this.okButton.UseVisualStyleBackColor = true; + this.okButton.Click += new System.EventHandler(this.okButton_Click); + // + // groupBox3 + // + this.groupBox3.Controls.Add(this.radioButton3); + this.groupBox3.Controls.Add(this.radioButton2); + this.groupBox3.Controls.Add(this.radioButton1); + this.groupBox3.Font = new System.Drawing.Font("Verdana", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238))); + this.groupBox3.Location = new System.Drawing.Point(25, 223); + this.groupBox3.Name = "groupBox3"; + this.groupBox3.Size = new System.Drawing.Size(362, 142); + this.groupBox3.TabIndex = 6; + this.groupBox3.TabStop = false; + this.groupBox3.Text = "Protokoll"; + // + // radioButton3 + // + this.radioButton3.AutoSize = true; + this.radioButton3.Location = new System.Drawing.Point(34, 100); + this.radioButton3.Name = "radioButton3"; + this.radioButton3.Size = new System.Drawing.Size(152, 27); + this.radioButton3.TabIndex = 2; + this.radioButton3.TabStop = true; + this.radioButton3.Text = "radioButton3"; + this.radioButton3.UseVisualStyleBackColor = true; + // + // radioButton2 + // + this.radioButton2.AutoSize = true; + this.radioButton2.Location = new System.Drawing.Point(34, 67); + this.radioButton2.Name = "radioButton2"; + this.radioButton2.Size = new System.Drawing.Size(152, 27); + this.radioButton2.TabIndex = 1; + this.radioButton2.TabStop = true; + this.radioButton2.Text = "radioButton2"; + this.radioButton2.UseVisualStyleBackColor = true; + // + // radioButton1 + // + this.radioButton1.AutoSize = true; + this.radioButton1.Location = new System.Drawing.Point(34, 34); + this.radioButton1.Name = "radioButton1"; + this.radioButton1.Size = new System.Drawing.Size(152, 27); + this.radioButton1.TabIndex = 0; + this.radioButton1.TabStop = true; + this.radioButton1.Text = "radioButton1"; + this.radioButton1.UseVisualStyleBackColor = true; + // + // groupBox4 + // + this.groupBox4.Controls.Add(this.label4); + this.groupBox4.Controls.Add(this.qFallTextBox); + this.groupBox4.Controls.Add(this.label1); + this.groupBox4.Controls.Add(this.qRiseTextBox); + this.groupBox4.Font = new System.Drawing.Font("Verdana", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238))); + this.groupBox4.Location = new System.Drawing.Point(25, 383); + this.groupBox4.Name = "groupBox4"; + this.groupBox4.Size = new System.Drawing.Size(361, 125); + this.groupBox4.TabIndex = 7; + this.groupBox4.TabStop = false; + this.groupBox4.Text = "Umschaltpunkte"; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(18, 79); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(64, 23); + this.label4.TabIndex = 7; + this.label4.Text = "Qfall:"; + // + // qFallTextBox + // + this.qFallTextBox.Location = new System.Drawing.Point(183, 77); + this.qFallTextBox.Name = "qFallTextBox"; + this.qFallTextBox.Size = new System.Drawing.Size(163, 31); + this.qFallTextBox.TabIndex = 6; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(18, 37); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(80, 23); + this.label1.TabIndex = 5; + this.label1.Text = "Qsteig:"; + // + // qRiseTextBox + // + this.qRiseTextBox.Location = new System.Drawing.Point(183, 34); + this.qRiseTextBox.Name = "qRiseTextBox"; + this.qRiseTextBox.Size = new System.Drawing.Size(163, 31); + this.qRiseTextBox.TabIndex = 4; + // + // CycleEndForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.BackColor = System.Drawing.Color.DarkGoldenrod; + this.ClientSize = new System.Drawing.Size(559, 530); + this.Controls.Add(this.groupBox4); + this.Controls.Add(this.groupBox3); + this.Controls.Add(this.okButton); + this.Controls.Add(this.groupBox2); + this.Controls.Add(this.groupBox1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow; + this.Name = "CycleEndForm"; + this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide; + this.Text = "Daten"; + this.TopMost = true; + this.Load += new System.EventHandler(this.CycleEndForm_Load); + this.groupBox2.ResumeLayout(false); + this.groupBox2.PerformLayout(); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.groupBox3.ResumeLayout(false); + this.groupBox3.PerformLayout(); + this.groupBox4.ResumeLayout(false); + this.groupBox4.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.GroupBox groupBox2; + private System.Windows.Forms.TextBox auxStateTextBox; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.TextBox mainStateTextBox; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Button okButton; + private System.Windows.Forms.GroupBox groupBox3; + private System.Windows.Forms.RadioButton radioButton3; + private System.Windows.Forms.RadioButton radioButton2; + private System.Windows.Forms.RadioButton radioButton1; + private System.Windows.Forms.GroupBox groupBox4; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.TextBox qFallTextBox; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox qRiseTextBox; + + } +} \ No newline at end of file diff --git a/TestBenchFramework/BenchControl/DataEntry/Munich/CycleEndForm.cs b/TestBenchFramework/BenchControl/DataEntry/Munich/CycleEndForm.cs new file mode 100644 index 000000000..2e9c0801f --- /dev/null +++ b/TestBenchFramework/BenchControl/DataEntry/Munich/CycleEndForm.cs @@ -0,0 +1,55 @@ +using System; +using System.Windows.Forms; + +namespace TBF.BenchControl.DataEntry.Munich +{ + public partial class CycleEndForm : Form, GenericDevices.IHasCompleted + { + // To be set before the form opens + public string ProtocolName1; + public string ProtocolName2; + public string ProtocolName3; + + // To be retrieved after the form closes + public string MainStateText; + public string AuxStateText; + public string ProtocolTitle; + + // Set to 'true' when the form closes + public bool Completed { get { return completed; } } + bool completed; + + public CycleEndForm() + { + InitializeComponent(); + completed = false; + // TODO: localize strings + } + + private void CycleEndForm_Load(object sender, EventArgs e) + { + radioButton1.Text = ProtocolName1; + radioButton2.Text = ProtocolName2; + radioButton3.Text = ProtocolName3; + qRiseTextBox.Text = Sequences.SequenceBase.Qrise.ToString("F3"); + qFallTextBox.Text = Sequences.SequenceBase.Qfall.ToString("F3"); + } + + private void okButton_Click(object sender, EventArgs e) + { + MainStateText = mainStateTextBox.Text; + AuxStateText = auxStateTextBox.Text; + + float umsch; + if (Utils.TryParseUFloat(qRiseTextBox.Text, out umsch)) Sequences.SequenceBase.Qrise = umsch; + if (Utils.TryParseUFloat(qFallTextBox.Text, out umsch)) Sequences.SequenceBase.Qfall = umsch; + + if (radioButton1.Checked) ProtocolTitle = ProtocolName1; + else if (radioButton2.Checked) ProtocolTitle = ProtocolName2; + else if (radioButton3.Checked) ProtocolTitle = ProtocolName3; + + completed = true; + Close(); + } + } +} diff --git a/TestBenchFramework/BenchControl/DataEntry/Munich/CycleEndForm.resx b/TestBenchFramework/BenchControl/DataEntry/Munich/CycleEndForm.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/TestBenchFramework/BenchControl/DataEntry/Munich/CycleEndForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/BenchControl/DataEntry/Munich/EntryForm.cs b/TestBenchFramework/BenchControl/DataEntry/Munich/EntryForm.cs new file mode 100644 index 000000000..264d4913c --- /dev/null +++ b/TestBenchFramework/BenchControl/DataEntry/Munich/EntryForm.cs @@ -0,0 +1,140 @@ +using System; +using System.Collections.Generic; +using TBF.BenchControl; + +namespace TBF.BenchControl.DataEntry.Munich +{ + public class EntryForm : Generic.IComponent, IOperation, GenericDevices.IDataEntry, GenericDevices.IHasProtocolTitle + { + readonly EntryFormCfg entryFormCfg; + public Generic.IComponentCfg Cfg { get { return entryFormCfg; } } + + public static void ResetStaticProperties() { } + + public string Name { get { return entryFormCfg.Name; } } + + /// + /// Properties set by the Begin and the End form + /// + public string MainBeginStateText { get { return mainBeginStateText; } } + string mainBeginStateText; + + public string AuxBegintateText { get { return auxBeginStateText; } } + string auxBeginStateText; + + public string ProtocolTitle { get { return protocolTitle; } } + string protocolTitle; + + + System.Windows.Forms.Form modelessDlg; + + IList waterMeters; + + public enum CurrentOp + { + None, + ShowFormAtCycleBeginning, + ShowFormAtCycleEnd, + } + + CurrentOp currentOp; + + public EntryForm(EntryFormCfg cfg) + { + if (cfg == null) throw new ArgumentNullException("cfg"); + this.entryFormCfg = cfg; + currentOp = CurrentOp.None; + } + + /// Reference to the operation + public IOperation ShowFormAtCycleBeginningOp(IList waterMeters) + { + if (currentOp != CurrentOp.None) throw new Exception("Sequence error"); + currentOp = CurrentOp.ShowFormAtCycleBeginning; + this.waterMeters = waterMeters; + return this; + } + + /// Reference to the operation + public IOperation ShowFormAtCycleEndOp(IList waterMeters) + { + if (currentOp != CurrentOp.None) throw new Exception("Sequence error"); + currentOp = CurrentOp.ShowFormAtCycleEnd; + this.waterMeters = waterMeters; + return this; + } + + delegate void EntryFormDlgt(EntryForm myRef); + /// + void OpenBeginningDlg(EntryForm myRef) + { + myRef.modelessDlg = new CycleBeginningForm(); + modelessDlg.Show(); + } + /// + void OpenEndDlg(EntryForm myRef) + { + CycleEndForm endForm = new CycleEndForm(); + endForm.ProtocolName1 = entryFormCfg.ProtocolTitle1; + endForm.ProtocolName2 = entryFormCfg.ProtocolTitle2; + endForm.ProtocolName3 = entryFormCfg.ProtocolTitle3; + myRef.modelessDlg = endForm; + modelessDlg.Show(); + } + + /// Start this operation + public void Start() + { + switch (currentOp) + { + case CurrentOp.ShowFormAtCycleBeginning: + Program.MainWnd.Invoke(new EntryFormDlgt(OpenBeginningDlg), this); + break; + case CurrentOp.ShowFormAtCycleEnd: + Program.MainWnd.Invoke(new EntryFormDlgt(OpenEndDlg), this); + break; + } + } + + /// Run this operation + /// Event.ResultsPrinted + public Event Run() + { + if (!(modelessDlg as GenericDevices.IHasCompleted).Completed) return Event.None; + + if (modelessDlg is CycleBeginningForm) + { + if (waterMeters.Count >= 1 && waterMeters[0] != null) + { + mainBeginStateText = (modelessDlg as CycleBeginningForm).MainStateText; + waterMeters[0].SerialNr = (modelessDlg as CycleBeginningForm).MainSNText; + } + if (waterMeters.Count >= 2 && waterMeters[1] != null) + { + auxBeginStateText = (modelessDlg as CycleBeginningForm).AuxStateText; + waterMeters[1].SerialNr = (modelessDlg as CycleBeginningForm).AuxSNText; + } + } + else + { + if (waterMeters.Count >= 1 && waterMeters[0] != null) + { + waterMeters[0].State = (modelessDlg as CycleEndForm).MainStateText; + } + if (waterMeters.Count >= 2 && waterMeters[1] != null) + { + waterMeters[1].State = (modelessDlg as CycleEndForm).AuxStateText; + } + protocolTitle = (modelessDlg as CycleEndForm).ProtocolTitle; + } + return Event.Done; + } + + /// Stop this operation + public void Stop() + { + modelessDlg = null; + currentOp = CurrentOp.None; + } + } +} diff --git a/TestBenchFramework/BenchControl/DataEntry/Munich/EntryFormCfg.cs b/TestBenchFramework/BenchControl/DataEntry/Munich/EntryFormCfg.cs new file mode 100644 index 000000000..888918a2f --- /dev/null +++ b/TestBenchFramework/BenchControl/DataEntry/Munich/EntryFormCfg.cs @@ -0,0 +1,62 @@ +using System; +using System.IO; +using System.Xml.Serialization; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.DataEntry.Munich +{ + public class EntryFormCfg : ComponentCfgBase, Generic.IComponentCfg + { + public string ProtocolTitle1; + public string ProtocolTitle2; + public string ProtocolTitle3; + + /// Parameterless constructor + public EntryFormCfg() + { + } + + /// + /// Data entry form configuration parameters + /// + /// Data entry form factory + /// Component name + public EntryFormCfg(IComponentFactory factory, string name, + string protocolTitle1, string protocolTitle2, string protocolTitle3) + : base(factory, name) + { + this.ProtocolTitle1 = protocolTitle1; + this.ProtocolTitle2 = protocolTitle2; + this.ProtocolTitle3 = protocolTitle3; + } + + public IComponentCfg Clone() + { + return new EntryFormCfg(Factory, Name, ProtocolTitle1, ProtocolTitle2, ProtocolTitle3); + } + + public string ToString(int i) + { + return string.Empty; + } + + public TBF.Entities.Component CreateDbEntity() + { + using (var writer = new StringWriter()) + { + (new XmlSerializer(GetType())).Serialize(writer, this); + return Entities.Component.CreateFromCfg(Name, Factory.ClassName, ParentName, ItemNr, DebugLevel, LogLevel, writer.ToString()); + } + } + + public static IComponentCfg CreateFromDbEntity(Entities.Component component, IComponentFactory factory) + { + using (var reader = new StringReader(component.Parameters)) + { + EntryFormCfg config = (EntryFormCfg)(new XmlSerializer(typeof(EntryFormCfg))).Deserialize(reader); + config.InitCfgBaseFromEntity(component, factory); + return config; + } + } + } +} diff --git a/TestBenchFramework/BenchControl/DataEntry/Munich/EntryFormCfgCtrl.cs b/TestBenchFramework/BenchControl/DataEntry/Munich/EntryFormCfgCtrl.cs new file mode 100644 index 000000000..abf86915a --- /dev/null +++ b/TestBenchFramework/BenchControl/DataEntry/Munich/EntryFormCfgCtrl.cs @@ -0,0 +1,67 @@ +using System; +using System.Windows.Forms; +using log4net; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.DataEntry.Munich +{ + public partial class EntryFormCfgCtrl : UserControl, IComponentCfgCtrl + { + static readonly ILog log = LogManager.GetLogger(typeof(EntryFormCfgCtrl)); + + EntryFormCfg config; + + public IComponentCfg Config + { + get { return config as IComponentCfg; } + set + { + config = value as EntryFormCfg; + Redraw(); + } + } + + public EntryFormCfgCtrl() + { + InitializeComponent(); + } + + private void EntryFormCfgCtrl_Load(object sender, EventArgs e) + { + Redraw(); + } + + void Redraw() + { + if (config == null) return; /// Control was not loaded, settings were not changed + classNameLabel.Text = config.Factory.ClassName; + nameTextBox.Text = config.Name; + protocolTitle1TextBox.Text = config.ProtocolTitle1; + protocolTitle2TextBox.Text = config.ProtocolTitle2; + protocolTitle3TextBox.Text = config.ProtocolTitle3; + } + + public void Unlock() + { + nameTextBox.Enabled = true; + protocolTitle1TextBox.Enabled = true; + protocolTitle2TextBox.Enabled = true; + protocolTitle3TextBox.Enabled = true; + } + + public CfgVerifyFlags VerifyCfg(ref string message) + { + CfgVerifyFlags flags = CfgVerifyFlags.None; + return flags; + } + + public void UpdateCfg() + { + if (config == null) return; /// Control was not loaded, settings were not changed + config.Name = nameTextBox.Text; + config.ProtocolTitle1 = protocolTitle1TextBox.Text; + config.ProtocolTitle2 = protocolTitle2TextBox.Text; + config.ProtocolTitle3 = protocolTitle3TextBox.Text; + } + } +} diff --git a/TestBenchFramework/BenchControl/DataEntry/Munich/EntryFormCfgCtrl.designer.cs b/TestBenchFramework/BenchControl/DataEntry/Munich/EntryFormCfgCtrl.designer.cs new file mode 100644 index 000000000..8f0992300 --- /dev/null +++ b/TestBenchFramework/BenchControl/DataEntry/Munich/EntryFormCfgCtrl.designer.cs @@ -0,0 +1,152 @@ +namespace TBF.BenchControl.DataEntry.Munich +{ + partial class EntryFormCfgCtrl + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.nameTextBox = new System.Windows.Forms.TextBox(); + this.nameLabel = new System.Windows.Forms.Label(); + this.classNameLabel = new System.Windows.Forms.Label(); + this.label1 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.label3 = new System.Windows.Forms.Label(); + this.protocolTitle1TextBox = new System.Windows.Forms.TextBox(); + this.protocolTitle2TextBox = new System.Windows.Forms.TextBox(); + this.protocolTitle3TextBox = new System.Windows.Forms.TextBox(); + this.SuspendLayout(); + // + // nameTextBox + // + this.nameTextBox.Enabled = false; + this.nameTextBox.Location = new System.Drawing.Point(137, 57); + this.nameTextBox.Name = "nameTextBox"; + this.nameTextBox.Size = new System.Drawing.Size(130, 20); + this.nameTextBox.TabIndex = 5; + // + // nameLabel + // + this.nameLabel.AutoSize = true; + this.nameLabel.Location = new System.Drawing.Point(27, 60); + this.nameLabel.Name = "nameLabel"; + this.nameLabel.Size = new System.Drawing.Size(35, 13); + this.nameLabel.TabIndex = 4; + this.nameLabel.Text = "Name"; + // + // classNameLabel + // + this.classNameLabel.AutoSize = true; + this.classNameLabel.Location = new System.Drawing.Point(134, 33); + this.classNameLabel.Name = "classNameLabel"; + this.classNameLabel.Size = new System.Drawing.Size(83, 13); + this.classNameLabel.TabIndex = 3; + this.classNameLabel.Text = "ComonentName"; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(27, 86); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(74, 13); + this.label1.TabIndex = 6; + this.label1.Text = "Protocol title 1"; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(27, 112); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(74, 13); + this.label2.TabIndex = 7; + this.label2.Text = "Protocol title 2"; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(27, 138); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(74, 13); + this.label3.TabIndex = 8; + this.label3.Text = "Protocol title 3"; + // + // protocolTitle1TextBox + // + this.protocolTitle1TextBox.Enabled = false; + this.protocolTitle1TextBox.Location = new System.Drawing.Point(137, 83); + this.protocolTitle1TextBox.Name = "protocolTitle1TextBox"; + this.protocolTitle1TextBox.Size = new System.Drawing.Size(130, 20); + this.protocolTitle1TextBox.TabIndex = 9; + // + // protocolTitle2TextBox + // + this.protocolTitle2TextBox.Enabled = false; + this.protocolTitle2TextBox.Location = new System.Drawing.Point(137, 109); + this.protocolTitle2TextBox.Name = "protocolTitle2TextBox"; + this.protocolTitle2TextBox.Size = new System.Drawing.Size(130, 20); + this.protocolTitle2TextBox.TabIndex = 10; + // + // protocolTitle3TextBox + // + this.protocolTitle3TextBox.Enabled = false; + this.protocolTitle3TextBox.Location = new System.Drawing.Point(137, 135); + this.protocolTitle3TextBox.Name = "protocolTitle3TextBox"; + this.protocolTitle3TextBox.Size = new System.Drawing.Size(130, 20); + this.protocolTitle3TextBox.TabIndex = 11; + // + // EntryFormCfgCtrl + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.protocolTitle3TextBox); + this.Controls.Add(this.protocolTitle2TextBox); + this.Controls.Add(this.protocolTitle1TextBox); + this.Controls.Add(this.label3); + this.Controls.Add(this.label2); + this.Controls.Add(this.label1); + this.Controls.Add(this.nameTextBox); + this.Controls.Add(this.nameLabel); + this.Controls.Add(this.classNameLabel); + this.Name = "EntryFormCfgCtrl"; + this.Size = new System.Drawing.Size(300, 200); + this.Load += new System.EventHandler(this.EntryFormCfgCtrl_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TextBox nameTextBox; + private System.Windows.Forms.Label nameLabel; + private System.Windows.Forms.Label classNameLabel; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.TextBox protocolTitle1TextBox; + private System.Windows.Forms.TextBox protocolTitle2TextBox; + private System.Windows.Forms.TextBox protocolTitle3TextBox; + } +} diff --git a/TestBenchFramework/BenchControl/DataEntry/Munich/EntryFormCfgCtrl.resx b/TestBenchFramework/BenchControl/DataEntry/Munich/EntryFormCfgCtrl.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/TestBenchFramework/BenchControl/DataEntry/Munich/EntryFormCfgCtrl.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/BenchControl/DataEntry/Munich/EntryFormFactory.cs b/TestBenchFramework/BenchControl/DataEntry/Munich/EntryFormFactory.cs new file mode 100644 index 000000000..010483299 --- /dev/null +++ b/TestBenchFramework/BenchControl/DataEntry/Munich/EntryFormFactory.cs @@ -0,0 +1,40 @@ +using System.Collections.Generic; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.DataEntry.Munich +{ + public class EntryFormFactory : IComponentFactory + { + public string ClassName { get { return "DataEntryForm-Munich"; } } + public bool HasProcedureParams { get { return false; } } + public bool HasTestParams { get { return false; } } + public IParamsProvider GetTestParams(Entities.ComponentTest testParams) { return null; } + public IParamsProvider GetProcedureParams(Entities.ComponentProcedure procedureParams) { return null; } + + /// Max. number of components of this class in the system + public int MaxCount { get { return 1; } } + + + public IComponentCfg DefaultConfig(IList components) + { + return new EntryFormCfg(this, "DataEntryForm-Munich", "Protokoll Werkprüfung", "Protokoll 2", "Protokoll 3"); + } + + public IComponentCfgCtrl CreateCfgCtrl() + { + return new EntryFormCfgCtrl(); + } + + public IComponent ComponentFromCmpntCfg(IComponentCfg config, IList components) + { + return new EntryForm((EntryFormCfg)config); + } + + public IComponentCfg CmpntCfgFromCmpntEntity(Entities.Component component) + { + return EntryFormCfg.CreateFromDbEntity(component, this); + } + + public void ResetStaticProperties() { EntryForm.ResetStaticProperties(); } + } +} diff --git a/TestBenchFramework/BenchControl/Elde/Common.cs b/TestBenchFramework/BenchControl/Elde/Common.cs new file mode 100644 index 000000000..899b38bc4 --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/Common.cs @@ -0,0 +1,71 @@ +using System; + +namespace TBF.BenchControl.Elde +{ + public enum Command + { + None = 0, /// Do nothing, just transfer data (route, etc.) + Start = 1, /// Start the measurement + Stop = 2, /// Stop the measurement + } + + public enum StatusP : ulong + { + RefFlowMeterMask = 0x7, + TestInProgress = 0x8, + TestCompleted = 0x10, + DiverterError = 0x20, + MsrmntWithDivrtr = 0x80, + RefPulsesMsrmnt = 0x100, + SynchroMethod = 0x800, + WaterMeterCalib = 0x1000, + EmgcyStopActive = 0x2000, + MsrmntGateActive = 0x4000, + TimeMeasurement = 0x8000, + FrequencyMeasured = 0x80000, + ADCError = 0x80000000, + TimeoutOccured = 0x100000000, + MeretAddresses = 0x200000000, + SampleBuferFull = 0x400000000, + ErrorTempMeter = 0x10000000000, + ErrorPressMeter1 = 0x1000000000000, + ErrorPressMeter2 = 0x2000000000000, + ErrorPressMeter3 = 0x4000000000000, + ErrorPressMeter4 = 0x8000000000000, + } + + public enum StopDevs + { + None = 0, + Reference = 0x01, + Diverter = 0x02, + GatePulse = 0x08, + TimeMeasurement = 0x10, + BypassDevCoupled2Div = 0x20, + RegValveRegulation = 0x80, + All = 0xFF, + } + + public enum TestMethods + { + Diverter = 0x01, /// 0x01 = Mass method (diverters are used), 0 = Volume method + FixedStart = 0x02, + Synchro = 0x04, /// 0x02 = Synchro method, 0 = Pulse counting + } + + public enum RegulValveMode : byte + { + None = 0, + PulseWidth = 1, /// Pulse width 0.05 .. 2 sec. + TargetPosition = 2, /// Low and high position (=DAC value) limits (0..100%) are specified + TargetFrequency = 3, /// Low and high frequency limits (0..2000Hz,0..2200Hz) are specified + Stop = 4, /// Stop regulation + } + + public enum RegulValveState + { + Idle = 0, + PwOrFreqRegul = 2, + DacValueRegul = 3, + } +} diff --git a/TestBenchFramework/BenchControl/Elde/ControlBoardCfg.cs b/TestBenchFramework/BenchControl/Elde/ControlBoardCfg.cs new file mode 100644 index 000000000..69e8f9842 --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/ControlBoardCfg.cs @@ -0,0 +1,52 @@ +using System.IO; +using System.Xml.Serialization; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.Elde +{ + public class ControlBoardCfg : ComponentCfgBase, IComponentCfg + { + public int ComPortNr; + + /// Parameterless constructor + public ControlBoardCfg() + { + } + /// Constructor + public ControlBoardCfg(IComponentFactory factory, string name, int comPortNr) + : base(factory, name) + { + this.ComPortNr = comPortNr; + } + + public IComponentCfg Clone() + { + return new ControlBoardCfg(Factory, Name, ComPortNr); + } + + public string ToString(int i) + { + return string.Format("COM{0}", ComPortNr); + } + + public TBF.Entities.Component CreateDbEntity() + { + using (var writer = new StringWriter()) + { + (new XmlSerializer(GetType())).Serialize(writer, this); + return Entities.Component.CreateFromCfg(Name, Factory.ClassName, ParentName, ItemNr, DebugLevel, LogLevel, writer.ToString()); + } + } + + public static IComponentCfg CreateFromDbEntity(Entities.Component tbfComponent, IComponentFactory factory) + { + using (var reader = new StringReader(tbfComponent.Parameters)) + { + ControlBoardCfg config = (ControlBoardCfg)(new XmlSerializer(typeof(ControlBoardCfg))).Deserialize(reader); + config.Name = tbfComponent.Name; + config.InitCfgBaseFromEntity(tbfComponent, factory); + return config; + } + } + } +} diff --git a/TestBenchFramework/BenchControl/Elde/ControlBoardCfgCtrl.Designer.cs b/TestBenchFramework/BenchControl/Elde/ControlBoardCfgCtrl.Designer.cs new file mode 100644 index 000000000..93f45b4ba --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/ControlBoardCfgCtrl.Designer.cs @@ -0,0 +1,106 @@ +namespace TBF.BenchControl.Elde +{ + partial class ControlBoardCfgCtrl + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.label1 = new System.Windows.Forms.Label(); + this.comPortNrTextBox = new System.Windows.Forms.TextBox(); + this.classNameLabel = new System.Windows.Forms.Label(); + this.nameLabel = new System.Windows.Forms.Label(); + this.nameTextBox = new System.Windows.Forms.TextBox(); + this.SuspendLayout(); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(44, 113); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(98, 13); + this.label1.TabIndex = 0; + this.label1.Text = "Serial Port Number:"; + // + // comPortNrTextBox + // + this.comPortNrTextBox.Enabled = false; + this.comPortNrTextBox.Location = new System.Drawing.Point(154, 110); + this.comPortNrTextBox.Name = "comPortNrTextBox"; + this.comPortNrTextBox.Size = new System.Drawing.Size(105, 20); + this.comPortNrTextBox.TabIndex = 1; + // + // classNameLabel + // + this.classNameLabel.AutoSize = true; + this.classNameLabel.Location = new System.Drawing.Point(151, 45); + this.classNameLabel.Name = "classNameLabel"; + this.classNameLabel.Size = new System.Drawing.Size(83, 13); + this.classNameLabel.TabIndex = 2; + this.classNameLabel.Text = "ComonentName"; + // + // nameLabel + // + this.nameLabel.AutoSize = true; + this.nameLabel.Location = new System.Drawing.Point(44, 79); + this.nameLabel.Name = "nameLabel"; + this.nameLabel.Size = new System.Drawing.Size(35, 13); + this.nameLabel.TabIndex = 3; + this.nameLabel.Text = "Name"; + // + // nameTextBox + // + this.nameTextBox.Enabled = false; + this.nameTextBox.Location = new System.Drawing.Point(154, 76); + this.nameTextBox.Name = "nameTextBox"; + this.nameTextBox.Size = new System.Drawing.Size(105, 20); + this.nameTextBox.TabIndex = 4; + // + // ControlBoardCfgCtrl + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.nameTextBox); + this.Controls.Add(this.nameLabel); + this.Controls.Add(this.classNameLabel); + this.Controls.Add(this.comPortNrTextBox); + this.Controls.Add(this.label1); + this.Name = "ControlBoardCfgCtrl"; + this.Size = new System.Drawing.Size(300, 200); + this.Load += new System.EventHandler(this.ControlBoardCfgCtrl_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox comPortNrTextBox; + private System.Windows.Forms.Label classNameLabel; + private System.Windows.Forms.Label nameLabel; + private System.Windows.Forms.TextBox nameTextBox; + } +} diff --git a/TestBenchFramework/BenchControl/Elde/ControlBoardCfgCtrl.cs b/TestBenchFramework/BenchControl/Elde/ControlBoardCfgCtrl.cs new file mode 100644 index 000000000..31100cbbc --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/ControlBoardCfgCtrl.cs @@ -0,0 +1,75 @@ +using System; +using System.Windows.Forms; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.Elde +{ + public partial class ControlBoardCfgCtrl : UserControl, IComponentCfgCtrl + { + ControlBoardCfg config; + public IComponentCfg Config + { + get { return config as IComponentCfg; } + set + { + config = value as ControlBoardCfg; + Redraw(); + } + } + + public ControlBoardCfgCtrl() + { + InitializeComponent(); + } + + private void ControlBoardCfgCtrl_Load(object sender, EventArgs e) + { + Redraw(); + } + + void Redraw() + { + if (config == null) return; /// Control was not loaded, settings were not changed + + classNameLabel.Text = config.Factory.ClassName; + nameTextBox.Text = config.Name; + comPortNrTextBox.Text = config.ComPortNr.ToString(); + } + + public void Unlock() + { + nameTextBox.Enabled = true; + comPortNrTextBox.Enabled = true; + } + + /// + /// Verify current user controls for validity. + /// Called when user wants to close/save the configuration. + /// + /// See VerifyFlags + public CfgVerifyFlags VerifyCfg(ref string message) + { + CfgVerifyFlags flags = CfgVerifyFlags.None; + + int dummy; + if (!int.TryParse(comPortNrTextBox.Text, out dummy) || dummy <= 0 || dummy > 999) + { + message += "Control board serial port number is invalid"; + flags |= CfgVerifyFlags.Error; + } + + return flags; + } + + /// + /// Save settings to the configuration class. + /// + public void UpdateCfg() + { + if (config == null) return; /// Control was not loaded, settings were not changed + /// + this.Name = nameTextBox.Text; + this.config.ComPortNr = int.Parse(comPortNrTextBox.Text); + } + } +} diff --git a/TestBenchFramework/BenchControl/Elde/ControlBoardCfgCtrl.resx b/TestBenchFramework/BenchControl/Elde/ControlBoardCfgCtrl.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/ControlBoardCfgCtrl.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/BenchControl/Elde/ControlBoardDev.cs b/TestBenchFramework/BenchControl/Elde/ControlBoardDev.cs new file mode 100644 index 000000000..42bdecdf1 --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/ControlBoardDev.cs @@ -0,0 +1,334 @@ +using System; +using System.Text; +using System.IO.Ports; +using System.Collections.Generic; +using TBF.BenchControl.Generic; +using TBF.BenchControl.GenericDevices; +using log4net; + +namespace TBF.BenchControl.Elde +{ + public class ControlBoardDev : IComponent, IDevice, IValveControl + { + /// + /// Info: + /// Warn: + /// Error: + /// + private static readonly ILog log = LogManager.GetLogger(typeof(ControlBoardDev)); + public override string ToString() { return string.Format("ControlBoardDev on com{0}", controlBoardCfg.ComPortNr); } + + public static void ResetStaticProperties() { } + + ControlBoardCfg controlBoardCfg; + public Generic.IComponentCfg Cfg { get { return controlBoardCfg; } } + + public string Name { get { return controlBoardCfg.Name; } } + + + /// + /// Reference to the control board component + /// + IControlCom controlCom; + + /// + /// Emergency stop signal state updated by RunDevice(). + /// 'modelessDlg' is notified about the changes and uses this information to change its visibility. + /// + //UiBridge.EmergencyStopEventArgs.State emergencyStopState; + + + /// + /// Public read only wrappers for Elde software component fields + /// + /// rvNr1 = 1 .. nrRegulValves (one based) + /// wmNr0 = 0 .. nrWaterMeters-1 (zero based) + /// tmpNr0 = 0 .. nrTempMeters-1 (zero based) + /// prsNr0 = 0 .. nrPressureMeters-1 (zero based) + /// + public StatusP StatusP { get { return controlCom.StatusP; } } + public float ReferenceFreq { get { return controlCom.ReferenceFreq; } } /// In [Hz] 0..2500, nom.=2000 + public int EtPulses(int wmNr0) { return controlCom.EtPulses(wmNr0); } + public int WMeterPulses(int wmNr0) { return controlCom.WMeterPulses(wmNr0); } + public int WMeterReference(int wmNr0) { return controlCom.WMeterReference(wmNr0); } + public uint RegulValveDAC { get { return controlCom.RegulValveDAC; } } + public float Pressure(int prsNr0) { return controlCom.Pressure(prsNr0); } + public float Temperature(int tmpNr0) { return controlCom.Temperature(tmpNr0); } + public RegulValveState RegulValveState(int rvNr1) { return (RegulValveState)controlCom.RegulValveState(rvNr1); } + public ulong RRoute { get { return controlCom.RRoute; } } + public uint DivTime { get { return controlCom.DivTime; } } + public float TTime { get { return controlCom.TTime; } } + public uint FmState { get { return controlCom.FmState; } } + public uint BeginState(int wmNr0) { return controlCom.BeginState(wmNr0); } + public float ReferenceFlow { get { return controlCom.ReferenceFlow; } } + public float RValvePosition(int rvNr1) { return controlCom.RValvePosition(rvNr1); } + public float DivSamples(int ms) { return controlCom.DivSamples(ms); } + public int ScopeSamples(int i, int j, int k) { return controlCom.ScopeSamples(i, j, k); } + public uint DigitalInputs { get { return controlCom.DigitalInputs; } } + public float AnalogInput(int adcNr0) { return controlCom.AnalogInput(adcNr0); } + public uint AnalogInputRaw(int adcNr0, int bank) { return controlCom.AnalogInputRaw(adcNr0, bank); } /// bank0=RV, bank1=Temp + public float ReferenceVolume { get { return controlCom.ReferenceVolume; } } + public float VyslExt(int wmNr0, int what) { return controlCom.VyslExt(wmNr0, what); } + + /// Extracted from the StatusP + public bool EmgcyStopActive { get { return (controlCom.StatusP & StatusP.EmgcyStopActive) != 0; } } + + /// State of valves sent out - buffered by the last SendCommand() + public ulong Route { get { return route; } } + + /// + /// Initialization data updated by constructors of children components + /// and sent to 'controlCom2panel' by SendCalibData() method. + /// + public uint[,] RegValveCalib = new uint[8, 2]; + public byte[] MeretRS485Address = new byte[4]; + public float[,] TempCalibData = new float[8, 5]; + + // Array length is the reference flowmeters count plus one +#if DN100 + public float[] EtCalib = new float[6] { 1, 1, 1, 1, 1, 1 }; +#elif MUNICH + public float[] EtCalib = new float[5] { 1, 1, 1, 1, 1 }; +#elif FUZHOU150 + public float[] EtCalib = new float[6] { 1, 1, 1, 1, 1, 1 }; +#endif + public uint[] DiverterEdge = new uint[2] { 50, 50 }; + public uint[] BalanceRange = new uint[2]; + + /// + /// Private values sent by the last SendCommand() + /// + bool sendCommandFlag; + Command cmd; + int refNr; + ulong route; + int refPulses; + TestMethods testMethods; + float filterConstant; + float[] FMFreq; + int regConst; + int shortImp; + StopDevs stopDevs; + + public void SetFMFreq(int index, float power) + { + if (index == 0) FMFreq = new float[2] { power, 0 }; + else if (index == 1) FMFreq = new float[2] { 0, power }; + else FMFreq = new float[2] { 0, 0 }; + } + + public void UpdateWeights() + { + for (int i = 0; i < MettlerToledo.BalanceDev.BalancesCount; i++) + { + controlCom.SetWeight(i, MettlerToledo.BalanceDev.Masses[i]); + } + } + + + /// + /// Constructor + /// + public ControlBoardDev(ControlBoardCfg cfg, IList components) + { + if (cfg == null) throw new ArgumentNullException("cfg"); + this.controlBoardCfg = cfg; + FMFreq = new float[2] { 0, 0 }; + } + + /// + /// Specific pre-initialization for control board only + /// + /// + public void InitializeComponent( +#if DN100 + ControlCom2VB.ControlCom2panel ctrlBrdComponent, +#elif MUNICH + ControlComponent3Munich.UserControl1 ctrlBrdComponent, +#elif FUZHOU150 + ControlComponent3Munich.UserControl1 ctrlBrdComponent, +#endif + float[] tankCapacities) + { + if (controlBoardCfg.DebugLevel == Entities.DebugMode.Simulate) + { + controlCom = new ControlComSim(); + } + else + { + int cnt = Math.Min(BalanceRange.Length, tankCapacities.Length); + for (int i = 0; i < cnt; i++) BalanceRange[i] = (uint)tankCapacities[i]; + controlCom = new ControlComWrap(ctrlBrdComponent); + } + } + + /// Initialize this device + public void Initialize() + { + controlCom.SendCalibData(RegValveCalib, + MeretRS485Address, + controlBoardCfg.ComPortNr, + TempCalibData, + EtCalib, + DiverterEdge, + BalanceRange); + } + + /// Run this device + public void RunDeviceBefore() + { + controlCom.RunDeviceBefore(); + + if (EmgcyStopActive) + { + /// SendCommand() arguments to clear the emergency stop state + sendCommandFlag = true; + this.cmd = Command.Stop; + this.stopDevs = StopDevs.All; + } + else + { + /// Reset all SendCommand() arguments + sendCommandFlag = false; + this.cmd = Command.None; + this.stopDevs = 0; + } + this.refNr = 0; + this.refPulses = 0; + this.testMethods = 0; + this.filterConstant = 0; + this.regConst = 0; + this.shortImp = 0; + } + + /// Run this device + public void RunDeviceAfter() + { + if (sendCommandFlag) + { + controlCom.SendCommand(cmd, refNr, route, refPulses, testMethods, + filterConstant, FMFreq, regConst, shortImp, stopDevs); + } + + controlCom.RunDeviceAfter(); + } + + /// Stop this device + public void StopDevice() + { + } + + /// + /// Sends a command to the control board. + /// + /// See ControlBoard.Command enum + /// Number of the etalon/reference (1..5) + /// Route: 64-bit installation specific number + /// kolko impulzov ma trvat skuska + /// See ControlBoard.TestMethods enum + /// 0 = No filtering (0..255) + /// Coefficient used to control reg. valves (1..100) + /// 0 = default value, 1 = spec. processing of very short pulses + /// What to stop + public void SendCommand(Command cmd, int refFlowmtrNr, ulong route, int totalRefPulses, TestMethods testMethods, + float filterConstant, int regConst, int shortImp, StopDevs stopDevs) + { + this.cmd = cmd; + this.refNr = refFlowmtrNr; + this.route = route; + this.refPulses = totalRefPulses; + this.testMethods = testMethods; + this.filterConstant = filterConstant; + this.regConst = regConst; + this.shortImp = shortImp; + this.stopDevs = stopDevs; + + sendCommandFlag = true; + } + + public void SetValves(ulong valvesToOpen, ulong valvesToClose) + { + route = (route | valvesToOpen) & (~valvesToClose); + sendCommandFlag = true; + } + + /// + /// Regulation valves control. + /// + /// Regulation valve nr. (1..5) + /// Valve regulation mode, see the enum + /// Target position or target frequency or pulse duration + public void ValveMove(int valveNo, RegulValveMode valveMode, float[] valveValue) + { + controlCom.ValveMove(valveNo, valveMode, valveValue); + } + + + /// + /// Open one valve and/or close one valve. + /// Events: ValvesSet + /// + /// Valve to be opened + /// Valve to be closed + /// Created operation + public IOperation SetValvesOp(IValve valveOpen, IValve valveClose) + { + return new Valve.SetValvesOp(this, valveOpen, valveClose); + } + + /// + /// Open and/or close multiple valves. + /// Events: ValvesSet + /// + /// A list of valves to be opened + /// A list of valves to be closed + /// Created operation + public IOperation SetValvesOp(IList valvesOpen, IList valvesClose) + { + return new Valve.SetValvesOp(this, valvesOpen, valvesClose); + } + + /// + /// Starts the measurement. + /// Events: MeasurementStarted + /// + /// Flow meter + /// An array of register readers + /// Number of reference pulses to complete the test + /// Created operation + public IOperation StartMeasurementOp(IFlowMeter flowMeter, int refPulses, TestMethods method) + { + return new StartMeasurementOp(this, flowMeter, refPulses, method); + } + + /// + /// Queries th econtrol board whether the measurement was completed. + /// Events: MeasurementCompleted or None + /// + /// Created operation + public IOperation QueryMeasurementEndOp() + { + return new QueryMeasurementEndOp(this); + } + + /// + /// Stop the previous control board operation (diverter, gate, etc.) + /// Events: PreviousStopped + /// + /// Created operation + public IOperation StopPreviousOp() + { + return new StopPreviousOp(this); + } + + /// + /// Updates the tank drawing and weight value in Elde software component. + /// + /// Current mass in [kg] or approx. volume in [l] + /// Created operation + public IOperation UpdateTankWeightOp() + { + return new UpdateTankWeightOp(this); + } + } +} diff --git a/TestBenchFramework/BenchControl/Elde/ControlBoardFactory.cs b/TestBenchFramework/BenchControl/Elde/ControlBoardFactory.cs new file mode 100644 index 000000000..a329e4e39 --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/ControlBoardFactory.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.Elde +{ + public class ControlBoardFactory : IComponentFactory + { + public string ClassName { get { return "ControlBoard"; } } + public bool HasProcedureParams { get { return false; } } + public bool HasTestParams { get { return false; } } + public IParamsProvider GetTestParams(Entities.ComponentTest testParams) { return null; } + public IParamsProvider GetProcedureParams(Entities.ComponentProcedure procedureParams) { return null; } + + /// Max. number of components of this class in the system + public int MaxCount { get { return 1; } } + + public IComponentCfg DefaultConfig(IList components) + { + return new ControlBoardCfg(this, "CB", 1); + } + + public IComponentCfgCtrl CreateCfgCtrl() + { + return new ControlBoardCfgCtrl(); + } + + public IComponent ComponentFromCmpntCfg(IComponentCfg config, IList components) + { + return new ControlBoardDev((ControlBoardCfg)config, components); + } + + public IComponentCfg CmpntCfgFromCmpntEntity(Entities.Component component) + { + return Elde.ControlBoardCfg.CreateFromDbEntity(component, this); + } + + public void ResetStaticProperties() { ControlBoardDev.ResetStaticProperties(); } + } +} diff --git a/TestBenchFramework/BenchControl/Elde/ControlComSim.cs b/TestBenchFramework/BenchControl/Elde/ControlComSim.cs new file mode 100644 index 000000000..49b070b1a --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/ControlComSim.cs @@ -0,0 +1,293 @@ +using System; +using System.Collections.Generic; +using System.Text; +using log4net; + +namespace TBF.BenchControl.Elde +{ + public class ControlComSim : TestBenchSim, IControlCom + { + private static readonly ILog log = LogManager.GetLogger(typeof(ControlComSim)); + public override string ToString() { return string.Format("ControlComSim"); } + + + StatusP statusP; + public StatusP StatusP { get { return statusP; } } + + float referenceFreq = 650.0f; + public float ReferenceFreq { get { return referenceFreq; } } + + int[] etPulses = new int[Program.WMsCount + 1]; + public int EtPulses(int wmNr1and0) + { + return etPulses[wmNr1and0]; + } + + float[] errFactor = new float[Program.WMsCount + 1]; /// Internal + float[] wMeterPulsesF = new float[Program.WMsCount + 1]; /// Internal + + int[] wMeterPulses = new int[Program.WMsCount + 1]; /// Rounded from wMeterPulsesF + public int WMeterPulses(int wmNr1) + { + return wMeterPulses[wmNr1]; + } + + int[] wMeterReference = new int[Program.WMsCount + 1]; + public int WMeterReference(int wmNr1) + { + return wMeterReference[wmNr1]; + } + + public uint RegulValveDAC { get { return 0; } } + + public float Pressure(int prsNr0) { return 0; } + public float Temperature(int tmpNr0) { return (float)(20 + tmpNr0); } + public RegulValveState RegulValveState(int rvNr1) { return 0; } + + public ulong RRoute { get { return route; } } + + public uint DivTime { get { return 0; } } + + float tTime = 0; + public float TTime { get { return tTime; } } + + public uint FmState { get { return 0; } } + public uint BeginState(int wmNr0) { return 0; } + + float referenceFlow; + public float ReferenceFlow { get { return referenceFlow; } } + + public float RValvePosition(int rvNr1) { return 0; } + public float DivSamples(int ms) { return 0; } + public int ScopeSamples(int i, int j, int k) { return 0; } + public uint DigitalInputs { get { return 0; } } + public float AnalogInput(int adcNr0) { return 0; } + public uint AnalogInputRaw(int adcNr0, int bank) { return 0; } /// bank0=RV, bank1=Temp + public float ReferenceVolume { get { return 0; } } + public float VyslExt(int wmNr0, int what) { return 0; } + public void SetWeight(int pos, float mass) { return; } /// not available in sim. mode + + /// + /// Private initialization data updated by contructors of children components + /// and sent to 'controlCom2panel' by SendCalibData() method. + /// + uint[,] regValveCalib; + byte[] meretRS485Address; + float[,] tempCalibData; + float[] etCalib; + uint[] diverterEdge; + uint[] balanceRange; + + /// + /// Private values set by SendCommand() + /// + Command cmd; + int refFlowmtrNr; + ulong route; + public ulong Route { get { return route; } } + int totalRefPulses; + TestMethods testMethods; + float filterConstant; + float[] FMFreq; + int regConst; + int shortImp; + StopDevs stopDevs; + + /// + /// Private values set by ValveMove() + /// + int regulValveNo; + RegulValveMode regulValveMode; + float[] regulValveValue; + + Random rand; + + /// + /// Constructor + /// + public ControlComSim() + { + rand = new Random(); + } + + /// + /// Sends calibration and configuration data to the control board. + /// + /// Regulating valves calib.coefs, ix1 = valve nr. (1..5), ix2 = coef.nr. (0..1), values typ. c0 = 0, c1 = 0.2 + /// Meret address, index = 0..1, value typ. 99 and 100 + /// COM port number of the control board (typ. 1) + /// Temp.calc.coefs, ix1 = temp.sens.nr. (0..7 ???), ix2 = coef.nr + /// Etalon nominal values + /// Percentages for switching of diverters, ix = diverter nr.(0,1), typ.value 50 (%) + public void SendCalibData(uint[,] rvCalib, byte[] meretA, int usedCom, float[,] tempCalib, float[] etCalib, uint[] divEdge, uint[] balanceRange) + { + this.regValveCalib = rvCalib; + this.meretRS485Address = meretA; + this.tempCalibData = tempCalib; + this.etCalib = etCalib; + this.diverterEdge = divEdge; + this.balanceRange = balanceRange; + } + + /// + /// Sends a command to the control board. + /// + /// See ControlBoard.Command enum + /// Number of the etalon/reference (1..5) + /// Route: 64-bit installation specific number + /// kolko impulzov ma trvat skuska + /// See ControlBoard.TestMethods enum + /// 0 = No filtering (0..255) + /// Freq.inverter control (not applicable in DT100, Munich) + /// Coefficient used to control reg. valves (1..100) + /// 0 = default value, 1 = spec. processing of very short pulses + /// What to stop + public void SendCommand(Command cmd, int refFlowmtrNr, ulong route, int totalRefPulses, TestMethods testMethods, + float filterConstant, float[] FMFreq, int regConst, int shortImp, StopDevs stopDevs) + { + Command lastCmd = this.cmd; + this.cmd = cmd; + this.refFlowmtrNr = refFlowmtrNr; + this.route = route; + RouteSim = route; + this.totalRefPulses = totalRefPulses; + this.testMethods = testMethods; + this.filterConstant = filterConstant; + this.FMFreq = FMFreq; + this.regConst = regConst; + this.shortImp = shortImp; + this.stopDevs = stopDevs; + + statusP = (StatusP)(((ulong)statusP & 0xFFFFFFFFFFFFFFF8L) | (ulong)refFlowmtrNr); + + if (cmd == Command.Start && lastCmd != Command.Start ) + { + statusP |= StatusP.TestInProgress; + /// + /// Clear all counters + /// + if (etPulses != null) { for (int i = 0; i < etPulses.Length; i++) etPulses[i] = 0; } + if (wMeterPulses != null) { for (int i = 0; i < wMeterPulses.Length; i++) wMeterPulses[i] = 0; } + if (wMeterPulsesF != null) { for (int i = 0; i < wMeterPulsesF.Length; i++) wMeterPulsesF[i] = 0; } + if (wMeterReference != null) { for (int i = 0; i < wMeterReference.Length; i++) wMeterReference[i] = 0; } + if (errFactor != null) + { + for (int i = 0; i < errFactor.Length; i++) errFactor[i] = ((float)rand.Next(100) + 950.0f) / 1000.0f; + } + tTime = 0; + } + else if (cmd == Command.Stop) + { + statusP = 0; + //statusP &= ~StatusP.Running; + } + } + + /// + /// Control of regulating valves. + /// + /// Regulating valve nr. (1..5) + /// ??? + /// ??? + public void ValveMove(int regulValveNo, RegulValveMode regulValveMode, float[] regulValveValue) + { + this.regulValveNo = regulValveNo; + this.regulValveMode = regulValveMode; + this.regulValveValue = regulValveValue; + } + + public void RunDeviceBefore() + { + base.RunDevice(regulValveNo, refFlowmtrNr, statusP); + + log.DebugFormat("refFreq=", referenceFreq); + + tTime += 1.0f; + + float Qnom = (regulValveNo > 0) ? etCalib[regulValveNo] : 0; + + switch (cmd) + { + case Command.None: + break; + + case Command.Start: + if ((testMethods & TestMethods.Diverter) == TestMethods.Diverter) + { + SetSimDiverter(true); + } + break; + + case Command.Stop: + if ((testMethods & TestMethods.Diverter) == TestMethods.Diverter) + { + SetSimDiverter(false); + } + break; + } + + switch (regulValveMode) + { + case RegulValveMode.TargetFrequency: + float targetFlow = ((regulValveValue[0] + regulValveValue[1]) / 2.0f) * (Qnom / 2000.0f); + UpdateSimFlow(targetFlow); + + //if (referenceFreq < valveValue[0]) referenceFreq += ((float)rand.Next(20) + 10.0f) / 2.0f; + //else if (referenceFreq > valveValue[1]) referenceFreq -= ((float)rand.Next(20) + 10.0f) / 2.0f; + //else referenceFreq += ((float)rand.Next(10) - 5.0f) / 2.0f; + referenceFreq = GetSimFlow() * 2000.0f / Qnom; + if (referenceFreq < 0) referenceFreq = 0; + if (referenceFreq > 2500) referenceFreq = 2500; + break; + + default: + break; + } + + referenceFlow = referenceFreq / 2000; + + bool stopTest = false; + if (cmd == Command.Start) + { + float pwFactor = 1.0f; + + /// Increment reference flow meters + for (int i = 0; i < Program.WMsCount; i++) + { + etPulses[i] += (int)referenceFreq; + if (etPulses[i] > totalRefPulses) + { + pwFactor = 1.0f - (float)(etPulses[i] - totalRefPulses) / referenceFreq; + etPulses[i] = totalRefPulses; + stopTest = true; + } + } + + /// Increment water meters + for (int i = 1; i < Program.WMsCount; i++) + { + const float wmPulsesPerLiter = 10.0f; + wMeterPulsesF[i] += errFactor[i] * pwFactor * ((float)rand.Next(100) + 450.0f) * wmPulsesPerLiter * GetSimFlow() / 1800.0f; + wMeterPulses[i] = (int)wMeterPulsesF[i]; + } + + if (etPulses[0] > totalRefPulses) + { + statusP |= StatusP.TestCompleted; + statusP &= ~StatusP.TestInProgress; + } + } + + if (stopTest) + { + SetSimDiverter(false); + statusP = (statusP | StatusP.TestCompleted); + statusP = (statusP & ~StatusP.TestInProgress); + } + } + + public void RunDeviceAfter() + { + } + } +} diff --git a/TestBenchFramework/BenchControl/Elde/ControlComWrap.cs b/TestBenchFramework/BenchControl/Elde/ControlComWrap.cs new file mode 100644 index 000000000..3c70f6602 --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/ControlComWrap.cs @@ -0,0 +1,265 @@ +using System; +using log4net; + +namespace TBF.BenchControl.Elde +{ + public class ControlComWrap : IControlCom + { + private static readonly ILog log = LogManager.GetLogger(typeof(ControlComWrap)); + + /// + /// Properties + /// + public StatusP StatusP { get { return (StatusP)ctrlBrdComponent.StatusP; } } + public float ReferenceFreq { get { return 1000.0f * ctrlBrdComponent.referenceFreq; } } /// In [Hz] 0..2500, nom.=2000 + public int EtPulses(int wmNr0) + { + return (int)ctrlBrdComponent.etPulses[wmNr0]; + } + public int WMeterPulses(int wmNr0) + { + return (int)ctrlBrdComponent.wMeterPuls[wmNr0]; + } + public int WMeterReference(int wmNr0) { return (int)ctrlBrdComponent.wMeterReference[wmNr0]; } + public uint RegulValveDAC { get { return ctrlBrdComponent.StavDA; } } + public float Pressure(int prsNr0) { return ctrlBrdComponent.pressure[prsNr0]; } + public float Temperature(int tmpNr0) { return ctrlBrdComponent.temperature[tmpNr0]; } + public RegulValveState RegulValveState(int rvNr1) { return (RegulValveState)ctrlBrdComponent.rValveStatus[rvNr1 - 1]; } + public ulong RRoute { get { return ctrlBrdComponent.rRoute; } } + public uint DivTime { get { return ctrlBrdComponent.divTime; } } + public float TTime { get { return ctrlBrdComponent.Ttime; } } + public uint FmState { get { return ctrlBrdComponent.fMState; } } + public uint BeginState(int wmNr0) { return ctrlBrdComponent.beginSt[wmNr0]; } + public float ReferenceFlow { get { return ctrlBrdComponent.referenceFlow; } } + public float RValvePosition(int rvNr1) + { + //return ctrlBrdComponent.RValvePosition[rvNr1 - 1]; + return ctrlBrdComponent.Analogy[rvNr1 - 1]; /// Fixes bug: RValvePosition returns 0 all the time + } + public float DivSamples(int ms) { return ctrlBrdComponent.DIVSamples[ms, 0]; } + public int ScopeSamples(int i, int j, int k) { return ctrlBrdComponent.ScopeSamples[i, j, k]; } + public uint DigitalInputs { get { return ctrlBrdComponent.Vstupy; } } + public float AnalogInput(int adcNr0) { return ctrlBrdComponent.Analogy[adcNr0]; } + public uint AnalogInputRaw(int adcNr0, int bank) { return ctrlBrdComponent.AnalogyRaw[adcNr0, bank]; } /// bank0=RV, bank1=Temp + public float ReferenceVolume { get { return ctrlBrdComponent.ReferenceVolume; } } + public float VyslExt(int wmNr0, int what) { return ctrlBrdComponent.VyslExt[wmNr0, what]; } + public void SetWeight(int pos, float mass) { ctrlBrdComponent.Weight[pos] = mass; } + + + /// + /// Reference to the control board component + /// +#if DN100 + private ControlCom2VB.ControlCom2panel ctrlBrdComponent; +#elif MUNICH + private ControlComponent3Munich.UserControl1 ctrlBrdComponent; +#elif FUZHOU150 + private ControlComponent3Munich.UserControl1 ctrlBrdComponent; +#endif + + /// + /// Constructor that initializes the control board component reference + /// + /// +#if DN100 + public ControlComWrap(ControlCom2VB.ControlCom2panel ctrlBrdComponent) +#elif MUNICH + public ControlComWrap(ControlComponent3Munich.UserControl1 ctrlBrdComponent) +#elif FUZHOU150 + public ControlComWrap(ControlComponent3Munich.UserControl1 ctrlBrdComponent) +#endif + { + this.ctrlBrdComponent = ctrlBrdComponent; + } + + + /// + /// Sends calibration and configuration data to the control board. + /// + /// Regulating valves calib.coefs, ix1 = valve nr. (1..5), ix2 = coef.nr. (0..1), values typ. c0 = 0, c1 = 0.2 + /// Meret address, index = 0..1, value typ. 99 and 100 + /// COM port number of the control board (typ. 1) + /// Temp.calc.coefs, ix1 = temp.sens.nr. (0..7 ???), ix2 = coef.nr + /// Etalon nominal values + /// Percentages for switching of diverters, ix = diverter nr.(0,1), typ.value 50 (%) + /// Balance range = volume of the tanks on the balaces (ix=0,1) + public void SendCalibData(uint[,] rvCalib, byte[] meretA, int usedCom, float[,] tempCalib, + float[] etCalib, uint[] divEdge, uint[] balanceRange) + { + if (Program.MainWnd.InvokeRequired) + { + /// When SendCalibData(...) called from the worker thread + object[] args = new object[] { rvCalib, meretA, usedCom, tempCalib, etCalib, divEdge, balanceRange }; + Program.MainWnd.Invoke((SendCalibDataDlgt)DoSendCalibData, args); /// Invoke required as component was created in UI thread + } + else + { + /// When SendCalibData(...) called from the UI thread + DoSendCalibData(rvCalib, meretA, usedCom, tempCalib, etCalib, divEdge, balanceRange); + } + } + /// + delegate void SendCalibDataDlgt(uint[,] rvCalib, byte[] meretA, int usedCom, float[,] tempCalib, + float[] etCalib, uint[] divEdge, uint[] balanceRange); + /// + private void DoSendCalibData(uint[,] rvCalib, byte[] meretA, int usedCom, float[,] tempCalib, + float[] etCalib, uint[] divEdge, uint[] balanceRange) + { + //TBF.UiBridge.Bridge.OnLog(this, string.Format("{0} SendCalibData(COM{1}) rvCalib[0,0]={2} rvCalib[0,1]={3} rvCalib[1,0]={4} rvCalib[1,1]={5}\r\n", + // DateTime.Now.ToLongTimeString(), usedCom, + // rvCalib[0,0], rvCalib[0,1], rvCalib[1,0], rvCalib[1,1])); + log.InfoFormat("SendCalibData(COM{0}) rvCalib[0,0]={1} rvCalib[0,1]={2} rvCalib[1,0]={3} rvCalib[1,1]={4}\r\n", + usedCom, rvCalib[0,0], rvCalib[0,1], rvCalib[1,0], rvCalib[1,1]); +#if (DN100) + ctrlBrdComponent.ExternalCom = true; +#endif + ctrlBrdComponent.SendCalibData(rvCalib, meretA, (byte)usedCom, tempCalib, etCalib, divEdge, balanceRange); + } + + + /// + /// Control of regulating valves. + /// + /// Regulating valve nr. (1..5) + /// Valve regulation mode, see the enum + /// Target position or target frequency or pulse duration + public void ValveMove(int valveNo, RegulValveMode valveMode, float[] valveValue) + { + if (Program.MainWnd.InvokeRequired) + { + /// When ValveMove(...) called from the worker thread + object[] args = new object[] { valveNo, valveMode, valveValue }; + Program.MainWnd.Invoke((ValveMoveDlgt)DoValveMove, args); /// When ValveMove called from a worker thread + } + else + { + /// When ValveMove(...) called from the UI thread + DoValveMove(valveNo, valveMode, valveValue); /// When ValveMove called from the UI thread + } + } + /// + delegate void ValveMoveDlgt(int valveNo, RegulValveMode valveMode, float[] valveValue); + /// + private void DoValveMove(int valveNo, RegulValveMode valveMode, float[] valveValue) + { + //TBF.UiBridge.Bridge.OnLog(this, string.Format("{0} ValveMove({1}, {2}, [{3}, {4}])\r\n", + // DateTime.Now.ToLongTimeString(), + // valveNo, + // valveMode, + // valveValue[0], + // valveValue[1])); + log.InfoFormat("ValveMove({0}, {1}, [{2}, {3}])\r\n", valveNo, valveMode, valveValue[0], valveValue[1]); + + ctrlBrdComponent.ValveMove((byte)valveNo, (byte)valveMode, valveValue); + } + + + /// + /// Sends a command to the control board. + /// + /// See ControlBoard.Command enum + /// Reference flow meter number (1..5) + /// Route: 64-bit installation specific number + /// Test duration as a number of reference flow meter pulses + /// See ControlBoard.TestMethods enum + /// 0 = No filtering (0..255) + /// Freq.inverter control (not applicable in DT100, Munich) + /// Coefficient used to control the regulation valve (1..100) + /// 0 = default value, 1 = spec. processing of very short pulses + /// What to stop + public void SendCommand(Command cmd, int refFlowMeterNr, ulong route, int totalRefPulses, TestMethods testMethods, + float filterConstant, float[] fmFreq, int regConst, int shortImp, StopDevs stopDevs) + { + if (Program.MainWnd.InvokeRequired) + { + /// When SendCommand(...) called from the worker thread + object[] args = new object[] { cmd, refFlowMeterNr, route, totalRefPulses, testMethods, + filterConstant, fmFreq, regConst, shortImp, stopDevs }; + Program.MainWnd.Invoke((SendCommandDlgt)DoSendCommand, args); /// Component was created in UI thread - use Invoke() + } + else + { + /// When SendCommand(...) called from the UI thread + DoSendCommand(cmd, refFlowMeterNr, route, totalRefPulses, testMethods, + filterConstant, fmFreq, regConst, shortImp, stopDevs); + } + } + /// + delegate void SendCommandDlgt(Command cmd, int refFlowmtrNr, ulong route, int totalRefPulses, TestMethods testMethods, + float filterConstant, float[] fmFreq, int regConst, int shortImp, StopDevs stopDevs); + /// + private void DoSendCommand(Command cmd, int refFlowMeterNr, ulong route, int totalRefPulses, TestMethods testMethods, + float filterConstant, float[] fmFreq, int regConst, int shortImp, StopDevs stopDevs) + { + //TBF.UiBridge.Bridge.OnLog(this, string.Format("{0} SendCommand({1}, {2}, {3}, {4}, {5}, {6}, [{7},{8}], {9}, {10}, {11})\r\n", + // DateTime.Now.ToLongTimeString(), + // cmd, + // refFlowMeterNr, + // route.ToString("X"), + // totalRefPulses, + // testMethods, + // filterConstant, + // fmFreq[0], + // fmFreq[1], + // regConst, + // shortImp, + // stopDevs)); + log.InfoFormat("SendCommand({0}, {1}, {2}, {3}, {4}, {5}, [{6},{7}], {8}, {9}, {10})\r\n", + cmd, + refFlowMeterNr, + route.ToString("X"), + totalRefPulses, + testMethods, + filterConstant, + fmFreq[0], + fmFreq[1], + regConst, + shortImp, + stopDevs); +#if DN100 + ctrlBrdComponent.SendCommand((uint)cmd, (byte)refFlowMeterNr, (ulong)route, (uint)totalRefPulses, (uint)testMethods, + filterConstant, fmFreq[0], (uint)regConst, (uint)shortImp, (uint)stopDevs); +#else + ctrlBrdComponent.SendCommand((uint)cmd, (byte)refFlowMeterNr, (ulong)route, (uint)refPulses, (uint)testMethods, + filterConstant, FMFreq, (uint)regConst, (uint)shortImp, (uint)stopDevs); +#endif + } + + + enum CommType + { + Rx, /// Receive data only + TxRx, /// Transmit and receive data + } + + public void RunDeviceBefore() + { + object[] args = new object[] { CommType.Rx }; + MakeCommDlgt dlgt = MakeComm; + Program.MainWnd.Invoke(dlgt, args); /// Invoke MakeExtComm(.) in the UI thread + } + + public void RunDeviceAfter() + { + object[] args = new object[] { CommType.TxRx }; + MakeCommDlgt dlgt = MakeComm; + Program.MainWnd.Invoke(dlgt, args); /// Invoke MakeExtComm(.) in the UI thread + } + + /// + /// A delegate to execute the SendCommand() in the UI thread + /// + delegate void MakeCommDlgt(CommType extComm); + + /// + /// Executes the SendCommand(...) and MakeExtCom() in the UI thread + /// + void MakeComm(CommType commType) + { + if (ctrlBrdComponent.ExternalCom) + { + ctrlBrdComponent.MakeExtCom((commType == CommType.Rx) ? false : true); + } + } + } +} diff --git a/TestBenchFramework/BenchControl/Elde/Diverter/Diverter.cs b/TestBenchFramework/BenchControl/Elde/Diverter/Diverter.cs new file mode 100644 index 000000000..d190fa317 --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/Diverter/Diverter.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using log4net; + +namespace TBF.BenchControl.Elde.Diverter +{ + public class Diverter : Generic.IComponent, GenericDevices.IDiverter + { + /// + /// Info: StartMassMeasurement() and "Balance response = .., Mass = ..." + /// Warn: Start measurement when busy is true + /// + private static readonly ILog log = LogManager.GetLogger(typeof(Diverter)); + public override string ToString() + { + return string.Format("Diverter({0},{1})", Name, diverterCfg.BitPosition); + } + + public static void ResetStaticProperties() { } + + private readonly DiverterCfg diverterCfg; + public Generic.IComponentCfg Cfg { get { return diverterCfg; } } + + public string Name { get { return diverterCfg.Name; } } + + readonly ControlBoardDev controlBoard; + + public readonly ulong Mask; /// derived from bitPosition in the constructor + + + public Diverter(DiverterCfg cfg, IList components) + { + if (cfg == null) throw new ArgumentNullException("cfg"); + this.diverterCfg = cfg; + + controlBoard = (ControlBoardDev)TbfComponents.FindComponent(cfg.ParentName, components); + if (controlBoard == null) throw new Exception("Cannot find " + Name + " parent"); + + if (cfg.BitPosition < 0 || cfg.BitPosition >= 64) throw new ArgumentOutOfRangeException("position"); + this.Mask = (((ulong)1) << cfg.BitPosition); + + log.Debug(this.ToString()); + } + + public bool State + { + get { return (controlBoard.Route & Mask) != 0; } + } + } +} diff --git a/TestBenchFramework/BenchControl/Elde/Diverter/DiverterCfg.cs b/TestBenchFramework/BenchControl/Elde/Diverter/DiverterCfg.cs new file mode 100644 index 000000000..b92f02192 --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/Diverter/DiverterCfg.cs @@ -0,0 +1,51 @@ +using System.IO; +using System.Xml.Serialization; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.Elde.Diverter +{ + public class DiverterCfg : ComponentCfgBase, IChildComponentCfg + { + public int BitPosition; + + /// Parameterless constructor + public DiverterCfg() + { + } + /// Constructor + public DiverterCfg(IComponentFactory factory, string name, string parentName, int bitPosition) + : base(factory, name, parentName) + { + this.BitPosition = bitPosition; + } + + public IComponentCfg Clone() + { + return new DiverterCfg(Factory, Name, ParentName, BitPosition); + } + + public string ToString(int i) + { + return string.Format("bit={0}", BitPosition); + } + + public TBF.Entities.Component CreateDbEntity() + { + using (var writer = new StringWriter()) + { + (new XmlSerializer(GetType())).Serialize(writer, this); + return Entities.Component.CreateFromCfg(Name, Factory.ClassName, ParentName, ItemNr, DebugLevel, LogLevel, writer.ToString()); + } + } + + public static IComponentCfg CreateFromDbEntity(Entities.Component component, IComponentFactory factory) + { + using (var reader = new StringReader(component.Parameters)) + { + DiverterCfg config = (DiverterCfg)(new XmlSerializer(typeof(DiverterCfg))).Deserialize(reader); + config.InitCfgBaseFromEntity(component, factory); + return config; + } + } + } +} diff --git a/TestBenchFramework/BenchControl/Elde/Diverter/DiverterCfgCtrl.Designer.cs b/TestBenchFramework/BenchControl/Elde/Diverter/DiverterCfgCtrl.Designer.cs new file mode 100644 index 000000000..93e7abf90 --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/Diverter/DiverterCfgCtrl.Designer.cs @@ -0,0 +1,130 @@ +namespace TBF.BenchControl.Elde.Diverter +{ + partial class DiverterCfgCtrl + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.nameTextBox = new System.Windows.Forms.TextBox(); + this.nameLabel = new System.Windows.Forms.Label(); + this.classNameLabel = new System.Windows.Forms.Label(); + this.parentNameLabel = new System.Windows.Forms.Label(); + this.bitPositionLabel = new System.Windows.Forms.Label(); + this.bitPositionTextBox = new System.Windows.Forms.TextBox(); + this.parentNameComboBox = new System.Windows.Forms.ComboBox(); + this.SuspendLayout(); + // + // nameTextBox + // + this.nameTextBox.Enabled = false; + this.nameTextBox.Location = new System.Drawing.Point(137, 41); + this.nameTextBox.Name = "nameTextBox"; + this.nameTextBox.Size = new System.Drawing.Size(130, 20); + this.nameTextBox.TabIndex = 2; + // + // nameLabel + // + this.nameLabel.AutoSize = true; + this.nameLabel.Location = new System.Drawing.Point(27, 44); + this.nameLabel.Name = "nameLabel"; + this.nameLabel.Size = new System.Drawing.Size(35, 13); + this.nameLabel.TabIndex = 1; + this.nameLabel.Text = "Name"; + // + // classNameLabel + // + this.classNameLabel.AutoSize = true; + this.classNameLabel.Location = new System.Drawing.Point(134, 17); + this.classNameLabel.Name = "classNameLabel"; + this.classNameLabel.Size = new System.Drawing.Size(83, 13); + this.classNameLabel.TabIndex = 0; + this.classNameLabel.Text = "ComonentName"; + // + // parentNameLabel + // + this.parentNameLabel.AutoSize = true; + this.parentNameLabel.Location = new System.Drawing.Point(27, 70); + this.parentNameLabel.Name = "parentNameLabel"; + this.parentNameLabel.Size = new System.Drawing.Size(69, 13); + this.parentNameLabel.TabIndex = 3; + this.parentNameLabel.Text = "Parent Name"; + // + // bitPositionLabel + // + this.bitPositionLabel.AutoSize = true; + this.bitPositionLabel.Location = new System.Drawing.Point(27, 96); + this.bitPositionLabel.Name = "bitPositionLabel"; + this.bitPositionLabel.Size = new System.Drawing.Size(59, 13); + this.bitPositionLabel.TabIndex = 5; + this.bitPositionLabel.Text = "Bit Position"; + // + // bitPositionTextBox + // + this.bitPositionTextBox.Enabled = false; + this.bitPositionTextBox.Location = new System.Drawing.Point(137, 93); + this.bitPositionTextBox.Name = "bitPositionTextBox"; + this.bitPositionTextBox.Size = new System.Drawing.Size(46, 20); + this.bitPositionTextBox.TabIndex = 6; + // + // parentNameComboBox + // + this.parentNameComboBox.Enabled = false; + this.parentNameComboBox.FormattingEnabled = true; + this.parentNameComboBox.Location = new System.Drawing.Point(137, 67); + this.parentNameComboBox.Name = "parentNameComboBox"; + this.parentNameComboBox.Size = new System.Drawing.Size(130, 21); + this.parentNameComboBox.TabIndex = 4; + // + // DiverterCfgCtrl + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.parentNameComboBox); + this.Controls.Add(this.bitPositionTextBox); + this.Controls.Add(this.bitPositionLabel); + this.Controls.Add(this.parentNameLabel); + this.Controls.Add(this.nameTextBox); + this.Controls.Add(this.nameLabel); + this.Controls.Add(this.classNameLabel); + this.Name = "DiverterCfgCtrl"; + this.Size = new System.Drawing.Size(300, 200); + this.Load += new System.EventHandler(this.DiverterCfgCtrl_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TextBox nameTextBox; + private System.Windows.Forms.Label nameLabel; + private System.Windows.Forms.Label classNameLabel; + private System.Windows.Forms.Label parentNameLabel; + private System.Windows.Forms.Label bitPositionLabel; + private System.Windows.Forms.TextBox bitPositionTextBox; + private System.Windows.Forms.ComboBox parentNameComboBox; + } +} diff --git a/TestBenchFramework/BenchControl/Elde/Diverter/DiverterCfgCtrl.cs b/TestBenchFramework/BenchControl/Elde/Diverter/DiverterCfgCtrl.cs new file mode 100644 index 000000000..b21753414 --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/Diverter/DiverterCfgCtrl.cs @@ -0,0 +1,89 @@ +using System; +using System.Windows.Forms; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.Elde.Diverter +{ + public partial class DiverterCfgCtrl : UserControl, IComponentCfgCtrl + { + ComponentParametersDlg parent; + DiverterCfg config; + public IComponentCfg Config + { + get { return config as IComponentCfg; } + set + { + config = value as DiverterCfg; + Redraw(); + } + } + + public DiverterCfgCtrl() + { + InitializeComponent(); + } + + private void DiverterCfgCtrl_Load(object sender, EventArgs e) + { + parent = ParentForm as ComponentParametersDlg; + if (parent == null) return; + + if (parent.TbfComponents != null) + { + foreach (var cmpnt in parent.TbfComponents) + { + if (TbfComponents.CmpntFactoryFromClassName(cmpnt.ClassName) is Elde.ControlBoardFactory) + { + parentNameComboBox.Items.Add(cmpnt.Name); + } + } + } + + Redraw(); + } + + void Redraw() + { + if (config == null) return; /// Control was not loaded, settings were not changed + + classNameLabel.Text = config.Factory.ClassName; + parentNameComboBox.Text = string.IsNullOrEmpty(config.ParentName) ? "---" : config.ParentName; + nameTextBox.Text = config.Name; + bitPositionTextBox.Text = config.BitPosition.ToString(); + } + + public void Unlock() + { + nameTextBox.Enabled = true; + parentNameComboBox.Enabled = true; + bitPositionTextBox.Enabled = true; + } + + public CfgVerifyFlags VerifyCfg(ref string message) + { + CfgVerifyFlags flags = CfgVerifyFlags.None; + + int dummy; + if (!parentNameComboBox.Items.Contains(parentNameComboBox.Text)) + { + flags |= CfgVerifyFlags.Error; + message += Environment.NewLine + "Invalid 'Parent Name'"; + } + if (!int.TryParse(bitPositionTextBox.Text, out dummy) || dummy < 0 || dummy >= 64) + { + flags |= CfgVerifyFlags.Error; + message += Environment.NewLine + "'Bit Position' should be between 0 and 63"; + } + return flags; + } + + public void UpdateCfg() + { + if (config == null) return; /// Control was not loaded, settings were not changed + + config.Name = nameTextBox.Text; + config.ParentName = parentNameComboBox.Text.Equals("---") ? string.Empty : parentNameComboBox.Text; + config.BitPosition = int.Parse(bitPositionTextBox.Text); + } + } +} diff --git a/TestBenchFramework/BenchControl/Elde/Diverter/DiverterCfgCtrl.resx b/TestBenchFramework/BenchControl/Elde/Diverter/DiverterCfgCtrl.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/Diverter/DiverterCfgCtrl.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/BenchControl/Elde/Diverter/DiverterFactory.cs b/TestBenchFramework/BenchControl/Elde/Diverter/DiverterFactory.cs new file mode 100644 index 000000000..728ab536f --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/Diverter/DiverterFactory.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.Elde.Diverter +{ + public class DiverterFactory : IComponentFactory + { + public string ClassName { get { return "Diverter"; } } + public bool HasProcedureParams { get { return false; } } + public bool HasTestParams { get { return false; } } + public IParamsProvider GetTestParams(Entities.ComponentTest testParams) { return null; } + public IParamsProvider GetProcedureParams(Entities.ComponentProcedure procedureParams) { return null; } + + /// Max. number of components of this class in the system + public int MaxCount { get { return 5; } } + + public IComponentCfg DefaultConfig(IList components) + { + return new DiverterCfg(this, "Diverter", "CB", 0); + } + + public IComponentCfgCtrl CreateCfgCtrl() + { + return new DiverterCfgCtrl(); + } + + public IComponent ComponentFromCmpntCfg(IComponentCfg config, IList components) + { + return new Diverter((DiverterCfg)config, components); + } + + public IComponentCfg CmpntCfgFromCmpntEntity(Entities.Component component) + { + return DiverterCfg.CreateFromDbEntity(component, this); + } + + public void ResetStaticProperties() { Diverter.ResetStaticProperties(); } + } +} diff --git a/TestBenchFramework/BenchControl/Elde/FlowMeter/FlowMeter.cs b/TestBenchFramework/BenchControl/Elde/FlowMeter/FlowMeter.cs new file mode 100644 index 000000000..a5ed94360 --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/FlowMeter/FlowMeter.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections.Generic; +using log4net; + +namespace TBF.BenchControl.Elde.FlowMeter +{ + public class FlowMeter : Generic.IComponent, GenericDevices.IFlowMeter + { + /// + /// Info: StartMassMeasurement() and "Balance response = .., Mass = ..." + /// Warn: Start measurement when busy is true + /// + private static readonly ILog log = LogManager.GetLogger(typeof(FlowMeter)); + public override string ToString() + { + return string.Format("FlowMeter({0},{1})", Name, Position); + } + + public static void ResetStaticProperties() { } + + FlowMeterCfg flowMeterCfg; + public Generic.IComponentCfg Cfg { get { return flowMeterCfg; } } + + public string Name { get { return flowMeterCfg.Name; } } + public IList Corrections { get { return flowMeterCfg.Corrections; } } + + public readonly ControlBoardDev ControlBoard; + + public readonly int Position; /// 1..4 + + readonly float nominalFlow; + public float NominalFlow { get { return nominalFlow; } } + + public FlowMeter(FlowMeterCfg cfg, IList components) + { + if (cfg == null) throw new ArgumentNullException("cfg"); + this.flowMeterCfg = cfg; + + ControlBoard = (ControlBoardDev)TbfComponents.FindComponent(cfg.ParentName, components); + if (ControlBoard == null) throw new Exception("Cannot find " + Name + " parent"); + + Position = cfg.Position; + + nominalFlow = cfg.NominalFlow; + ControlBoard.EtCalib[Position] = NominalFlow; + + /// Prepare data for SendCalibData() control board component method + + log.Debug(this.ToString()); + } + + /// + /// Events: FlowDone, Error + /// + /// Reference to a variable for the flow in Bar + /// ReadFlowOp instance reference casted to IOperaton + public IOperation ReadFlowOp(ref FloatBox flow) + { + return new ReadFlowOp(this, ref flow); + } + + /// + /// Events: flowDone, Error + /// + /// Reference to a variable for the flow in Bar + /// Event returned when measurement done + /// ReadFlowOp instance reference casted to IOperaton + public IOperation ReadFlowOp(ref FloatBox flow, Event flowDone) + { + return new ReadFlowOp(this, ref flow, flowDone); + } + } +} diff --git a/TestBenchFramework/BenchControl/Elde/FlowMeter/FlowMeterCfg.cs b/TestBenchFramework/BenchControl/Elde/FlowMeter/FlowMeterCfg.cs new file mode 100644 index 000000000..58519eb3e --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/FlowMeter/FlowMeterCfg.cs @@ -0,0 +1,61 @@ +using System; +using System.IO; +using System.Xml.Serialization; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.Elde.FlowMeter +{ + public class FlowMeterCfg : ComponentCfgBase, Generic.IChildComponentCfg + { + public int Position; /// 1..5 + + public float NominalFlow; /// Nominal flow in m3/h at output frequency 2000 Hz + + /// Parameterless constructor + public FlowMeterCfg() + { + } + + /// + /// Flow meter configuration parameters + /// + /// Flow meter name + /// Position on the control board 1..5 + public FlowMeterCfg(IComponentFactory factory, string name, string parentName, int position, float nominalFlow) + : base(factory, name, parentName) + { + if (position < 1 || position > 5) throw new ArgumentOutOfRangeException("position"); + this.Position = position; + this.NominalFlow = nominalFlow; + } + + public IComponentCfg Clone() + { + return new FlowMeterCfg(Factory, Name, ParentName, Position, NominalFlow); + } + + public string ToString(int i) + { + return string.Format("position={0}, nominalFlow={1}", Position, NominalFlow); + } + + public TBF.Entities.Component CreateDbEntity() + { + using (var writer = new StringWriter()) + { + (new XmlSerializer(GetType())).Serialize(writer, this); + return Entities.Component.CreateFromCfg(Name, Factory.ClassName, ParentName, ItemNr, DebugLevel, LogLevel, writer.ToString()); + } + } + + public static IComponentCfg CreateFromDbEntity(Entities.Component component, IComponentFactory factory) + { + using (var reader = new StringReader(component.Parameters)) + { + FlowMeterCfg config = (FlowMeterCfg)(new XmlSerializer(typeof(FlowMeterCfg))).Deserialize(reader); + config.InitCfgBaseFromEntity(component, factory); + return config; + } + } + } +} diff --git a/TestBenchFramework/BenchControl/Elde/FlowMeter/FlowMeterCfgCtrl.Designer.cs b/TestBenchFramework/BenchControl/Elde/FlowMeter/FlowMeterCfgCtrl.Designer.cs new file mode 100644 index 000000000..a5061f73d --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/FlowMeter/FlowMeterCfgCtrl.Designer.cs @@ -0,0 +1,153 @@ +namespace TBF.BenchControl.Elde.FlowMeter +{ + partial class FlowMeterCfgCtrl + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.positionTextBox = new System.Windows.Forms.TextBox(); + this.positionLabel = new System.Windows.Forms.Label(); + this.parentNameLabel = new System.Windows.Forms.Label(); + this.nameTextBox = new System.Windows.Forms.TextBox(); + this.nameLabel = new System.Windows.Forms.Label(); + this.classNameLabel = new System.Windows.Forms.Label(); + this.nominalFlowTextBox = new System.Windows.Forms.TextBox(); + this.nominalFlowLabel = new System.Windows.Forms.Label(); + this.parentNameComboBox = new System.Windows.Forms.ComboBox(); + this.SuspendLayout(); + // + // positionTextBox + // + this.positionTextBox.Enabled = false; + this.positionTextBox.Location = new System.Drawing.Point(224, 113); + this.positionTextBox.Name = "positionTextBox"; + this.positionTextBox.Size = new System.Drawing.Size(46, 20); + this.positionTextBox.TabIndex = 6; + // + // positionLabel + // + this.positionLabel.AutoSize = true; + this.positionLabel.Location = new System.Drawing.Point(30, 116); + this.positionLabel.Name = "positionLabel"; + this.positionLabel.Size = new System.Drawing.Size(44, 13); + this.positionLabel.TabIndex = 5; + this.positionLabel.Text = "Position"; + // + // parentNameLabel + // + this.parentNameLabel.AutoSize = true; + this.parentNameLabel.Location = new System.Drawing.Point(30, 90); + this.parentNameLabel.Name = "parentNameLabel"; + this.parentNameLabel.Size = new System.Drawing.Size(69, 13); + this.parentNameLabel.TabIndex = 3; + this.parentNameLabel.Text = "Parent Name"; + // + // nameTextBox + // + this.nameTextBox.Enabled = false; + this.nameTextBox.Location = new System.Drawing.Point(140, 61); + this.nameTextBox.Name = "nameTextBox"; + this.nameTextBox.Size = new System.Drawing.Size(130, 20); + this.nameTextBox.TabIndex = 2; + // + // nameLabel + // + this.nameLabel.AutoSize = true; + this.nameLabel.Location = new System.Drawing.Point(30, 64); + this.nameLabel.Name = "nameLabel"; + this.nameLabel.Size = new System.Drawing.Size(35, 13); + this.nameLabel.TabIndex = 1; + this.nameLabel.Text = "Name"; + // + // classNameLabel + // + this.classNameLabel.AutoSize = true; + this.classNameLabel.Location = new System.Drawing.Point(137, 37); + this.classNameLabel.Name = "classNameLabel"; + this.classNameLabel.Size = new System.Drawing.Size(83, 13); + this.classNameLabel.TabIndex = 0; + this.classNameLabel.Text = "ComonentName"; + // + // nominalFlowTextBox + // + this.nominalFlowTextBox.Enabled = false; + this.nominalFlowTextBox.Location = new System.Drawing.Point(224, 138); + this.nominalFlowTextBox.Name = "nominalFlowTextBox"; + this.nominalFlowTextBox.Size = new System.Drawing.Size(46, 20); + this.nominalFlowTextBox.TabIndex = 8; + // + // nominalFlowLabel + // + this.nominalFlowLabel.AutoSize = true; + this.nominalFlowLabel.Location = new System.Drawing.Point(30, 141); + this.nominalFlowLabel.Name = "nominalFlowLabel"; + this.nominalFlowLabel.Size = new System.Drawing.Size(140, 13); + this.nominalFlowLabel.TabIndex = 7; + this.nominalFlowLabel.Text = "Nominal flow [m3/h @2kHz]"; + // + // parentNameComboBox + // + this.parentNameComboBox.Enabled = false; + this.parentNameComboBox.FormattingEnabled = true; + this.parentNameComboBox.Location = new System.Drawing.Point(140, 87); + this.parentNameComboBox.Name = "parentNameComboBox"; + this.parentNameComboBox.Size = new System.Drawing.Size(130, 21); + this.parentNameComboBox.TabIndex = 4; + // + // FlowMeterCfgCtrl + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.parentNameComboBox); + this.Controls.Add(this.nominalFlowTextBox); + this.Controls.Add(this.nominalFlowLabel); + this.Controls.Add(this.positionTextBox); + this.Controls.Add(this.positionLabel); + this.Controls.Add(this.parentNameLabel); + this.Controls.Add(this.nameTextBox); + this.Controls.Add(this.nameLabel); + this.Controls.Add(this.classNameLabel); + this.Name = "FlowMeterCfgCtrl"; + this.Size = new System.Drawing.Size(300, 200); + this.Load += new System.EventHandler(this.FlowMeterCfgCtrl_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TextBox positionTextBox; + private System.Windows.Forms.Label positionLabel; + private System.Windows.Forms.Label parentNameLabel; + private System.Windows.Forms.TextBox nameTextBox; + private System.Windows.Forms.Label nameLabel; + private System.Windows.Forms.Label classNameLabel; + private System.Windows.Forms.TextBox nominalFlowTextBox; + private System.Windows.Forms.Label nominalFlowLabel; + private System.Windows.Forms.ComboBox parentNameComboBox; + } +} diff --git a/TestBenchFramework/BenchControl/Elde/FlowMeter/FlowMeterCfgCtrl.cs b/TestBenchFramework/BenchControl/Elde/FlowMeter/FlowMeterCfgCtrl.cs new file mode 100644 index 000000000..c45142bc3 --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/FlowMeter/FlowMeterCfgCtrl.cs @@ -0,0 +1,102 @@ +using System; +using System.Globalization; +using System.Windows.Forms; +using log4net; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.Elde.FlowMeter +{ + public partial class FlowMeterCfgCtrl : UserControl, IComponentCfgCtrl + { + static readonly ILog log = LogManager.GetLogger(typeof(FlowMeterCfgCtrl)); + + ComponentParametersDlg parent; + FlowMeterCfg config; + public IComponentCfg Config + { + get { return config as IComponentCfg; } + set + { + config = value as FlowMeterCfg; + Redraw(); + } + } + + public FlowMeterCfgCtrl() + { + InitializeComponent(); + } + + private void FlowMeterCfgCtrl_Load(object sender, EventArgs e) + { + parent = ParentForm as ComponentParametersDlg; + if (parent == null) return; + + if (parent.TbfComponents != null) + { + foreach (var cmpnt in parent.TbfComponents) + { + if (TbfComponents.CmpntFactoryFromClassName(cmpnt.ClassName) is Elde.ControlBoardFactory) + { + parentNameComboBox.Items.Add(cmpnt.Name); + } + } + } + + Redraw(); + } + + void Redraw() + { + if (config == null) return; /// Control was not loaded, settings were not changed + + classNameLabel.Text = config.Factory.ClassName; + nameTextBox.Text = config.Name; + parentNameComboBox.Text = string.IsNullOrEmpty(config.ParentName) ? "---" : config.ParentName; + positionTextBox.Text = config.Position.ToString(); + nominalFlowTextBox.Text = config.NominalFlow.ToString(); + } + + public void Unlock() + { + nameTextBox.Enabled = true; + parentNameComboBox.Enabled = true; + positionTextBox.Enabled = true; + nominalFlowTextBox.Enabled = true; + } + + public CfgVerifyFlags VerifyCfg(ref string message) + { + CfgVerifyFlags flags = CfgVerifyFlags.None; + + int dummy; + if (!parentNameComboBox.Items.Contains(parentNameComboBox.Text)) + { + flags |= CfgVerifyFlags.Error; + message += Environment.NewLine + "Invalid 'Parent Name'"; + } + if (!int.TryParse(positionTextBox.Text, out dummy) || dummy < 1 || dummy > 5) + { + flags |= CfgVerifyFlags.Error; + message += Environment.NewLine + "'Position' should be between 1 and 5"; + } + float fdummy; + if (!Utils.TryParseUFloat(nominalFlowTextBox.Text, out fdummy) || fdummy < 0.2 || fdummy > 1000) + { + flags |= CfgVerifyFlags.Error; + message += Environment.NewLine + "'Nominal flow' should be between 0.2 and 1000"; + } + return flags; + } + + public void UpdateCfg() + { + if (config == null) return; /// Control was not loaded, settings were not changed + + config.Name = nameTextBox.Text; + config.ParentName = parentNameComboBox.Text.Equals("---") ? string.Empty : parentNameComboBox.Text; + config.Position = int.Parse(positionTextBox.Text); + Utils.TryParseUFloat(nominalFlowTextBox.Text, out config.NominalFlow); + } + } +} diff --git a/TestBenchFramework/BenchControl/Elde/FlowMeter/FlowMeterCfgCtrl.resx b/TestBenchFramework/BenchControl/Elde/FlowMeter/FlowMeterCfgCtrl.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/FlowMeter/FlowMeterCfgCtrl.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/BenchControl/Elde/FlowMeter/FlowMeterFactory.cs b/TestBenchFramework/BenchControl/Elde/FlowMeter/FlowMeterFactory.cs new file mode 100644 index 000000000..33b572de7 --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/FlowMeter/FlowMeterFactory.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.Elde.FlowMeter +{ + public class FlowMeterFactory : IComponentFactory + { + public string ClassName { get { return "FlowMeter"; } } + public bool HasProcedureParams { get { return false; } } + public bool HasTestParams { get { return false; } } + public IParamsProvider GetTestParams(Entities.ComponentTest testParams) { return null; } + public IParamsProvider GetProcedureParams(Entities.ComponentProcedure procedureParams) { return null; } + + /// Max. number of components of this class in the system + public int MaxCount { get { return 5; } } + + + public IComponentCfg DefaultConfig(IList components) + { + return new FlowMeterCfg(this, "FlowMeter", "CB", 1, 1); + } + + public IComponentCfgCtrl CreateCfgCtrl() + { + return new FlowMeterCfgCtrl(); + } + + public IComponent ComponentFromCmpntCfg(IComponentCfg config, IList components) + { + return new FlowMeter((FlowMeterCfg)config, components); + } + + public IComponentCfg CmpntCfgFromCmpntEntity(Entities.Component component) + { + return FlowMeterCfg.CreateFromDbEntity(component, this); + } + + public void ResetStaticProperties() { FlowMeter.ResetStaticProperties(); } + } +} diff --git a/TestBenchFramework/BenchControl/Elde/FlowMeter/ReadFlowOp.cs b/TestBenchFramework/BenchControl/Elde/FlowMeter/ReadFlowOp.cs new file mode 100644 index 000000000..297e46277 --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/FlowMeter/ReadFlowOp.cs @@ -0,0 +1,65 @@ +using System; +using log4net; + +namespace TBF.BenchControl.Elde.FlowMeter +{ + public class ReadFlowOp : IOperation + { + private static readonly ILog log = LogManager.GetLogger(typeof(ReadFlowOp)); + public override string ToString() { return string.Format("ReadFlowOp(.,{0},{1},.)", eventDone, flowMeterNr); } + + /// Set by the constructor + readonly ControlBoardDev controlBoard; + readonly int flowMeterNr; + readonly Event eventDone; + FloatBox flow; + + /// + /// Events: FlowInDone, FlowOutDone or Error + /// + /// Flow meter reference + /// Reference to the measured flow variable, value is in bar + /// Event to be returned by Run() when completed OK + public ReadFlowOp(FlowMeter flowMeter, ref FloatBox flow, Event eventDone) + { + if (flowMeter == null) throw new ArgumentNullException("flowMeter"); + this.controlBoard = flowMeter.ControlBoard; + this.flowMeterNr = flowMeter.Position; + this.eventDone = eventDone; + this.flow = flow; + + log.Debug(this.ToString()); + } + public ReadFlowOp(FlowMeter flowMeter, ref FloatBox flow) + : this(flowMeter, ref flow, Event.FlowMeasurementDone) + { + } + + /// Start this operation + public void Start() + { + } + + /// Run this operation + /// + /// Event.FlowInDone or Event.FlowOutDone + /// + public Event Run() + { + if (flowMeterNr == (int)(controlBoard.StatusP & StatusP.RefFlowMeterMask)) + { + flow.F = controlBoard.ReferenceFlow; + return eventDone; + } + else + { + return Event.Error; + } + } + + /// Stop this operation + public void Stop() + { + } + } +} diff --git a/TestBenchFramework/BenchControl/Elde/IControlCom.cs b/TestBenchFramework/BenchControl/Elde/IControlCom.cs new file mode 100644 index 000000000..5615ef8e9 --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/IControlCom.cs @@ -0,0 +1,69 @@ + +namespace TBF.BenchControl.Elde +{ + interface IControlCom + { + StatusP StatusP { get; } + float ReferenceFreq { get; } + int EtPulses(int wmNr0); + int WMeterPulses(int wmNr0); + int WMeterReference(int wmNr0); + uint RegulValveDAC { get; } + float Pressure(int prsNr0); + float Temperature(int tmpNr0); + RegulValveState RegulValveState(int rvNr1); + ulong RRoute { get; } + uint DivTime { get; } + float TTime { get; } + uint FmState { get; } + uint BeginState(int wmNr0); + float ReferenceFlow { get; } + float RValvePosition(int rvNr1); + float DivSamples(int ms); + int ScopeSamples(int i, int j, int k); + uint DigitalInputs { get; } + float AnalogInput(int adcNr0); + uint AnalogInputRaw(int adcNr0, int bank); + float ReferenceVolume { get; } + float VyslExt(int wmNr0, int what); + void SetWeight(int pos, float mass); + + /// + /// Sends calibration and configuration data to the control board. + /// + /// Regulating valves calib.coefs, ix1 = valve nr. (1..5), ix2 = coef.nr. (0..1), values typ. c0 = 0, c1 = 0.2 + /// Meret address, index = 0..1, value typ. 99 and 100 + /// COM port number of the control board (typ. 1) + /// Temp.calc.coefs, ix1 = temp.sens.nr. (0..7 ???), ix2 = coef.nr + /// Etalon nominal values + /// Percentages for switching of diverters, ix = diverter nr.(0,1), typ.value 50 (%) + void SendCalibData(uint[,] rvCalib, byte[] meretA, int usedCom, float[,] tempCalib, float[] etCalib, uint[] divEdge, uint[] balanceRange); + + /// + /// Updates a command that is regularly sent to the control board by SendCommand. + /// + /// See ControlBoard.Command enum + /// Number of the etalon/reference (1..5) + /// Route: 64-bit installation specific number + /// kolko impulzov ma trvat skuska + /// See ControlBoard.TestMethods enum + /// 0 = No filtering (0..255) + /// Freq.inverter control (not applicable in DT100, Munich) + /// Coefficient used to control reg. valves (1..100) + /// 0 = default value, 1 = spec. processing of very short pulses + /// What to stop + void SendCommand(Command cmd, int refNr, ulong route, int refPulses, TestMethods testMethods, + float filterConstant, float[] fmFreq, int regConst, int shortImp, StopDevs stopDevs); + + /// + /// Control of regulating valves. + /// + /// Regulating valve nr. (1..5) + /// ??? + /// ??? + void ValveMove(int valveNo, RegulValveMode valveMode, float[] valveValue); + + void RunDeviceBefore(); + void RunDeviceAfter(); + } +} diff --git a/TestBenchFramework/BenchControl/Elde/PressureMeter/PressureMeter.cs b/TestBenchFramework/BenchControl/Elde/PressureMeter/PressureMeter.cs new file mode 100644 index 000000000..d0dffc877 --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/PressureMeter/PressureMeter.cs @@ -0,0 +1,71 @@ +using System; +using System.Collections.Generic; +using log4net; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.Elde.PressureMeter +{ + public class PressureMeter : IComponent, GenericDevices.IPressureMeter + { + /// + /// Info: StartMassMeasurement() and "Balance response = .., Mass = ..." + /// Warn: Start measurement when busy is true + /// + private static readonly ILog log = LogManager.GetLogger(typeof(PressureMeter)); + public override string ToString() + { + return string.Format("PressureMeter({0},{1})", Name, Index); + } + + public static void ResetStaticProperties() { } + + readonly PressureMeterCfg pressureMeterCfg; + public Generic.IComponentCfg Cfg { get { return pressureMeterCfg; } } + + public string Name { get { return pressureMeterCfg.Name; } } + public IList Corrections { get { return pressureMeterCfg.Corrections; } } + + public readonly ControlBoardDev ControlBoard; + + public readonly int Index; /// 0..3 + public readonly byte RS485Address; /// 0..255 + + public PressureMeter(PressureMeterCfg cfg, IList components) + { + if (cfg == null) throw new ArgumentNullException("cfg"); + this.pressureMeterCfg = cfg; + + ControlBoard = (ControlBoardDev)TbfComponents.FindComponent(cfg.ParentName, components); + if (ControlBoard == null) throw new Exception("Cannot find " + Name + " parent"); + + Index = cfg.Position; + RS485Address = cfg.RS485Address; + + /// Prepare data for SendCalibData() control board component method + ControlBoard.MeretRS485Address[Index] = RS485Address; + + log.Debug(this.ToString()); + } + + /// + /// Events: PressureDone, Error + /// + /// Reference to a variable for the pressure in Bar + /// ReadPressureOp instance reference casted to IOperaton + public IOperation ReadPressureOp(ref FloatBox pressure) + { + return new ReadPressureOp(this, ref pressure); + } + + /// + /// Events: pressureDone, Error + /// + /// Reference to a variable for the pressure in Bar + /// Event returned when measurement done + /// ReadPressureOp instance reference casted to IOperaton + public IOperation ReadPressureOp(ref FloatBox pressure, Event pressureDone) + { + return new ReadPressureOp(this, ref pressure, pressureDone); + } + } +} diff --git a/TestBenchFramework/BenchControl/Elde/PressureMeter/PressureMeterCfg.cs b/TestBenchFramework/BenchControl/Elde/PressureMeter/PressureMeterCfg.cs new file mode 100644 index 000000000..61ee4e6ea --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/PressureMeter/PressureMeterCfg.cs @@ -0,0 +1,63 @@ +using System; +using System.IO; +using System.Xml.Serialization; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.Elde.PressureMeter +{ + public class PressureMeterCfg : ComponentCfgBase, Generic.IChildComponentCfg + { + public int Position; /// 0..7 + public byte RS485Address; /// 0..255 + + /// Parameterless constructor + public PressureMeterCfg() + { + } + /// + /// Regulation valve configuration parameters + /// + /// Regulation valve name + /// Position on the control board 1..5 + /// 0..1023 + /// 0..1023 + public PressureMeterCfg(IComponentFactory factory, string name, string parentName, int index, byte rs485Address) + : base(factory, name, parentName) + { + if (index < 0 || index > 7) throw new ArgumentOutOfRangeException("Position"); + this.Position = index; + + if (rs485Address < 0 || rs485Address > 255) throw new ArgumentOutOfRangeException("RS485Address"); + this.RS485Address = rs485Address; + } + + public IComponentCfg Clone() + { + return new PressureMeterCfg(Factory, Name, ParentName, Position, RS485Address); + } + + public string ToString(int i) + { + return string.Format("index={0}, RS485 address={1}", Position, RS485Address); + } + + public TBF.Entities.Component CreateDbEntity() + { + using (var writer = new StringWriter()) + { + (new XmlSerializer(GetType())).Serialize(writer, this); + return Entities.Component.CreateFromCfg(Name, Factory.ClassName, ParentName, ItemNr, DebugLevel, LogLevel, writer.ToString()); + } + } + + public static IComponentCfg CreateFromDbEntity(Entities.Component component, IComponentFactory factory) + { + using (var reader = new StringReader(component.Parameters)) + { + PressureMeterCfg config = (PressureMeterCfg)(new XmlSerializer(typeof(PressureMeterCfg))).Deserialize(reader); + config.InitCfgBaseFromEntity(component, factory); + return config; + } + } + } +} diff --git a/TestBenchFramework/BenchControl/Elde/PressureMeter/PressureMeterCfgCtrl.Designer.cs b/TestBenchFramework/BenchControl/Elde/PressureMeter/PressureMeterCfgCtrl.Designer.cs new file mode 100644 index 000000000..f96f3df12 --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/PressureMeter/PressureMeterCfgCtrl.Designer.cs @@ -0,0 +1,153 @@ +namespace TBF.BenchControl.Elde.PressureMeter +{ + partial class PressureMeterCfgCtrl + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.positionTextBox = new System.Windows.Forms.TextBox(); + this.positionLabel = new System.Windows.Forms.Label(); + this.parentNameLabel = new System.Windows.Forms.Label(); + this.nameTextBox = new System.Windows.Forms.TextBox(); + this.nameLabel = new System.Windows.Forms.Label(); + this.componentNameLabel = new System.Windows.Forms.Label(); + this.rs485AddressLabel = new System.Windows.Forms.Label(); + this.rs485AddressTextBox = new System.Windows.Forms.TextBox(); + this.parentNameComboBox = new System.Windows.Forms.ComboBox(); + this.SuspendLayout(); + // + // positionTextBox + // + this.positionTextBox.Enabled = false; + this.positionTextBox.Location = new System.Drawing.Point(138, 104); + this.positionTextBox.Name = "positionTextBox"; + this.positionTextBox.Size = new System.Drawing.Size(46, 20); + this.positionTextBox.TabIndex = 6; + // + // positionLabel + // + this.positionLabel.AutoSize = true; + this.positionLabel.Location = new System.Drawing.Point(28, 107); + this.positionLabel.Name = "positionLabel"; + this.positionLabel.Size = new System.Drawing.Size(44, 13); + this.positionLabel.TabIndex = 5; + this.positionLabel.Text = "Position"; + // + // parentNameLabel + // + this.parentNameLabel.AutoSize = true; + this.parentNameLabel.Location = new System.Drawing.Point(28, 81); + this.parentNameLabel.Name = "parentNameLabel"; + this.parentNameLabel.Size = new System.Drawing.Size(69, 13); + this.parentNameLabel.TabIndex = 3; + this.parentNameLabel.Text = "Parent Name"; + // + // nameTextBox + // + this.nameTextBox.Enabled = false; + this.nameTextBox.Location = new System.Drawing.Point(138, 52); + this.nameTextBox.Name = "nameTextBox"; + this.nameTextBox.Size = new System.Drawing.Size(130, 20); + this.nameTextBox.TabIndex = 2; + // + // nameLabel + // + this.nameLabel.AutoSize = true; + this.nameLabel.Location = new System.Drawing.Point(28, 55); + this.nameLabel.Name = "nameLabel"; + this.nameLabel.Size = new System.Drawing.Size(35, 13); + this.nameLabel.TabIndex = 1; + this.nameLabel.Text = "Name"; + // + // componentNameLabel + // + this.componentNameLabel.AutoSize = true; + this.componentNameLabel.Location = new System.Drawing.Point(135, 28); + this.componentNameLabel.Name = "componentNameLabel"; + this.componentNameLabel.Size = new System.Drawing.Size(83, 13); + this.componentNameLabel.TabIndex = 0; + this.componentNameLabel.Text = "ComonentName"; + // + // rs485AddressLabel + // + this.rs485AddressLabel.AutoSize = true; + this.rs485AddressLabel.Location = new System.Drawing.Point(28, 133); + this.rs485AddressLabel.Name = "rs485AddressLabel"; + this.rs485AddressLabel.Size = new System.Drawing.Size(81, 13); + this.rs485AddressLabel.TabIndex = 7; + this.rs485AddressLabel.Text = "RS485 Address"; + // + // rs485AddressTextBox + // + this.rs485AddressTextBox.Enabled = false; + this.rs485AddressTextBox.Location = new System.Drawing.Point(138, 130); + this.rs485AddressTextBox.Name = "rs485AddressTextBox"; + this.rs485AddressTextBox.Size = new System.Drawing.Size(46, 20); + this.rs485AddressTextBox.TabIndex = 8; + // + // parentNameComboBox + // + this.parentNameComboBox.Enabled = false; + this.parentNameComboBox.FormattingEnabled = true; + this.parentNameComboBox.Location = new System.Drawing.Point(138, 78); + this.parentNameComboBox.Name = "parentNameComboBox"; + this.parentNameComboBox.Size = new System.Drawing.Size(130, 21); + this.parentNameComboBox.TabIndex = 4; + // + // PressureMeterCfgCtrl + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.parentNameComboBox); + this.Controls.Add(this.rs485AddressTextBox); + this.Controls.Add(this.rs485AddressLabel); + this.Controls.Add(this.positionTextBox); + this.Controls.Add(this.positionLabel); + this.Controls.Add(this.parentNameLabel); + this.Controls.Add(this.nameTextBox); + this.Controls.Add(this.nameLabel); + this.Controls.Add(this.componentNameLabel); + this.Name = "PressureMeterCfgCtrl"; + this.Size = new System.Drawing.Size(300, 200); + this.Load += new System.EventHandler(this.PressureMeterCfgCtrl_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TextBox positionTextBox; + private System.Windows.Forms.Label positionLabel; + private System.Windows.Forms.Label parentNameLabel; + private System.Windows.Forms.TextBox nameTextBox; + private System.Windows.Forms.Label nameLabel; + private System.Windows.Forms.Label componentNameLabel; + private System.Windows.Forms.Label rs485AddressLabel; + private System.Windows.Forms.TextBox rs485AddressTextBox; + private System.Windows.Forms.ComboBox parentNameComboBox; + } +} diff --git a/TestBenchFramework/BenchControl/Elde/PressureMeter/PressureMeterCfgCtrl.cs b/TestBenchFramework/BenchControl/Elde/PressureMeter/PressureMeterCfgCtrl.cs new file mode 100644 index 000000000..0bf078eee --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/PressureMeter/PressureMeterCfgCtrl.cs @@ -0,0 +1,100 @@ +using System; +using System.Windows.Forms; +using log4net; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.Elde.PressureMeter +{ + public partial class PressureMeterCfgCtrl : UserControl, IComponentCfgCtrl + { + static readonly ILog log = LogManager.GetLogger(typeof(PressureMeterCfgCtrl)); + + ComponentParametersDlg parent; + PressureMeterCfg config; + public IComponentCfg Config + { + get { return config as IComponentCfg; } + set + { + config = value as PressureMeterCfg; + Redraw(); + } + } + + public PressureMeterCfgCtrl() + { + InitializeComponent(); + } + + private void PressureMeterCfgCtrl_Load(object sender, EventArgs e) + { + parent = ParentForm as ComponentParametersDlg; + if (parent == null) return; + + if (parent.TbfComponents != null) + { + foreach (var cmpnt in parent.TbfComponents) + { + if (TbfComponents.CmpntFactoryFromClassName(cmpnt.ClassName) is Elde.ControlBoardFactory) + { + parentNameComboBox.Items.Add(cmpnt.Name); + } + } + } + + Redraw(); + } + + void Redraw() + { + if (config == null) return; /// Control was not loaded, settings were not changed + + componentNameLabel.Text = config.Factory.ClassName; + nameTextBox.Text = config.Name; + parentNameComboBox.Text = string.IsNullOrEmpty(config.ParentName) ? "---" : config.ParentName; + positionTextBox.Text = config.Position.ToString(); + rs485AddressTextBox.Text = config.RS485Address.ToString(); + } + + public void Unlock() + { + nameTextBox.Enabled = true; + parentNameComboBox.Enabled = true; + positionTextBox.Enabled = true; + rs485AddressTextBox.Enabled = true; + } + + public CfgVerifyFlags VerifyCfg(ref string message) + { + CfgVerifyFlags flags = CfgVerifyFlags.None; + + int dummy; + if (!parentNameComboBox.Items.Contains(parentNameComboBox.Text)) + { + flags |= CfgVerifyFlags.Error; + message += Environment.NewLine + "Invalid 'Parent Name'"; + } + if (!int.TryParse(positionTextBox.Text, out dummy) || dummy < 0 || dummy > 7) + { + flags |= CfgVerifyFlags.Error; + message += Environment.NewLine + "'Position' should be between 0 and 7"; + } + if (!int.TryParse(rs485AddressTextBox.Text, out dummy) || dummy < 0 || dummy > 255) + { + flags |= CfgVerifyFlags.Error; + message += Environment.NewLine + "'RS485 Address' should be between 0 and 255"; + } + return flags; + } + + public void UpdateCfg() + { + if (config == null) return; /// Control was not loaded, settings were not changed + + config.Name = nameTextBox.Text; + config.ParentName = parentNameComboBox.Text.Equals("---") ? string.Empty : parentNameComboBox.Text; + config.Position = int.Parse(positionTextBox.Text); + config.RS485Address = (byte)int.Parse(rs485AddressTextBox.Text); + } + } +} diff --git a/TestBenchFramework/BenchControl/Elde/PressureMeter/PressureMeterCfgCtrl.resx b/TestBenchFramework/BenchControl/Elde/PressureMeter/PressureMeterCfgCtrl.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/PressureMeter/PressureMeterCfgCtrl.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/BenchControl/Elde/PressureMeter/PressureMeterFactory.cs b/TestBenchFramework/BenchControl/Elde/PressureMeter/PressureMeterFactory.cs new file mode 100644 index 000000000..6745a3ce5 --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/PressureMeter/PressureMeterFactory.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.Elde.PressureMeter +{ + public class PressureMeterFactory : IComponentFactory + { + public string ClassName { get { return "PressureMeter"; } } + public bool HasProcedureParams { get { return false; } } + public bool HasTestParams { get { return false; } } + public IParamsProvider GetTestParams(Entities.ComponentTest testParams) { return null; } + public IParamsProvider GetProcedureParams(Entities.ComponentProcedure procedureParams) { return null; } + + /// Max. number of components of this class in the system + public int MaxCount { get { return 5; } } + + public IComponentCfg DefaultConfig(IList components) + { + return new PressureMeterCfg(this, "PressureMeter", "CB", 1, 99); + } + + public IComponentCfgCtrl CreateCfgCtrl() + { + return new PressureMeterCfgCtrl(); + } + + public IComponent ComponentFromCmpntCfg(IComponentCfg config, IList components) + { + return new PressureMeter((PressureMeterCfg)config, components); + } + + public IComponentCfg CmpntCfgFromCmpntEntity(Entities.Component component) + { + return PressureMeterCfg.CreateFromDbEntity(component, this); + } + + public void ResetStaticProperties() { PressureMeter.ResetStaticProperties(); } + } +} diff --git a/TestBenchFramework/BenchControl/Elde/PressureMeter/ReadPressureOp.cs b/TestBenchFramework/BenchControl/Elde/PressureMeter/ReadPressureOp.cs new file mode 100644 index 000000000..5213a1f01 --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/PressureMeter/ReadPressureOp.cs @@ -0,0 +1,58 @@ +using System; +using log4net; + +namespace TBF.BenchControl.Elde.PressureMeter +{ + public class ReadPressureOp : IOperation + { + private static readonly ILog log = LogManager.GetLogger(typeof(ReadPressureOp)); + public override string ToString() { return string.Format("ReadPressureOp(.,{0},{1},.)", eventDone, pressureMeterNr); } + + /// Set by the constructor + readonly ControlBoardDev controlBoardDev; + readonly int pressureMeterNr; + readonly Event eventDone; + FloatBox pressure; + + /// + /// Events: PressureInDone, PressureOutDone or Error + /// + /// Pressure meter reference + /// Reference to the measured pressure variable, value is in bar + /// Event to be returned by Run() when completed OK + public ReadPressureOp(PressureMeter pressureMeter, ref FloatBox pressure, Event eventDone) + { + if (pressureMeter == null) throw new ArgumentNullException("pressureMeter"); + this.controlBoardDev = pressureMeter.ControlBoard; + this.pressureMeterNr = pressureMeter.Index; + this.eventDone = eventDone; + this.pressure = pressure; + + log.Debug(this.ToString()); + } + public ReadPressureOp(PressureMeter pressureMeter, ref FloatBox pressure) + : this(pressureMeter, ref pressure, Event.PressureDone) + { + } + + /// Start this operation + public void Start() + { + } + + /// Run this operation + /// + /// Event.PressureInDone or Event.PressureOutDone + /// + public Event Run() + { + pressure.F = controlBoardDev.Pressure(pressureMeterNr); + return eventDone; + } + + /// Stop this operation + public void Stop() + { + } + } +} diff --git a/TestBenchFramework/BenchControl/Elde/Pump/Pump.cs b/TestBenchFramework/BenchControl/Elde/Pump/Pump.cs new file mode 100644 index 000000000..87f8caa32 --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/Pump/Pump.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; +using log4net; + +namespace TBF.BenchControl.Elde.Pump +{ + public class Pump : Generic.IComponent, GenericDevices.IPump, GenericDevices.IValve + { + /// + /// Info: StartMassMeasurement() and "Balance response = .., Mass = ..." + /// Warn: Start measurement when busy is true + /// + private static readonly ILog log = LogManager.GetLogger(typeof(Pump)); + public override string ToString() + { + return string.Format("Pump(name={0}, bit={1})", Name, bitPosition); + } + + public static void ResetStaticProperties() { } + + private readonly PumpCfg pumpCfg; + public Generic.IComponentCfg Cfg { get { return pumpCfg; } } + + public string Name { get { return pumpCfg.Name; } } + + public GenericDevices.IValve CoupledTo { get { return null; } } + public bool Invert { get { return false; } } + public int LagOpening { get { return 0; } } + public int LagClosing { get { return 0; } } + + readonly ControlBoardDev controlBoard; + readonly int bitPosition; /// 0 .. 63 + + public readonly ulong Mask; /// derived from bitPosition in the constructor + + + public Pump(PumpCfg cfg, IList components) + { + if (cfg == null) throw new ArgumentNullException("cfg"); + this.pumpCfg = cfg; + + controlBoard = (ControlBoardDev)TbfComponents.FindComponent(cfg.ParentName, components); + if (controlBoard == null) throw new Exception("Cannot find " + Name + " parent"); + + this.bitPosition = cfg.BitPosition; + this.Mask = (((ulong)1) << bitPosition); + + log.Debug(this.ToString()); + } + + public bool State + { + get { return (controlBoard.Route & Mask) != 0; } + } + } +} diff --git a/TestBenchFramework/BenchControl/Elde/Pump/PumpCfg.cs b/TestBenchFramework/BenchControl/Elde/Pump/PumpCfg.cs new file mode 100644 index 000000000..6e3d95714 --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/Pump/PumpCfg.cs @@ -0,0 +1,52 @@ +using System.IO; +using System.Xml.Serialization; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.Elde.Pump +{ + public class PumpCfg : ComponentCfgBase, IChildComponentCfg + { + public int BitPosition; + + /// Parameterless constructor + public PumpCfg() + { + } + + /// Constructor + public PumpCfg(IComponentFactory factory, string name, string parentName, int bitPosition) + : base(factory, name, parentName) + { + this.BitPosition = bitPosition; + } + + public IComponentCfg Clone() + { + return new PumpCfg(Factory, Name, ParentName, BitPosition); + } + + public string ToString(int i) + { + return string.Format("bit={0}", BitPosition); + } + + public TBF.Entities.Component CreateDbEntity() + { + using (var writer = new StringWriter()) + { + (new XmlSerializer(GetType())).Serialize(writer, this); + return Entities.Component.CreateFromCfg(Name, Factory.ClassName, ParentName, ItemNr, DebugLevel, LogLevel, writer.ToString()); + } + } + + public static IComponentCfg CreateFromDbEntity(Entities.Component component, IComponentFactory factory) + { + using (var reader = new StringReader(component.Parameters)) + { + PumpCfg config = (PumpCfg)(new XmlSerializer(typeof(PumpCfg))).Deserialize(reader); + config.InitCfgBaseFromEntity(component, factory); + return config; + } + } + } +} diff --git a/TestBenchFramework/BenchControl/Elde/Pump/PumpCfgCtrl.Designer.cs b/TestBenchFramework/BenchControl/Elde/Pump/PumpCfgCtrl.Designer.cs new file mode 100644 index 000000000..1a21a54de --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/Pump/PumpCfgCtrl.Designer.cs @@ -0,0 +1,130 @@ +namespace TBF.BenchControl.Elde.Pump +{ + partial class PumpCfgCtrl + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.bitPositionTextBox = new System.Windows.Forms.TextBox(); + this.bitPositionLabel = new System.Windows.Forms.Label(); + this.parentNameLabel = new System.Windows.Forms.Label(); + this.nameTextBox = new System.Windows.Forms.TextBox(); + this.nameLabel = new System.Windows.Forms.Label(); + this.classNameLabel = new System.Windows.Forms.Label(); + this.parentNameComboBox = new System.Windows.Forms.ComboBox(); + this.SuspendLayout(); + // + // bitPositionTextBox + // + this.bitPositionTextBox.Enabled = false; + this.bitPositionTextBox.Location = new System.Drawing.Point(122, 99); + this.bitPositionTextBox.Name = "bitPositionTextBox"; + this.bitPositionTextBox.Size = new System.Drawing.Size(46, 20); + this.bitPositionTextBox.TabIndex = 6; + // + // bitPositionLabel + // + this.bitPositionLabel.AutoSize = true; + this.bitPositionLabel.Location = new System.Drawing.Point(36, 102); + this.bitPositionLabel.Name = "bitPositionLabel"; + this.bitPositionLabel.Size = new System.Drawing.Size(59, 13); + this.bitPositionLabel.TabIndex = 5; + this.bitPositionLabel.Text = "Bit Position"; + // + // parentNameLabel + // + this.parentNameLabel.AutoSize = true; + this.parentNameLabel.Location = new System.Drawing.Point(36, 76); + this.parentNameLabel.Name = "parentNameLabel"; + this.parentNameLabel.Size = new System.Drawing.Size(69, 13); + this.parentNameLabel.TabIndex = 3; + this.parentNameLabel.Text = "Parent Name"; + // + // nameTextBox + // + this.nameTextBox.Enabled = false; + this.nameTextBox.Location = new System.Drawing.Point(122, 47); + this.nameTextBox.Name = "nameTextBox"; + this.nameTextBox.Size = new System.Drawing.Size(130, 20); + this.nameTextBox.TabIndex = 2; + // + // nameLabel + // + this.nameLabel.AutoSize = true; + this.nameLabel.Location = new System.Drawing.Point(36, 50); + this.nameLabel.Name = "nameLabel"; + this.nameLabel.Size = new System.Drawing.Size(35, 13); + this.nameLabel.TabIndex = 1; + this.nameLabel.Text = "Name"; + // + // classNameLabel + // + this.classNameLabel.AutoSize = true; + this.classNameLabel.Location = new System.Drawing.Point(119, 21); + this.classNameLabel.Name = "classNameLabel"; + this.classNameLabel.Size = new System.Drawing.Size(83, 13); + this.classNameLabel.TabIndex = 0; + this.classNameLabel.Text = "ComonentName"; + // + // parentNameComboBox + // + this.parentNameComboBox.Enabled = false; + this.parentNameComboBox.FormattingEnabled = true; + this.parentNameComboBox.Location = new System.Drawing.Point(122, 73); + this.parentNameComboBox.Name = "parentNameComboBox"; + this.parentNameComboBox.Size = new System.Drawing.Size(130, 21); + this.parentNameComboBox.TabIndex = 4; + // + // PumpCfgCtrl + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.parentNameComboBox); + this.Controls.Add(this.bitPositionTextBox); + this.Controls.Add(this.bitPositionLabel); + this.Controls.Add(this.parentNameLabel); + this.Controls.Add(this.nameTextBox); + this.Controls.Add(this.nameLabel); + this.Controls.Add(this.classNameLabel); + this.Name = "PumpCfgCtrl"; + this.Size = new System.Drawing.Size(300, 200); + this.Load += new System.EventHandler(this.PumpCfgCtrl_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TextBox bitPositionTextBox; + private System.Windows.Forms.Label bitPositionLabel; + private System.Windows.Forms.Label parentNameLabel; + private System.Windows.Forms.TextBox nameTextBox; + private System.Windows.Forms.Label nameLabel; + private System.Windows.Forms.Label classNameLabel; + private System.Windows.Forms.ComboBox parentNameComboBox; + } +} diff --git a/TestBenchFramework/BenchControl/Elde/Pump/PumpCfgCtrl.cs b/TestBenchFramework/BenchControl/Elde/Pump/PumpCfgCtrl.cs new file mode 100644 index 000000000..b5b868e93 --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/Pump/PumpCfgCtrl.cs @@ -0,0 +1,92 @@ +using System; +using System.Windows.Forms; +using log4net; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.Elde.Pump +{ + public partial class PumpCfgCtrl : UserControl, IComponentCfgCtrl + { + static readonly ILog log = LogManager.GetLogger(typeof(PumpCfgCtrl)); + + ComponentParametersDlg parent; + PumpCfg config; + public IComponentCfg Config + { + get { return config as IComponentCfg; } + set + { + config = value as PumpCfg; + Redraw(); + } + } + + public PumpCfgCtrl() + { + InitializeComponent(); + } + + private void PumpCfgCtrl_Load(object sender, EventArgs e) + { + parent = ParentForm as ComponentParametersDlg; + if (parent == null) return; + + if (parent.TbfComponents != null) + { + foreach (var cmpnt in parent.TbfComponents) + { + if (TbfComponents.CmpntFactoryFromClassName(cmpnt.ClassName) is Elde.ControlBoardFactory) + { + parentNameComboBox.Items.Add(cmpnt.Name); + } + } + } + + Redraw(); + } + + void Redraw() + { + if (config == null) return; /// Control was not loaded, settings were not changed + + classNameLabel.Text = config.Factory.ClassName; + nameTextBox.Text = config.Name; + parentNameComboBox.Text = string.IsNullOrEmpty(config.ParentName) ? "---" : config.ParentName; + bitPositionTextBox.Text = config.BitPosition.ToString(); + } + + public void Unlock() + { + nameTextBox.Enabled = true; + parentNameComboBox.Enabled = true; + bitPositionTextBox.Enabled = true; + } + + public void UpdateCfg() + { + if (config == null) return; /// Control was not loaded, settings were not changed + + config.Name = nameTextBox.Text; + config.ParentName = parentNameComboBox.Text.Equals("---") ? string.Empty : parentNameComboBox.Text; + config.BitPosition = int.Parse(bitPositionTextBox.Text); + } + + public CfgVerifyFlags VerifyCfg(ref string message) + { + CfgVerifyFlags flags = CfgVerifyFlags.None; + + int dummy; + if (!parentNameComboBox.Items.Contains(parentNameComboBox.Text)) + { + flags |= CfgVerifyFlags.Error; + message += Environment.NewLine + "Invalid 'Parent Name'"; + } + if (!int.TryParse(bitPositionTextBox.Text, out dummy) || dummy < 0 || dummy >= 64) + { + flags |= CfgVerifyFlags.Error; + message += Environment.NewLine + "'Bit Position' should be between 0 and 63"; + } + return flags; + } + } +} diff --git a/TestBenchFramework/BenchControl/Elde/Pump/PumpCfgCtrl.resx b/TestBenchFramework/BenchControl/Elde/Pump/PumpCfgCtrl.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/Pump/PumpCfgCtrl.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/BenchControl/Elde/Pump/PumpFactory.cs b/TestBenchFramework/BenchControl/Elde/Pump/PumpFactory.cs new file mode 100644 index 000000000..e5e92bd55 --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/Pump/PumpFactory.cs @@ -0,0 +1,39 @@ +using System.Collections.Generic; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.Elde.Pump +{ + public class PumpFactory : IComponentFactory + { + public string ClassName { get { return "Pump"; } } + public bool HasProcedureParams { get { return false; } } + public bool HasTestParams { get { return false; } } + public IParamsProvider GetTestParams(Entities.ComponentTest testParams) { return null; } + public IParamsProvider GetProcedureParams(Entities.ComponentProcedure procedureParams) { return null; } + + /// Max. number of components of this class in the system + public int MaxCount { get { return int.MaxValue; } } + + public IComponentCfg DefaultConfig(IList components) + { + return new PumpCfg(this, "Pump", "CB", 0); + } + + public IComponentCfgCtrl CreateCfgCtrl() + { + return new PumpCfgCtrl(); + } + + public IComponent ComponentFromCmpntCfg(IComponentCfg config, IList components) + { + return new Pump((PumpCfg)config, components); + } + + public IComponentCfg CmpntCfgFromCmpntEntity(Entities.Component component) + { + return PumpCfg.CreateFromDbEntity(component, this); + } + + public void ResetStaticProperties() { Pump.ResetStaticProperties(); } + } +} diff --git a/TestBenchFramework/BenchControl/Elde/PumpWithFM/FMPumpTestParams.cs b/TestBenchFramework/BenchControl/Elde/PumpWithFM/FMPumpTestParams.cs new file mode 100644 index 000000000..04d3356a1 --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/PumpWithFM/FMPumpTestParams.cs @@ -0,0 +1,151 @@ +using System; +using System.IO; +using System.Text; +using System.Xml.Serialization; +using TBF.BenchControl.Generic; +using TBF.Resources; + +namespace TBF.BenchControl.Elde.PumpWithFM +{ + public class FMPumpTestParams : IParamsProvider, ITestParams + { + public float Power; /// Target=terminal flow durning detection when increasing or decreasing the flow + + string[] paramNames = new string[] + { + Strings.PowerPct, + }; + public string ParamName(int i) { return paramNames[i]; } + + public string ToString(int i) + { + switch (i) + { + case 0: return Power.ToString("F1"); + default: return string.Empty; + } + } + + public void UpdateParam(int i, string strValue) + { + switch (i) + { + case 0: Power = Utils.ParseUFloat(strValue); return; + default: return; + } + } + + public bool ValidateParam(int i, string strValue, out string message) + { + message = string.Empty; + + float dummy; + switch (i) + { + case 0: + if (Utils.TryParseUFloat(strValue, out dummy)) return true; + break; + default: + message = "Invalid index"; + return false; + } + + message = ParamName(i) + " is invalid"; + return false; + } + + #region Boilerplate code + + public int ParamsCount() { return paramNames.Length; } + + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < ParamsCount(); i++) + { + if (i != 0) sb.Append("; "); + sb.Append(ParamName(i)); + sb.Append("="); + sb.Append(ToString(i)); + } + return sb.ToString(); + } + + [XmlIgnore] + public Entities.ComponentTest TestParamsEntity { get { return testParamsEntity; } } + Entities.ComponentTest testParamsEntity; + + [XmlIgnore] + public string ComponentName { get { return componentName; } } + string componentName; + + [XmlIgnore] + public Entities.Test Test { get { return test; } } + Entities.Test test; + + /// Parameterless constructor + public FMPumpTestParams() + { + Power = 50.0f; + } + + public FMPumpTestParams(Entities.ComponentTest testParamsEntity, string componentName, Entities.Test test) + : this() + { + this.testParamsEntity = testParamsEntity; + this.componentName = componentName; + this.test = test; + } + + public TBF.Entities.ComponentTest ToDbEntity(IComponent component, Entities.Test test) + { + using (var writer = new StringWriter()) + { + /// Serialize this class with parameters + (new XmlSerializer(GetType())).Serialize(writer, this); + + /// Create and return the ComponentTest entity + TBF.Entities.ComponentTest entity = new TBF.Entities.ComponentTest(); + entity.CmpntName = component.Cfg.Name; + entity.Parameters = writer.ToString(); + entity.Test = test; + return entity; + } + } + + public void UpdateDbEntity() + { + using (var writer = new StringWriter()) + { + /// Serialize this class and update the entity + (new XmlSerializer(GetType())).Serialize(writer, this); + testParamsEntity.Parameters = writer.ToString(); + testParamsEntity.CmpntName = componentName; + testParamsEntity.Test = test; + + } + } + + public static IParamsProvider GetTestParams(Entities.ComponentTest testParamsEntity) + { + if (testParamsEntity == null) return new FMPumpTestParams(); + + FMPumpTestParams testParams; + try + { + testParams = (FMPumpTestParams)(new XmlSerializer(typeof(FMPumpTestParams))) + .Deserialize(new StringReader(testParamsEntity.Parameters)); + } + catch + { + testParams = new FMPumpTestParams(); + } + testParams.testParamsEntity = testParamsEntity; + testParams.componentName = testParamsEntity.CmpntName; + testParams.test = testParamsEntity.Test; + return testParams; + } + + #endregion + } +} diff --git a/TestBenchFramework/BenchControl/Elde/PumpWithFM/Pump.cs b/TestBenchFramework/BenchControl/Elde/PumpWithFM/Pump.cs new file mode 100644 index 000000000..48f2eab18 --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/PumpWithFM/Pump.cs @@ -0,0 +1,117 @@ +using System; +using System.Collections.Generic; +using log4net; + +namespace TBF.BenchControl.Elde.PumpWithFM +{ + public class Pump : Generic.IComponent, GenericDevices.IPumpFM, GenericDevices.IValve, IOperation + { + /// + /// Info: StartMassMeasurement() and "Balance response = .., Mass = ..." + /// Warn: Start measurement when busy is true + /// + private static readonly ILog log = LogManager.GetLogger(typeof(Pump)); + public override string ToString() + { + return string.Format("Pump(name={0}, bit={1}, idx={2})", Name, bitPosition, FMIndex); + } + + public static void ResetStaticProperties() { } + + private readonly PumpCfg pumpCfg; + public Generic.IComponentCfg Cfg { get { return pumpCfg; } } + + public string Name { get { return pumpCfg.Name; } } + + public GenericDevices.IValve CoupledTo { get { return null; } } + public bool Invert { get { return false; } } + public int LagOpening { get { return 0; } } + public int LagClosing { get { return 0; } } + + readonly ControlBoardDev controlBoard; + readonly int bitPosition; /// 0 .. 63 + int FMIndex; /// 0 .. FMPumpsCount-1 + + public readonly ulong Mask; /// derived from bitPosition in the constructor + + public bool State + { + get { return (controlBoard.Route & Mask) != 0; } + } + + + public Pump(PumpCfg cfg, IList components) + { + if (cfg == null) throw new ArgumentNullException("cfg"); + this.pumpCfg = cfg; + + controlBoard = (ControlBoardDev)TbfComponents.FindComponent(cfg.ParentName, components); + if (controlBoard == null) throw new Exception("Cannot find " + Name + " parent"); + + this.bitPosition = cfg.BitPosition; + this.Mask = (((ulong)1) << bitPosition); + this.FMIndex = cfg.FMIndex; + + log.Debug(this.ToString()); + } + + /// + /// The currently running operation. + /// + public enum CurrentOp + { + None, + TurnOn, + TurnOff, + } + /// + CurrentOp currentOp; + + /// + /// Turn the pump frequency inverter on. + /// + public IOperation TurnOn() + { + if (currentOp != CurrentOp.None) throw new Exception("Sequence error"); + currentOp = CurrentOp.TurnOn; + return this; + } + + /// + /// Turn the pump frequency inverter on. + /// + public IOperation TurnOff() + { + if (currentOp != CurrentOp.None) throw new Exception("Sequence error"); + currentOp = CurrentOp.TurnOff; + return this; + } + + /// Start the operation + public void Start() + { + switch (currentOp) + { + case CurrentOp.TurnOn: + controlBoard.SetFMFreq(FMIndex, 50.0f); + return; + case CurrentOp.TurnOff: + default: + controlBoard.SetFMFreq(FMIndex, 0.0f); + return; + } + } + + /// Run the operation + public Event Run() + { + return Event.TurnPumpOnOffDone; + } + + /// Stop the operation + public void Stop() + { + currentOp = CurrentOp.None; + } + } +} diff --git a/TestBenchFramework/BenchControl/Elde/PumpWithFM/PumpCfg.cs b/TestBenchFramework/BenchControl/Elde/PumpWithFM/PumpCfg.cs new file mode 100644 index 000000000..4c52a8f63 --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/PumpWithFM/PumpCfg.cs @@ -0,0 +1,53 @@ +using System.IO; +using System.Xml.Serialization; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.Elde.PumpWithFM +{ + public class PumpCfg : ComponentCfgBase, IChildComponentCfg + { + public int BitPosition; + public int FMIndex; + + /// Parameterless constructor + public PumpCfg() + { + } + /// Constructor + public PumpCfg(IComponentFactory factory, string name, string parentName, int bitPosition, int fmIndex) + : base(factory, name, parentName) + { + this.BitPosition = bitPosition; + this.FMIndex = fmIndex; + } + + public IComponentCfg Clone() + { + return new PumpCfg(Factory, Name, ParentName, BitPosition, FMIndex); + } + + public string ToString(int i) + { + return string.Format("bit={0}, fmIdx={1}", BitPosition, FMIndex); + } + + public TBF.Entities.Component CreateDbEntity() + { + using (var writer = new StringWriter()) + { + (new XmlSerializer(GetType())).Serialize(writer, this); + return Entities.Component.CreateFromCfg(Name, Factory.ClassName, ParentName, ItemNr, DebugLevel, LogLevel, writer.ToString()); + } + } + + public static IComponentCfg CreateFromDbEntity(Entities.Component component, IComponentFactory factory) + { + using (var reader = new StringReader(component.Parameters)) + { + PumpCfg config = (PumpCfg)(new XmlSerializer(typeof(PumpCfg))).Deserialize(reader); + config.InitCfgBaseFromEntity(component, factory); + return config; + } + } + } +} diff --git a/TestBenchFramework/BenchControl/Elde/PumpWithFM/PumpCfgCtrl.Designer.cs b/TestBenchFramework/BenchControl/Elde/PumpWithFM/PumpCfgCtrl.Designer.cs new file mode 100644 index 000000000..a8b21c99a --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/PumpWithFM/PumpCfgCtrl.Designer.cs @@ -0,0 +1,153 @@ +namespace TBF.BenchControl.Elde.PumpWithFM +{ + partial class PumpCfgCtrl + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.bitPositionTextBox = new System.Windows.Forms.TextBox(); + this.bitPositionLabel = new System.Windows.Forms.Label(); + this.parentNameLabel = new System.Windows.Forms.Label(); + this.nameTextBox = new System.Windows.Forms.TextBox(); + this.nameLabel = new System.Windows.Forms.Label(); + this.classNameLabel = new System.Windows.Forms.Label(); + this.parentNameComboBox = new System.Windows.Forms.ComboBox(); + this.fmIndexTextBox = new System.Windows.Forms.TextBox(); + this.fmIndexLabel = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // bitPositionTextBox + // + this.bitPositionTextBox.Enabled = false; + this.bitPositionTextBox.Location = new System.Drawing.Point(122, 99); + this.bitPositionTextBox.Name = "bitPositionTextBox"; + this.bitPositionTextBox.Size = new System.Drawing.Size(46, 20); + this.bitPositionTextBox.TabIndex = 6; + // + // bitPositionLabel + // + this.bitPositionLabel.AutoSize = true; + this.bitPositionLabel.Location = new System.Drawing.Point(36, 102); + this.bitPositionLabel.Name = "bitPositionLabel"; + this.bitPositionLabel.Size = new System.Drawing.Size(59, 13); + this.bitPositionLabel.TabIndex = 5; + this.bitPositionLabel.Text = "Bit Position"; + // + // parentNameLabel + // + this.parentNameLabel.AutoSize = true; + this.parentNameLabel.Location = new System.Drawing.Point(36, 76); + this.parentNameLabel.Name = "parentNameLabel"; + this.parentNameLabel.Size = new System.Drawing.Size(69, 13); + this.parentNameLabel.TabIndex = 3; + this.parentNameLabel.Text = "Parent Name"; + // + // nameTextBox + // + this.nameTextBox.Enabled = false; + this.nameTextBox.Location = new System.Drawing.Point(122, 47); + this.nameTextBox.Name = "nameTextBox"; + this.nameTextBox.Size = new System.Drawing.Size(130, 20); + this.nameTextBox.TabIndex = 2; + // + // nameLabel + // + this.nameLabel.AutoSize = true; + this.nameLabel.Location = new System.Drawing.Point(36, 50); + this.nameLabel.Name = "nameLabel"; + this.nameLabel.Size = new System.Drawing.Size(35, 13); + this.nameLabel.TabIndex = 1; + this.nameLabel.Text = "Name"; + // + // classNameLabel + // + this.classNameLabel.AutoSize = true; + this.classNameLabel.Location = new System.Drawing.Point(119, 21); + this.classNameLabel.Name = "classNameLabel"; + this.classNameLabel.Size = new System.Drawing.Size(83, 13); + this.classNameLabel.TabIndex = 0; + this.classNameLabel.Text = "ComonentName"; + // + // parentNameComboBox + // + this.parentNameComboBox.Enabled = false; + this.parentNameComboBox.FormattingEnabled = true; + this.parentNameComboBox.Location = new System.Drawing.Point(122, 73); + this.parentNameComboBox.Name = "parentNameComboBox"; + this.parentNameComboBox.Size = new System.Drawing.Size(130, 21); + this.parentNameComboBox.TabIndex = 4; + // + // fmIndexTextBox + // + this.fmIndexTextBox.Enabled = false; + this.fmIndexTextBox.Location = new System.Drawing.Point(122, 124); + this.fmIndexTextBox.Name = "fmIndexTextBox"; + this.fmIndexTextBox.Size = new System.Drawing.Size(46, 20); + this.fmIndexTextBox.TabIndex = 8; + // + // fmIndexLabel + // + this.fmIndexLabel.AutoSize = true; + this.fmIndexLabel.Location = new System.Drawing.Point(36, 127); + this.fmIndexLabel.Name = "fmIndexLabel"; + this.fmIndexLabel.Size = new System.Drawing.Size(51, 13); + this.fmIndexLabel.TabIndex = 7; + this.fmIndexLabel.Text = "FM Index"; + // + // PumpCfgCtrl + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.fmIndexTextBox); + this.Controls.Add(this.fmIndexLabel); + this.Controls.Add(this.parentNameComboBox); + this.Controls.Add(this.bitPositionTextBox); + this.Controls.Add(this.bitPositionLabel); + this.Controls.Add(this.parentNameLabel); + this.Controls.Add(this.nameTextBox); + this.Controls.Add(this.nameLabel); + this.Controls.Add(this.classNameLabel); + this.Name = "PumpCfgCtrl"; + this.Size = new System.Drawing.Size(300, 200); + this.Load += new System.EventHandler(this.PumpCfgCtrl_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TextBox bitPositionTextBox; + private System.Windows.Forms.Label bitPositionLabel; + private System.Windows.Forms.Label parentNameLabel; + private System.Windows.Forms.TextBox nameTextBox; + private System.Windows.Forms.Label nameLabel; + private System.Windows.Forms.Label classNameLabel; + private System.Windows.Forms.ComboBox parentNameComboBox; + private System.Windows.Forms.TextBox fmIndexTextBox; + private System.Windows.Forms.Label fmIndexLabel; + } +} diff --git a/TestBenchFramework/BenchControl/Elde/PumpWithFM/PumpCfgCtrl.cs b/TestBenchFramework/BenchControl/Elde/PumpWithFM/PumpCfgCtrl.cs new file mode 100644 index 000000000..41141e3fd --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/PumpWithFM/PumpCfgCtrl.cs @@ -0,0 +1,100 @@ +using System; +using System.Windows.Forms; +using log4net; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.Elde.PumpWithFM +{ + public partial class PumpCfgCtrl : UserControl, IComponentCfgCtrl + { + static readonly ILog log = LogManager.GetLogger(typeof(PumpCfgCtrl)); + + ComponentParametersDlg parent; + PumpCfg config; + public IComponentCfg Config + { + get { return config as IComponentCfg; } + set + { + config = value as PumpCfg; + Redraw(); + } + } + + public PumpCfgCtrl() + { + InitializeComponent(); + } + + private void PumpCfgCtrl_Load(object sender, EventArgs e) + { + parent = ParentForm as ComponentParametersDlg; + if (parent == null) return; + + if (parent.TbfComponents != null) + { + foreach (var cmpnt in parent.TbfComponents) + { + if (TbfComponents.CmpntFactoryFromClassName(cmpnt.ClassName) is Elde.ControlBoardFactory) + { + parentNameComboBox.Items.Add(cmpnt.Name); + } + } + } + + Redraw(); + } + + void Redraw() + { + if (config == null) return; /// Control was not loaded, settings were not changed + + classNameLabel.Text = config.Factory.ClassName; + nameTextBox.Text = config.Name; + parentNameComboBox.Text = string.IsNullOrEmpty(config.ParentName) ? "---" : config.ParentName; + bitPositionTextBox.Text = config.BitPosition.ToString(); + fmIndexTextBox.Text = config.FMIndex.ToString(); + } + + public void Unlock() + { + nameTextBox.Enabled = true; + parentNameComboBox.Enabled = true; + bitPositionTextBox.Enabled = true; + fmIndexTextBox.Enabled = true; + } + + public void UpdateCfg() + { + if (config == null) return; /// Control was not loaded, settings were not changed + + config.Name = nameTextBox.Text; + config.ParentName = parentNameComboBox.Text.Equals("---") ? string.Empty : parentNameComboBox.Text; + config.BitPosition = int.Parse(bitPositionTextBox.Text); + config.FMIndex = int.Parse(fmIndexTextBox.Text); + } + + public CfgVerifyFlags VerifyCfg(ref string message) + { + CfgVerifyFlags flags = CfgVerifyFlags.None; + + int dummy; + if (!parentNameComboBox.Items.Contains(parentNameComboBox.Text)) + { + flags |= CfgVerifyFlags.Error; + message += Environment.NewLine + "Invalid 'Parent Name'"; + } + if (!int.TryParse(bitPositionTextBox.Text, out dummy) || dummy < 0 || dummy >= 64) + { + flags |= CfgVerifyFlags.Error; + message += Environment.NewLine + "'Bit Position' should be between 0 and 63"; + } + if (!int.TryParse(fmIndexTextBox.Text, out dummy) || dummy < 0) + { + flags |= CfgVerifyFlags.Error; + message += Environment.NewLine + "'FM Index' should be between 0 and FMPumpsCount - 1"; + } + return flags; + } + } +} diff --git a/TestBenchFramework/BenchControl/Elde/PumpWithFM/PumpCfgCtrl.resx b/TestBenchFramework/BenchControl/Elde/PumpWithFM/PumpCfgCtrl.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/PumpWithFM/PumpCfgCtrl.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/BenchControl/Elde/PumpWithFM/PumpFactory.cs b/TestBenchFramework/BenchControl/Elde/PumpWithFM/PumpFactory.cs new file mode 100644 index 000000000..f9d60cd82 --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/PumpWithFM/PumpFactory.cs @@ -0,0 +1,42 @@ +using System.Collections.Generic; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.Elde.PumpWithFM +{ + public class PumpFactory : IComponentFactory + { + public string ClassName { get { return "PumpWithFM"; } } + public bool HasProcedureParams { get { return false; } } + public bool HasTestParams { get { return true; } } + public IParamsProvider GetProcedureParams(Entities.ComponentProcedure procedureParams) { return null; } + public IParamsProvider GetTestParams(Entities.ComponentTest testParams) + { + return FMPumpTestParams.GetTestParams(testParams); + } + + /// Max. number of components of this class in the system + public int MaxCount { get { return int.MaxValue; } } + + public IComponentCfg DefaultConfig(IList components) + { + return new PumpCfg(this, "Pump", "CB", 0, 0); + } + + public IComponentCfgCtrl CreateCfgCtrl() + { + return new PumpCfgCtrl(); + } + + public IComponent ComponentFromCmpntCfg(IComponentCfg config, IList components) + { + return new Pump((PumpCfg)config, components); + } + + public IComponentCfg CmpntCfgFromCmpntEntity(Entities.Component component) + { + return PumpCfg.CreateFromDbEntity(component, this); + } + + public void ResetStaticProperties() { Pump.ResetStaticProperties(); } + } +} diff --git a/TestBenchFramework/BenchControl/Elde/QueryMeasurementEndOp.cs b/TestBenchFramework/BenchControl/Elde/QueryMeasurementEndOp.cs new file mode 100644 index 000000000..c341a6c75 --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/QueryMeasurementEndOp.cs @@ -0,0 +1,59 @@ +using System; +using log4net; + +namespace TBF.BenchControl.Elde +{ + public class QueryMeasurementEndOp : IOperation + { + private static readonly ILog log = LogManager.GetLogger(typeof(QueryMeasurementEndOp)); + public override string ToString() { return string.Format("QueryMeasurementEndOp(.,{0})", eventDone); } + + /// Set by the constructor + readonly ControlBoardDev controlBoard; + readonly Event eventDone; + + bool done = false; + + /// + /// Events: MeasurementCompleted + /// + /// Event to be returned by Run() when completed OK + public QueryMeasurementEndOp(ControlBoardDev controlBoardDev, Event eventDone) + { + if (controlBoardDev == null) throw new ArgumentNullException("controlBoardDev"); + this.controlBoard = controlBoardDev; + this.eventDone = eventDone; + + log.Debug(this.ToString()); + } + public QueryMeasurementEndOp(ControlBoardDev controlBoardDev) + : this(controlBoardDev, Event.MeasurementCompleted) + { + } + + /// Start this operation + public void Start() + { + } + + /// Run this operation + /// + /// Event.FlowInDone or Event.FlowOutDone + /// + public Event Run() + { + if (done) return eventDone; + if (0 != (controlBoard.StatusP & StatusP.TestCompleted)) + { + done = true; + return eventDone; + } + return Event.None; + } + + /// Stop this operation + public void Stop() + { + } + } +} diff --git a/TestBenchFramework/BenchControl/Elde/RegisterReader/RRProcedureParams.cs b/TestBenchFramework/BenchControl/Elde/RegisterReader/RRProcedureParams.cs new file mode 100644 index 000000000..30a90f4c0 --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/RegisterReader/RRProcedureParams.cs @@ -0,0 +1,155 @@ +using System; +using System.IO; +using System.Text; +using System.Xml.Serialization; +using TBF.BenchControl.Generic; +using TBF.Resources; + +namespace TBF.BenchControl.Elde.RegisterReader +{ + public class RRProcedureParams : IParamsProvider, IProcedureParams + { + public float PulsesPerLtr; /// Target low limit of the flow increase or decrease + + string[] paramNames = new string[] + { + Strings.PulsesPerLtr, + }; + public string ParamName(int i) { return paramNames[i]; } + + public string ToString(int i) + { + switch (i) + { + case 0: return PulsesPerLtr.ToString(); + default: return string.Empty; + } + } + + /// + /// Parameterless constructor - sets default values of parameters. + /// + public RRProcedureParams() + { + PulsesPerLtr = 1.0f; + } + + /// Retrieves parameters from UI controls + public void UpdateParam(int i, string strValue) + { + switch (i) + { + case 0: PulsesPerLtr = Utils.ParseUFloat(strValue); return; + default: return; + } + } + + /// Verifies whether strings in UI controls represent valid parameters + public bool ValidateParam(int i, string strValue, out string message) + { + message = string.Empty; + + float dummy; + switch (i) + { + case 0: + if (Utils.TryParseUFloat(strValue, out dummy)) return true; + break; + default: + message = "Invalid index"; + return false; + } + + message = ParamName(i) + " is invalid"; + return false; + } + + #region Boilerplate code + + public int ParamsCount() { return paramNames.Length; } + + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < ParamsCount(); i++) + { + if (i != 0) sb.Append("; "); + sb.Append(ParamName(i)); + sb.Append("="); + sb.Append(ToString(i)); + } + return sb.ToString(); + } + + [XmlIgnore] + public Entities.ComponentProcedure ProcedureParamsEntity { get { return procedureParamsEntity; } } + Entities.ComponentProcedure procedureParamsEntity; + + [XmlIgnore] + public string ComponentName { get { return componentName; } } + string componentName; + + [XmlIgnore] + public Entities.Procedure Procedure { get { return procedure; } } + Entities.Procedure procedure; + + public RRProcedureParams(Entities.ComponentProcedure procedureParamsEntity, string componentName, Entities.Procedure procedure) + : this() + { + this.procedureParamsEntity = procedureParamsEntity; + this.componentName = componentName; + this.procedure = procedure; + } + + public TBF.Entities.ComponentProcedure ToDbEntity(IComponent component, Entities.Procedure procedure) + { + using (var writer = new StringWriter()) + { + /// Serialize this class with parameters + (new XmlSerializer(GetType())).Serialize(writer, this); + + /// Create and return the ComponentProcedure entity + TBF.Entities.ComponentProcedure entity = new TBF.Entities.ComponentProcedure(); + entity.CmpntName = component.Cfg.Name; + entity.Parameters = writer.ToString(); + entity.Procedure = procedure; + return entity; + } + } + + public void UpdateDbEntity() + { + using (var writer = new StringWriter()) + { + /// Serialize this class and update the entity + (new XmlSerializer(GetType())).Serialize(writer, this); + procedureParamsEntity.Parameters = writer.ToString(); + procedureParamsEntity.CmpntName = componentName; + procedureParamsEntity.Procedure = procedure; + + } + } + + public static IParamsProvider GetProcedureParams(Entities.ComponentProcedure procedureParamsEntity) + { + if (procedureParamsEntity == null) return new RRProcedureParams(); + + RRProcedureParams procedureParams; + try + { + procedureParams = (RRProcedureParams)(new XmlSerializer(typeof(RRProcedureParams))) + .Deserialize(new StringReader(procedureParamsEntity.Parameters)); + } + catch + { + procedureParams = new RRProcedureParams(); + } + procedureParams.procedureParamsEntity = procedureParamsEntity; + procedureParams.componentName = procedureParamsEntity.CmpntName; + procedureParams.procedure = procedureParamsEntity.Procedure; + return procedureParams; + } + + #endregion + } +} diff --git a/TestBenchFramework/BenchControl/Elde/RegisterReader/ReadReferenceForRegisterOp.cs b/TestBenchFramework/BenchControl/Elde/RegisterReader/ReadReferenceForRegisterOp.cs new file mode 100644 index 000000000..43ee94aa7 --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/RegisterReader/ReadReferenceForRegisterOp.cs @@ -0,0 +1,58 @@ +using System; +using log4net; + +namespace TBF.BenchControl.Elde.RegisterReader +{ + public class ReadReferenceForRegisterOp : IOperation + { + private static readonly ILog log = LogManager.GetLogger(typeof(ReadReferenceForRegisterOp)); + public override string ToString() { return string.Format("ReadWaterMeterOp(.,{0},{1},.)", eventDone, registerNr); } + + /// Set by the constructor + readonly ControlBoardDev controlBoard; + readonly int registerNr; /// 0 .. nr.watermeters-1 + readonly Event eventDone; + IntBox pulses; + + /// + /// Events: or Error + /// + /// Flow meter reference + /// Reference to the measured flow variable, value is in bar + /// Event to be returned by Run() when completed OK + public ReadReferenceForRegisterOp(Elde.RegisterReader.RegisterReader register, ref IntBox pulses, Event eventDone) + { + if (register == null) throw new ArgumentNullException("register"); + this.controlBoard = register.ControlBoard; + this.registerNr = register.Position; + this.eventDone = eventDone; + this.pulses = pulses; + + log.Debug(this.ToString()); + } + public ReadReferenceForRegisterOp(Elde.RegisterReader.RegisterReader register, ref IntBox pulses) + : this(register, ref pulses, Event.ReadReferenceDone) + { + } + + /// Start this operation + public void Start() + { + } + + /// Run this operation + /// + /// Event.FlowInDone or Event.FlowOutDone + /// + public Event Run() + { + pulses.N = (int)controlBoard.EtPulses(registerNr); + return eventDone; + } + + /// Stop this operation + public void Stop() + { + } + } +} diff --git a/TestBenchFramework/BenchControl/Elde/RegisterReader/ReadRegisterOp.cs b/TestBenchFramework/BenchControl/Elde/RegisterReader/ReadRegisterOp.cs new file mode 100644 index 000000000..4d9e01d5b --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/RegisterReader/ReadRegisterOp.cs @@ -0,0 +1,71 @@ +using System; +using log4net; + +namespace TBF.BenchControl.Elde.RegisterReader +{ + public class ReadRegisterOp : IOperation + { + private static readonly ILog log = LogManager.GetLogger(typeof(ReadRegisterOp)); + public override string ToString() { return string.Format("ReadRegisterOp({0})", reader.Name); } + + /// Set by the constructor + readonly RegisterReader reader; + IntBox pulses; + IntBox refPulses; + + /// + /// Events: Event.ReadRegisterDone or Event.Error + /// + /// Register reader reference + /// Reference to a field with the water meter pulses + public ReadRegisterOp(GenericDevices.IRegisterReader reader, ref IntBox pulses) + { + this.reader = reader as RegisterReader; + if (reader == null) throw new ArgumentNullException("reader is null or it is not Elde"); + + this.pulses = pulses; + log.Debug(this.ToString()); + } + + /// + /// Events: Event.ReadRegisterDone or Event.Error + /// + /// Register reader reference + /// Reference to a Box with the water meter pulses + /// Reference to a Box with the reference flow meter pulses synchronized with the water meter + public ReadRegisterOp(GenericDevices.IRegisterReader reader, ref IntBox pulses, ref IntBox refPulses) + : this(reader, ref pulses) + { + this.refPulses = refPulses; + log.Debug(this.ToString()); + } + + private void ReadPulses() + { + pulses.N = (int)reader.ControlBoard.WMeterPulses(reader.Position); + if (refPulses != null) + { + refPulses.N = (int)reader.ControlBoard.EtPulses(reader.Position); + } + } + + /// Start this operation + public void Start() + { + ReadPulses(); + } + + /// Run this operation + /// eventDone + public Event Run() + { + ReadPulses(); + return Event.ReadRegisterDone; + } + + /// Stop this operation + public void Stop() + { + } + } +} diff --git a/TestBenchFramework/BenchControl/Elde/RegisterReader/RegisterReader.cs b/TestBenchFramework/BenchControl/Elde/RegisterReader/RegisterReader.cs new file mode 100644 index 000000000..88dd05637 --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/RegisterReader/RegisterReader.cs @@ -0,0 +1,82 @@ +using System; +using System.Collections.Generic; +using log4net; + +namespace TBF.BenchControl.Elde.RegisterReader +{ + public class RegisterReader : ComponentBase, GenericDevices.IRegisterReader + { + /// + /// Info: StartMassMeasurement() and "Balance response = .., Mass = ..." + /// Warn: Start measurement when busy is true + /// + private static readonly ILog log = LogManager.GetLogger(typeof(RegisterReader)); + public override string ToString() + { + return string.Format("Register({0},{1})", Name, Position); + } + + public static void ResetStaticProperties() { } + + RegisterReaderCfg registerReaderCfg; + + public float PulsesPerLtr + { + get + { + return (ProcedureParams is RRProcedureParams) ? (ProcedureParams as RRProcedureParams).PulsesPerLtr : 0; + } + } + + public readonly ControlBoardDev ControlBoard; + + public readonly int Position; /// 1 .. inf + + public RegisterReader(RegisterReaderCfg cfg, IList components) + : base(cfg) + { + if (cfg == null) throw new ArgumentNullException("cfg"); + this.registerReaderCfg = cfg; + + ControlBoard = (ControlBoardDev)TbfComponents.FindComponent(cfg.ParentName, components); + if (ControlBoard == null) throw new Exception("Cannot find " + Name + " parent"); + + Position = cfg.Position; + + /// Prepare data for SendCalibData() control board component method + + log.Debug(this.ToString()); + } + + /// + /// Events: Event.ReadRegisterDone, Event.Error + /// + /// Reference to a variable for the water meter pulses + /// ReadWaterMeter instance reference casted to IOperaton + public IOperation ReadRegisterOp(ref IntBox pulses) + { + return new ReadRegisterOp(this, ref pulses); + } + + /// + /// Events: Event.ReadRegisterDone, Event.Error + /// + /// Reference to a variable for the water meter pulses + /// Reference to a variable for the related reference flowmeter pulses + /// Reference to operation object instance + public IOperation ReadRegisterOp(ref IntBox pulses, ref IntBox refPulses) + { + return new ReadRegisterOp(this, ref pulses, ref refPulses); + } + + /// + /// Events: ReadReferenceDone, Error + /// + /// Reference to a variable for the water meter pulses + /// Reference to operation object instance + public IOperation ReadReferenceForRegisterOp(ref IntBox pulses, ref IntBox refPulses) + { + return new ReadReferenceForRegisterOp(this, ref pulses); + } + } +} diff --git a/TestBenchFramework/BenchControl/Elde/RegisterReader/RegisterReaderCfg.cs b/TestBenchFramework/BenchControl/Elde/RegisterReader/RegisterReaderCfg.cs new file mode 100644 index 000000000..584eab6b4 --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/RegisterReader/RegisterReaderCfg.cs @@ -0,0 +1,60 @@ +using System; +using System.IO; +using System.Xml.Serialization; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.Elde.RegisterReader +{ + public class RegisterReaderCfg : ComponentCfgBase, Generic.IChildComponentCfg + { + public int Position; /// 1..nrWaterMeters + + /// Parameterless constructor + public RegisterReaderCfg() + { + } + /// + /// Regulation valve configuration parameters + /// + /// Regulation valve name + /// Position on the control board 1 .. nrWaterMeters + public RegisterReaderCfg(IComponentFactory factory, string name, string parentName, int position) + : base(factory, name, parentName) + { + if (position < 1 || position >= 2 * Program.WMsCount) + { + throw new ArgumentOutOfRangeException("position"); + } + this.Position = position; + } + + public IComponentCfg Clone() + { + return new RegisterReaderCfg(Factory, Name, ParentName, Position); + } + + public string ToString(int i) + { + return string.Format("position={0}", Position); + } + + public TBF.Entities.Component CreateDbEntity() + { + using (var writer = new StringWriter()) + { + (new XmlSerializer(GetType())).Serialize(writer, this); + return Entities.Component.CreateFromCfg(Name, Factory.ClassName, ParentName, ItemNr, DebugLevel, LogLevel, writer.ToString()); + } + } + + public static IComponentCfg CreateFromDbEntity(Entities.Component component, IComponentFactory factory) + { + using (var reader = new StringReader(component.Parameters)) + { + RegisterReaderCfg config = (RegisterReaderCfg)(new XmlSerializer(typeof(RegisterReaderCfg))).Deserialize(reader); + config.InitCfgBaseFromEntity(component, factory); + return config; + } + } + } +} diff --git a/TestBenchFramework/BenchControl/Elde/RegisterReader/RegisterReaderCfgCtrl.Designer.cs b/TestBenchFramework/BenchControl/Elde/RegisterReader/RegisterReaderCfgCtrl.Designer.cs new file mode 100644 index 000000000..d73b92337 --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/RegisterReader/RegisterReaderCfgCtrl.Designer.cs @@ -0,0 +1,130 @@ +namespace TBF.BenchControl.Elde.RegisterReader +{ + partial class RegisterReaderCfgCtrl + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.positionTextBox = new System.Windows.Forms.TextBox(); + this.positionLabel = new System.Windows.Forms.Label(); + this.parentNameLabel = new System.Windows.Forms.Label(); + this.nameTextBox = new System.Windows.Forms.TextBox(); + this.nameLabel = new System.Windows.Forms.Label(); + this.componentNameLabel = new System.Windows.Forms.Label(); + this.parentNameComboBox = new System.Windows.Forms.ComboBox(); + this.SuspendLayout(); + // + // positionTextBox + // + this.positionTextBox.Enabled = false; + this.positionTextBox.Location = new System.Drawing.Point(136, 119); + this.positionTextBox.Name = "positionTextBox"; + this.positionTextBox.Size = new System.Drawing.Size(46, 20); + this.positionTextBox.TabIndex = 6; + // + // positionLabel + // + this.positionLabel.AutoSize = true; + this.positionLabel.Location = new System.Drawing.Point(26, 122); + this.positionLabel.Name = "positionLabel"; + this.positionLabel.Size = new System.Drawing.Size(44, 13); + this.positionLabel.TabIndex = 5; + this.positionLabel.Text = "Position"; + // + // parentNameLabel + // + this.parentNameLabel.AutoSize = true; + this.parentNameLabel.Location = new System.Drawing.Point(26, 96); + this.parentNameLabel.Name = "parentNameLabel"; + this.parentNameLabel.Size = new System.Drawing.Size(69, 13); + this.parentNameLabel.TabIndex = 3; + this.parentNameLabel.Text = "Parent Name"; + // + // nameTextBox + // + this.nameTextBox.Enabled = false; + this.nameTextBox.Location = new System.Drawing.Point(136, 67); + this.nameTextBox.Name = "nameTextBox"; + this.nameTextBox.Size = new System.Drawing.Size(130, 20); + this.nameTextBox.TabIndex = 2; + // + // nameLabel + // + this.nameLabel.AutoSize = true; + this.nameLabel.Location = new System.Drawing.Point(26, 70); + this.nameLabel.Name = "nameLabel"; + this.nameLabel.Size = new System.Drawing.Size(35, 13); + this.nameLabel.TabIndex = 1; + this.nameLabel.Text = "Name"; + // + // componentNameLabel + // + this.componentNameLabel.AutoSize = true; + this.componentNameLabel.Location = new System.Drawing.Point(133, 43); + this.componentNameLabel.Name = "componentNameLabel"; + this.componentNameLabel.Size = new System.Drawing.Size(83, 13); + this.componentNameLabel.TabIndex = 0; + this.componentNameLabel.Text = "ComonentName"; + // + // parentNameComboBox + // + this.parentNameComboBox.Enabled = false; + this.parentNameComboBox.FormattingEnabled = true; + this.parentNameComboBox.Location = new System.Drawing.Point(136, 93); + this.parentNameComboBox.Name = "parentNameComboBox"; + this.parentNameComboBox.Size = new System.Drawing.Size(130, 21); + this.parentNameComboBox.TabIndex = 4; + // + // RegisterReaderCfgCtrl + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.parentNameComboBox); + this.Controls.Add(this.positionTextBox); + this.Controls.Add(this.positionLabel); + this.Controls.Add(this.parentNameLabel); + this.Controls.Add(this.nameTextBox); + this.Controls.Add(this.nameLabel); + this.Controls.Add(this.componentNameLabel); + this.Name = "RegisterReaderCfgCtrl"; + this.Size = new System.Drawing.Size(300, 200); + this.Load += new System.EventHandler(this.RegisterReaderCfgCtrl_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TextBox positionTextBox; + private System.Windows.Forms.Label positionLabel; + private System.Windows.Forms.Label parentNameLabel; + private System.Windows.Forms.TextBox nameTextBox; + private System.Windows.Forms.Label nameLabel; + private System.Windows.Forms.Label componentNameLabel; + private System.Windows.Forms.ComboBox parentNameComboBox; + } +} diff --git a/TestBenchFramework/BenchControl/Elde/RegisterReader/RegisterReaderCfgCtrl.cs b/TestBenchFramework/BenchControl/Elde/RegisterReader/RegisterReaderCfgCtrl.cs new file mode 100644 index 000000000..79709154f --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/RegisterReader/RegisterReaderCfgCtrl.cs @@ -0,0 +1,92 @@ +using System; +using System.Windows.Forms; +using log4net; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.Elde.RegisterReader +{ + public partial class RegisterReaderCfgCtrl : UserControl, IComponentCfgCtrl + { + static readonly ILog log = LogManager.GetLogger(typeof(RegisterReaderCfgCtrl)); + + ComponentParametersDlg parent; + RegisterReaderCfg config; + public IComponentCfg Config + { + get { return config as IComponentCfg; } + set + { + config = value as RegisterReaderCfg; + Redraw(); + } + } + + public RegisterReaderCfgCtrl() + { + InitializeComponent(); + } + + private void RegisterReaderCfgCtrl_Load(object sender, EventArgs e) + { + parent = ParentForm as ComponentParametersDlg; + if (parent == null) return; + + if (parent.TbfComponents != null) + { + foreach (var cmpnt in parent.TbfComponents) + { + if (TbfComponents.CmpntFactoryFromClassName(cmpnt.ClassName) is Elde.ControlBoardFactory) + { + parentNameComboBox.Items.Add(cmpnt.Name); + } + } + } + + Redraw(); + } + + void Redraw() + { + if (config == null) return; /// Control was not loaded, settings were not changed + + componentNameLabel.Text = config.Factory.ClassName; + nameTextBox.Text = config.Name; + parentNameComboBox.Text = string.IsNullOrEmpty(config.ParentName) ? "---" : config.ParentName; + positionTextBox.Text = config.Position.ToString(); + } + + public void Unlock() + { + nameTextBox.Enabled = true; + parentNameComboBox.Enabled = true; + positionTextBox.Enabled = true; + } + + public CfgVerifyFlags VerifyCfg(ref string message) + { + CfgVerifyFlags flags = CfgVerifyFlags.None; + + int dummy; + if (!parentNameComboBox.Items.Contains(parentNameComboBox.Text)) + { + flags |= CfgVerifyFlags.Error; + message += Environment.NewLine + "Invalid 'Parent Name'"; + } + if (!int.TryParse(positionTextBox.Text, out dummy) || (dummy < 1) || (dummy > 2 * Program.WMsCount)) + { + flags |= CfgVerifyFlags.Error; + message += Environment.NewLine + "'Position' should be >= 1"; + } + return flags; + } + + public void UpdateCfg() + { + if (config == null) return; /// Control was not loaded, settings were not changed + + config.Name = nameTextBox.Text; + config.ParentName = parentNameComboBox.Text.Equals("---") ? string.Empty : parentNameComboBox.Text; + config.Position = int.Parse(positionTextBox.Text); + } + } +} diff --git a/TestBenchFramework/BenchControl/Elde/RegisterReader/RegisterReaderCfgCtrl.resx b/TestBenchFramework/BenchControl/Elde/RegisterReader/RegisterReaderCfgCtrl.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/RegisterReader/RegisterReaderCfgCtrl.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/BenchControl/Elde/RegisterReader/RegisterReaderFactory.cs b/TestBenchFramework/BenchControl/Elde/RegisterReader/RegisterReaderFactory.cs new file mode 100644 index 000000000..a2a97f5e9 --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/RegisterReader/RegisterReaderFactory.cs @@ -0,0 +1,46 @@ +using System.Collections.Generic; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.Elde.RegisterReader +{ + public class RegisterReaderFactory : IComponentFactory + { + public string ClassName { get { return "RegisterReader"; } } + + /// Max. number of components of this class in the system + public int MaxCount { get { return Program.WMsCount; } } + + public IComponentCfg DefaultConfig(IList components) + { + return new RegisterReaderCfg(this, "Sick", "CB", 1); + } + + public IComponentCfgCtrl CreateCfgCtrl() + { + return new RegisterReaderCfgCtrl(); + } + + public IComponent ComponentFromCmpntCfg(IComponentCfg config, IList components) + { + return new RegisterReader((RegisterReaderCfg)config, components); + } + + public IComponentCfg CmpntCfgFromCmpntEntity(Entities.Component component) + { + return RegisterReaderCfg.CreateFromDbEntity(component, this); + } + + public bool HasProcedureParams { get { return true; } } + /// + public IParamsProvider GetProcedureParams(Entities.ComponentProcedure procedureParams) + { + return RRProcedureParams.GetProcedureParams(procedureParams); + } + + public bool HasTestParams { get { return false; } } + /// + public IParamsProvider GetTestParams(Entities.ComponentTest testParams) { return null; } + + public void ResetStaticProperties() { RegisterReader.ResetStaticProperties(); } + } +} diff --git a/TestBenchFramework/BenchControl/Elde/RegulValve/ChangeValvePositionOp.cs b/TestBenchFramework/BenchControl/Elde/RegulValve/ChangeValvePositionOp.cs new file mode 100644 index 000000000..3c1adf65b --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/RegulValve/ChangeValvePositionOp.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; +using log4net; +using TBF.BenchControl.GenericDevices; + +namespace TBF.BenchControl.Elde.RegulValve +{ + public class ChangeRegulValvePositionOp : IOperation + { + private static readonly ILog log = LogManager.GetLogger(typeof(ChangeRegulValvePositionOp)); + public override string ToString() + { + return string.Format("ChangeRegulValvePositionOp({0},{1}s)", regulValve.Name, timePulseSec.ToString("F2")); + } + + /// Set by the constructor + readonly ControlBoardDev controlBoard; + readonly RegulValve regulValve; + readonly int regulValveNr; + readonly float timePulseSec; + + /// Process values + bool firstRun; + + /// + /// Set required water flow. + /// Events: FlowSet, FlowTimeOut + /// + /// Control board device + /// Regulation valve component + /// Lower limit of the position to be achieved + /// Upper limit of the position to be achieved + /// Timeout in sec. for setting the flow + /// Only Elde.Valve flow are used, other flow on the lists are ignored + public ChangeRegulValvePositionOp(ControlBoardDev controlBoard, RegulValve regulValve, float timePulseSec) + { + if (controlBoard == null) throw new ArgumentNullException("ctrlBoard"); + this.controlBoard = controlBoard; + + this.regulValve = regulValve as RegulValve; + if (regulValve == null) throw new ArgumentNullException("regValve is null or not Elde"); + this.regulValveNr = this.regulValve.Position; + + this.timePulseSec = timePulseSec; + + log.Debug(this.ToString()); + } + + /// Start this operation + public void Start() + { + firstRun = true; + float positionPct = controlBoard.RValvePosition(regulValveNr); + log.WarnFormat("RV#={0}, actPos={1}%", regulValveNr, positionPct.ToString("F1")); + + controlBoard.ValveMove(regulValveNr, + RegulValveMode.PulseWidth, + new float[2] { timePulseSec, timePulseSec }); + } + + /// Run this operation + /// + /// Event.SetFlowDone + /// + public Event Run() + { + float positionPct = controlBoard.RValvePosition(regulValveNr); + log.WarnFormat("RV#={0}, actPos={1}%", regulValveNr, positionPct.ToString("F1")); + + return Event.PositionReached; + } + + /// Stop this operation + public void Stop() + { + } + } +} diff --git a/TestBenchFramework/BenchControl/Elde/RegulValve/RegulValve.cs b/TestBenchFramework/BenchControl/Elde/RegulValve/RegulValve.cs new file mode 100644 index 000000000..62a6c51e4 --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/RegulValve/RegulValve.cs @@ -0,0 +1,102 @@ +using System; +using System.Collections.Generic; +using log4net; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.Elde.RegulValve +{ + public class RegulValve : IComponent, GenericDevices.IRegulValve + { + /// + /// Info: StartMassMeasurement() and "Balance response = .., Mass = ..." + /// Warn: Start measurement when busy is true + /// + private static readonly ILog log = LogManager.GetLogger(typeof(RegulValve)); + public override string ToString() + { + return string.Format("RegulationValve({0},{1})", Name, Position); + } + + public static void ResetStaticProperties() { } + + public RegulValveCfg RegulValveCfg; + public Generic.IComponentCfg Cfg { get { return RegulValveCfg; } } + + public string Name { get { return Cfg.Name; } } + + IDictionary dict; + public IDictionary Dict { get { return dict; } } + + readonly ControlBoardDev controlBoard; + + public readonly int Position; /// 0..7 + public readonly int DacValueClosed; /// 0..1023 + public readonly int DacValueOpen; /// 0..1023 + + public RegulValve(RegulValveCfg cfg, IList components) + { + if (cfg == null) throw new ArgumentNullException("cfg"); + this.RegulValveCfg = cfg; + + controlBoard = (ControlBoardDev)TbfComponents.FindComponent(cfg.ParentName, components); + if (controlBoard == null) throw new Exception("Cannot find " + Name + " parent"); + + this.Position = cfg.Position; + this.DacValueClosed = cfg.DacValueClosed; + this.DacValueOpen = cfg.DacValueOpen; + this.dict = new Dictionary(); + + this.controlBoard.RegValveCalib[Position - 1, 0] = (uint)DacValueClosed; + this.controlBoard.RegValveCalib[Position - 1, 1] = (uint)DacValueOpen; + + log.Debug(this.ToString()); + } + + /// + /// Operation to set the water flow within tolerances + /// Events: Event.None, Event.FlowReached, Event.FlowTimeOut + /// + /// Flowmeter component + /// Lower limit of the required flow [m3/h] + /// Higher limit of the required flow [m3/h] + /// Measured flow [m3/h] + /// Timeout in [s] + /// SetFlowOp instance + public IOperation SetFlowOp(GenericDevices.IFlowMeter flowMeter, float requiredFlowLo, float requiredFlowHi, FloatBox measuredFlow, int timeout) + { + return new SetFlowOp(controlBoard, this, flowMeter, requiredFlowLo, requiredFlowHi, measuredFlow, timeout); + } + + /// + /// Operation to set the water flow within tolerances. Leave the measurement running. + /// Events: Event.None, Event.FlowReached, Event.FlowTimeOut + /// + /// Flowmeter component + /// Lower limit of the required flow [m3/h] + /// Higher limit of the required flow [m3/h] + /// Measured flow [m3/h] + /// Timeout in [s] + /// SetFlowOp instance + public IOperation SetFlowAndMeasureOp(GenericDevices.IFlowMeter flowMeter, float requiredFlowLo, float requiredFlowHi, FloatBox measuredFlow, int timeout) + { + return new SetFlowOp(controlBoard, this, flowMeter, requiredFlowLo, requiredFlowHi, measuredFlow, timeout, true); + } + + /// + /// Operation to set the regulation valve to a required position + /// Events: Event.None + /// + /// Lower limit of the required valve position in [%] + /// Higher limit of the required valve position in [%] + /// SetPositionOp instance + public IOperation SetRegulValvePositionOp(float pctLo, float pctHi, int timeoutMs) + { + return new SetRegulValvePositionOp(controlBoard, this, pctLo, pctHi, timeoutMs); + } + + public IOperation ChangeRegulValvePositionOp(float timePulseSec) + { + return new ChangeRegulValvePositionOp(controlBoard, this, timePulseSec); + } + } +} diff --git a/TestBenchFramework/BenchControl/Elde/RegulValve/RegulValveCfg.cs b/TestBenchFramework/BenchControl/Elde/RegulValve/RegulValveCfg.cs new file mode 100644 index 000000000..debb2f32b --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/RegulValve/RegulValveCfg.cs @@ -0,0 +1,73 @@ +using System; +using System.IO; +using System.Xml.Serialization; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.Elde.RegulValve +{ + public class RegulValveCfg : ComponentCfgBase, IChildComponentCfg + { + public int Position; /// 0..7 + public int DacValueClosed; /// 0..1023 + public int DacValueOpen; /// 0..1023 + public int PidCoef; /// 1..100 + public bool StoredPositionReuse; /// true = store and re-use previous regulation valve positions + + /// Parameterless constructor + public RegulValveCfg() + { + } + /// + /// Regulation valve configuration parameters + /// + /// Regulation valve name + /// Position on the control board 0..7 + /// 0..1023 + /// 0..1023 + /// 1..100 + public RegulValveCfg(IComponentFactory factory, string name, string parentName, int position, int dacValueClosed, int dacValueOpen, int pidCoef, bool storedPositionReuse) + : base(factory, name, parentName) + { + if (position < 0 || position > 7) throw new ArgumentOutOfRangeException("position"); + if (dacValueClosed < 0 || dacValueClosed > 1023) throw new ArgumentOutOfRangeException("dacValueOpen"); + if (dacValueOpen < 0 || dacValueOpen > 1023) throw new ArgumentOutOfRangeException("dacValueOpen"); + if (pidCoef < 1 || pidCoef > 100) throw new ArgumentOutOfRangeException("pidCoef"); + + this.Position = position; + this.DacValueClosed = dacValueClosed; + this.DacValueOpen = dacValueOpen; + this.PidCoef = pidCoef; + this.StoredPositionReuse = storedPositionReuse; + } + + public IComponentCfg Clone() + { + return new RegulValveCfg(Factory, Name, ParentName, Position, DacValueClosed, DacValueOpen, PidCoef, StoredPositionReuse); + } + + public string ToString(int i) + { + return string.Format("position={0}, DAC-closed={1}, DAC-open={2}, PID={3}, posReuse={4}", + Position, DacValueClosed, DacValueOpen, PidCoef, StoredPositionReuse); + } + + public TBF.Entities.Component CreateDbEntity() + { + using (var writer = new StringWriter()) + { + (new XmlSerializer(GetType())).Serialize(writer, this); + return Entities.Component.CreateFromCfg(Name, Factory.ClassName, ParentName, ItemNr, DebugLevel, LogLevel, writer.ToString()); + } + } + + public static IComponentCfg CreateFromDbEntity(Entities.Component component, IComponentFactory factory) + { + using (var reader = new StringReader(component.Parameters)) + { + RegulValveCfg config = (RegulValveCfg)(new XmlSerializer(typeof(RegulValveCfg))).Deserialize(reader); + config.InitCfgBaseFromEntity(component, factory); + return config; + } + } + } +} diff --git a/TestBenchFramework/BenchControl/Elde/RegulValve/RegulValveCfgCtrl.Designer.cs b/TestBenchFramework/BenchControl/Elde/RegulValve/RegulValveCfgCtrl.Designer.cs new file mode 100644 index 000000000..20eaac9b5 --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/RegulValve/RegulValveCfgCtrl.Designer.cs @@ -0,0 +1,213 @@ +namespace TBF.BenchControl.Elde.RegulValve +{ + partial class RegulValveCfgCtrl + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.positionTextBox = new System.Windows.Forms.TextBox(); + this.positionLabel = new System.Windows.Forms.Label(); + this.parentNameLabel = new System.Windows.Forms.Label(); + this.nameTextBox = new System.Windows.Forms.TextBox(); + this.nameLabel = new System.Windows.Forms.Label(); + this.classNameLabel = new System.Windows.Forms.Label(); + this.dacClosedLabel = new System.Windows.Forms.Label(); + this.dacClosedTextBox = new System.Windows.Forms.TextBox(); + this.dacOpenTextBox = new System.Windows.Forms.TextBox(); + this.dacOpenLabel = new System.Windows.Forms.Label(); + this.parentNameComboBox = new System.Windows.Forms.ComboBox(); + this.pidCoefLabel = new System.Windows.Forms.Label(); + this.pidCoefTextBox = new System.Windows.Forms.TextBox(); + this.storedPosReuseCheckBox = new System.Windows.Forms.CheckBox(); + this.SuspendLayout(); + // + // positionTextBox + // + this.positionTextBox.Enabled = false; + this.positionTextBox.Location = new System.Drawing.Point(138, 78); + this.positionTextBox.Name = "positionTextBox"; + this.positionTextBox.Size = new System.Drawing.Size(46, 20); + this.positionTextBox.TabIndex = 6; + // + // positionLabel + // + this.positionLabel.AutoSize = true; + this.positionLabel.Location = new System.Drawing.Point(28, 81); + this.positionLabel.Name = "positionLabel"; + this.positionLabel.Size = new System.Drawing.Size(18, 13); + this.positionLabel.TabIndex = 5; + this.positionLabel.Text = "ID"; + // + // parentNameLabel + // + this.parentNameLabel.AutoSize = true; + this.parentNameLabel.Location = new System.Drawing.Point(28, 57); + this.parentNameLabel.Name = "parentNameLabel"; + this.parentNameLabel.Size = new System.Drawing.Size(69, 13); + this.parentNameLabel.TabIndex = 3; + this.parentNameLabel.Text = "Parent Name"; + // + // nameTextBox + // + this.nameTextBox.Enabled = false; + this.nameTextBox.Location = new System.Drawing.Point(138, 30); + this.nameTextBox.Name = "nameTextBox"; + this.nameTextBox.Size = new System.Drawing.Size(130, 20); + this.nameTextBox.TabIndex = 2; + // + // nameLabel + // + this.nameLabel.AutoSize = true; + this.nameLabel.Location = new System.Drawing.Point(28, 33); + this.nameLabel.Name = "nameLabel"; + this.nameLabel.Size = new System.Drawing.Size(35, 13); + this.nameLabel.TabIndex = 1; + this.nameLabel.Text = "Name"; + // + // classNameLabel + // + this.classNameLabel.AutoSize = true; + this.classNameLabel.Location = new System.Drawing.Point(135, 9); + this.classNameLabel.Name = "classNameLabel"; + this.classNameLabel.Size = new System.Drawing.Size(89, 13); + this.classNameLabel.TabIndex = 0; + this.classNameLabel.Text = "ComponentName"; + // + // dacClosedLabel + // + this.dacClosedLabel.AutoSize = true; + this.dacClosedLabel.Location = new System.Drawing.Point(28, 104); + this.dacClosedLabel.Name = "dacClosedLabel"; + this.dacClosedLabel.Size = new System.Drawing.Size(93, 13); + this.dacClosedLabel.TabIndex = 7; + this.dacClosedLabel.Text = "DAC when Closed"; + // + // dacClosedTextBox + // + this.dacClosedTextBox.Enabled = false; + this.dacClosedTextBox.Location = new System.Drawing.Point(138, 101); + this.dacClosedTextBox.Name = "dacClosedTextBox"; + this.dacClosedTextBox.Size = new System.Drawing.Size(46, 20); + this.dacClosedTextBox.TabIndex = 8; + // + // dacOpenTextBox + // + this.dacOpenTextBox.Enabled = false; + this.dacOpenTextBox.Location = new System.Drawing.Point(138, 124); + this.dacOpenTextBox.Name = "dacOpenTextBox"; + this.dacOpenTextBox.Size = new System.Drawing.Size(46, 20); + this.dacOpenTextBox.TabIndex = 10; + // + // dacOpenLabel + // + this.dacOpenLabel.AutoSize = true; + this.dacOpenLabel.Location = new System.Drawing.Point(28, 127); + this.dacOpenLabel.Name = "dacOpenLabel"; + this.dacOpenLabel.Size = new System.Drawing.Size(87, 13); + this.dacOpenLabel.TabIndex = 9; + this.dacOpenLabel.Text = "DAC when Open"; + // + // parentNameComboBox + // + this.parentNameComboBox.Enabled = false; + this.parentNameComboBox.FormattingEnabled = true; + this.parentNameComboBox.Location = new System.Drawing.Point(138, 54); + this.parentNameComboBox.Name = "parentNameComboBox"; + this.parentNameComboBox.Size = new System.Drawing.Size(130, 21); + this.parentNameComboBox.TabIndex = 4; + // + // pidCoefLabel + // + this.pidCoefLabel.AutoSize = true; + this.pidCoefLabel.Location = new System.Drawing.Point(28, 150); + this.pidCoefLabel.Name = "pidCoefLabel"; + this.pidCoefLabel.Size = new System.Drawing.Size(78, 13); + this.pidCoefLabel.TabIndex = 11; + this.pidCoefLabel.Text = "PID Coefficient"; + // + // pidCoefTextBox + // + this.pidCoefTextBox.Enabled = false; + this.pidCoefTextBox.Location = new System.Drawing.Point(138, 147); + this.pidCoefTextBox.Name = "pidCoefTextBox"; + this.pidCoefTextBox.Size = new System.Drawing.Size(46, 20); + this.pidCoefTextBox.TabIndex = 12; + // + // storedPosReuseCheckBox + // + this.storedPosReuseCheckBox.AutoSize = true; + this.storedPosReuseCheckBox.Enabled = false; + this.storedPosReuseCheckBox.Location = new System.Drawing.Point(31, 174); + this.storedPosReuseCheckBox.Name = "storedPosReuseCheckBox"; + this.storedPosReuseCheckBox.Size = new System.Drawing.Size(162, 17); + this.storedPosReuseCheckBox.TabIndex = 13; + this.storedPosReuseCheckBox.Text = "Enable stored position re-use"; + this.storedPosReuseCheckBox.UseVisualStyleBackColor = true; + // + // RegulValveCfgCtrl + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.storedPosReuseCheckBox); + this.Controls.Add(this.pidCoefTextBox); + this.Controls.Add(this.pidCoefLabel); + this.Controls.Add(this.parentNameComboBox); + this.Controls.Add(this.dacOpenTextBox); + this.Controls.Add(this.dacOpenLabel); + this.Controls.Add(this.dacClosedTextBox); + this.Controls.Add(this.dacClosedLabel); + this.Controls.Add(this.positionTextBox); + this.Controls.Add(this.positionLabel); + this.Controls.Add(this.parentNameLabel); + this.Controls.Add(this.nameTextBox); + this.Controls.Add(this.nameLabel); + this.Controls.Add(this.classNameLabel); + this.Name = "RegulValveCfgCtrl"; + this.Size = new System.Drawing.Size(300, 200); + this.Load += new System.EventHandler(this.RegulationValveCfgCtrl_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TextBox positionTextBox; + private System.Windows.Forms.Label positionLabel; + private System.Windows.Forms.Label parentNameLabel; + private System.Windows.Forms.TextBox nameTextBox; + private System.Windows.Forms.Label nameLabel; + private System.Windows.Forms.Label classNameLabel; + private System.Windows.Forms.Label dacClosedLabel; + private System.Windows.Forms.TextBox dacClosedTextBox; + private System.Windows.Forms.TextBox dacOpenTextBox; + private System.Windows.Forms.Label dacOpenLabel; + private System.Windows.Forms.ComboBox parentNameComboBox; + private System.Windows.Forms.Label pidCoefLabel; + private System.Windows.Forms.TextBox pidCoefTextBox; + private System.Windows.Forms.CheckBox storedPosReuseCheckBox; + } +} diff --git a/TestBenchFramework/BenchControl/Elde/RegulValve/RegulValveCfgCtrl.cs b/TestBenchFramework/BenchControl/Elde/RegulValve/RegulValveCfgCtrl.cs new file mode 100644 index 000000000..ad870b19f --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/RegulValve/RegulValveCfgCtrl.cs @@ -0,0 +1,120 @@ +using System; +using System.Windows.Forms; +using log4net; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.Elde.RegulValve +{ + public partial class RegulValveCfgCtrl : UserControl, IComponentCfgCtrl + { + static readonly ILog log = LogManager.GetLogger(typeof(RegulValveCfgCtrl)); + + ComponentParametersDlg parent; + RegulValveCfg config; + public IComponentCfg Config + { + get { return config as IComponentCfg; } + set + { + config = value as RegulValveCfg; + Redraw(); + } + } + + public RegulValveCfgCtrl() + { + InitializeComponent(); + } + + private void RegulationValveCfgCtrl_Load(object sender, EventArgs e) + { + parent = ParentForm as ComponentParametersDlg; + if (parent == null) return; + + if (parent.TbfComponents != null) + { + foreach (var cmpnt in parent.TbfComponents) + { + if (TbfComponents.CmpntFactoryFromClassName(cmpnt.ClassName) is Elde.ControlBoardFactory) + { + parentNameComboBox.Items.Add(cmpnt.Name); + } + } + } + + Redraw(); + } + + void Redraw() + { + if (config == null) return; /// Control was not loaded, settings were not changed + + classNameLabel.Text = config.Factory.ClassName; + nameTextBox.Text = config.Name; + parentNameComboBox.Text = string.IsNullOrEmpty(config.ParentName) ? "---" : config.ParentName; + positionTextBox.Text = config.Position.ToString(); + dacClosedTextBox.Text = config.DacValueClosed.ToString(); + dacOpenTextBox.Text = config.DacValueOpen.ToString(); + pidCoefTextBox.Text = config.PidCoef.ToString(); + storedPosReuseCheckBox.Checked = config.StoredPositionReuse; + } + + public void Unlock() + { + nameTextBox.Enabled = true; + parentNameComboBox.Enabled = true; + positionTextBox.Enabled = true; + dacClosedTextBox.Enabled = true; + dacOpenTextBox.Enabled = true; + pidCoefTextBox.Enabled = true; + storedPosReuseCheckBox.Enabled = true; + } + + public CfgVerifyFlags VerifyCfg(ref string message) + { + CfgVerifyFlags flags = CfgVerifyFlags.None; + + int dummy; + if (!parentNameComboBox.Items.Contains(parentNameComboBox.Text)) + { + flags |= CfgVerifyFlags.Error; + message += Environment.NewLine + "Invalid 'Parent Name'"; + } + if (!int.TryParse(positionTextBox.Text, out dummy) || dummy < 1 || dummy > 5) + { + flags |= CfgVerifyFlags.Error; + message += Environment.NewLine + "'Position' should be between 1 and 5"; + } + if (!int.TryParse(dacClosedTextBox.Text, out dummy) || dummy < 0 || dummy > 1023) + { + flags |= CfgVerifyFlags.Error; + message += Environment.NewLine + "'DAC when Closed' should be between 0 and 1023"; + } + if (!int.TryParse(dacOpenTextBox.Text, out dummy) || dummy < 0 || dummy > 1023) + { + flags |= CfgVerifyFlags.Error; + message += Environment.NewLine + "'DAC when Open' should be between 0 and 1023"; + } + if (!int.TryParse(pidCoefTextBox.Text, out dummy) || dummy < 0 || dummy > 100) + { + flags |= CfgVerifyFlags.Error; + message += Environment.NewLine + "'PID Coefficient' should be between 0 and 100"; + } + + return flags; + } + + public void UpdateCfg() + { + if (config == null) return; /// Control was not loaded, settings were not changed + + config.Name = nameTextBox.Text; + config.ParentName = parentNameComboBox.Text.Equals("---") ? string.Empty : parentNameComboBox.Text; + config.Position = int.Parse(positionTextBox.Text); + config.DacValueClosed = int.Parse(dacClosedTextBox.Text); + config.DacValueOpen = int.Parse(dacOpenTextBox.Text); + config.PidCoef = int.Parse(pidCoefTextBox.Text); + config.StoredPositionReuse = storedPosReuseCheckBox.Checked; + } + } +} diff --git a/TestBenchFramework/BenchControl/Elde/RegulValve/RegulValveCfgCtrl.resx b/TestBenchFramework/BenchControl/Elde/RegulValve/RegulValveCfgCtrl.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/RegulValve/RegulValveCfgCtrl.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/BenchControl/Elde/RegulValve/RegulValveFactory.cs b/TestBenchFramework/BenchControl/Elde/RegulValve/RegulValveFactory.cs new file mode 100644 index 000000000..041e71e0e --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/RegulValve/RegulValveFactory.cs @@ -0,0 +1,39 @@ +using System.Collections.Generic; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.Elde.RegulValve +{ + public class RegulValveFactory : IComponentFactory + { + public string ClassName { get { return "RegulationValve"; } } + public bool HasProcedureParams { get { return false; } } + public bool HasTestParams { get { return false; } } + public IParamsProvider GetTestParams(Entities.ComponentTest testParams) { return null; } + public IParamsProvider GetProcedureParams(Entities.ComponentProcedure procedureParams) { return null; } + + /// Max. number of components of this class in the system + public int MaxCount { get { return 5; } } + + public IComponentCfg DefaultConfig(IList components) + { + return new RegulValveCfg(this, "RegulationValve", "CB", 1, 100, 500, 20, false); + } + + public IComponentCfgCtrl CreateCfgCtrl() + { + return new RegulValveCfgCtrl(); + } + + public IComponent ComponentFromCmpntCfg(IComponentCfg config, IList components) + { + return new RegulValve((RegulValveCfg)config, components); + } + + public IComponentCfg CmpntCfgFromCmpntEntity(Entities.Component component) + { + return RegulValveCfg.CreateFromDbEntity(component, this); + } + + public void ResetStaticProperties() { RegulValve.ResetStaticProperties(); } + } +} diff --git a/TestBenchFramework/BenchControl/Elde/RegulValve/SetFlowOp.cs b/TestBenchFramework/BenchControl/Elde/RegulValve/SetFlowOp.cs new file mode 100644 index 000000000..0ae4845c1 --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/RegulValve/SetFlowOp.cs @@ -0,0 +1,269 @@ +using System; +using System.Collections.Generic; +using log4net; +using TBF.BenchControl.GenericDevices; + +namespace TBF.BenchControl.Elde.RegulValve +{ + public class SetFlowOp : IOperation + { + private static readonly ILog log = LogManager.GetLogger(typeof(SetFlowOp)); + public override string ToString() + { + return string.Format("SetFlowOp({0},{1},{2})", regulValve.Name, reqFlowLo, reqFlowHi); + } + + /// Set by the constructor + readonly ControlBoardDev controlBoard; + readonly Elde.FlowMeter.FlowMeter flowMeter; + readonly Elde.RegulValve.RegulValve regulValve; + readonly int regulValveNr; + readonly int flowMeterNr; + readonly float reqFlowLo; + readonly float reqFlowHi; + readonly float reqFlowAve; + readonly int timeout; + readonly bool leaveMeasurementRunning; + + /// Process values + enum OpState + { + Idle = 0, + ValveMoveToPosition, + SettingPosition, + ValveMoveToFlow, + SettingFlow, + FlowReached, + } + OpState opState; + + float targetPositionLo; + float targetPositionHi; + + int expireTime; + FloatBox measuredFlow; + + + /// + /// Set required water flow. Conditionally leave the measurement running. + /// Events: FlowSet, FlowTimeOut + /// + /// Control board device + /// Regulation valve component + /// Flowmeter component + /// Lower limit of the flow to be achieved in [m3/h] + /// Upper limit of the flow to be achieved in [m3/h] + /// Timeout for the flow setting in [s] + /// true = Leave the measurement running after op. stop + /// Only Elde.Valve flow are used, other flow on the lists are ignored + public SetFlowOp(ControlBoardDev controlBoard, IRegulValve regulValve, IFlowMeter flowMeter, + float requiredFlowLo, float requiredFlowHi, FloatBox measuredFlow, int timeout, bool leaveMeasurementRunning) + { + if (controlBoard == null) throw new ArgumentNullException("ctrlBoard"); + this.controlBoard = controlBoard; + + this.regulValve = regulValve as Elde.RegulValve.RegulValve; + if (regulValve == null) throw new ArgumentNullException("regValve is null or not Elde"); + this.regulValveNr = this.regulValve.Position; + + this.flowMeter = flowMeter as Elde.FlowMeter.FlowMeter; + if (flowMeter == null) throw new ArgumentNullException("flowMeter in null or not Elde"); + this.flowMeterNr = this.flowMeter.Position; + + this.reqFlowLo = requiredFlowLo; + this.reqFlowHi = requiredFlowHi; + this.reqFlowAve = (reqFlowLo + reqFlowHi) / 2.0f; + this.measuredFlow = measuredFlow; + + this.timeout = timeout; + + this.leaveMeasurementRunning = leaveMeasurementRunning; + + log.Debug(this.ToString()); + } + + /// + /// Set required water flow - Do not leave the measurement running. + /// Events: FlowSet + /// + public SetFlowOp(ControlBoardDev controlBoard, IRegulValve regValve, IFlowMeter flowMeter, + float requiredFlowLo, float requiredFlowHi, FloatBox measuredFlow, int timeout) + : this(controlBoard, regValve, flowMeter, requiredFlowLo, requiredFlowHi, measuredFlow, timeout, false) + { + } + + /// + /// Set required water flow - No timeout. + /// Events: FlowSet + /// + public SetFlowOp(ControlBoardDev controlBoard, IRegulValve regValve, IFlowMeter flowMeter, + float requiredFlowLo, float requiredFlowHi, FloatBox measuredFlow) + : this(controlBoard, regValve, flowMeter, requiredFlowLo, requiredFlowHi, measuredFlow, int.MaxValue, false) + { + } + + /// + /// Fetch target position limits from the dictionary or return false + /// + /// Average of the flow targer range (input) + /// Target valve position low limit (output) + /// Target valve position high limit (output) + /// true when positions for the target flow are stored in the memory, otherwise return false + bool FetchTargetPosition(float avgReqFlow, out float positionLo, out float positionHi) + { + float targetPosition; + if (regulValve.Dict.TryGetValue(avgReqFlow, out targetPosition)) + { + positionLo = Math.Max(targetPosition * 0.95f, 0.0f); + positionHi = Math.Min(targetPosition * 1.05f, 100.0f); + return true; + } + else + { + positionLo = 0.0f; + positionHi = 0.0f; + return false; + } + } + + void StoreTargetPosition(float avgReqFlow, float actPosition) + { + if (!regulValve.Dict.ContainsKey(reqFlowAve)) + { + regulValve.Dict.Add(new KeyValuePair(avgReqFlow, actPosition)); + } + return; + } + + /// Start this operation + public void Start() + { + if (regulValve.RegulValveCfg.StoredPositionReuse && FetchTargetPosition(reqFlowAve, out targetPositionLo, out targetPositionHi)) + { + log.InfoFormat("Start(): rv#={0} flowMtr#={1} TARGET: flowLo={2} flowHi={3} FETCHED: posLo={4} posHi={5}", + regulValveNr, flowMeterNr, reqFlowLo, reqFlowHi, targetPositionLo, targetPositionHi); + + opState = OpState.ValveMoveToPosition; + } + else + { + log.InfoFormat("Start(): rv#={0} flowMtr#={1} TARGET: flowLo={2} flowHi={3}", + regulValveNr, flowMeterNr, reqFlowLo, reqFlowHi); + + opState = OpState.ValveMoveToFlow; + } + + expireTime = StateMachine.CurrentTime + timeout; + if (expireTime < 0) expireTime = int.MaxValue; + + TestMethods tm = 0; + StopDevs sd = 0; + controlBoard.SendCommand(Command.Start, flowMeterNr, controlBoard.Route, int.MaxValue, tm, + 0.0f, regulValve.RegulValveCfg.PidCoef, 0, sd); + } + + /// Run this operation + /// + /// Event.None, Event.FlowReached, Event.RegulValveTimeOut, Event.Error + /// + public Event Run() + { + float rvPosition = controlBoard.RValvePosition(regulValveNr); + float flowMtrFreq = controlBoard.ReferenceFreq; + float flow = flowMtrFreq * flowMeter.NominalFlow / 2000.0f; + + if (measuredFlow != null) measuredFlow.F = flow; + + log.InfoFormat("Run(): rv#={0} pos={1}% freq={2} flow={3} opState={4}", + regulValveNr, rvPosition.ToString("F1"), flowMtrFreq, flow, opState); + + if (opState == OpState.ValveMoveToPosition) + { + controlBoard.ValveMove(regulValveNr, RegulValveMode.TargetPosition, + new float[2] { targetPositionLo, targetPositionHi }); + + opState = OpState.SettingPosition; + return Event.None; + } + else if (opState == OpState.SettingPosition) + { + if ((targetPositionLo <= rvPosition) && (rvPosition <= targetPositionHi)) + { + opState = OpState.ValveMoveToFlow; + } + return Event.None; + } + else if (opState == OpState.ValveMoveToFlow) + { + if (reqFlowLo >= reqFlowHi || reqFlowLo > flowMeter.NominalFlow || reqFlowHi <= 0) + { + return Event.Error; + } + + log.InfoFormat("Run(): rv#={0} flowMtr#={1} TARGET: flowLo={2} flowHi={3}", + regulValveNr, flowMeterNr, reqFlowLo, reqFlowHi); + + float freqLo = 2000.0f * reqFlowLo / flowMeter.NominalFlow; + float freqHi = 2000.0f * reqFlowHi / flowMeter.NominalFlow; + controlBoard.ValveMove(regulValveNr, RegulValveMode.TargetFrequency, + new float[2] { freqLo, freqHi }); + + opState = OpState.SettingFlow; + return Event.None; + } + else if (opState == OpState.SettingFlow) + { + if ((reqFlowLo <= flow) && (flow <= reqFlowHi)) + { + if (regulValve.RegulValveCfg.StoredPositionReuse) + { + float storedPosition; + if (regulValve.Dict.TryGetValue(reqFlowAve, out storedPosition)) + { + /// update the stored valve position + StoreTargetPosition(reqFlowAve, (rvPosition + storedPosition) / 2.0f); + log.InfoFormat("Run(): rv#={0} reqFlow={1} pos={2}% stored={3} <--- Updating a stored position", + regulValveNr, reqFlowAve, rvPosition.ToString("F1"), storedPosition); + } + else + { + /// store the valve position + StoreTargetPosition(reqFlowAve, rvPosition); + log.InfoFormat("Run(): rv#={0} reqFlow={1} pos={2}% <--- Storing a new position", + regulValveNr, reqFlowAve, rvPosition.ToString("F1")); + } + } + + opState = OpState.FlowReached; + return Event.FlowReached; + } + else if (StateMachine.CurrentTime > expireTime) + { + return Event.RegulValveTimeOut; + } + else + { + return Event.None; + } + } + else /// opState == OpState.FlowReached + { + return Event.FlowReached; + } + } + + /// Start this operation + public void Stop() + { + opState = OpState.Idle; + + if (leaveMeasurementRunning) return; + + /// Stop measurement + TestMethods tm = 0; + StopDevs sd = StopDevs.RegValveRegulation; + controlBoard.SendCommand(Command.Stop, flowMeterNr, controlBoard.Route, 50000, tm, + 0.0f, 20, 0, sd); + } + } +} diff --git a/TestBenchFramework/BenchControl/Elde/RegulValve/SetRegulValvePositionOp.cs b/TestBenchFramework/BenchControl/Elde/RegulValve/SetRegulValvePositionOp.cs new file mode 100644 index 000000000..2421d3c7f --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/RegulValve/SetRegulValvePositionOp.cs @@ -0,0 +1,127 @@ +using System; +using System.Collections.Generic; +using log4net; +using TBF.BenchControl.GenericDevices; + +namespace TBF.BenchControl.Elde.RegulValve +{ + public class SetRegulValvePositionOp : IOperation + { + private static readonly ILog log = LogManager.GetLogger(typeof(SetRegulValvePositionOp)); + public override string ToString() + { + return string.Format("SetRegulValvePositionOp({0},{1},{2})", regulValve.Name, posLoPct, posHiPct); + } + + /// Set by the constructor + readonly ControlBoardDev controlBoard; + readonly RegulValve regulValve; + readonly int regulValveNr; + readonly float posLoPct; + readonly float posHiPct; + readonly int timeout; + + /// Process values + bool firstRun; + int expireTime; + bool positionReached; + + /// + /// Set required water flow. + /// Events: FlowSet, FlowTimeOut + /// + /// Control board device + /// Regulation valve component + /// Lower limit of the position to be achieved + /// Upper limit of the position to be achieved + /// Timeout in sec. for setting the flow + /// Only Elde.Valve flow are used, other flow on the lists are ignored + public SetRegulValvePositionOp(ControlBoardDev controlBoard, RegulValve regulValve, float posLoPct, float posHiPct, int timeout) + { + if (controlBoard == null) throw new ArgumentNullException("ctrlBoard"); + this.controlBoard = controlBoard; + + this.regulValve = regulValve as RegulValve; + if (regulValve == null) throw new ArgumentNullException("regValve is null or not Elde"); + this.regulValveNr = this.regulValve.Position; + + this.posLoPct = posLoPct; + this.posHiPct = posHiPct; + + this.timeout = timeout; + + log.Debug(this.ToString()); + } + + /// + /// Set required water flow - no timeout. + /// Events: FlowSet + /// + public SetRegulValvePositionOp(ControlBoardDev controlBoard, RegulValve regValve, float posLoPct, float posHiPct) + : this(controlBoard, regValve, posLoPct, posHiPct, int.MaxValue) + { + } + + /// Start this operation + public void Start() + { + firstRun = true; + positionReached = false; + expireTime = StateMachine.CurrentTime + timeout; + log.InfoFormat("Start(): RV#={0}, reqPosLo={1}%, reqPosHi={2}%", regulValveNr, posLoPct.ToString("F1"), posHiPct.ToString("F1")); + } + + /// Run this operation + /// + /// Event.SetFlowDone + /// + public Event Run() + { + if (firstRun) + { + if (posLoPct >= posHiPct || posLoPct >= 100.0f || posHiPct <= 0) + { + return Event.Error; + } + + firstRun = false; + + controlBoard.ValveMove(regulValveNr, + RegulValveMode.TargetPosition, + new float[2] { posLoPct, posHiPct }); + return Event.None; + } + + if (positionReached) return Event.PositionReached; + + float positionPct = controlBoard.RValvePosition(regulValveNr); + log.WarnFormat("Run(): RV#={0}, actPos={1}%", regulValveNr, positionPct.ToString("F1")); + + if (posLoPct >= posHiPct || posLoPct >= 100.0f || posHiPct <= 0) + { + return Event.Error; + } + else if (posLoPct <= positionPct && positionPct <= posHiPct) + { + positionReached = true; + return Event.PositionReached; + } + else if (StateMachine.CurrentTime > expireTime) + { + return Event.RegulValveTimeOut; + } + else + { + return Event.None; + } + } + + /// Stop this operation + public void Stop() + { + controlBoard.ValveMove(regulValveNr, + RegulValveMode.Stop, + new float[2] { posLoPct, posHiPct }); + } + } +} diff --git a/TestBenchFramework/BenchControl/Elde/StartMeasurementOp.cs b/TestBenchFramework/BenchControl/Elde/StartMeasurementOp.cs new file mode 100644 index 000000000..569a600cb --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/StartMeasurementOp.cs @@ -0,0 +1,68 @@ +using System; +using log4net; + +namespace TBF.BenchControl.Elde +{ + public class StartMeasurementOp : IOperation + { + private static readonly ILog log = LogManager.GetLogger(typeof(StartMeasurementOp)); + public override string ToString() { return string.Format("StartMeasurementOp(ref={0},pulses={1})", flowMeter.Position, refPulses); } + + /// Set by the constructor + readonly ControlBoardDev controlBoard; + readonly Elde.FlowMeter.FlowMeter flowMeter; + readonly int refPulses; /// Number of reference pulses for a complete test + readonly TestMethods testMethod; + + bool started = false; + + /// + /// Starts the measurement. + /// Events: MeasurementStarted + /// + /// Control board component reference + /// Flow meter component reference + /// Register readers references + /// Water volume for the test in liters + public StartMeasurementOp(ControlBoardDev controlBoardDev, GenericDevices.IFlowMeter flowMeter, int refPulses, TestMethods method) + { + if (controlBoardDev == null) throw new ArgumentNullException("controlBoardDev"); + this.controlBoard = controlBoardDev; + + this.flowMeter = flowMeter as Elde.FlowMeter.FlowMeter; + if (this.flowMeter == null) throw new ArgumentException("flowMeter is null or is not Elde"); + + this.refPulses = refPulses; + this.testMethod = method; + + log.Debug(this.ToString()); + } + + /// Start this operation + public void Start() + { + controlBoard.SendCommand(Command.Start, flowMeter.Position, controlBoard.RRoute, refPulses, testMethod, + 0.0f, 20, 0, StopDevs.None); + } + + /// Run this operation + /// + /// Event.FlowInDone or Event.FlowOutDone + /// + public Event Run() + { + if (started) return Event.MeasurementStarted; + if (0 != (controlBoard.StatusP & StatusP.TestInProgress)) + { + started = true; + return Event.MeasurementStarted; + } + return Event.None; + } + + /// Stop this operation + public void Stop() + { + } + } +} diff --git a/TestBenchFramework/BenchControl/Elde/StopPreviousOp.cs b/TestBenchFramework/BenchControl/Elde/StopPreviousOp.cs new file mode 100644 index 000000000..02312595e --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/StopPreviousOp.cs @@ -0,0 +1,63 @@ +using System; +using log4net; + +namespace TBF.BenchControl.Elde +{ + public class StopPreviousOp : IOperation + { + private static readonly ILog log = LogManager.GetLogger(typeof(StopPreviousOp)); + public override string ToString() { return string.Format("StopPreviousOp(.)"); } + + /// Set by the constructor + readonly ControlBoardDev controlBoard; + + bool stopped = false; + + /// + /// Stop the previous control board operation (diverter, gate, etc.) + /// Events: None or PreviousStopped + /// + /// Control board component reference + public StopPreviousOp(ControlBoardDev controlBoardDev) + { + if (controlBoardDev == null) throw new ArgumentNullException("controlBoardDev"); + this.controlBoard = controlBoardDev; + + log.Debug(this.ToString()); + } + + /// Start this operation + public void Start() + { + controlBoard.SendCommand(Command.Stop, + 0, /// ref. flowmeter number + controlBoard.RRoute, /// route + 0, /// ref. pulses + TestMethods.Diverter, + 0.0f, + 20, + 0, + StopDevs.Diverter | StopDevs.GatePulse | StopDevs.Reference | StopDevs.RegValveRegulation); + } + + /// Run this operation + /// + /// Event.None or Event.PreviousStopped + /// + public Event Run() + { + if (stopped) return Event.PreviousStopped; + if (0 == (controlBoard.StatusP & StatusP.TestCompleted)) + { + stopped = true; + return Event.PreviousStopped; + } + return Event.None; + } + + /// Stop this operation + public void Stop() + { + } + } +} diff --git a/TestBenchFramework/BenchControl/Elde/TempMeter/ReadTempOp.cs b/TestBenchFramework/BenchControl/Elde/TempMeter/ReadTempOp.cs new file mode 100644 index 000000000..40251e171 --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/TempMeter/ReadTempOp.cs @@ -0,0 +1,57 @@ +using System; +using log4net; + +namespace TBF.BenchControl.Elde.TempMeter +{ + public class ReadTempOp : IOperation + { + private static readonly ILog log = LogManager.GetLogger(typeof(ReadTempOp)); + public override string ToString() { return string.Format("ReadTempOp(.,{0},{1},.)", eventDone, tempMeterNr); } + + /// Set by the constructor + ControlBoardDev controlBoardDev; + Event eventDone; + int tempMeterNr; + FloatBox temp; + + /// + /// Events: TempInDone, TempOutDone, TempDivDone or Error + /// + /// TempMeter reference + /// Reference to the variable, value is in degree Celsius + /// Event to be returned by Run() when completed OK + public ReadTempOp(TempMeter tempMeter, ref FloatBox temp, Event eventDone) + { + if (tempMeter == null) throw new ArgumentNullException("tempMeter"); + this.controlBoardDev = tempMeter.ControlBoard; + this.tempMeterNr = tempMeter.Index; + this.temp = temp; + this.eventDone = eventDone; + log.Debug(this.ToString()); + } + public ReadTempOp(TempMeter tempMeter, ref FloatBox temp) + : this(tempMeter, ref temp, Event.TempDone) + { + } + + /// Start this operation + public void Start() + { + } + + /// Run this operation + /// + /// Event.TempInDone, Event.TempOutDone or Event.TempDivDone + /// + public Event Run() + { + temp.F = controlBoardDev.Temperature(tempMeterNr); + return eventDone; + } + + /// Stop this operation + public void Stop() + { + } + } +} diff --git a/TestBenchFramework/BenchControl/Elde/TempMeter/TempMeter.cs b/TestBenchFramework/BenchControl/Elde/TempMeter/TempMeter.cs new file mode 100644 index 000000000..6acd88bf5 --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/TempMeter/TempMeter.cs @@ -0,0 +1,82 @@ +using System; +using System.Collections.Generic; +using log4net; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.Elde.TempMeter +{ + public class TempMeter : IComponent, GenericDevices.ITempMeter + { + /// + /// Info: StartMassMeasurement() and "Balance response = .., Mass = ..." + /// Warn: Start measurement when busy is true + /// + private static readonly ILog log = LogManager.GetLogger(typeof(TempMeter)); + public override string ToString() + { + return string.Format("TempMeter({0},{1})", Name, Index); + } + + public static void ResetStaticProperties() { } + + TempMeterCfg tempMeterCfg; + public Generic.IComponentCfg Cfg { get { return tempMeterCfg; } } + + public string Name { get { return tempMeterCfg.Name; } } + + public readonly ControlBoardDev ControlBoard; + + public readonly int Index; /// 0..7 + public readonly float A1; + public readonly float A2; + public readonly float A3; + public readonly float A4; + public readonly float A5; + + public TempMeter(TempMeterCfg cfg, IList components) + { + if (cfg == null) throw new ArgumentNullException("cfg"); + this.tempMeterCfg = cfg; + + ControlBoard = (ControlBoardDev)TbfComponents.FindComponent(cfg.ParentName, components); + if (ControlBoard == null) throw new Exception("Cannot find " + Name + " parent"); + + Index = cfg.Position; + A1 = cfg.A1; + A2 = cfg.A2; + A3 = cfg.A3; + A4 = cfg.A4; + A5 = cfg.A5; + + /// Prepare data for SendCalibData() control board component method + ControlBoard.TempCalibData[Index, 0] = A1; + ControlBoard.TempCalibData[Index, 1] = A2; + ControlBoard.TempCalibData[Index, 2] = A3; + ControlBoard.TempCalibData[Index, 3] = A4; + ControlBoard.TempCalibData[Index, 4] = A5; + + log.Debug(this.ToString()); + } + + /// + /// Events: TempDone, Error + /// + /// Reference to a variable for the temperature in Celsius + /// ReadTempOp instance reference casted to IOperaton + public IOperation ReadTempOp(ref FloatBox temp) + { + return new ReadTempOp(this, ref temp); + } + + /// + /// Events: tempDone, Error + /// + /// Reference to a variable for the temperature in Celsius + /// Event returned when measurement done + /// ReadTempOp instance reference casted to IOperaton + public IOperation ReadTempOp(ref FloatBox temp, Event tempDone) + { + return new ReadTempOp(this, ref temp, tempDone); + } + } +} diff --git a/TestBenchFramework/BenchControl/Elde/TempMeter/TempMeterCfg.cs b/TestBenchFramework/BenchControl/Elde/TempMeter/TempMeterCfg.cs new file mode 100644 index 000000000..cb7dc18c6 --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/TempMeter/TempMeterCfg.cs @@ -0,0 +1,78 @@ +using System; +using System.IO; +using System.Xml.Serialization; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.Elde.TempMeter +{ + public class TempMeterCfg : ComponentCfgBase, IChildComponentCfg + { + public int Position; /// 0..7 + + public float A1; + public float A2; + public float A3; + public float A4; + public float A5; + + /// Parameterless constructor + public TempMeterCfg() + { + } + /// + /// Temperature meter configuration parameters + /// + /// Temperature meter name + /// Position on the control board 0..7 + /// A1 + /// A2 + /// A3 + /// A4 + /// A5 + public TempMeterCfg(IComponentFactory factory, string name, string parentName, int index, float a1, float a2, float a3, float a4, float a5) + : base(factory, name, parentName) + { + if (index < 0 || index > 7) throw new ArgumentOutOfRangeException("position"); + this.Position = index; + + this.A1 = a1; + this.A2 = a2; + this.A3 = a3; + this.A4 = a4; + this.A5 = a5; + } + public TempMeterCfg(IComponentFactory factory, string name, string parentName, int index) + : this(factory, name, parentName, index, -21.0116f, 0.0017727f, 0.00000000068422f, -7.40415E-16f, 0) + { + } + + public IComponentCfg Clone() + { + return new TempMeterCfg(Factory, Name, ParentName, Position, A1, A2, A3, A4, A5); + } + + public string ToString(int i) + { + return string.Format("index={0}, A1={1}, A2={2}, A3={3}, A4={4}, A5={5}", Position, A1, A2, A3, A4, A5); + } + + public TBF.Entities.Component CreateDbEntity() + { + using (var writer = new StringWriter()) + { + (new XmlSerializer(GetType())).Serialize(writer, this); + return Entities.Component.CreateFromCfg(Name, Factory.ClassName, ParentName, ItemNr, DebugLevel, LogLevel, writer.ToString()); + } + } + + public static IComponentCfg CreateFromDbEntity(Entities.Component component, IComponentFactory factory) + { + using (var reader = new StringReader(component.Parameters)) + { + TempMeterCfg config = (TempMeterCfg)(new XmlSerializer(typeof(TempMeterCfg))).Deserialize(reader); + config.InitCfgBaseFromEntity(component, factory); + return config; + } + } + } +} diff --git a/TestBenchFramework/BenchControl/Elde/TempMeter/TempMeterCfgCtrl.Designer.cs b/TestBenchFramework/BenchControl/Elde/TempMeter/TempMeterCfgCtrl.Designer.cs new file mode 100644 index 000000000..1c4296443 --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/TempMeter/TempMeterCfgCtrl.Designer.cs @@ -0,0 +1,245 @@ +namespace TBF.BenchControl.Elde.TempMeter +{ + partial class TempMeterCfgCtrl + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.positionTextBox = new System.Windows.Forms.TextBox(); + this.positionLabel = new System.Windows.Forms.Label(); + this.parentNameLabel = new System.Windows.Forms.Label(); + this.nameTextBox = new System.Windows.Forms.TextBox(); + this.nameLabel = new System.Windows.Forms.Label(); + this.classNameLabel = new System.Windows.Forms.Label(); + this.a1TextBox = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.a2TextBox = new System.Windows.Forms.TextBox(); + this.label2 = new System.Windows.Forms.Label(); + this.a3TextBox = new System.Windows.Forms.TextBox(); + this.label3 = new System.Windows.Forms.Label(); + this.a5TextBox = new System.Windows.Forms.TextBox(); + this.label5 = new System.Windows.Forms.Label(); + this.a4TextBox = new System.Windows.Forms.TextBox(); + this.label4 = new System.Windows.Forms.Label(); + this.parentNameComboBox = new System.Windows.Forms.ComboBox(); + this.SuspendLayout(); + // + // positionTextBox + // + this.positionTextBox.Enabled = false; + this.positionTextBox.Location = new System.Drawing.Point(130, 82); + this.positionTextBox.Name = "positionTextBox"; + this.positionTextBox.Size = new System.Drawing.Size(46, 20); + this.positionTextBox.TabIndex = 6; + // + // positionLabel + // + this.positionLabel.AutoSize = true; + this.positionLabel.Location = new System.Drawing.Point(20, 85); + this.positionLabel.Name = "positionLabel"; + this.positionLabel.Size = new System.Drawing.Size(44, 13); + this.positionLabel.TabIndex = 5; + this.positionLabel.Text = "Position"; + // + // parentNameLabel + // + this.parentNameLabel.AutoSize = true; + this.parentNameLabel.Location = new System.Drawing.Point(20, 61); + this.parentNameLabel.Name = "parentNameLabel"; + this.parentNameLabel.Size = new System.Drawing.Size(69, 13); + this.parentNameLabel.TabIndex = 3; + this.parentNameLabel.Text = "Parent Name"; + // + // nameTextBox + // + this.nameTextBox.Enabled = false; + this.nameTextBox.Location = new System.Drawing.Point(130, 34); + this.nameTextBox.Name = "nameTextBox"; + this.nameTextBox.Size = new System.Drawing.Size(130, 20); + this.nameTextBox.TabIndex = 2; + // + // nameLabel + // + this.nameLabel.AutoSize = true; + this.nameLabel.Location = new System.Drawing.Point(20, 37); + this.nameLabel.Name = "nameLabel"; + this.nameLabel.Size = new System.Drawing.Size(35, 13); + this.nameLabel.TabIndex = 1; + this.nameLabel.Text = "Name"; + // + // classNameLabel + // + this.classNameLabel.AutoSize = true; + this.classNameLabel.Location = new System.Drawing.Point(127, 10); + this.classNameLabel.Name = "classNameLabel"; + this.classNameLabel.Size = new System.Drawing.Size(83, 13); + this.classNameLabel.TabIndex = 0; + this.classNameLabel.Text = "ComonentName"; + // + // a1TextBox + // + this.a1TextBox.Enabled = false; + this.a1TextBox.Location = new System.Drawing.Point(130, 107); + this.a1TextBox.Name = "a1TextBox"; + this.a1TextBox.Size = new System.Drawing.Size(130, 20); + this.a1TextBox.TabIndex = 8; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(20, 110); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(20, 13); + this.label1.TabIndex = 7; + this.label1.Text = "A1"; + // + // a2TextBox + // + this.a2TextBox.Enabled = false; + this.a2TextBox.Location = new System.Drawing.Point(130, 128); + this.a2TextBox.Name = "a2TextBox"; + this.a2TextBox.Size = new System.Drawing.Size(130, 20); + this.a2TextBox.TabIndex = 10; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(20, 131); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(20, 13); + this.label2.TabIndex = 9; + this.label2.Text = "A2"; + // + // a3TextBox + // + this.a3TextBox.Enabled = false; + this.a3TextBox.Location = new System.Drawing.Point(130, 149); + this.a3TextBox.Name = "a3TextBox"; + this.a3TextBox.Size = new System.Drawing.Size(130, 20); + this.a3TextBox.TabIndex = 12; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(20, 152); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(20, 13); + this.label3.TabIndex = 11; + this.label3.Text = "A3"; + // + // a5TextBox + // + this.a5TextBox.Enabled = false; + this.a5TextBox.Location = new System.Drawing.Point(130, 191); + this.a5TextBox.Name = "a5TextBox"; + this.a5TextBox.Size = new System.Drawing.Size(130, 20); + this.a5TextBox.TabIndex = 16; + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point(20, 194); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(20, 13); + this.label5.TabIndex = 15; + this.label5.Text = "A5"; + // + // a4TextBox + // + this.a4TextBox.Enabled = false; + this.a4TextBox.Location = new System.Drawing.Point(130, 170); + this.a4TextBox.Name = "a4TextBox"; + this.a4TextBox.Size = new System.Drawing.Size(130, 20); + this.a4TextBox.TabIndex = 14; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(20, 173); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(20, 13); + this.label4.TabIndex = 13; + this.label4.Text = "A4"; + // + // parentNameComboBox + // + this.parentNameComboBox.Enabled = false; + this.parentNameComboBox.FormattingEnabled = true; + this.parentNameComboBox.Location = new System.Drawing.Point(130, 58); + this.parentNameComboBox.Name = "parentNameComboBox"; + this.parentNameComboBox.Size = new System.Drawing.Size(130, 21); + this.parentNameComboBox.TabIndex = 4; + // + // TempMeterCfgCtrl + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.parentNameComboBox); + this.Controls.Add(this.a5TextBox); + this.Controls.Add(this.label5); + this.Controls.Add(this.a4TextBox); + this.Controls.Add(this.label4); + this.Controls.Add(this.a3TextBox); + this.Controls.Add(this.label3); + this.Controls.Add(this.a2TextBox); + this.Controls.Add(this.label2); + this.Controls.Add(this.a1TextBox); + this.Controls.Add(this.label1); + this.Controls.Add(this.positionTextBox); + this.Controls.Add(this.positionLabel); + this.Controls.Add(this.parentNameLabel); + this.Controls.Add(this.nameTextBox); + this.Controls.Add(this.nameLabel); + this.Controls.Add(this.classNameLabel); + this.Name = "TempMeterCfgCtrl"; + this.Size = new System.Drawing.Size(300, 240); + this.Load += new System.EventHandler(this.TempMeterCfgCtrl_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TextBox positionTextBox; + private System.Windows.Forms.Label positionLabel; + private System.Windows.Forms.Label parentNameLabel; + private System.Windows.Forms.TextBox nameTextBox; + private System.Windows.Forms.Label nameLabel; + private System.Windows.Forms.Label classNameLabel; + private System.Windows.Forms.TextBox a1TextBox; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox a2TextBox; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.TextBox a3TextBox; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.TextBox a5TextBox; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.TextBox a4TextBox; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.ComboBox parentNameComboBox; + } +} diff --git a/TestBenchFramework/BenchControl/Elde/TempMeter/TempMeterCfgCtrl.cs b/TestBenchFramework/BenchControl/Elde/TempMeter/TempMeterCfgCtrl.cs new file mode 100644 index 000000000..c5f3ec2aa --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/TempMeter/TempMeterCfgCtrl.cs @@ -0,0 +1,140 @@ +using System; +using System.Globalization; +using System.Windows.Forms; +using log4net; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.Elde.TempMeter +{ + public partial class TempMeterCfgCtrl : UserControl, IComponentCfgCtrl + { + static readonly ILog log = LogManager.GetLogger(typeof(TempMeterCfgCtrl)); + + ComponentParametersDlg parent; + TempMeterCfg config; + public IComponentCfg Config + { + get { return config as IComponentCfg; } + set + { + config = value as TempMeterCfg; + Redraw(); + } + } + + public TempMeterCfgCtrl() + { + InitializeComponent(); + } + + private void TempMeterCfgCtrl_Load(object sender, EventArgs e) + { + parent = ParentForm as ComponentParametersDlg; + if (parent == null) return; + + if (parent.TbfComponents != null) + { + foreach (var cmpnt in parent.TbfComponents) + { + if (TbfComponents.CmpntFactoryFromClassName(cmpnt.ClassName) is Elde.ControlBoardFactory) + { + parentNameComboBox.Items.Add(cmpnt.Name); + } + } + } + + Redraw(); + } + + void Redraw() + { + if (config == null) return; /// Control was not loaded, settings were not changed + + classNameLabel.Text = config.Factory.ClassName; + nameTextBox.Text = config.Name; + parentNameComboBox.Text = string.IsNullOrEmpty(config.ParentName) ? "---" : config.ParentName; + positionTextBox.Text = config.Position.ToString(); + a1TextBox.Text = config.A1.ToString(); + a2TextBox.Text = config.A2.ToString(); + a3TextBox.Text = config.A3.ToString(); + a4TextBox.Text = config.A4.ToString(); + a5TextBox.Text = config.A5.ToString(); + } + + public void Unlock() + { + nameTextBox.Enabled = true; + parentNameComboBox.Enabled = true; + positionTextBox.Enabled = true; + a1TextBox.Enabled = true; + a2TextBox.Enabled = true; + a3TextBox.Enabled = true; + a4TextBox.Enabled = true; + a5TextBox.Enabled = true; + } + + public CfgVerifyFlags VerifyCfg(ref string message) + { + CfgVerifyFlags flags = CfgVerifyFlags.None; + + int dummy; + if (!parentNameComboBox.Items.Contains(parentNameComboBox.Text)) + { + flags |= CfgVerifyFlags.Error; + message += Environment.NewLine + "Invalid 'Parent Name'"; + } + if (!int.TryParse(positionTextBox.Text, out dummy) || dummy < 0 || dummy > 7) + { + flags |= CfgVerifyFlags.Error; + message += Environment.NewLine + "'Position' should be between 0 and 7"; + } + + float fdummy; + if (!Utils.TryParseEFloat(a1TextBox.Text, out fdummy)) + { + flags |= CfgVerifyFlags.Error; + message += Environment.NewLine + "'A1' is not valid"; + } + + if (!Utils.TryParseEFloat(a2TextBox.Text, out fdummy)) + { + flags |= CfgVerifyFlags.Error; + message += Environment.NewLine + "'A2' is not valid"; + } + + if (!Utils.TryParseEFloat(a3TextBox.Text, out fdummy)) + { + flags |= CfgVerifyFlags.Error; + message += Environment.NewLine + "'A3' is not valid"; + } + + if (!Utils.TryParseEFloat(a4TextBox.Text, out fdummy)) + { + flags |= CfgVerifyFlags.Error; + message += Environment.NewLine + "'A4' is not valid"; + } + + if (!Utils.TryParseEFloat(a5TextBox.Text, out fdummy)) + { + flags |= CfgVerifyFlags.Error; + message += Environment.NewLine + "'A5' is not valid"; + } + + return flags; + } + + public void UpdateCfg() + { + if (config == null) return; /// Control was not loaded, settings were not changed + + config.Name = nameTextBox.Text; + config.ParentName = parentNameComboBox.Text.Equals("---") ? string.Empty : parentNameComboBox.Text; + config.Position = int.Parse(positionTextBox.Text); + bool updateOk = Utils.TryParseEFloat(a1TextBox.Text, out config.A1) && + Utils.TryParseEFloat(a2TextBox.Text, out config.A2) && + Utils.TryParseEFloat(a3TextBox.Text, out config.A3) && + Utils.TryParseEFloat(a4TextBox.Text, out config.A4) && + Utils.TryParseEFloat(a5TextBox.Text, out config.A5); + } + } +} diff --git a/TestBenchFramework/BenchControl/Elde/TempMeter/TempMeterCfgCtrl.resx b/TestBenchFramework/BenchControl/Elde/TempMeter/TempMeterCfgCtrl.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/TempMeter/TempMeterCfgCtrl.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/BenchControl/Elde/TempMeter/TempMeterFactory.cs b/TestBenchFramework/BenchControl/Elde/TempMeter/TempMeterFactory.cs new file mode 100644 index 000000000..6cab71abd --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/TempMeter/TempMeterFactory.cs @@ -0,0 +1,39 @@ +using System.Collections.Generic; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.Elde.TempMeter +{ + public class TempMeterFactory : IComponentFactory + { + public string ClassName { get { return "TempMeter"; } } + public bool HasProcedureParams { get { return false; } } + public bool HasTestParams { get { return false; } } + public IParamsProvider GetTestParams(Entities.ComponentTest testParams) { return null; } + public IParamsProvider GetProcedureParams(Entities.ComponentProcedure procedureParams) { return null; } + + /// Max. number of components of this class in the system + public int MaxCount { get { return 8; } } + + public IComponentCfg DefaultConfig(IList components) + { + return new TempMeterCfg(this, "TempMeter", "CB", 0); + } + + public IComponentCfgCtrl CreateCfgCtrl() + { + return new TempMeterCfgCtrl(); + } + + public IComponent ComponentFromCmpntCfg(IComponentCfg config, IList components) + { + return new TempMeter((TempMeterCfg)config, components); + } + + public IComponentCfg CmpntCfgFromCmpntEntity(Entities.Component component) + { + return TempMeterCfg.CreateFromDbEntity(component, this); + } + + public void ResetStaticProperties() { TempMeter.ResetStaticProperties(); } + } +} diff --git a/TestBenchFramework/BenchControl/Elde/UpdateTankWeightOp.cs b/TestBenchFramework/BenchControl/Elde/UpdateTankWeightOp.cs new file mode 100644 index 000000000..0a620546b --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/UpdateTankWeightOp.cs @@ -0,0 +1,48 @@ +using System; +using log4net; + +namespace TBF.BenchControl.Elde +{ + public class UpdateTankWeightOp : IOperation + { + private static readonly ILog log = LogManager.GetLogger(typeof(UpdateTankWeightOp)); + public override string ToString() { return string.Format("UpdateTankWeightOp(.)"); } + + /// Set by the constructor + readonly ControlBoardDev controlBoard; + + /// + /// Stop the previous control board operation (diverter, gate, etc.) + /// Events: None or PreviousStopped + /// + /// Control board component reference + public UpdateTankWeightOp(ControlBoardDev controlBoardDev) + { + if (controlBoardDev == null) throw new ArgumentNullException("controlBoardDev"); + this.controlBoard = controlBoardDev; + + log.Debug(this.ToString()); + } + + /// Start this operation + public void Start() + { + controlBoard.UpdateWeights(); + } + + /// Run this operation + /// + /// Event.None or Event.PreviousStopped + /// + public Event Run() + { + controlBoard.UpdateWeights(); + return Event.None; + } + + /// Stop this operation + public void Stop() + { + } + } +} diff --git a/TestBenchFramework/BenchControl/Elde/Valve/SetValvesOp.cs b/TestBenchFramework/BenchControl/Elde/Valve/SetValvesOp.cs new file mode 100644 index 000000000..a83210ffa --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/Valve/SetValvesOp.cs @@ -0,0 +1,195 @@ +using System; +using System.Collections.Generic; +using log4net; +using TBF.BenchControl.GenericDevices; + +namespace TBF.BenchControl.Elde.Valve +{ + public class SetValvesOp : IOperation + { + private static readonly ILog log = LogManager.GetLogger(typeof(SetValvesOp)); + + /// Set by the constructor + ControlBoardDev controlBoard; + + class SwitchPoint + { + public int TimeSec; + public IList VOpen; + public IList VClose; + public ulong MasksOpen; + public ulong MasksClose; + } + + IList switchPointsRaw; + IList switchPoints; + int nextIx; + int swStartTime; + + /// + /// Processes coupled valves and creates switch points. + /// + /// A list of opening master valves + /// A list of closing master valves + /// + IList CollectSwitchPoints(IList valvesOpen, IList valvesClose) + { + IList result = new List(); + result.Add(new SwitchPoint { TimeSec = 0, VOpen = valvesOpen, VClose = valvesClose }); + + foreach (var valve in StateMachine.CoupledValves) + { + if ((!valve.Invert && valvesOpen.Contains(valve.CoupledTo)) || + (valve.Invert && valvesClose.Contains(valve.CoupledTo))) + { + /// The coupled valve 'valve' is opening + int time = valve.LagOpening; + if (time == 0) + { + result[0].VOpen.Add(valve); + } + else + { + result.Add(new SwitchPoint { TimeSec = time, + VOpen = ValveBase.MakeList(valve), + VClose = new List() }); + } + } + else if ((!valve.Invert && valvesClose.Contains(valve.CoupledTo)) || + (valve.Invert && valvesOpen.Contains(valve.CoupledTo))) + { + /// The coupled valve 'valve' is closing + int time = valve.LagClosing; + if (time == 0) + { + result[0].VClose.Add(valve); + } + else + { + result.Add(new SwitchPoint { TimeSec = time, + VOpen = new List(), + VClose = ValveBase.MakeList(valve) }); + } + } + } + return result; + } + + + IList SortAndMergeSwitchPoints(IList unsorted) + { + IList result = new List(); + + SwitchPoint lastAdded = null; + while (unsorted.Count > 0) + { + SwitchPoint first = null; + foreach (var point in unsorted) + { + if (first == null || first.TimeSec > point.TimeSec) first = point; + } + if (lastAdded == null || lastAdded.TimeSec != first.TimeSec) + { + result.Add(first); + lastAdded = first; + } + else + { + lastAdded.VOpen = ValveBase.Merge(lastAdded.VOpen, first.VOpen); + lastAdded.VClose = ValveBase.Merge(lastAdded.VClose, first.VClose); + } + unsorted.Remove(first); + } + return result; + } + + + void MakeMasks(IList switchPoints, int timeShift) + { + foreach (var point in switchPoints) + { + /// Only Elde.Valve valves are used, other valves are ignored + point.MasksOpen = 0; + foreach (var valve in point.VOpen) + { + if (valve is Valve) point.MasksOpen |= (valve as Valve).Mask; + if (valve is Pump.Pump) point.MasksOpen |= (valve as Pump.Pump).Mask; + if (valve is PumpWithFM.Pump) point.MasksOpen |= (valve as PumpWithFM.Pump).Mask; + } + point.MasksClose = 0; + foreach (var valve in point.VClose) + { + if (valve is Valve) point.MasksClose |= (valve as Valve).Mask; + if (valve is Pump.Pump) point.MasksClose |= (valve as Pump.Pump).Mask; + if (valve is PumpWithFM.Pump) point.MasksClose |= (valve as PumpWithFM.Pump).Mask; + } + point.TimeSec += timeShift; + } + } + + + /// + /// Open and/or close multiple valves. + /// Events: ValvesSet + /// + /// Control board device + /// A list of opening master valves + /// A list of closing master valves + /// Only Elde.Valve valves are used, other valves on the lists are ignored + public SetValvesOp(ControlBoardDev controlBoard, IList valvesOpen, IList valvesClose) + { + if (controlBoard == null) throw new ArgumentNullException("ctrlBoard"); + this.controlBoard = controlBoard; + + if (valvesOpen == null) valvesOpen = new List(); + if (valvesClose == null) valvesOpen = new List(); + + switchPointsRaw = CollectSwitchPoints(valvesOpen, valvesClose); + switchPoints = SortAndMergeSwitchPoints(switchPointsRaw); + int timeShift = -switchPoints[0].TimeSec; + MakeMasks(switchPoints, timeShift); + } + + /// + /// Open one valve and/or close one valve. + /// Events: ValvesSet + /// + /// Control board device + /// Valve to be opened + /// Valve to be closed + /// Only Elde.Valve valves are used, other valves on the lists are ignored + public SetValvesOp(ControlBoardDev controlBoard, IValve valveOpen, IValve valveClose) + : this(controlBoard, ValveBase.MakeList(valveOpen), ValveBase.MakeList(valveClose)) + { + } + + /// Start this operation + public void Start() + { + controlBoard.SetValves(switchPoints[0].MasksOpen, switchPoints[0].MasksClose); + swStartTime = StateMachine.CurrentTime; + nextIx = 1; + } + + /// Run this operation + /// + /// Event.SetValvesDone + /// + public Event Run() + { + if (nextIx >= switchPoints.Count) return Event.ValvesSet; + + if (StateMachine.CurrentTime >= swStartTime + switchPoints[nextIx].TimeSec) + { + controlBoard.SetValves(switchPoints[nextIx].MasksOpen, switchPoints[nextIx].MasksClose); + nextIx++; + } + return Event.None; + } + + /// Start this operation + public void Stop() + { + } + } +} diff --git a/TestBenchFramework/BenchControl/Elde/Valve/Valve.cs b/TestBenchFramework/BenchControl/Elde/Valve/Valve.cs new file mode 100644 index 000000000..f6a8cad22 --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/Valve/Valve.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; +using log4net; +using TBF.BenchControl.GenericDevices; + +namespace TBF.BenchControl.Elde.Valve +{ + public class Valve : GenericDevices.ValveBase, Generic.IComponent, IValve + { + /// + /// Info: StartMassMeasurement() and "Balance response = .., Mass = ..." + /// Warn: Start measurement when busy is true + /// + private static readonly ILog log = LogManager.GetLogger(typeof(Valve)); + public override string ToString() + { + return string.Format("Valve({0},{1},{2})", Name, bitPosition, (CoupledTo != null ? CoupledTo.Cfg.Name : "-")); + } + + public static void ResetStaticProperties() { } + + readonly ValveCfg valveCfg; + public Generic.IComponentCfg Cfg { get { return valveCfg; } } + + readonly IValve coupledTo; + readonly ControlBoardDev controlBoard; + readonly int bitPosition; /// 0 .. 63 + + public string Name { get { return valveCfg.Name; } } + public IValve CoupledTo { get { return coupledTo; } } + public bool Invert { get { return valveCfg.Invert; } } + public int LagOpening { get { return valveCfg.LagOpening; } } + public int LagClosing { get { return valveCfg.LagClosing; } } + + public readonly ulong Mask; /// derived from bitPosition in the constructor + + + public Valve(ValveCfg cfg, IList components) + { + if (cfg == null) throw new ArgumentNullException("cfg"); + this.valveCfg = cfg; + + controlBoard = (ControlBoardDev)TbfComponents.FindComponent(cfg.ParentName, components); + if (controlBoard == null) throw new Exception("Cannot find " + Name + " parent"); + + if (bitPosition < 0 || bitPosition >= 64) throw new ArgumentOutOfRangeException("position"); + this.bitPosition = cfg.BitPosition; + this.Mask = (((ulong)1) << bitPosition); + + if (cfg.CoupledToName != null) + { + this.coupledTo = (IValve)TbfComponents.FindComponent(cfg.CoupledToName, components); + } + + log.Debug(this.ToString()); + } + + public bool State + { + get { return (controlBoard.Route & Mask) != 0; } + } + } +} diff --git a/TestBenchFramework/BenchControl/Elde/Valve/ValveCfg.cs b/TestBenchFramework/BenchControl/Elde/Valve/ValveCfg.cs new file mode 100644 index 000000000..059025cd9 --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/Valve/ValveCfg.cs @@ -0,0 +1,67 @@ +using System.IO; +using System.Xml.Serialization; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.Elde.Valve +{ + public class ValveCfg : ComponentCfgBase, IChildComponentCfg + { + public int BitPosition; /// Bit-position + public string CoupledToName; /// Name of the coupled valve or null + public bool Invert; /// The coupled valve has inverted position + public int LagOpening; /// Delay (referred to the master valve) when opening this valve in [s] + public int LagClosing; /// Delay (referred to the master valve) when closing this valve in [s] + /// Negative values of delays mean an earlier function of the coupled valve. + + /// Parameterless constructor + public ValveCfg() + { + } + /// Constructor 1 + public ValveCfg(IComponentFactory factory, string name, string parentName, int bitPosition, string coupledToName, bool invert, int lagOpening, int lagClosing) + : base(factory, name, parentName) + { + this.BitPosition = bitPosition; + this.CoupledToName = coupledToName; + this.Invert = invert; + this.LagOpening = lagOpening; + this.LagClosing = lagClosing; + } + /// Constructor 2 without CoupledTo valve + public ValveCfg(IComponentFactory factory, string name, string parentName, int bitPosition) + : this(factory, name, parentName, bitPosition, null, false, 0, 0) + { + } + + public IComponentCfg Clone() + { + return new ValveCfg(Factory, Name, ParentName, BitPosition, CoupledToName, Invert, LagOpening, LagClosing); + } + + public string ToString(int i) + { + return string.Format("bit={0}, coupledTo={1}, invert={2}, lagOpen={3}, lagClose={4}", + BitPosition, CoupledToName, (Invert ? "yes" : "no"), LagOpening, LagClosing); + } + + public TBF.Entities.Component CreateDbEntity() + { + using (var writer = new StringWriter()) + { + (new XmlSerializer(GetType())).Serialize(writer, this); + return Entities.Component.CreateFromCfg(Name, Factory.ClassName, ParentName, ItemNr, + DebugLevel, LogLevel, writer.ToString()); + } + } + + public static IComponentCfg CreateFromDbEntity(Entities.Component component, IComponentFactory factory) + { + using (var reader = new StringReader(component.Parameters)) + { + ValveCfg config = (ValveCfg)(new XmlSerializer(typeof(ValveCfg))).Deserialize(reader); + config.InitCfgBaseFromEntity(component, factory); + return config; + } + } + } +} diff --git a/TestBenchFramework/BenchControl/Elde/Valve/ValveCfgCtrl.Designer.cs b/TestBenchFramework/BenchControl/Elde/Valve/ValveCfgCtrl.Designer.cs new file mode 100644 index 000000000..c1803b628 --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/Valve/ValveCfgCtrl.Designer.cs @@ -0,0 +1,214 @@ +namespace TBF.BenchControl.Elde.Valve +{ + partial class ValveCfgCtrl + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.bitPositionTextBox = new System.Windows.Forms.TextBox(); + this.bitPositionLabel = new System.Windows.Forms.Label(); + this.parentNameLabel = new System.Windows.Forms.Label(); + this.nameTextBox = new System.Windows.Forms.TextBox(); + this.nameLabel = new System.Windows.Forms.Label(); + this.classNameLabel = new System.Windows.Forms.Label(); + this.coupledToLabel = new System.Windows.Forms.Label(); + this.invertCheckBox = new System.Windows.Forms.CheckBox(); + this.parentNameComboBox = new System.Windows.Forms.ComboBox(); + this.lagOpeningLabel = new System.Windows.Forms.Label(); + this.lagClosingLabel = new System.Windows.Forms.Label(); + this.lagOpeningTextBox = new System.Windows.Forms.TextBox(); + this.lagClosingTextBox = new System.Windows.Forms.TextBox(); + this.coupledToComboBox = new System.Windows.Forms.ComboBox(); + this.SuspendLayout(); + // + // bitPositionTextBox + // + this.bitPositionTextBox.Enabled = false; + this.bitPositionTextBox.Location = new System.Drawing.Point(138, 82); + this.bitPositionTextBox.Name = "bitPositionTextBox"; + this.bitPositionTextBox.Size = new System.Drawing.Size(81, 20); + this.bitPositionTextBox.TabIndex = 6; + // + // bitPositionLabel + // + this.bitPositionLabel.AutoSize = true; + this.bitPositionLabel.Location = new System.Drawing.Point(22, 85); + this.bitPositionLabel.Name = "bitPositionLabel"; + this.bitPositionLabel.Size = new System.Drawing.Size(59, 13); + this.bitPositionLabel.TabIndex = 5; + this.bitPositionLabel.Text = "Bit Position"; + // + // parentNameLabel + // + this.parentNameLabel.AutoSize = true; + this.parentNameLabel.Location = new System.Drawing.Point(22, 60); + this.parentNameLabel.Name = "parentNameLabel"; + this.parentNameLabel.Size = new System.Drawing.Size(69, 13); + this.parentNameLabel.TabIndex = 3; + this.parentNameLabel.Text = "Parent Name"; + // + // nameTextBox + // + this.nameTextBox.Enabled = false; + this.nameTextBox.Location = new System.Drawing.Point(138, 33); + this.nameTextBox.Name = "nameTextBox"; + this.nameTextBox.Size = new System.Drawing.Size(130, 20); + this.nameTextBox.TabIndex = 2; + // + // nameLabel + // + this.nameLabel.AutoSize = true; + this.nameLabel.Location = new System.Drawing.Point(22, 36); + this.nameLabel.Name = "nameLabel"; + this.nameLabel.Size = new System.Drawing.Size(35, 13); + this.nameLabel.TabIndex = 1; + this.nameLabel.Text = "Name"; + // + // classNameLabel + // + this.classNameLabel.AutoSize = true; + this.classNameLabel.Location = new System.Drawing.Point(136, 13); + this.classNameLabel.Name = "classNameLabel"; + this.classNameLabel.Size = new System.Drawing.Size(83, 13); + this.classNameLabel.TabIndex = 0; + this.classNameLabel.Text = "ComonentName"; + // + // coupledToLabel + // + this.coupledToLabel.AutoSize = true; + this.coupledToLabel.Location = new System.Drawing.Point(22, 124); + this.coupledToLabel.Name = "coupledToLabel"; + this.coupledToLabel.Size = new System.Drawing.Size(56, 13); + this.coupledToLabel.TabIndex = 7; + this.coupledToLabel.Text = "Copled To"; + // + // invertCheckBox + // + this.invertCheckBox.AutoSize = true; + this.invertCheckBox.Enabled = false; + this.invertCheckBox.Location = new System.Drawing.Point(232, 124); + this.invertCheckBox.Name = "invertCheckBox"; + this.invertCheckBox.Size = new System.Drawing.Size(53, 17); + this.invertCheckBox.TabIndex = 9; + this.invertCheckBox.Text = "Invert"; + this.invertCheckBox.UseVisualStyleBackColor = true; + // + // parentNameComboBox + // + this.parentNameComboBox.Enabled = false; + this.parentNameComboBox.FormattingEnabled = true; + this.parentNameComboBox.Location = new System.Drawing.Point(138, 57); + this.parentNameComboBox.Name = "parentNameComboBox"; + this.parentNameComboBox.Size = new System.Drawing.Size(130, 21); + this.parentNameComboBox.TabIndex = 4; + // + // lagOpeningLabel + // + this.lagOpeningLabel.AutoSize = true; + this.lagOpeningLabel.Location = new System.Drawing.Point(22, 147); + this.lagOpeningLabel.Name = "lagOpeningLabel"; + this.lagOpeningLabel.Size = new System.Drawing.Size(109, 13); + this.lagOpeningLabel.TabIndex = 10; + this.lagOpeningLabel.Text = "Lag when opening [s]"; + // + // lagClosingLabel + // + this.lagClosingLabel.AutoSize = true; + this.lagClosingLabel.Location = new System.Drawing.Point(22, 171); + this.lagClosingLabel.Name = "lagClosingLabel"; + this.lagClosingLabel.Size = new System.Drawing.Size(104, 13); + this.lagClosingLabel.TabIndex = 11; + this.lagClosingLabel.Text = "Lag when closing [s]"; + // + // lagOpeningTextBox + // + this.lagOpeningTextBox.Enabled = false; + this.lagOpeningTextBox.Location = new System.Drawing.Point(138, 144); + this.lagOpeningTextBox.Name = "lagOpeningTextBox"; + this.lagOpeningTextBox.Size = new System.Drawing.Size(81, 20); + this.lagOpeningTextBox.TabIndex = 12; + // + // lagClosingTextBox + // + this.lagClosingTextBox.Enabled = false; + this.lagClosingTextBox.Location = new System.Drawing.Point(138, 168); + this.lagClosingTextBox.Name = "lagClosingTextBox"; + this.lagClosingTextBox.Size = new System.Drawing.Size(81, 20); + this.lagClosingTextBox.TabIndex = 13; + // + // coupledToComboBox + // + this.coupledToComboBox.Enabled = false; + this.coupledToComboBox.FormattingEnabled = true; + this.coupledToComboBox.Location = new System.Drawing.Point(138, 121); + this.coupledToComboBox.Name = "coupledToComboBox"; + this.coupledToComboBox.Size = new System.Drawing.Size(81, 21); + this.coupledToComboBox.TabIndex = 14; + // + // ValveCfgCtrl + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.coupledToComboBox); + this.Controls.Add(this.lagClosingTextBox); + this.Controls.Add(this.lagOpeningTextBox); + this.Controls.Add(this.lagClosingLabel); + this.Controls.Add(this.lagOpeningLabel); + this.Controls.Add(this.parentNameComboBox); + this.Controls.Add(this.invertCheckBox); + this.Controls.Add(this.coupledToLabel); + this.Controls.Add(this.bitPositionTextBox); + this.Controls.Add(this.bitPositionLabel); + this.Controls.Add(this.parentNameLabel); + this.Controls.Add(this.nameTextBox); + this.Controls.Add(this.nameLabel); + this.Controls.Add(this.classNameLabel); + this.Name = "ValveCfgCtrl"; + this.Size = new System.Drawing.Size(300, 200); + this.Load += new System.EventHandler(this.ValveCfgCtrl_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TextBox bitPositionTextBox; + private System.Windows.Forms.Label bitPositionLabel; + private System.Windows.Forms.Label parentNameLabel; + private System.Windows.Forms.TextBox nameTextBox; + private System.Windows.Forms.Label nameLabel; + private System.Windows.Forms.Label classNameLabel; + private System.Windows.Forms.Label coupledToLabel; + private System.Windows.Forms.CheckBox invertCheckBox; + private System.Windows.Forms.ComboBox parentNameComboBox; + private System.Windows.Forms.Label lagOpeningLabel; + private System.Windows.Forms.Label lagClosingLabel; + private System.Windows.Forms.TextBox lagOpeningTextBox; + private System.Windows.Forms.TextBox lagClosingTextBox; + private System.Windows.Forms.ComboBox coupledToComboBox; + } +} diff --git a/TestBenchFramework/BenchControl/Elde/Valve/ValveCfgCtrl.cs b/TestBenchFramework/BenchControl/Elde/Valve/ValveCfgCtrl.cs new file mode 100644 index 000000000..28a190ce3 --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/Valve/ValveCfgCtrl.cs @@ -0,0 +1,125 @@ +using System; +using System.Windows.Forms; +using log4net; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.Elde.Valve +{ + public partial class ValveCfgCtrl : UserControl, IComponentCfgCtrl + { + static readonly ILog log = LogManager.GetLogger(typeof(ValveCfgCtrl)); + + ComponentParametersDlg parent; + ValveCfg config; + public IComponentCfg Config + { + get { return config as IComponentCfg; } + set + { + config = value as ValveCfg; + Redraw(); + } + } + + public ValveCfgCtrl() + { + InitializeComponent(); + } + + private void ValveCfgCtrl_Load(object sender, EventArgs e) + { + parent = ParentForm as ComponentParametersDlg; + if (parent == null) return; + + if (parent.TbfComponents != null) + { + parentNameComboBox.Items.Add("---"); + coupledToComboBox.Items.Add("---"); + foreach (var cmpnt in parent.TbfComponents) + { + if (TbfComponents.CmpntFactoryFromClassName(cmpnt.ClassName) is Elde.ControlBoardFactory) + { + parentNameComboBox.Items.Add(cmpnt.Name); + } + if (TbfComponents.CmpntFactoryFromClassName(cmpnt.ClassName) is Elde.Valve.ValveFactory) + { + coupledToComboBox.Items.Add(cmpnt.Name); + } + } + } + + Redraw(); + } + + void Redraw() + { + if (config == null) return; /// Control was not loaded, settings were not changed + + classNameLabel.Text = config.Factory.ClassName; + nameTextBox.Text = config.Name; + parentNameComboBox.Text = string.IsNullOrEmpty(config.ParentName) ? "---" : config.ParentName; + bitPositionTextBox.Text = config.BitPosition.ToString(); + coupledToComboBox.Text = string.IsNullOrEmpty(config.CoupledToName) ? "---" : config.CoupledToName; + invertCheckBox.Checked = config.Invert; + lagOpeningTextBox.Text = config.LagOpening.ToString(); + lagClosingTextBox.Text = config.LagClosing.ToString(); + } + + public void Unlock() + { + nameTextBox.Enabled = true; + parentNameComboBox.Enabled = true; + bitPositionTextBox.Enabled = true; + coupledToComboBox.Enabled = true; + invertCheckBox.Enabled = true; + lagOpeningTextBox.Enabled = true; + lagClosingTextBox.Enabled = true; + } + + public void UpdateCfg() + { + if (config == null) return; /// Control was not loaded, settings were not changed + + config.Name = nameTextBox.Text; + config.ParentName = parentNameComboBox.Text.Equals("---") ? string.Empty : parentNameComboBox.Text; + config.BitPosition = int.Parse(bitPositionTextBox.Text); + config.CoupledToName = coupledToComboBox.Text.Equals("---") ? string.Empty : coupledToComboBox.Text; + config.Invert = invertCheckBox.Checked; + config.LagOpening = int.Parse(lagOpeningTextBox.Text); + config.LagClosing = int.Parse(lagClosingTextBox.Text); + } + + public CfgVerifyFlags VerifyCfg(ref string message) + { + CfgVerifyFlags flags = CfgVerifyFlags.None; + + int dummy; + if (!parentNameComboBox.Items.Contains(parentNameComboBox.Text)) + { + flags |= CfgVerifyFlags.Error; + message += Environment.NewLine + "Invalid 'Parent Name'"; + } + if (!coupledToComboBox.Items.Contains(coupledToComboBox.Text)) + { + flags |= CfgVerifyFlags.Error; + message += Environment.NewLine + "Invalid 'Coupled To'"; + } + if (!int.TryParse(bitPositionTextBox.Text, out dummy) || dummy < 0 || dummy >= 64) + { + flags |= CfgVerifyFlags.Error; + message += Environment.NewLine + "'Bit Position' should be between 0 and 63"; + } + if (!int.TryParse(lagOpeningTextBox.Text, out dummy)) + { + flags |= CfgVerifyFlags.Error; + message += Environment.NewLine + "'Delay when opening' error"; + } + if (!int.TryParse(lagClosingTextBox.Text, out dummy)) + { + flags |= CfgVerifyFlags.Error; + message += Environment.NewLine + "'Delay when closing' error"; + } + return flags; + } + } +} diff --git a/TestBenchFramework/BenchControl/Elde/Valve/ValveCfgCtrl.resx b/TestBenchFramework/BenchControl/Elde/Valve/ValveCfgCtrl.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/Valve/ValveCfgCtrl.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/BenchControl/Elde/Valve/ValveFactory.cs b/TestBenchFramework/BenchControl/Elde/Valve/ValveFactory.cs new file mode 100644 index 000000000..1130758e7 --- /dev/null +++ b/TestBenchFramework/BenchControl/Elde/Valve/ValveFactory.cs @@ -0,0 +1,39 @@ +using System.Collections.Generic; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.Elde.Valve +{ + public class ValveFactory : IComponentFactory + { + public string ClassName { get { return "Valve"; } } + public bool HasProcedureParams { get { return false; } } + public bool HasTestParams { get { return false; } } + public IParamsProvider GetTestParams(Entities.ComponentTest testParams) { return null; } + public IParamsProvider GetProcedureParams(Entities.ComponentProcedure procedureParams) { return null; } + + /// Max. number of components of this class in the system + public int MaxCount { get { return int.MaxValue; } } + + public IComponentCfg DefaultConfig(IList components) + { + return new ValveCfg(this, "Valve", "CB", 0); + } + + public IComponentCfgCtrl CreateCfgCtrl() + { + return new ValveCfgCtrl(); + } + + public IComponent ComponentFromCmpntCfg(IComponentCfg config, IList components) + { + return new Valve((ValveCfg)config, components); + } + + public IComponentCfg CmpntCfgFromCmpntEntity(Entities.Component component) + { + return ValveCfg.CreateFromDbEntity(component, this); + } + + public void ResetStaticProperties() { Valve.ResetStaticProperties(); } + } +} diff --git a/TestBenchFramework/BenchControl/Events.cs b/TestBenchFramework/BenchControl/Events.cs new file mode 100644 index 000000000..c53d95239 --- /dev/null +++ b/TestBenchFramework/BenchControl/Events.cs @@ -0,0 +1,97 @@ +namespace TBF.BenchControl +{ + /// + /// Lower level measurement event provided by devices and polled by operations + /// + public enum MsrmntState + { + Valid, + Overload, + Failed, + Busy, + } + + /// + /// Flags returned by each device configuration control Verify(...) function. + /// + public enum CfgVerifyFlags + { + None = 0, + Error = 0x1, /// Some settings in the user control are invalid and cannot be set + Warning = 0x02, /// Some settings in the user control are suspicious, can be set after user confirmation + } + + /// + /// StateMachine events (issued by operations, IOperation derived classes) + /// + public enum Event + { + None = 0, + Done, + ValvesSet, + AmbientDone, + BalanceDone, + BalanceOverload, + PressureDone, + PressureInDone, + PressureOutDone, + TempDone, + TempInDone, + TempOutDone, + TempDivDone, + FlowMeasurementDone, + FlowReached, + PositionReached, + RegulValveTimeOut, /// Maximum allowed flow setting time has elapsed + ReadRegisterDone, + ReadReferenceDone, + AllPositionsReached, /// Used in SetAllRegulValvesOp + TurnPumpOnOffDone, + + /// CheckUi events + UiCmdStartTest, + UiCmdStartQ1, + UiCmdStartQ2, + UiCmdStartQ3, + UiCmdStartCycle, + UiCmdStop, + UiCmdPurgeBegin, + UiCmdPurgeEnd, + UiCmdEmptyTank1, + UiCmdEmptyTank2, + UiCmdTestOpticalHeads, + UiCmdResetResults, + UiCmdAcceptResults, + UiCmdCalibration, + UiCmdCameraTest, + UiCmdSensitivityTest, + UiCmdB1, + UiCmdB2, + UiCmdB3, + + /// Process/Test oriented + PreviousStopped, + Wait, + ProcedureLoaded, + MeasurementStarted, + ReadAllRegistersDone, + MeasurementCompleted, + ResultsPrinted, + ResultsWritten, + + /// Timer events + TimerExpired, + + /// IDC camera events + CameraBusy, + CameraOpCompleted, + CameraOpFailed, + + /// Generic + Error, /// Many ops.: Fatal error occurred + ConfigurationError, + Yes, + No, + Next, /// To move to the next state when debugging + } +} diff --git a/TestBenchFramework/BenchControl/FeedingPath.cs b/TestBenchFramework/BenchControl/FeedingPath.cs new file mode 100644 index 000000000..a4f8ec2ce --- /dev/null +++ b/TestBenchFramework/BenchControl/FeedingPath.cs @@ -0,0 +1,42 @@ +using System.Collections.Generic; +using TBF.BenchControl.GenericDevices; + +namespace TBF.BenchControl +{ + public class FeedingPath + { + public int ItemNr; + public string Name; + public float Qfrom; + public float Qto; + public IValve Pump; /// pump to use with this path or null + public IList ValvesOpen; /// a list of valves to open or null + public IList ValvesClose; /// a list of valves to close or null + + /// Constructor from name, the rest is empty + public FeedingPath(string name, int itemNr) + { + ItemNr = itemNr; + Name = name; + ValvesOpen = new List(); + ValvesClose = new List(); + } + + /// Constructor from data entity + public FeedingPath(Entities.FeedingPath entity, IList components) + : this(entity.Name, entity.ItemNr) + { + Qfrom = entity.Qfrom; + Qto = entity.Qto; + Pump = (IValve)TbfComponents.FindComponent(entity.Pump, components); + + string[] vOpen = entity.ValvesOpen.Split(new char[] { ';' }); + ValvesOpen = new List(); + foreach (var vName in vOpen) ValvesOpen.Add((IValve)TbfComponents.FindComponent(vName, components)); + + string[] vClose = entity.ValvesClose.Split(new char[] { ';' }); + ValvesClose = new List(); + foreach (var vName in vClose) ValvesClose.Add((IValve)TbfComponents.FindComponent(vName, components)); + } + } +} diff --git a/TestBenchFramework/BenchControl/FloatBox.cs b/TestBenchFramework/BenchControl/FloatBox.cs new file mode 100644 index 000000000..c4e555dab --- /dev/null +++ b/TestBenchFramework/BenchControl/FloatBox.cs @@ -0,0 +1,22 @@ +namespace TBF.BenchControl +{ + public class FloatBox + { + public float F; + + public FloatBox() + { + F = 0.0f; + } + + public FloatBox(float f) + { + F = f; + } + + public override string ToString() + { + return F.ToString(); + } + } +} diff --git a/TestBenchFramework/BenchControl/Formulas.cs b/TestBenchFramework/BenchControl/Formulas.cs new file mode 100644 index 000000000..bbf02b438 --- /dev/null +++ b/TestBenchFramework/BenchControl/Formulas.cs @@ -0,0 +1,133 @@ +using System; +using System.Collections.Generic; + +namespace TBF.BenchControl +{ + public static class Formulas + { + /// + /// Calculate water density from temperature + /// + /// Temperature in [degC] + /// Density in [kg/m3] + public static float WaterDensityFromTemp(float t) + { + double tt = (double)t; + const double a0 = 999.842594; + const double a1 = 0.06793952; + const double a2 = -0.00909529; + const double a3 = 0.0001001685; + const double a4 = -0.000001120083; + const double a5 = 6.536332e-09; + + return (float)(((((a5 * tt + a4) * tt + a3) * tt + a2) * tt + a1) * tt + a0); + } + + + public static float AirDensityFromAmbientVales(float tempC, float pressureBar, float humiPct) + { + double pressurePa = 100000.0 * (double)pressureBar; /// [Pa] + double tempKelvin = 273.15 + (double)tempC; + double coef1 = 1.2811805 / 10000.0 * tempKelvin * tempKelvin + - 1.950987 / 100.0 * tempKelvin + + 34.04926034 + - 6.353631 * 1000.0 / tempKelvin; + double coef3 = humiPct / 100.0 * System.Math.Exp(coef1) / pressurePa; + double airDensityKgm3 = 0.00348353 * pressurePa * (1.0 - 0.378 * coef3) / tempKelvin; /// kg/m3 + return (float)airDensityKgm3; + } + + /// + /// Convert 'pulses' to 'volume', prevent division by zero + /// + public static float VolumeFromPulses(int pulses, float pulsesPerLiter) + { + if (pulsesPerLiter <= float.Epsilon) return 0; + return Convert.ToSingle(pulses) / pulsesPerLiter; + } + + /// + /// Calculate the error in % from 'measured' and 'true' volume, prevent division by zero + /// + public static float ErrorFromVolumes(float measuredVolume, float trueVolume) + { + if (trueVolume <= float.Epsilon) + { + if (measuredVolume <= float.Epsilon) return 0; + return 100.0f; + } + return 100.0f * (measuredVolume - trueVolume) / trueVolume; + } + + /// + /// Calcuate progress of the test while setting the flow. + /// + /// Current time from the beginning in [s] + /// Estimated time to set the flow in [s] + /// Estimated test time in [s] + /// Test progress 0 .. 1.0f + public static float TestProgress(float currentTime, float flowSetTime, float testTime) + { + // Never return more then 'fixedPart' + if (flowSetTime <= float.Epsilon) return 0; + float fixedPart = flowSetTime / (flowSetTime + testTime); + return (currentTime < flowSetTime) ? (currentTime / flowSetTime) * fixedPart : fixedPart; + } + + /// + /// Calculate progress of the test during measurement. + /// + /// Current number of reference pulses + /// Total number of reference pulses to complete the test + /// Estimated time to set the flow in [s] + /// Estimated test time in [s] + /// Test progress 0 .. 1.0f + public static float TestProgress(int refPulses, int totalPulses, float flowSetTime, float testTime) + { + // Never return less then 'fixedPart' and more then 1.0f + if (refPulses > totalPulses) refPulses = totalPulses; + float fixedPart = flowSetTime / (flowSetTime + testTime); + return fixedPart + (1.0f - fixedPart) * Convert.ToSingle(refPulses) / Convert.ToSingle(totalPulses); + } + + /// + /// Calculates corrected value form a list of corrections by interpolation. + /// It is assumed that values in the list 'corrections' are sorted. + /// + /// Raw uncorrected value + /// Sorted (value, correction) pairs + /// Corrected value + public static float CorrectedValue(float rawValue, IList corrections) + { + if (corrections == null || corrections.Count == 0) return rawValue; + + if (rawValue < corrections[0].Measurement) + { + return rawValue + corrections[0].Correction; + } + + int count = corrections.Count; + for (int i = 1; i < count; i++) + { + if (rawValue < corrections[i].Measurement) + { + float d1 = rawValue - corrections[i-1].Measurement; + float d2 = corrections[i].Measurement - rawValue; + + float corr; + if (d1 + d2 <= float.Epsilon) + { + corr = (corrections[i - 1].Correction + corrections[i].Correction) / 2.0f; + } + else + { + corr = (corrections[i - 1].Correction * d2 + corrections[i].Correction * d1) / (d1 + d2); + } + return rawValue + corr; + } + } + + return rawValue + corrections[count - 1].Correction; + } + } +} diff --git a/TestBenchFramework/BenchControl/Generic/IChildComponentCfg.cs b/TestBenchFramework/BenchControl/Generic/IChildComponentCfg.cs new file mode 100644 index 000000000..9f28e4eaf --- /dev/null +++ b/TestBenchFramework/BenchControl/Generic/IChildComponentCfg.cs @@ -0,0 +1,8 @@ + +namespace TBF.BenchControl.Generic +{ + interface IChildComponentCfg : IComponentCfg + { + + } +} diff --git a/TestBenchFramework/BenchControl/Generic/IComponent.cs b/TestBenchFramework/BenchControl/Generic/IComponent.cs new file mode 100644 index 000000000..d80c1a45e --- /dev/null +++ b/TestBenchFramework/BenchControl/Generic/IComponent.cs @@ -0,0 +1,8 @@ + +namespace TBF.BenchControl.Generic +{ + public interface IComponent + { + IComponentCfg Cfg { get; } + } +} diff --git a/TestBenchFramework/BenchControl/Generic/IComponentCfg.cs b/TestBenchFramework/BenchControl/Generic/IComponentCfg.cs new file mode 100644 index 000000000..24bb65d0d --- /dev/null +++ b/TestBenchFramework/BenchControl/Generic/IComponentCfg.cs @@ -0,0 +1,47 @@ +using System.Collections.Generic; + +namespace TBF.BenchControl.Generic +{ + public interface IComponentCfg + { + /// + /// Unique component # (0 .. nr.of components-1) + /// + int ItemNr { get; set; } + + /// + /// Component name + /// + string Name { get; set; } + + /// + /// Reference to the component factory (it is a singleton) + /// + IComponentFactory Factory { get; } + + /// + /// Component class / component type name + /// + string ParentName { get; set; } + + /// + /// Debug level, 0 = debugging off + /// + Entities.DebugMode DebugLevel { get; set; } + + /// + /// Log level, 0 = logging off + /// + Entities.LogLevel LogLevel { get; } + + /// + /// Measurement correction values + /// + IList Corrections { get; } + + IComponentCfg Clone(); + TBF.Entities.Component CreateDbEntity(); + + string ToString(int i); + } +} diff --git a/TestBenchFramework/BenchControl/Generic/IComponentCfgCtrl.cs b/TestBenchFramework/BenchControl/Generic/IComponentCfgCtrl.cs new file mode 100644 index 000000000..69db0ee14 --- /dev/null +++ b/TestBenchFramework/BenchControl/Generic/IComponentCfgCtrl.cs @@ -0,0 +1,28 @@ + +namespace TBF.BenchControl.Generic +{ + public interface IComponentCfgCtrl + { + /// + /// Reference to device configuration class instance + /// + IComponentCfg Config { get; set; } + + /// + /// Verify current user controls for validity. + /// Called when user wants to close/save the configuration. + /// + /// See VerifyFlags + CfgVerifyFlags VerifyCfg(ref string message); + + /// + /// Save settings to the configuration class. + /// + void Unlock(); + + /// + /// Save settings to the configuration class. + /// + void UpdateCfg(); + } +} diff --git a/TestBenchFramework/BenchControl/Generic/IComponentFactory.cs b/TestBenchFramework/BenchControl/Generic/IComponentFactory.cs new file mode 100644 index 000000000..7e5b0091b --- /dev/null +++ b/TestBenchFramework/BenchControl/Generic/IComponentFactory.cs @@ -0,0 +1,42 @@ +using System.Collections.Generic; + +namespace TBF.BenchControl.Generic +{ + public interface IComponentFactory + { + string ClassName { get; } /// Name of the class of components (for instance "Valve") + bool HasProcedureParams { get; } /// true = create an entity with component specific procedure parameters + bool HasTestParams { get; } /// true = create an entity with component specific test parameters + + /// + /// Max. number of components of this class in the system: 1, some integer value or int.MaxValue + /// + int MaxCount { get; } + + /// + /// Returns the default configuration + /// + IComponentCfg DefaultConfig(IList components); + + /// + /// Returns the UserControl used inside ComponentConfigForm to display and edit the configuration + /// + IComponentCfgCtrl CreateCfgCtrl(); + + /// + /// Returns the component + /// + IComponent ComponentFromCmpntCfg(IComponentCfg config, IList components); + + /// + /// Converts an Entities.Component object into an instance of an appropriate class implementing IComponentCfg + /// + IComponentCfg CmpntCfgFromCmpntEntity(Entities.Component component); + + IParamsProvider GetTestParams(Entities.ComponentTest testParams); + IParamsProvider GetProcedureParams(Entities.ComponentProcedure procedureParams); + + + void ResetStaticProperties(); + } +} diff --git a/TestBenchFramework/BenchControl/Generic/IDevice.cs b/TestBenchFramework/BenchControl/Generic/IDevice.cs new file mode 100644 index 000000000..142480ec5 --- /dev/null +++ b/TestBenchFramework/BenchControl/Generic/IDevice.cs @@ -0,0 +1,35 @@ +namespace TBF.BenchControl.Generic +{ + public interface IDevice + { + void Initialize(); + + /// + /// This function is invoked regularly each 1000 ms (once per second) + /// just before Start(), Run() and Stop() functions of acrive operations. + /// + /// It runs in a thread created by class Machine (not the user interface thread). + /// The function should not block (otherwise it blocks all other devices) !!! + /// In case needed, the device must create its own thread to handle hardware + /// without any interference with the rest of the system. + /// + void RunDeviceBefore(); + + /// + /// This function is invoked regularly each 1000 ms (once per second) + /// just before Start(), Run() and Stop() functions of acrive operations. + /// + /// It runs in a thread created by class Machine (not the user interface thread). + /// The function should not block (otherwise it blocks all other devices) !!! + /// In case needed, the device must create its own thread to handle hardware + /// without any interference with the rest of the system. + /// + void RunDeviceAfter(); + + /// + /// Should be invoked once before state machine is stopped and program exits. + /// Only Stop() operations may be called afterwards (No Start() / Run() operation). + /// + void StopDevice(); + } +} diff --git a/TestBenchFramework/BenchControl/Generic/IParamsProvider.cs b/TestBenchFramework/BenchControl/Generic/IParamsProvider.cs new file mode 100644 index 000000000..9e021d852 --- /dev/null +++ b/TestBenchFramework/BenchControl/Generic/IParamsProvider.cs @@ -0,0 +1,43 @@ + +namespace TBF.BenchControl.Generic +{ + public interface IParamsProvider + { + string ComponentName { get; } + + /// + /// Number of parameters + /// + int ParamsCount(); + + /// + /// Parameter names + /// + /// Zero based index of the parameter + string ParamName(int ix); + + /// + /// Parameter values in string form + /// + /// Zero based index of the parameter + string ToString(int i); + + /// + /// Validates the string representation of a parameter + /// + /// Zero based index of the parameter + /// String representation of the parameter + /// Warning message in case the string is wrong or null + /// true = string is OK, false = string is wrong (see 'message') + bool ValidateParam(int ix, string strValue, out string message); + + /// + /// Update the parameter from a string + /// + /// Zero based index of the parameter + /// String representation of the parameter + void UpdateParam(int ix, string strValue); + + void UpdateDbEntity(); + } +} diff --git a/TestBenchFramework/BenchControl/Generic/IProcedureParams.cs b/TestBenchFramework/BenchControl/Generic/IProcedureParams.cs new file mode 100644 index 000000000..53e1e6274 --- /dev/null +++ b/TestBenchFramework/BenchControl/Generic/IProcedureParams.cs @@ -0,0 +1,9 @@ + +namespace TBF.BenchControl.Generic +{ + public interface IProcedureParams + { + Entities.ComponentProcedure ProcedureParamsEntity { get; } + TBF.Entities.ComponentProcedure ToDbEntity(IComponent component, Entities.Procedure procedure); + } +} diff --git a/TestBenchFramework/BenchControl/Generic/ITestParams.cs b/TestBenchFramework/BenchControl/Generic/ITestParams.cs new file mode 100644 index 000000000..b9a34dcc1 --- /dev/null +++ b/TestBenchFramework/BenchControl/Generic/ITestParams.cs @@ -0,0 +1,9 @@ + +namespace TBF.BenchControl.Generic +{ + public interface ITestParams + { + Entities.ComponentTest TestParamsEntity { get; } + TBF.Entities.ComponentTest ToDbEntity(IComponent component, Entities.Test test); + } +} diff --git a/TestBenchFramework/BenchControl/GenericDevices/IAmbient.cs b/TestBenchFramework/BenchControl/GenericDevices/IAmbient.cs new file mode 100644 index 000000000..15d101d10 --- /dev/null +++ b/TestBenchFramework/BenchControl/GenericDevices/IAmbient.cs @@ -0,0 +1,16 @@ +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.GenericDevices +{ + public interface IAmbient : IComponent + { + /// + /// Events: Event.AmbientDone, Event.Error + /// + /// FloatBox for the air temperature in [deg.C] + /// FloatBox for the air pressure in [mBar] + /// FloatBox for the air humidity in [%] + /// Operation + IOperation ReadAmbientOp(FloatBox temperature, FloatBox pressure, FloatBox humidity); + } +} diff --git a/TestBenchFramework/BenchControl/GenericDevices/IBalance.cs b/TestBenchFramework/BenchControl/GenericDevices/IBalance.cs new file mode 100644 index 000000000..e373eea65 --- /dev/null +++ b/TestBenchFramework/BenchControl/GenericDevices/IBalance.cs @@ -0,0 +1,48 @@ +using System.Collections.Generic; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.GenericDevices +{ + /// + /// Basic balance functions + /// + public interface IBalance : IDevice, IComponent + { + /// + /// Camera number: 0-based index required for communication with the Elde component + /// + int BalanceNr { get; } + + /// + /// Balance water tank capacity in kg or ltr + /// + float Capacity { get; } + + /// + /// Measurement correction table + /// + IList Corrections { get; } + + /// + /// Events: BalanceDone, Error + /// + /// Reference to a variable for 'tara' in kg + /// TaringOp instance reference casted to IOperaton + IOperation TaringOp(ref FloatBox tara); + + /// + /// Events: BalanceDone, Error + /// + /// Reference to a variable for the measured mass in kg + /// ReadMassOp instance reference casted to IOperaton + IOperation ReadMassOp(ref FloatBox mass); + + /// + /// Events: BalanceDone, Error + /// + /// Reference to a variable for the measured mass in kg + /// Required mass readings count (>= 3) + /// ReadMassAverageOp instance reference casted to IOperaton + IOperation ReadStableMassOp(ref FloatBox mass, int readingsCount); + } +} diff --git a/TestBenchFramework/BenchControl/GenericDevices/IBalance2.cs b/TestBenchFramework/BenchControl/GenericDevices/IBalance2.cs new file mode 100644 index 000000000..6a200d774 --- /dev/null +++ b/TestBenchFramework/BenchControl/GenericDevices/IBalance2.cs @@ -0,0 +1,14 @@ +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.GenericDevices +{ + public interface IBalance2 : IBalance, IComponent + { + /// + /// Events: Done, Error + /// + /// Reference to the serialNumber + /// GetBalanceSNOp instance reference casted to IOperaton + IOperation GetBalanceSNOp(ref string serialNumber); + } +} diff --git a/TestBenchFramework/BenchControl/GenericDevices/ICamera.cs b/TestBenchFramework/BenchControl/GenericDevices/ICamera.cs new file mode 100644 index 000000000..3a8becf71 --- /dev/null +++ b/TestBenchFramework/BenchControl/GenericDevices/ICamera.cs @@ -0,0 +1,46 @@ +using TBF.BenchControl; + +namespace TBF.BenchControl.GenericDevices +{ + public interface ICamera : Generic.IComponent + { + /// + /// Camera number: 0-based index required for communication with 'Pictures'screen + /// + int CameraNr { get; } + + float Brightness { get; } + + /// + /// Grab an image. + /// + /// Reference to operation object instance + IOperation GrabOp(); + + /// + /// Display live image. + /// + /// Reference to operation object instance + IOperation LiveOp(); + + /// + /// Display live detail to focus the camera. + /// + /// Reference to operation object instance + IOperation FocusOp(); + + /// + /// Watermeter wheel/arrow detection process. + /// + /// Region of interest (1..4) + /// Reference to operation object instance + IOperation DetectOp(int roiId, Cameras.IdcCamera.IWorkerCmd cmd); + + /// + /// Watermeter wheel/arrow angle measurement process. + /// + /// Region of interest (1..4) + /// Reference to operation object instance + IOperation MeasureOp(int roiId, Cameras.IdcCamera.IWorkerCmd cmd); + } +} diff --git a/TestBenchFramework/BenchControl/GenericDevices/ICameraRoi.cs b/TestBenchFramework/BenchControl/GenericDevices/ICameraRoi.cs new file mode 100644 index 000000000..4f993a26d --- /dev/null +++ b/TestBenchFramework/BenchControl/GenericDevices/ICameraRoi.cs @@ -0,0 +1,23 @@ +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.GenericDevices +{ + public interface ICameraRoi : IComponent, IRegisterReader + { + GenericDevices.ICamera Camera { get; } + + /// + /// Watermeter wheel/arrow detection process. + /// + /// Region of interest (1..4) + /// Reference to operation object instance + IOperation DetectOp(); + + /// + /// Watermeter wheel/arrow angle measurement process. + /// + /// Region of interest (1..4) + /// Reference to operation object instance + IOperation MeasureOp(); + } +} diff --git a/TestBenchFramework/BenchControl/GenericDevices/IDataEntry.cs b/TestBenchFramework/BenchControl/GenericDevices/IDataEntry.cs new file mode 100644 index 000000000..2f5fa0c24 --- /dev/null +++ b/TestBenchFramework/BenchControl/GenericDevices/IDataEntry.cs @@ -0,0 +1,11 @@ +using System.Collections.Generic; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.GenericDevices +{ + public interface IDataEntry : IComponent + { + IOperation ShowFormAtCycleBeginningOp(IList waterMeters); + IOperation ShowFormAtCycleEndOp(IList waterMeters); + } +} diff --git a/TestBenchFramework/BenchControl/GenericDevices/IDiverter.cs b/TestBenchFramework/BenchControl/GenericDevices/IDiverter.cs new file mode 100644 index 000000000..2ab6fe8fd --- /dev/null +++ b/TestBenchFramework/BenchControl/GenericDevices/IDiverter.cs @@ -0,0 +1,12 @@ +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.GenericDevices +{ + public interface IDiverter : IComponent + { + /// + /// Diverter state: true = to tank, false = bypass tank + /// + bool State { get; } + } +} diff --git a/TestBenchFramework/BenchControl/GenericDevices/IFlowMeter.cs b/TestBenchFramework/BenchControl/GenericDevices/IFlowMeter.cs new file mode 100644 index 000000000..f99eaea86 --- /dev/null +++ b/TestBenchFramework/BenchControl/GenericDevices/IFlowMeter.cs @@ -0,0 +1,36 @@ +using System.Collections.Generic; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.GenericDevices +{ + /// + /// Basic flow meter functions + /// + public interface IFlowMeter : IComponent + { + /// + /// Nominal flow @2kHz output frequency in m3 + /// + float NominalFlow { get; } + + /// + /// Measurement correction table + /// + IList Corrections { get; } + + /// + /// Events: FlowDone, Error + /// + /// Reference to a variable for the measured flow in xxx + /// ReadFlowOp instance reference casted to IOperaton + IOperation ReadFlowOp(ref FloatBox flow); + + /// + /// Events: flowDone, Error + /// + /// Reference to a variable for the measured flow in xxx + /// Event returned when measurement done + /// ReadFlowOp instance reference casted to IOperaton + IOperation ReadFlowOp(ref FloatBox flow, Event flowDone); + } +} diff --git a/TestBenchFramework/BenchControl/GenericDevices/IHasCompleted.cs b/TestBenchFramework/BenchControl/GenericDevices/IHasCompleted.cs new file mode 100644 index 000000000..894c2e851 --- /dev/null +++ b/TestBenchFramework/BenchControl/GenericDevices/IHasCompleted.cs @@ -0,0 +1,8 @@ + +namespace TBF.BenchControl.GenericDevices +{ + interface IHasCompleted + { + bool Completed { get; } + } +} diff --git a/TestBenchFramework/BenchControl/GenericDevices/IHasProtocolTitle.cs b/TestBenchFramework/BenchControl/GenericDevices/IHasProtocolTitle.cs new file mode 100644 index 000000000..2c096630d --- /dev/null +++ b/TestBenchFramework/BenchControl/GenericDevices/IHasProtocolTitle.cs @@ -0,0 +1,8 @@ + +namespace TBF.BenchControl.GenericDevices +{ + public interface IHasProtocolTitle + { + string ProtocolTitle { get; } + } +} diff --git a/TestBenchFramework/BenchControl/GenericDevices/IPressureMeter.cs b/TestBenchFramework/BenchControl/GenericDevices/IPressureMeter.cs new file mode 100644 index 000000000..117551dff --- /dev/null +++ b/TestBenchFramework/BenchControl/GenericDevices/IPressureMeter.cs @@ -0,0 +1,31 @@ +using System.Collections.Generic; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.GenericDevices +{ + /// + /// Basic pressure meter functions + /// + public interface IPressureMeter : IComponent + { + /// + /// Measurement correction table + /// + IList Corrections { get; } + + /// + /// Events: PressureDone, Error + /// + /// Reference to a variable for the measured pressure in bar + /// ReadPressureOp instance reference casted to IOperaton + IOperation ReadPressureOp(ref FloatBox pressure); + + /// + /// Events: pressureDone, Error + /// + /// Reference to a variable for the measured pressure in bar + /// Event returned when measurement done + /// ReadPressureOp instance reference casted to IOperaton + IOperation ReadPressureOp(ref FloatBox pressure, Event pressureDone); + } +} diff --git a/TestBenchFramework/BenchControl/GenericDevices/IPump.cs b/TestBenchFramework/BenchControl/GenericDevices/IPump.cs new file mode 100644 index 000000000..8da3c6d72 --- /dev/null +++ b/TestBenchFramework/BenchControl/GenericDevices/IPump.cs @@ -0,0 +1,12 @@ +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.GenericDevices +{ + public interface IPump : IComponent + { + /// + /// Pump state: true = on, false = off + /// + bool State { get; } + } +} diff --git a/TestBenchFramework/BenchControl/GenericDevices/IPumpFM.cs b/TestBenchFramework/BenchControl/GenericDevices/IPumpFM.cs new file mode 100644 index 000000000..1f268054e --- /dev/null +++ b/TestBenchFramework/BenchControl/GenericDevices/IPumpFM.cs @@ -0,0 +1,21 @@ +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.GenericDevices +{ + /// + /// A pump controlled by a frequency inverter + /// using the test parameter 'Power' (0 .. 100.0f %) + /// + public interface IPumpFM : IPump + { + /// + /// Turns the frequency inverter on using the test parameter 'Power' (0 .. 100.0f %) + /// + IOperation TurnOn(); + + /// + /// Turns the frequency inverter off + /// + IOperation TurnOff(); + } +} diff --git a/TestBenchFramework/BenchControl/GenericDevices/IRegisterReader.cs b/TestBenchFramework/BenchControl/GenericDevices/IRegisterReader.cs new file mode 100644 index 000000000..aabdc54e1 --- /dev/null +++ b/TestBenchFramework/BenchControl/GenericDevices/IRegisterReader.cs @@ -0,0 +1,12 @@ +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.GenericDevices +{ + public interface IRegisterReader : IComponent + { + float PulsesPerLtr { get; } + IOperation ReadRegisterOp(ref IntBox pulses); + IOperation ReadRegisterOp(ref IntBox pulses, ref IntBox refPulses); + IOperation ReadReferenceForRegisterOp(ref IntBox pulses, ref IntBox refPulses); + } +} diff --git a/TestBenchFramework/BenchControl/GenericDevices/IRegulValve.cs b/TestBenchFramework/BenchControl/GenericDevices/IRegulValve.cs new file mode 100644 index 000000000..4b55c1513 --- /dev/null +++ b/TestBenchFramework/BenchControl/GenericDevices/IRegulValve.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.GenericDevices +{ + public interface IRegulValve : IComponent + { + IDictionary Dict { get; } + + /// + /// Operation to set the water flow within tolerances + /// Events: Event.None, Event.FlowReached, Event.FlowTimeOut + /// + /// Lower limit of the required flow [m3/h] + /// Higher limit of the required flow [m3/h] + /// Measured flow [m3/h] + /// Timeout in [s] + /// SetFlowOp instance + IOperation SetFlowOp(IFlowMeter flowMeter, float requiredFlowLo, float requiredFlowHi, FloatBox measuredFlow, int timeout); + + /// + /// Operation to set the water flow within tolerances. Leave the measurement running. + /// Events: Event.None, Event.FlowReached, Event.FlowTimeOut + /// + /// Lower limit of the required flow [m3/h] + /// Higher limit of the required flow [m3/h] + /// Measured flow [m3/h] + /// Timeout in [s] + /// SetFlowOp instance + IOperation SetFlowAndMeasureOp(IFlowMeter flowMeter, float requiredFlowLo, float requiredFlowHi, FloatBox measuredFlow, int timeout); + + /// + /// Operation to set the regulation valve to a required position + /// Events: Event.None + /// + /// Lower limit of the required valve position in % + /// Higher limit of the required valve position in % + /// Timeout in [s] + /// SetPositionOp instance + IOperation SetRegulValvePositionOp(float posLoPct, float posHiPct, int timeout); + + /// + /// Operation to set the regulation valve to a required position + /// Events: Event.None + /// + /// Time pulse in sec + /// SetPositionOp instance + IOperation ChangeRegulValvePositionOp(float timePulseSec); + } +} diff --git a/TestBenchFramework/BenchControl/GenericDevices/IResultsPrinter.cs b/TestBenchFramework/BenchControl/GenericDevices/IResultsPrinter.cs new file mode 100644 index 000000000..de9fb7be1 --- /dev/null +++ b/TestBenchFramework/BenchControl/GenericDevices/IResultsPrinter.cs @@ -0,0 +1,18 @@ +using System.Collections.Generic; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.GenericDevices +{ + public interface IResultsPrinter : IComponent + { + /// + /// Prints the test cycle results, Events: Event.ResultsPrinted + /// + /// Results to print + /// Reference to the operation + IOperation PrintResultsOp(BenchControl.BenchId.Component benchId, + IList waterMeters, + IList results, + string title); + } +} diff --git a/TestBenchFramework/BenchControl/GenericDevices/IResultsWriter.cs b/TestBenchFramework/BenchControl/GenericDevices/IResultsWriter.cs new file mode 100644 index 000000000..c2c206cee --- /dev/null +++ b/TestBenchFramework/BenchControl/GenericDevices/IResultsWriter.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.GenericDevices +{ + public interface IResultsWriter : IComponent + { + /// + /// Writes the test cycle results into a file, Events: Event.ResultsWritten + /// + /// Results to write into a file + /// Reference to the operation + IOperation WriteResultsOp(IList results); + } +} diff --git a/TestBenchFramework/BenchControl/GenericDevices/ITempMeter.cs b/TestBenchFramework/BenchControl/GenericDevices/ITempMeter.cs new file mode 100644 index 000000000..147ec1eb4 --- /dev/null +++ b/TestBenchFramework/BenchControl/GenericDevices/ITempMeter.cs @@ -0,0 +1,24 @@ +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.GenericDevices +{ + /// + /// Basic temperature meter functions + /// + public interface ITempMeter : IComponent + { + /// + /// Events: TempDone, Error + /// + /// Reference to a variable for the temperature in Celsius + /// ReadTempInOp instance reference casted to IOperaton + IOperation ReadTempOp(ref FloatBox temp); + + /// + /// Events: tempDone, Error + /// + /// Reference to a variable for the temperature in Celsius + /// ReadTempInOp instance reference casted to IOperaton + IOperation ReadTempOp(ref FloatBox temp, Event tempDone); + } +} diff --git a/TestBenchFramework/BenchControl/GenericDevices/ITestMethod.cs b/TestBenchFramework/BenchControl/GenericDevices/ITestMethod.cs new file mode 100644 index 000000000..fc0a61938 --- /dev/null +++ b/TestBenchFramework/BenchControl/GenericDevices/ITestMethod.cs @@ -0,0 +1,9 @@ +using System.Collections.Generic; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.GenericDevices +{ + public interface ITestMethod : IComponent, ISequence + { + } +} diff --git a/TestBenchFramework/BenchControl/GenericDevices/IValve.cs b/TestBenchFramework/BenchControl/GenericDevices/IValve.cs new file mode 100644 index 000000000..e3dfda958 --- /dev/null +++ b/TestBenchFramework/BenchControl/GenericDevices/IValve.cs @@ -0,0 +1,37 @@ +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.GenericDevices +{ + public interface IValve : IComponent + { + /// + /// Valve state: true = open, false = closed + /// + bool State { get; } + + /// + /// Coupled valve or null. + /// This valve is a slave and follows the coupled valve, which is a master. + /// In case of CoupledValve == null, this valve can be independently controlled. + /// + IValve CoupledTo { get; } + + /// + /// The coupled valve is inverted referred to the master valve. + /// This property is used only in case 'CoupledTo' is non-null. + /// + bool Invert { get; } + + /// + /// Delay (referred to the master valve) when opening this (coupled, slave) valve in [s] + /// This property is used only in case 'CoupledTo' is non-null. + /// + int LagOpening { get; } + + /// + /// Delay (referred to the master valve) when opening this (coupled, slave) valve in [s] + /// This property is used only in case 'CoupledTo' is non-null. + /// + int LagClosing { get; } + } +} diff --git a/TestBenchFramework/BenchControl/GenericDevices/IValveControl.cs b/TestBenchFramework/BenchControl/GenericDevices/IValveControl.cs new file mode 100644 index 000000000..912745c92 --- /dev/null +++ b/TestBenchFramework/BenchControl/GenericDevices/IValveControl.cs @@ -0,0 +1,25 @@ +using System.Collections.Generic; + +namespace TBF.BenchControl.GenericDevices +{ + public interface IValveControl + { + /// + /// Open one valve and/or close one valve. + /// Events: RouteDone, Error + /// + /// Valve to be opened + /// Valve to be closed + /// Newly created operation instance reference casted to IOperaton + IOperation SetValvesOp(IValve valveToOpen, IValve valveToClose); + + /// + /// Open and/or close multiple valves. + /// Events: RouteDone, Error + /// + /// A list of valves to be opened + /// A list of valves to be closed + /// Newly created operation instance reference casted to IOperaton + IOperation SetValvesOp(IList valvesToOpen, IList valvesToClose); + } +} diff --git a/TestBenchFramework/BenchControl/GenericDevices/IWaterMeter.cs b/TestBenchFramework/BenchControl/GenericDevices/IWaterMeter.cs new file mode 100644 index 000000000..33f075a0e --- /dev/null +++ b/TestBenchFramework/BenchControl/GenericDevices/IWaterMeter.cs @@ -0,0 +1,14 @@ +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.GenericDevices +{ + public interface IWaterMeter : IComponent + { + string Producer { get; } + float Qn { get; } + string ApprovalInfo { get; } + string MetrologicalClass { get; } + string SerialNr { get; set; } + string State { get; set; } + } +} diff --git a/TestBenchFramework/BenchControl/GenericDevices/ValveBase.cs b/TestBenchFramework/BenchControl/GenericDevices/ValveBase.cs new file mode 100644 index 000000000..94ca500dc --- /dev/null +++ b/TestBenchFramework/BenchControl/GenericDevices/ValveBase.cs @@ -0,0 +1,72 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace TBF.BenchControl.GenericDevices +{ + public class ValveBase + { + /// + /// Process the list of components and return all valves (masters and coupled) + /// + public static IList AllValves(IList cmpnts) + { + IList result = new List(); + foreach (var cmpnt in cmpnts) if (cmpnt is IValve) result.Add(cmpnt as IValve); + return result; + } + + /// + /// Process the list of components and return the masters valves + /// + public static IList MasterValves(IList cmpnts) + { + IList result = new List(); + foreach (var cmpnt in cmpnts) + { + IValve valve = cmpnt as IValve; + if (valve != null && valve.CoupledTo == null) result.Add(valve); + } + return result; + } + + /// + /// Process the list of components and return the coupled valves + /// + public static IList CoupledValves(IList cmpnts) + { + IList result = new List(); + foreach (var cmpnt in cmpnts) + { + IValve valve = cmpnt as IValve; + if (valve != null && valve.CoupledTo != null) result.Add(valve); + } + return result; + } + + public static IList MakeList(IValve valve) + { + IList result = new List(); + if (valve != null) result.Add(valve); + return result; + } + + public static IList Merge(IList valves1, IList valves2) + { + IList result = new List(); + if (valves1 != null) foreach (var valve in valves1) result.Add(valve); + if (valves2 != null) foreach (var valve in valves2) result.Add(valve); + return result; + } + + public static IList Merge(IList valves1, IList valves2, IList valves3) + { + IList result = new List(); + if (valves1 != null) foreach (var valve in valves1) result.Add(valve); + if (valves2 != null) foreach (var valve in valves2) result.Add(valve); + if (valves3 != null) foreach (var valve in valves3) result.Add(valve); + return result; + } + } +} diff --git a/TestBenchFramework/BenchControl/Greco/Ambient.cs b/TestBenchFramework/BenchControl/Greco/Ambient.cs new file mode 100644 index 000000000..fe25a1833 --- /dev/null +++ b/TestBenchFramework/BenchControl/Greco/Ambient.cs @@ -0,0 +1,186 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO.Ports; +using System.Text; +using log4net; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.Greco +{ + /// + /// Ambient temperature / humidity / pressure meter 'Greco' connected via serial interface (RS232) + /// Connection settings: 19200 Bd 8-bits No-parity 1-stop-bit Flow control: none or hardware. + /// + public class Ambient : TestBenchSim, IComponent, IDevice, IOperation, GenericDevices.IAmbient + { + /// + /// Info: Successful measurement + /// Warn: Invalid serial response format + /// + private static readonly ILog log = LogManager.GetLogger(typeof(Ambient)); + + public static void ResetStaticProperties() { } + + private readonly AmbientCfg ambientCfg; + public Generic.IComponentCfg Cfg { get { return ambientCfg; } } + + public string Name { get { return ambientCfg.Name; } } + + /// Private fields + SerialPort serialPort; + StringBuilder measurementBuilder; + + /// The state of the measurement + MsrmntState msrmntState; + + /// Measured temperature when MsrmntState == MsrmntState.Valid + float temperature; + + /// Measured humidity when MsrmntState == MsrmntState.Valid + float humidity; + + /// Measured pressure when MsrmntState == MsrmntState.Valid + float pressure; + + /// Measurement time stamp when MsrmntState == MsrmntState.Valid + int msrmntTimeStamp; + + /// + /// Ambient temperature / humidity / pressure meter 'Greco' connected via serial interface (RS232) + /// Connection settings: 19200 Bd 8-bits No-parity 1-stop-bit Flow control: none or hardware. + /// + public Ambient(AmbientCfg cfg, IList components) + { + if (cfg == null) throw new ArgumentNullException("cfg"); + this.ambientCfg = cfg; + } + + public new void Initialize() + { + if (ambientCfg.DebugLevel == Entities.DebugMode.Simulate) + { + temperature = 20.0f; + humidity = 40.0f; + pressure = 1.0f; + msrmntTimeStamp = StateMachine.CurrentTime; + msrmntState = BenchControl.MsrmntState.Valid; + return; + } + + string comPortName = "COM" + ambientCfg.ComPortNr.ToString(); + serialPort = new SerialPort(comPortName, ambientCfg.BaudRate, ambientCfg.Parity, ambientCfg.DataBits, ambientCfg.StopBits); + serialPort.Handshake = ambientCfg.Handshake; + serialPort.Open(); + measurementBuilder = new StringBuilder(40); + msrmntState = MsrmntState.Busy; + } + + /// Run this device + public void RunDeviceBefore() + { + if (ambientCfg.DebugLevel == Entities.DebugMode.Simulate) + { + msrmntTimeStamp = StateMachine.CurrentTime; + return; + } + + measurementBuilder.Append(serialPort.ReadExisting()); + int len = measurementBuilder.Length; + + /// + /// Device sends each 20 sec one line of ASCII text with data in the following format: + /// (temp) 6 characters, two decimal digits, with leading spaces + /// TAB 1 character + /// (humi) 6 characters, two decimal digits, with leading spaces + /// TAB 1 character + /// (pressure) 6 characters, one decimal digits, with leading spaces is LT 1000 + /// CR + LF 2 characters + /// Example: + /// 23.42 38.08 1061.1 + /// 23.39 38.04 1060.8 + /// 23.39 38.08 1061.4 + /// + if (len >= 22) + { + string measurement = measurementBuilder.ToString(); + measurementBuilder.Clear(); + + float t = 0; + float h = 0; + float p = 0; + if (float.TryParse(measurement.Substring(len - 22, 6), NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingWhite, + CultureInfo.InvariantCulture, out t) && + measurement[len - 16] == '\t' && + float.TryParse(measurement.Substring(len - 15, 6), NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingWhite, + CultureInfo.InvariantCulture, out h) && + measurement[len - 9] == '\t' && + float.TryParse(measurement.Substring(len - 8, 6), NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingWhite, + CultureInfo.InvariantCulture, out p) && + measurement[len - 2] == '\r' && + measurement[len - 1] == '\n') + { + temperature = t; + humidity = h; + pressure = p; + msrmntTimeStamp = StateMachine.CurrentTime; + msrmntState = MsrmntState.Valid; + + log.InfoFormat("Msrmnt OK: time = {0}, temp={1}, humi={2}, pres={3}", msrmntTimeStamp, t, h, p); + } + else + { + log.Warn("Invalid string received: " + measurement); + } + } + } + + /// Run this device + public void RunDeviceAfter() + { + } + + /// Stop this device + public void StopDevice() + { + if (serialPort != null) serialPort.Close(); + } + + /// + /// Boxes for the operation result + /// + FloatBox tempBox; + FloatBox pressureBox; + FloatBox humiBox; + + public IOperation ReadAmbientOp(FloatBox temperature, FloatBox pressure, FloatBox humidity) + { + this.tempBox = temperature; + this.pressureBox = pressure; + this.humiBox = humidity; + return this; + } + + /// Start this operation + public void Start() + { + } + + /// Run this operation + /// + /// Event.FlowInDone or Event.FlowOutDone + /// + public Event Run() + { + tempBox.F = temperature; + pressureBox.F = pressure; + humiBox.F = humidity; + return Event.AmbientDone; + } + + /// Stop this operation + public void Stop() + { + } + } +} diff --git a/TestBenchFramework/BenchControl/Greco/AmbientCfg.cs b/TestBenchFramework/BenchControl/Greco/AmbientCfg.cs new file mode 100644 index 000000000..470dc9687 --- /dev/null +++ b/TestBenchFramework/BenchControl/Greco/AmbientCfg.cs @@ -0,0 +1,62 @@ +using System.IO; +using System.IO.Ports; +using System.Xml.Serialization; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.Greco +{ + public class AmbientCfg : ComponentCfgBase, Generic.IComponentCfg + { + public int ComPortNr; + public int BaudRate; + public Parity Parity; + public int DataBits; + public StopBits StopBits; + public Handshake Handshake; + + /// Parameterless constructor + public AmbientCfg() + { + } + /// Constructor + public AmbientCfg(IComponentFactory factory, string name, int comPortNr, int baudRate, Parity parity, int dataBits, StopBits stopBits, Handshake handshake) + : base(factory, name) + { + this.ComPortNr = comPortNr; + this.BaudRate = baudRate; + this.Parity = parity; + this.DataBits = dataBits; + this.StopBits = stopBits; + this.Handshake = handshake; + } + + public IComponentCfg Clone() + { + return new AmbientCfg(Factory, Name, ComPortNr, BaudRate, Parity, DataBits, StopBits, Handshake); + } + + public string ToString(int i) + { + return string.Format("COM{0}, {1}Bd, {2}bits, parity={3}, stopBits={4}, {5}", ComPortNr, BaudRate, DataBits, Parity, StopBits, Handshake); + } + + public TBF.Entities.Component CreateDbEntity() + { + using (var writer = new StringWriter()) + { + (new XmlSerializer(GetType())).Serialize(writer, this); + return Entities.Component.CreateFromCfg(Name, Factory.ClassName, ParentName, ItemNr, DebugLevel, LogLevel, writer.ToString()); + } + } + + public static IComponentCfg CreateFromDbEntity(Entities.Component component, IComponentFactory factory) + { + using (var reader = new StringReader(component.Parameters)) + { + AmbientCfg config = (AmbientCfg)(new XmlSerializer(typeof(AmbientCfg))).Deserialize(reader); + config.InitCfgBaseFromEntity(component, factory); + return config; + } + } + } +} diff --git a/TestBenchFramework/BenchControl/Greco/AmbientCfgCtrl.Designer.cs b/TestBenchFramework/BenchControl/Greco/AmbientCfgCtrl.Designer.cs new file mode 100644 index 000000000..4894b0f03 --- /dev/null +++ b/TestBenchFramework/BenchControl/Greco/AmbientCfgCtrl.Designer.cs @@ -0,0 +1,226 @@ +namespace TBF.BenchControl.Greco +{ + partial class AmbientCfgCtrl + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.comPortNrTextBox = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.baudRateLabel = new System.Windows.Forms.Label(); + this.baudRateTextBox = new System.Windows.Forms.TextBox(); + this.partityLabel = new System.Windows.Forms.Label(); + this.dataBitsLabel = new System.Windows.Forms.Label(); + this.dataBitsTextBox = new System.Windows.Forms.TextBox(); + this.stopBitsLabel = new System.Windows.Forms.Label(); + this.handshakeLabel = new System.Windows.Forms.Label(); + this.nameTextBox = new System.Windows.Forms.TextBox(); + this.nameLabel = new System.Windows.Forms.Label(); + this.classNameLabel = new System.Windows.Forms.Label(); + this.parityComboBox = new System.Windows.Forms.ComboBox(); + this.stopBitsComboBox = new System.Windows.Forms.ComboBox(); + this.handshakeComboBox = new System.Windows.Forms.ComboBox(); + this.SuspendLayout(); + // + // comPortNrTextBox + // + this.comPortNrTextBox.Enabled = false; + this.comPortNrTextBox.Location = new System.Drawing.Point(140, 52); + this.comPortNrTextBox.Name = "comPortNrTextBox"; + this.comPortNrTextBox.Size = new System.Drawing.Size(34, 20); + this.comPortNrTextBox.TabIndex = 4; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(29, 55); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(98, 13); + this.label1.TabIndex = 3; + this.label1.Text = "Serial Port Number:"; + // + // baudRateLabel + // + this.baudRateLabel.AutoSize = true; + this.baudRateLabel.Location = new System.Drawing.Point(29, 79); + this.baudRateLabel.Name = "baudRateLabel"; + this.baudRateLabel.Size = new System.Drawing.Size(58, 13); + this.baudRateLabel.TabIndex = 5; + this.baudRateLabel.Text = "Baud Rate"; + // + // baudRateTextBox + // + this.baudRateTextBox.Enabled = false; + this.baudRateTextBox.Location = new System.Drawing.Point(140, 76); + this.baudRateTextBox.Name = "baudRateTextBox"; + this.baudRateTextBox.Size = new System.Drawing.Size(130, 20); + this.baudRateTextBox.TabIndex = 6; + // + // partityLabel + // + this.partityLabel.AutoSize = true; + this.partityLabel.Location = new System.Drawing.Point(29, 103); + this.partityLabel.Name = "partityLabel"; + this.partityLabel.Size = new System.Drawing.Size(33, 13); + this.partityLabel.TabIndex = 7; + this.partityLabel.Text = "Parity"; + // + // dataBitsLabel + // + this.dataBitsLabel.AutoSize = true; + this.dataBitsLabel.Location = new System.Drawing.Point(29, 127); + this.dataBitsLabel.Name = "dataBitsLabel"; + this.dataBitsLabel.Size = new System.Drawing.Size(50, 13); + this.dataBitsLabel.TabIndex = 9; + this.dataBitsLabel.Text = "Data Bits"; + // + // dataBitsTextBox + // + this.dataBitsTextBox.Enabled = false; + this.dataBitsTextBox.Location = new System.Drawing.Point(140, 124); + this.dataBitsTextBox.Name = "dataBitsTextBox"; + this.dataBitsTextBox.Size = new System.Drawing.Size(34, 20); + this.dataBitsTextBox.TabIndex = 10; + // + // stopBitsLabel + // + this.stopBitsLabel.AutoSize = true; + this.stopBitsLabel.Location = new System.Drawing.Point(29, 151); + this.stopBitsLabel.Name = "stopBitsLabel"; + this.stopBitsLabel.Size = new System.Drawing.Size(49, 13); + this.stopBitsLabel.TabIndex = 11; + this.stopBitsLabel.Text = "Stop Bits"; + // + // handshakeLabel + // + this.handshakeLabel.AutoSize = true; + this.handshakeLabel.Location = new System.Drawing.Point(29, 175); + this.handshakeLabel.Name = "handshakeLabel"; + this.handshakeLabel.Size = new System.Drawing.Size(62, 13); + this.handshakeLabel.TabIndex = 13; + this.handshakeLabel.Text = "Handshake"; + // + // nameTextBox + // + this.nameTextBox.Enabled = false; + this.nameTextBox.Location = new System.Drawing.Point(140, 28); + this.nameTextBox.Name = "nameTextBox"; + this.nameTextBox.Size = new System.Drawing.Size(130, 20); + this.nameTextBox.TabIndex = 2; + // + // nameLabel + // + this.nameLabel.AutoSize = true; + this.nameLabel.Location = new System.Drawing.Point(30, 31); + this.nameLabel.Name = "nameLabel"; + this.nameLabel.Size = new System.Drawing.Size(35, 13); + this.nameLabel.TabIndex = 1; + this.nameLabel.Text = "Name"; + // + // classNameLabel + // + this.classNameLabel.AutoSize = true; + this.classNameLabel.Location = new System.Drawing.Point(137, 7); + this.classNameLabel.Name = "classNameLabel"; + this.classNameLabel.Size = new System.Drawing.Size(83, 13); + this.classNameLabel.TabIndex = 0; + this.classNameLabel.Text = "ComonentName"; + // + // parityComboBox + // + this.parityComboBox.Enabled = false; + this.parityComboBox.FormattingEnabled = true; + this.parityComboBox.Location = new System.Drawing.Point(140, 100); + this.parityComboBox.Name = "parityComboBox"; + this.parityComboBox.Size = new System.Drawing.Size(130, 21); + this.parityComboBox.TabIndex = 8; + // + // stopBitsComboBox + // + this.stopBitsComboBox.Enabled = false; + this.stopBitsComboBox.FormattingEnabled = true; + this.stopBitsComboBox.Location = new System.Drawing.Point(140, 148); + this.stopBitsComboBox.Name = "stopBitsComboBox"; + this.stopBitsComboBox.Size = new System.Drawing.Size(130, 21); + this.stopBitsComboBox.TabIndex = 12; + // + // handshakeComboBox + // + this.handshakeComboBox.Enabled = false; + this.handshakeComboBox.FormattingEnabled = true; + this.handshakeComboBox.Location = new System.Drawing.Point(140, 172); + this.handshakeComboBox.Name = "handshakeComboBox"; + this.handshakeComboBox.Size = new System.Drawing.Size(130, 21); + this.handshakeComboBox.TabIndex = 14; + // + // AmbientCfgCtrl + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.BackColor = System.Drawing.SystemColors.Control; + this.Controls.Add(this.handshakeComboBox); + this.Controls.Add(this.stopBitsComboBox); + this.Controls.Add(this.parityComboBox); + this.Controls.Add(this.nameTextBox); + this.Controls.Add(this.nameLabel); + this.Controls.Add(this.classNameLabel); + this.Controls.Add(this.handshakeLabel); + this.Controls.Add(this.stopBitsLabel); + this.Controls.Add(this.dataBitsTextBox); + this.Controls.Add(this.dataBitsLabel); + this.Controls.Add(this.partityLabel); + this.Controls.Add(this.baudRateTextBox); + this.Controls.Add(this.baudRateLabel); + this.Controls.Add(this.comPortNrTextBox); + this.Controls.Add(this.label1); + this.Name = "AmbientCfgCtrl"; + this.Size = new System.Drawing.Size(300, 240); + this.Load += new System.EventHandler(this.AbbientCfgCtrl_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TextBox comPortNrTextBox; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label baudRateLabel; + private System.Windows.Forms.TextBox baudRateTextBox; + private System.Windows.Forms.Label partityLabel; + private System.Windows.Forms.Label dataBitsLabel; + private System.Windows.Forms.TextBox dataBitsTextBox; + private System.Windows.Forms.Label stopBitsLabel; + private System.Windows.Forms.Label handshakeLabel; + private System.Windows.Forms.TextBox nameTextBox; + private System.Windows.Forms.Label nameLabel; + private System.Windows.Forms.Label classNameLabel; + private System.Windows.Forms.ComboBox parityComboBox; + private System.Windows.Forms.ComboBox stopBitsComboBox; + private System.Windows.Forms.ComboBox handshakeComboBox; + + } +} diff --git a/TestBenchFramework/BenchControl/Greco/AmbientCfgCtrl.cs b/TestBenchFramework/BenchControl/Greco/AmbientCfgCtrl.cs new file mode 100644 index 000000000..23399502e --- /dev/null +++ b/TestBenchFramework/BenchControl/Greco/AmbientCfgCtrl.cs @@ -0,0 +1,156 @@ +using System; +using System.Windows.Forms; +using System.IO.Ports; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.Greco +{ + public partial class AmbientCfgCtrl : UserControl, IComponentCfgCtrl + { + AmbientCfg config; + + public IComponentCfg Config + { + get { return config as IComponentCfg; } + set + { + config = value as AmbientCfg; + Redraw(); + } + } + + public AmbientCfgCtrl() + { + InitializeComponent(); + + parityComboBox.Items.Add(Parity.None.ToString()); + parityComboBox.Items.Add(Parity.Even.ToString()); + parityComboBox.Items.Add(Parity.Odd.ToString()); + + stopBitsComboBox.Items.Add(StopBits.None.ToString()); + stopBitsComboBox.Items.Add(StopBits.One.ToString()); + stopBitsComboBox.Items.Add(StopBits.OnePointFive.ToString()); + stopBitsComboBox.Items.Add(StopBits.Two.ToString()); + + handshakeComboBox.Items.Add(Handshake.None.ToString()); + handshakeComboBox.Items.Add(Handshake.RequestToSend.ToString()); + handshakeComboBox.Items.Add(Handshake.XOnXOff.ToString()); + } + + int GetParityIx(Parity par) + { + if (par == Parity.None) return 0; + if (par == Parity.Even) return 0; + if (par == Parity.Odd) return 0; + return -1; + } + Parity GetParity(string str) + { + if (str.Equals(Parity.None.ToString())) return Parity.None; + if (str.Equals(Parity.Even.ToString())) return Parity.Even; + if (str.Equals(Parity.Odd.ToString())) return Parity.Odd; + return (Parity)(-1); + } + + int GetStopBitsIx(StopBits sb) + { + if (sb == StopBits.None) return 0; + if (sb == StopBits.One) return 1; + if (sb == StopBits.OnePointFive) return 2; + if (sb == StopBits.Two) return 3; + return -1; + } + StopBits GetStopBits(string str) + { + if (str.Equals(StopBits.None.ToString())) return StopBits.None; + if (str.Equals(StopBits.One.ToString())) return StopBits.One; + if (str.Equals(StopBits.OnePointFive.ToString())) return StopBits.OnePointFive; + if (str.Equals(StopBits.Two.ToString())) return StopBits.Two; + return (StopBits)(-1); + } + + int GetHandshakeIx(Handshake par) + { + if (par == Handshake.None) return 0; + if (par == Handshake.RequestToSend) return 0; + if (par == Handshake.XOnXOff) return 0; + return -1; + } + Handshake GetHandshake(string str) + { + if (str.Equals(Handshake.None.ToString())) return Handshake.None; + if (str.Equals(Handshake.RequestToSend.ToString())) return Handshake.RequestToSend; + if (str.Equals(Handshake.XOnXOff.ToString())) return Handshake.XOnXOff; + return (Handshake)(-1); + } + + private void AbbientCfgCtrl_Load(object sender, EventArgs e) + { + Redraw(); + } + + void Redraw() + { + if (config == null) return; /// Control was not loaded, settings were not changed + + classNameLabel.Text = config.Factory.ClassName; + nameTextBox.Text = config.Name; + comPortNrTextBox.Text = config.ComPortNr.ToString(); + baudRateTextBox.Text = config.BaudRate.ToString(); + parityComboBox.Text = config.Parity.ToString(); + dataBitsTextBox.Text = config.DataBits.ToString(); + stopBitsComboBox.Text = config.StopBits.ToString(); + handshakeComboBox.Text = config.Handshake.ToString(); + } + + public void Unlock() + { + nameTextBox.Enabled = true; + comPortNrTextBox.Enabled = true; + baudRateTextBox.Enabled = true; + parityComboBox.Enabled = true; + dataBitsTextBox.Enabled = true; + stopBitsComboBox.Enabled = true; + handshakeComboBox.Enabled = true; + } + + public void UpdateCfg() + { + if (config == null) return; /// Control was not loaded, settings were not changed + + config.Name = nameTextBox.Text; + config.ComPortNr = int.Parse(comPortNrTextBox.Text); + config.BaudRate = int.Parse(baudRateTextBox.Text); + config.Parity = GetParity(parityComboBox.SelectedItem.ToString()); + config.DataBits = int.Parse(dataBitsTextBox.Text); + config.StopBits = GetStopBits(stopBitsComboBox.SelectedItem.ToString()); + config.Handshake = GetHandshake(handshakeComboBox.SelectedItem.ToString()); + } + + public CfgVerifyFlags VerifyCfg(ref string message) + { + CfgVerifyFlags flags = CfgVerifyFlags.None; + + int dummy; + if (!int.TryParse(comPortNrTextBox.Text, out dummy) || dummy < 1 || dummy > 999) + { + flags |= CfgVerifyFlags.Error; + message += Environment.NewLine + "'Serial Port Number' is not valid"; + } + + if (!int.TryParse(baudRateTextBox.Text, out dummy) || dummy < 150 || dummy > 115200) + { + flags |= CfgVerifyFlags.Error; + message += Environment.NewLine + "'Baud Rate' is not valid"; + } + + if (!int.TryParse(dataBitsTextBox.Text, out dummy) || dummy < 7 || dummy > 8) + { + flags |= CfgVerifyFlags.Error; + message += Environment.NewLine + "'Data Bits' is not valid"; + } + + return flags; + } + } +} diff --git a/TestBenchFramework/BenchControl/Greco/AmbientCfgCtrl.resx b/TestBenchFramework/BenchControl/Greco/AmbientCfgCtrl.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/TestBenchFramework/BenchControl/Greco/AmbientCfgCtrl.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/BenchControl/Greco/AmbientFactory.cs b/TestBenchFramework/BenchControl/Greco/AmbientFactory.cs new file mode 100644 index 000000000..8d3332142 --- /dev/null +++ b/TestBenchFramework/BenchControl/Greco/AmbientFactory.cs @@ -0,0 +1,40 @@ +using System.Collections.Generic; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.Greco +{ + public class AmbientFactory : IComponentFactory + { + public string ClassName { get { return "Greco Ambient"; } } + public bool HasProcedureParams { get { return false; } } + public bool HasTestParams { get { return false; } } + public IParamsProvider GetTestParams(Entities.ComponentTest testParams) { return null; } + public IParamsProvider GetProcedureParams(Entities.ComponentProcedure procedureParams) { return null; } + + /// Max. number of components of this class in the system + public int MaxCount { get { return 1; } } + + public IComponentCfg DefaultConfig(IList components) + { + return new AmbientCfg(this, "Ambient", 6, 19200, System.IO.Ports.Parity.None, 8, + System.IO.Ports.StopBits.One, System.IO.Ports.Handshake.None); + } + + public IComponentCfgCtrl CreateCfgCtrl() + { + return new AmbientCfgCtrl(); + } + + public IComponent ComponentFromCmpntCfg(IComponentCfg config, IList components) + { + return new Ambient((AmbientCfg)config, components); + } + + public IComponentCfg CmpntCfgFromCmpntEntity(Entities.Component component) + { + return Greco.AmbientCfg.CreateFromDbEntity(component, this); + } + + public void ResetStaticProperties() { Ambient.ResetStaticProperties(); } + } +} diff --git a/TestBenchFramework/BenchControl/IOperation.cs b/TestBenchFramework/BenchControl/IOperation.cs new file mode 100644 index 000000000..d6b064bba --- /dev/null +++ b/TestBenchFramework/BenchControl/IOperation.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace TBF.BenchControl +{ + /// + /// This interface has to be implemented by each 'operation'. 'operations' are classes + /// in TBF.BenchControl name space with a class name ending with 'Op' (e.g. TimerOp). + /// This class name rule is a convention, not a requirement. + /// + public interface IOperation + { + /// + /// Method is called when a state machine enters a state in which this operation + /// takes place/ will be executed. + /// Method is not called when this operation took place also in the previous state. + /// StateMachine checks whether Start() should be called depending on the previous + /// and the current state. + /// + /// true on success + void Start(); + + /// + /// Method is called in regular time intervals when state machine is + /// in a state in which this operation takes place. + /// During operation the IOparation derived object may issue events, + /// that means Run() method returns a value different from Event.Void (=0). + /// Examples: Timer expired + /// + /// + Event Run(); + + /// + /// Method is called when the state machine leaves a state in which + /// this operation takes place / was executed. + /// Method is not called when this operation takes place also in the next state. + /// StateMachine checks whether Start() should be called depending on the previous + /// and the current state. + /// + void Stop(); + } +} diff --git a/TestBenchFramework/BenchControl/ISequence.cs b/TestBenchFramework/BenchControl/ISequence.cs new file mode 100644 index 000000000..11d515305 --- /dev/null +++ b/TestBenchFramework/BenchControl/ISequence.cs @@ -0,0 +1,10 @@ +using System; +using System.Collections.Generic; + +namespace TBF.BenchControl +{ + public interface ISequence + { + IList Execute(Entities.Test test); + } +} diff --git a/TestBenchFramework/BenchControl/IntBox.cs b/TestBenchFramework/BenchControl/IntBox.cs new file mode 100644 index 000000000..0d1b892b7 --- /dev/null +++ b/TestBenchFramework/BenchControl/IntBox.cs @@ -0,0 +1,22 @@ +namespace TBF.BenchControl +{ + public class IntBox + { + public int N; + + public IntBox() + { + N = 0; + } + + public IntBox(int n) + { + N = n; + } + + public override string ToString() + { + return N.ToString(); + } + } +} diff --git a/TestBenchFramework/BenchControl/MetersPath.cs b/TestBenchFramework/BenchControl/MetersPath.cs new file mode 100644 index 000000000..11a3ccab6 --- /dev/null +++ b/TestBenchFramework/BenchControl/MetersPath.cs @@ -0,0 +1,33 @@ +using System.Collections.Generic; +using TBF.BenchControl.GenericDevices; + +namespace TBF.BenchControl +{ + public class MetersPath + { + public int ItemNr; + public string Name; + public float Qfrom; + public float Qto; + public IRegisterReader[] RegisterReaders; + + /// Constructor from name, the rest is empty + public MetersPath(string name, int itemNr) + { + ItemNr = itemNr; + Name = name; + RegisterReaders = new IRegisterReader[Program.WMsCount]; + } + + public MetersPath(Entities.MetersPath entity, IList components) + : this(entity.Name, entity.ItemNr) + { + Qfrom = entity.Qfrom; + Qto = entity.Qto; + for (int i = 0; i < Program.WMsCount; i++) + { + RegisterReaders[i] = (IRegisterReader)TbfComponents.FindComponent(entity.GetSensor(i), components); + } + } + } +} diff --git a/TestBenchFramework/BenchControl/MettlerToledo/BalanceCfg.cs b/TestBenchFramework/BenchControl/MettlerToledo/BalanceCfg.cs new file mode 100644 index 000000000..de94c9e26 --- /dev/null +++ b/TestBenchFramework/BenchControl/MettlerToledo/BalanceCfg.cs @@ -0,0 +1,66 @@ +using System.IO; +using System.IO.Ports; +using System.Xml.Serialization; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.MettlerToledo +{ + public class BalanceCfg : ComponentCfgBase, Generic.IComponentCfg + { + public int ComPortNr; + public int BaudRate; + public Parity Parity; + public int DataBits; + public StopBits StopBits; + public Handshake Handshake; + + public float Capacity; /// Balance range in 'kg' or tank volume in 'l' + + /// Parameterless constructor + public BalanceCfg() + { + } + + /// Constructor + public BalanceCfg(IComponentFactory factory, string name, int comPortNr, int baudRate, Parity parity, int dataBits, StopBits stopBits, Handshake handshake, float capacity) + : base(factory, name) + { + this.ComPortNr = comPortNr; + this.BaudRate = baudRate; + this.Parity = parity; + this.DataBits = dataBits; + this.StopBits = stopBits; + this.Handshake = handshake; + this.Capacity = capacity; + } + + public IComponentCfg Clone() + { + return new BalanceCfg(Factory, Name, ComPortNr, BaudRate, Parity, DataBits, StopBits, Handshake, Capacity); + } + + public string ToString(int i) + { + return string.Format("COM{0}, {1}Bd, {2}bits, parity={3}, stopBits={4}, {5}, capacity={6}kg", ComPortNr, BaudRate, DataBits, Parity, StopBits, Handshake, Capacity); + } + + public TBF.Entities.Component CreateDbEntity() + { + using (var writer = new StringWriter()) + { + (new XmlSerializer(GetType())).Serialize(writer, this); + return Entities.Component.CreateFromCfg(Name, Factory.ClassName, ParentName, ItemNr, DebugLevel, LogLevel, writer.ToString()); + } + } + + public static IComponentCfg CreateFromDbEntity(Entities.Component component, IComponentFactory factory) + { + using (var reader = new StringReader(component.Parameters)) + { + BalanceCfg config = (BalanceCfg)(new XmlSerializer(typeof(BalanceCfg))).Deserialize(reader); + config.InitCfgBaseFromEntity(component, factory); + return config; + } + } + } +} diff --git a/TestBenchFramework/BenchControl/MettlerToledo/BalanceCfgCtrl.Designer.cs b/TestBenchFramework/BenchControl/MettlerToledo/BalanceCfgCtrl.Designer.cs new file mode 100644 index 000000000..fad4eb468 --- /dev/null +++ b/TestBenchFramework/BenchControl/MettlerToledo/BalanceCfgCtrl.Designer.cs @@ -0,0 +1,259 @@ +namespace TBF.BenchControl.MettlerToledo +{ + partial class BalanceCfgCtrl + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.handshakeComboBox = new System.Windows.Forms.ComboBox(); + this.stopBitsComboBox = new System.Windows.Forms.ComboBox(); + this.parityComboBox = new System.Windows.Forms.ComboBox(); + this.nameTextBox = new System.Windows.Forms.TextBox(); + this.nameLabel = new System.Windows.Forms.Label(); + this.classNameLabel = new System.Windows.Forms.Label(); + this.handshakeLabel = new System.Windows.Forms.Label(); + this.stopBitsLabel = new System.Windows.Forms.Label(); + this.dataBitsTextBox = new System.Windows.Forms.TextBox(); + this.dataBitsLabel = new System.Windows.Forms.Label(); + this.partityLabel = new System.Windows.Forms.Label(); + this.baudRateTextBox = new System.Windows.Forms.TextBox(); + this.baudRateLabel = new System.Windows.Forms.Label(); + this.comPortNrTextBox = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.rangeLabel = new System.Windows.Forms.Label(); + this.rangeTextBox = new System.Windows.Forms.TextBox(); + this.label2 = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // handshakeComboBox + // + this.handshakeComboBox.Enabled = false; + this.handshakeComboBox.FormattingEnabled = true; + this.handshakeComboBox.Location = new System.Drawing.Point(136, 173); + this.handshakeComboBox.Name = "handshakeComboBox"; + this.handshakeComboBox.Size = new System.Drawing.Size(130, 21); + this.handshakeComboBox.TabIndex = 14; + // + // stopBitsComboBox + // + this.stopBitsComboBox.Enabled = false; + this.stopBitsComboBox.FormattingEnabled = true; + this.stopBitsComboBox.Location = new System.Drawing.Point(136, 149); + this.stopBitsComboBox.Name = "stopBitsComboBox"; + this.stopBitsComboBox.Size = new System.Drawing.Size(130, 21); + this.stopBitsComboBox.TabIndex = 12; + // + // parityComboBox + // + this.parityComboBox.Enabled = false; + this.parityComboBox.FormattingEnabled = true; + this.parityComboBox.Location = new System.Drawing.Point(136, 101); + this.parityComboBox.Name = "parityComboBox"; + this.parityComboBox.Size = new System.Drawing.Size(130, 21); + this.parityComboBox.TabIndex = 8; + // + // nameTextBox + // + this.nameTextBox.Enabled = false; + this.nameTextBox.Location = new System.Drawing.Point(136, 29); + this.nameTextBox.Name = "nameTextBox"; + this.nameTextBox.Size = new System.Drawing.Size(130, 20); + this.nameTextBox.TabIndex = 2; + // + // nameLabel + // + this.nameLabel.AutoSize = true; + this.nameLabel.Location = new System.Drawing.Point(26, 32); + this.nameLabel.Name = "nameLabel"; + this.nameLabel.Size = new System.Drawing.Size(35, 13); + this.nameLabel.TabIndex = 1; + this.nameLabel.Text = "Name"; + // + // classNameLabel + // + this.classNameLabel.AutoSize = true; + this.classNameLabel.Location = new System.Drawing.Point(133, 8); + this.classNameLabel.Name = "classNameLabel"; + this.classNameLabel.Size = new System.Drawing.Size(83, 13); + this.classNameLabel.TabIndex = 0; + this.classNameLabel.Text = "ComonentName"; + // + // handshakeLabel + // + this.handshakeLabel.AutoSize = true; + this.handshakeLabel.Location = new System.Drawing.Point(25, 176); + this.handshakeLabel.Name = "handshakeLabel"; + this.handshakeLabel.Size = new System.Drawing.Size(62, 13); + this.handshakeLabel.TabIndex = 13; + this.handshakeLabel.Text = "Handshake"; + // + // stopBitsLabel + // + this.stopBitsLabel.AutoSize = true; + this.stopBitsLabel.Location = new System.Drawing.Point(25, 152); + this.stopBitsLabel.Name = "stopBitsLabel"; + this.stopBitsLabel.Size = new System.Drawing.Size(49, 13); + this.stopBitsLabel.TabIndex = 11; + this.stopBitsLabel.Text = "Stop Bits"; + // + // dataBitsTextBox + // + this.dataBitsTextBox.Enabled = false; + this.dataBitsTextBox.Location = new System.Drawing.Point(136, 125); + this.dataBitsTextBox.Name = "dataBitsTextBox"; + this.dataBitsTextBox.Size = new System.Drawing.Size(43, 20); + this.dataBitsTextBox.TabIndex = 10; + // + // dataBitsLabel + // + this.dataBitsLabel.AutoSize = true; + this.dataBitsLabel.Location = new System.Drawing.Point(25, 128); + this.dataBitsLabel.Name = "dataBitsLabel"; + this.dataBitsLabel.Size = new System.Drawing.Size(50, 13); + this.dataBitsLabel.TabIndex = 9; + this.dataBitsLabel.Text = "Data Bits"; + // + // partityLabel + // + this.partityLabel.AutoSize = true; + this.partityLabel.Location = new System.Drawing.Point(25, 104); + this.partityLabel.Name = "partityLabel"; + this.partityLabel.Size = new System.Drawing.Size(33, 13); + this.partityLabel.TabIndex = 7; + this.partityLabel.Text = "Parity"; + // + // baudRateTextBox + // + this.baudRateTextBox.Enabled = false; + this.baudRateTextBox.Location = new System.Drawing.Point(136, 77); + this.baudRateTextBox.Name = "baudRateTextBox"; + this.baudRateTextBox.Size = new System.Drawing.Size(130, 20); + this.baudRateTextBox.TabIndex = 6; + // + // baudRateLabel + // + this.baudRateLabel.AutoSize = true; + this.baudRateLabel.Location = new System.Drawing.Point(25, 80); + this.baudRateLabel.Name = "baudRateLabel"; + this.baudRateLabel.Size = new System.Drawing.Size(58, 13); + this.baudRateLabel.TabIndex = 5; + this.baudRateLabel.Text = "Baud Rate"; + // + // comPortNrTextBox + // + this.comPortNrTextBox.Enabled = false; + this.comPortNrTextBox.Location = new System.Drawing.Point(136, 53); + this.comPortNrTextBox.Name = "comPortNrTextBox"; + this.comPortNrTextBox.Size = new System.Drawing.Size(43, 20); + this.comPortNrTextBox.TabIndex = 4; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(25, 56); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(98, 13); + this.label1.TabIndex = 3; + this.label1.Text = "Serial Port Number:"; + // + // rangeLabel + // + this.rangeLabel.AutoSize = true; + this.rangeLabel.Location = new System.Drawing.Point(25, 201); + this.rangeLabel.Name = "rangeLabel"; + this.rangeLabel.Size = new System.Drawing.Size(76, 13); + this.rangeLabel.TabIndex = 15; + this.rangeLabel.Text = "Tank Capacity"; + // + // rangeTextBox + // + this.rangeTextBox.Enabled = false; + this.rangeTextBox.Location = new System.Drawing.Point(136, 198); + this.rangeTextBox.Name = "rangeTextBox"; + this.rangeTextBox.Size = new System.Drawing.Size(43, 20); + this.rangeTextBox.TabIndex = 16; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(185, 201); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(19, 13); + this.label2.TabIndex = 17; + this.label2.Text = "kg"; + // + // BalanceCfgCtrl + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.label2); + this.Controls.Add(this.rangeTextBox); + this.Controls.Add(this.rangeLabel); + this.Controls.Add(this.handshakeComboBox); + this.Controls.Add(this.stopBitsComboBox); + this.Controls.Add(this.parityComboBox); + this.Controls.Add(this.nameTextBox); + this.Controls.Add(this.nameLabel); + this.Controls.Add(this.classNameLabel); + this.Controls.Add(this.handshakeLabel); + this.Controls.Add(this.stopBitsLabel); + this.Controls.Add(this.dataBitsTextBox); + this.Controls.Add(this.dataBitsLabel); + this.Controls.Add(this.partityLabel); + this.Controls.Add(this.baudRateTextBox); + this.Controls.Add(this.baudRateLabel); + this.Controls.Add(this.comPortNrTextBox); + this.Controls.Add(this.label1); + this.Name = "BalanceCfgCtrl"; + this.Size = new System.Drawing.Size(300, 240); + this.Load += new System.EventHandler(this.BalanceCfgCtrl_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.ComboBox handshakeComboBox; + private System.Windows.Forms.ComboBox stopBitsComboBox; + private System.Windows.Forms.ComboBox parityComboBox; + private System.Windows.Forms.TextBox nameTextBox; + private System.Windows.Forms.Label nameLabel; + private System.Windows.Forms.Label classNameLabel; + private System.Windows.Forms.Label handshakeLabel; + private System.Windows.Forms.Label stopBitsLabel; + private System.Windows.Forms.TextBox dataBitsTextBox; + private System.Windows.Forms.Label dataBitsLabel; + private System.Windows.Forms.Label partityLabel; + private System.Windows.Forms.TextBox baudRateTextBox; + private System.Windows.Forms.Label baudRateLabel; + private System.Windows.Forms.TextBox comPortNrTextBox; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label rangeLabel; + private System.Windows.Forms.TextBox rangeTextBox; + private System.Windows.Forms.Label label2; + } +} diff --git a/TestBenchFramework/BenchControl/MettlerToledo/BalanceCfgCtrl.cs b/TestBenchFramework/BenchControl/MettlerToledo/BalanceCfgCtrl.cs new file mode 100644 index 000000000..a5de5e9a8 --- /dev/null +++ b/TestBenchFramework/BenchControl/MettlerToledo/BalanceCfgCtrl.cs @@ -0,0 +1,167 @@ +using System; +using System.Globalization; +using System.Windows.Forms; +using System.IO.Ports; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.MettlerToledo +{ + public partial class BalanceCfgCtrl : UserControl, IComponentCfgCtrl + { + BalanceCfg config; + + public IComponentCfg Config + { + get { return config as IComponentCfg; } + set + { + config = value as BalanceCfg; + Redraw(); + } + } + + public BalanceCfgCtrl() + { + InitializeComponent(); + + parityComboBox.Items.Add(Parity.None.ToString()); + parityComboBox.Items.Add(Parity.Even.ToString()); + parityComboBox.Items.Add(Parity.Odd.ToString()); + + stopBitsComboBox.Items.Add(StopBits.None.ToString()); + stopBitsComboBox.Items.Add(StopBits.One.ToString()); + stopBitsComboBox.Items.Add(StopBits.OnePointFive.ToString()); + stopBitsComboBox.Items.Add(StopBits.Two.ToString()); + + handshakeComboBox.Items.Add(Handshake.None.ToString()); + handshakeComboBox.Items.Add(Handshake.RequestToSend.ToString()); + handshakeComboBox.Items.Add(Handshake.XOnXOff.ToString()); + } + + int GetParityIx(Parity par) + { + if (par == Parity.None) return 0; + if (par == Parity.Even) return 0; + if (par == Parity.Odd) return 0; + return -1; + } + Parity GetParity(string str) + { + if (str.Equals(Parity.None.ToString())) return Parity.None; + if (str.Equals(Parity.Even.ToString())) return Parity.Even; + if (str.Equals(Parity.Odd.ToString())) return Parity.Odd; + return (Parity)(-1); + } + + int GetStopBitsIx(StopBits sb) + { + if (sb == StopBits.None) return 0; + if (sb == StopBits.One) return 1; + if (sb == StopBits.OnePointFive) return 2; + if (sb == StopBits.Two) return 3; + return -1; + } + StopBits GetStopBits(string str) + { + if (str.Equals(StopBits.None.ToString())) return StopBits.None; + if (str.Equals(StopBits.One.ToString())) return StopBits.One; + if (str.Equals(StopBits.OnePointFive.ToString())) return StopBits.OnePointFive; + if (str.Equals(StopBits.Two.ToString())) return StopBits.Two; + return (StopBits)(-1); + } + + int GetHandshakeIx(Handshake par) + { + if (par == Handshake.None) return 0; + if (par == Handshake.RequestToSend) return 0; + if (par == Handshake.XOnXOff) return 0; + return -1; + } + Handshake GetHandshake(string str) + { + if (str.Equals(Handshake.None.ToString())) return Handshake.None; + if (str.Equals(Handshake.RequestToSend.ToString())) return Handshake.RequestToSend; + if (str.Equals(Handshake.XOnXOff.ToString())) return Handshake.XOnXOff; + return (Handshake)(-1); + } + + private void BalanceCfgCtrl_Load(object sender, EventArgs e) + { + Redraw(); + } + + void Redraw() + { + if (config == null) return; /// Control was not loaded, settings were not changed + + classNameLabel.Text = config.Factory.ClassName; + nameTextBox.Text = config.Name; + comPortNrTextBox.Text = config.ComPortNr.ToString(); + baudRateTextBox.Text = config.BaudRate.ToString(); + parityComboBox.Text = config.Parity.ToString(); + dataBitsTextBox.Text = config.DataBits.ToString(); + stopBitsComboBox.Text = config.StopBits.ToString(); + handshakeComboBox.Text = config.Handshake.ToString(); + rangeTextBox.Text = config.Capacity.ToString(); + } + + public void Unlock() + { + nameTextBox.Enabled = true; + comPortNrTextBox.Enabled = true; + baudRateTextBox.Enabled = true; + parityComboBox.Enabled = true; + dataBitsTextBox.Enabled = true; + stopBitsComboBox.Enabled = true; + handshakeComboBox.Enabled = true; + rangeTextBox.Enabled = true; + } + + public CfgVerifyFlags VerifyCfg(ref string message) + { + CfgVerifyFlags flags = CfgVerifyFlags.None; + + int dummy; + if (!int.TryParse(comPortNrTextBox.Text, out dummy) || dummy < 1 || dummy > 999) + { + flags |= CfgVerifyFlags.Error; + message += Environment.NewLine + "'Serial Port Number' is not valid"; + } + if (!int.TryParse(baudRateTextBox.Text, out dummy) || dummy < 150 || dummy > 115200) + { + flags |= CfgVerifyFlags.Error; + message += Environment.NewLine + "'Baud Rate' is not valid"; + } + if (!int.TryParse(dataBitsTextBox.Text, out dummy) || dummy < 7 || dummy > 8) + { + flags |= CfgVerifyFlags.Error; + message += Environment.NewLine + "'Data Bits' is not valid"; + } + float fdummy; + bool floatOk = (float.TryParse(rangeTextBox.Text, NumberStyles.AllowDecimalPoint, CultureInfo.CurrentCulture, out fdummy) || + float.TryParse(rangeTextBox.Text, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out fdummy)); + if (!floatOk || fdummy <= 0) + { + flags |= CfgVerifyFlags.Error; + message += Environment.NewLine + "'Range' is not valid"; + } + + return flags; + } + + public void UpdateCfg() + { + if (config == null) return; /// Control was not loaded, settings were not changed + + config.Name = nameTextBox.Text; + config.ComPortNr = int.Parse(comPortNrTextBox.Text); + config.BaudRate = int.Parse(baudRateTextBox.Text); + config.Parity = GetParity(parityComboBox.SelectedItem.ToString()); + config.DataBits = int.Parse(dataBitsTextBox.Text); + config.StopBits = GetStopBits(stopBitsComboBox.SelectedItem.ToString()); + config.Handshake = GetHandshake(handshakeComboBox.SelectedItem.ToString()); + bool floatOk = (float.TryParse(rangeTextBox.Text, NumberStyles.AllowDecimalPoint, CultureInfo.CurrentCulture, out config.Capacity) || + float.TryParse(rangeTextBox.Text, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out config.Capacity)); + } + } +} diff --git a/TestBenchFramework/BenchControl/MettlerToledo/BalanceCfgCtrl.resx b/TestBenchFramework/BenchControl/MettlerToledo/BalanceCfgCtrl.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/TestBenchFramework/BenchControl/MettlerToledo/BalanceCfgCtrl.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/BenchControl/MettlerToledo/BalanceDev.cs b/TestBenchFramework/BenchControl/MettlerToledo/BalanceDev.cs new file mode 100644 index 000000000..65f9f90c5 --- /dev/null +++ b/TestBenchFramework/BenchControl/MettlerToledo/BalanceDev.cs @@ -0,0 +1,423 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Text; +using System.IO.Ports; +using log4net; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.MettlerToledo +{ + /// + /// Mettler Toledo ICS4_5 Weighting terminal connected via serial interface (RS232) + /// + /// + /// Implemented and tested on 15.10.2013 by Milan Hanajik + /// + public class BalanceDev : TestBenchSim, IComponent, IDevice, GenericDevices.IBalance + { + /// + /// Info: StartMassMeasurement() and "Balnce response = .., Mass = ..." + /// Warn: Start measurement when busy is true + /// + private static readonly ILog log = LogManager.GetLogger(typeof(BalanceDev)); + public override string ToString() { return string.Format("{0}, Mettler-Toledo Balance", balanceCfg.Name); } + + /// + /// Enumeration of balances via static fields and methods + /// + static int nextBalanceIdx = 0; + public static void ResetStaticProperties() { nextBalanceIdx = 0; } + public static int BalancesCount { get { return nextBalanceIdx; } } + public static BalanceDev[] Balances; + public static float[] Masses; + /// + protected int balanceNr; /// 0-based balance number + + protected readonly BalanceCfg balanceCfg; + public Generic.IComponentCfg Cfg { get { return balanceCfg; } } + + protected SerialPort serialPort; + protected StringBuilder stringBuilder; + + public string Name { get { return balanceCfg.Name; } } + public int BalanceNr { get { return balanceNr; } } + public float Capacity { get { return balanceCfg.Capacity; } } + public IList Corrections { get { return balanceCfg.Corrections; } } + + /// The state of the mass measurement + public MsrmntState MsrmntState + { + get { return msrmntState; } + } + protected MsrmntState msrmntState; + + /// The mass after StartMassMeasurement() when MsrmntState == MsrmntState.Valid + public float Mass + { + get { return mass; } + } + protected float mass; + + /// The time stamp after StartMassMeasurement() when MsrmntState == MsrmntState.Valid + public int MsrmntTimeStamp + { + get { return msrmntTimeStamp; } + } + protected int msrmntTimeStamp; + + /// + /// Constructor + /// + /// Balance properties + public BalanceDev(BalanceCfg cfg, IList components) + { + if (cfg == null) throw new ArgumentNullException("cfg"); + this.balanceCfg = cfg; + + balanceNr = nextBalanceIdx++; + Masses = new float[nextBalanceIdx]; /// (re)initialize the static array of masses of all balances + + if (Balances == null || Balances.Length < nextBalanceIdx) + { + BalanceDev[] balancesSoFar = Balances; + Balances = new BalanceDev[nextBalanceIdx]; + if (balancesSoFar != null) for (int i = 0; i < balancesSoFar.Length; i++) Balances[i] = balancesSoFar[i]; + Balances[nextBalanceIdx - 1] = this; + } + } + + public new void Initialize() + { + msrmntState = MsrmntState.Failed; /// Data not valid yet + + if (balanceCfg.DebugLevel == Entities.DebugMode.Simulate) return; + + stringBuilder = new StringBuilder(40); + string comPortName = "COM" + balanceCfg.ComPortNr.ToString(); + serialPort = new SerialPort(comPortName, balanceCfg.BaudRate, balanceCfg.Parity, balanceCfg.DataBits, balanceCfg.StopBits); + serialPort.Handshake = balanceCfg.Handshake; + serialPort.Open(); + } + + public void ZeroWhenStable() + { + if (balanceCfg.DebugLevel == Entities.DebugMode.Simulate) return; + + if (msrmntState == MsrmntState.Busy) + { + log.Warn("ZeroWhenStable() returns without starting zeroing the scale because measurementState == MeasurementState.Busy"); + return; + } + + log.Info("ZeroWhenStable()"); + + msrmntState = MsrmntState.Busy; + stringBuilder.Clear(); + serialPort.Write("Z\r\n"); + } + + public void Taring() + { + if (balanceCfg.DebugLevel == Entities.DebugMode.Simulate) return; + + if (msrmntState == MsrmntState.Busy) + { + log.Warn("Taring() returns without starting taring the scale because measurementState == MeasurementState.Busy"); + return; + } + + log.Info("Taring()"); + + msrmntState = MsrmntState.Busy; + stringBuilder.Clear(); + serialPort.Write("T\r\n"); + } + + /// + /// Get a stable mass measurement + /// + public void GetStableMassMeasurement() + { + if (balanceCfg.DebugLevel == Entities.DebugMode.Simulate) return; + + if (msrmntState == MsrmntState.Busy) + { + log.Warn("GetStableMassMeasurement() returns without starting a measurement because measurementState == MeasurementState.Busy"); + return; + } + + log.Info("GetStableMassMeasurement()"); + + msrmntState = MsrmntState.Busy; + stringBuilder.Clear(); + serialPort.Write("S\r\n"); + } + + /// + /// Get an immediate mass measurement + /// + public void GetImmediateMassMeasurement() + { + if (balanceCfg.DebugLevel == Entities.DebugMode.Simulate) return; + + if (msrmntState == MsrmntState.Busy) + { + log.Warn("GetImmediateMassMeasurement() returns without starting a measurement because measurementState == MeasurementState.Busy"); + return; + } + + log.Info("GetImmediateMassMeasurement()"); + + msrmntState = MsrmntState.Busy; + stringBuilder.Clear(); + serialPort.Write("SI\r\n"); + } + + /// Units for SetUnits() argument + public enum Units + { + g, + kg, + t, + lb, + oz + } + + /// + /// Get the serial number + /// + /// After a successful SetUnits(kg) mass is still sent in g. MH 15.10.2013 + public void SetUnits(Units unit) + { + if (balanceCfg.DebugLevel == Entities.DebugMode.Simulate) return; + + if (msrmntState == MsrmntState.Busy) + { + log.Warn("SetUnits() returns without setting the units because measurementState == MeasurementState.Busy"); + return; + } + + log.InfoFormat("SetUnits({0})", unit); + + msrmntState = MsrmntState.Busy; + stringBuilder.Clear(); + switch (unit) + { + case Units.g: serialPort.Write("U g\r\n"); break; + case Units.kg: serialPort.Write("U kg\r\n"); break; + case Units.t: serialPort.Write("U t\r\n"); break; + case Units.lb: serialPort.Write("U lb\r\n"); break; + case Units.oz: serialPort.Write("U oz\r\n"); break; + } + } + + /// + /// Parse characters received from the serial port + /// + public virtual void RunDeviceBefore() + { + if (balanceCfg.DebugLevel == Entities.DebugMode.Simulate) + { + mass = GetSimMass(balanceNr); + Masses[balanceNr] = mass; + msrmntState = MsrmntState.Valid; + msrmntTimeStamp = StateMachine.CurrentTime; + return; + } + + log.Debug("RunDevice()"); + + if (msrmntState != MsrmntState.Busy) return; /// No measurement in progress + + string justReceived = serialPort.ReadExisting(); + if (justReceived != null && justReceived.Length > 0) + { + log.Debug("RunDevice() received " + justReceived); + stringBuilder.Append(justReceived); + } + + string currentBuffer = stringBuilder.ToString(); + int eolPos = currentBuffer.IndexOf("\r\n"); + if (eolPos >= 0) + { + msrmntTimeStamp = StateMachine.CurrentTime; + + /// Get part of theh string before EOL + string received = currentBuffer.Substring(0, eolPos); + + /// Put the rest back to the string builder + stringBuilder.Clear(); + if (currentBuffer.Length > eolPos + 2) + { + stringBuilder.Append(currentBuffer.Substring(eolPos + 2)); + } + + while (true) + { + string tmp = received.Replace(" ", " "); + if (tmp.Length == received.Length) break; + received = tmp; + } + + string[] fields = received.Split(new char[] { ' ' }); + + if (fields.Length == 1 && fields[0].Equals("ZA")) /// Zero when stable + { + mass = 0; + Masses[balanceNr] = mass; + //msrmntState = MsrmntState.Valid; + log.InfoFormat("Balance response = \"{0}\"", received); + return; + } + else if (fields.Length < 2) + { + msrmntState = MsrmntState.Failed; + log.WarnFormat("Balance response = \"{0}\", Unexpected error !!!", received); + return; + } + + if (fields[0].Equals("Z")) /// Zero when stable + { + if (fields.Length == 2 && fields[1].Equals("A")) + { + mass = 0; + Masses[balanceNr] = mass; + //msrmntState = MsrmntState.Valid; + log.InfoFormat("Balance response = \"{0}\"", received); + return; + } + else + { + msrmntState = MsrmntState.Failed; + log.WarnFormat("Balance response = \"{0}\", error !!!", received); + } + } + else if (fields[0].Equals("S")) /// Stable mass: field[1] = field[2] = "kg" + { + if (fields.Length >= 3 && + float.TryParse(fields[1], + NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign, + CultureInfo.InvariantCulture, + out mass)) + { + if (fields[2].Equals("g")) mass /= 1000.0f; + if (fields[2].Equals("t")) mass *= 1000.0f; + Masses[balanceNr] = mass; + msrmntState = MsrmntState.Valid; + log.InfoFormat("Balance response = \"{0}\", Mass = {1}", received, mass); + } + else if (fields.Length == 2 && fields[1].Equals("-")) + { + mass = 0; + Masses[balanceNr] = mass; + msrmntState = MsrmntState.Valid; + log.InfoFormat("Balance response = \"{0}\", Mass = {1}", received, mass); + } + else + { + msrmntState = MsrmntState.Failed; + log.WarnFormat("Balance response = \"{0}\", Overload or and unexpected error !!!", received); + bool b = float.TryParse(fields[1], NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign, CultureInfo.InvariantCulture, out mass); + + } + } + else if (fields[0].Equals("SD")) /// Dynamic mass: field[1] = field[2] = "kg" + { + if (fields.Length >= 3 && + float.TryParse(fields[1], + NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign, + CultureInfo.InvariantCulture, + out mass)) + { + if (fields[2].Equals("g")) mass /= 1000.0f; + if (fields[2].Equals("t")) mass *= 1000.0f; + Masses[balanceNr] = mass; + msrmntState = MsrmntState.Valid; + log.InfoFormat("Balance response = \"{0}\", Mass = {1}", received, mass); + } + else if (fields.Length == 2 && fields[1].Equals("-")) + { + mass = 0; + Masses[balanceNr] = mass; + msrmntState = MsrmntState.Valid; + log.InfoFormat("Balance response = \"{0}\", Mass = {1}", received, mass); + } + else + { + msrmntState = MsrmntState.Failed; + log.WarnFormat("Balance response = \"{0}\", Overload or and unexpected error !!!", received); + bool b = float.TryParse(fields[1], NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign, CultureInfo.InvariantCulture, out mass); + + } + } + else if (fields[0].Equals("TB")) /// Taring + { + if (fields.Length >= 3 && + float.TryParse(fields[1], + NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign, + CultureInfo.InvariantCulture, + out mass)) + { + if (fields[2].Equals("g")) mass /= 1000.0f; + if (fields[2].Equals("t")) mass *= 1000.0f; + msrmntState = MsrmntState.Valid; + log.InfoFormat("Balance response = \"{0}\", Tara = {1}", received, mass); + } + else + { + msrmntState = MsrmntState.Failed; + log.WarnFormat("Balance response = \"{0}\", Overload or and unexpected error !!!", received); + } + } + else + { + msrmntState = MsrmntState.Failed; + log.WarnFormat("Balance response = \"{0}\", Unexpected error !!!", received); + } + } + } + + /// Run this device + public void RunDeviceAfter() + { + } + + /// Stop this device + public void StopDevice() + { + if (serialPort != null) serialPort.Close(); + } + + /// + /// Events: BalanceDone, Error + /// + /// Reference to a variable for 'tara' in kg + /// TaringOp instance reference casted to IOperaton + public IOperation TaringOp(ref FloatBox tara) + { + return new TaringOp(this, ref tara); + } + + /// + /// Events: BalanceDone, Error + /// + /// Reference to a variable for the measured mass in kg + /// ReadMassOp instance reference casted to IOperaton + public IOperation ReadMassOp(ref FloatBox mass) + { + return new ReadMassOp(this, ref mass); + } + + /// + /// Events: BalanceDone, Error + /// + /// Reference to a variable for the measured mass in kg + /// Required mass readings count (>= 3) + /// ReadMassAverageOp instance reference casted to IOperaton + public IOperation ReadStableMassOp(ref FloatBox mass, int readingsCount) + { + return new ReadStableMassOp(this, ref mass, readingsCount); + } + } +} diff --git a/TestBenchFramework/BenchControl/MettlerToledo/BalanceFactory.cs b/TestBenchFramework/BenchControl/MettlerToledo/BalanceFactory.cs new file mode 100644 index 000000000..4ff847339 --- /dev/null +++ b/TestBenchFramework/BenchControl/MettlerToledo/BalanceFactory.cs @@ -0,0 +1,41 @@ +using System.Collections.Generic; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.MettlerToledo +{ + public class BalanceFactory : IComponentFactory + { + public string ClassName { get { return "MettlerToledo Balance"; } } + public bool HasProcedureParams { get { return false; } } + public bool HasTestParams { get { return false; } } + public IParamsProvider GetTestParams(Entities.ComponentTest testParams) { return null; } + public IParamsProvider GetProcedureParams(Entities.ComponentProcedure procedureParams) { return null; } + + /// Max. number of components of this class in the system + public int MaxCount { get { return 5; } } + + public IComponentCfg DefaultConfig(IList components) + { + return new BalanceCfg(this, "Balance1", 3, 2400, System.IO.Ports.Parity.Even, 7, + System.IO.Ports.StopBits.One, System.IO.Ports.Handshake.XOnXOff, + 200); // kg + } + + public IComponentCfgCtrl CreateCfgCtrl() + { + return new BalanceCfgCtrl(); + } + + public IComponent ComponentFromCmpntCfg(IComponentCfg config, IList components) + { + return new BalanceDev((BalanceCfg)config, components); + } + + public IComponentCfg CmpntCfgFromCmpntEntity(Entities.Component component) + { + return MettlerToledo.BalanceCfg.CreateFromDbEntity(component, this); + } + + public void ResetStaticProperties() { BalanceDev.ResetStaticProperties(); } + } +} diff --git a/TestBenchFramework/BenchControl/MettlerToledo/BalanceNewDev.cs b/TestBenchFramework/BenchControl/MettlerToledo/BalanceNewDev.cs new file mode 100644 index 000000000..bbd8021d2 --- /dev/null +++ b/TestBenchFramework/BenchControl/MettlerToledo/BalanceNewDev.cs @@ -0,0 +1,264 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Text; +using System.IO.Ports; +using log4net; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.MettlerToledo +{ + /// + /// Mettler Toledo ICS4_5 Weighting terminal connected via serial interface (RS232) + /// + /// + /// Implemented and tested on 15.10.2013 by Milan Hanajik + /// + public class BalanceNewDev : BalanceDev, IComponent, IDevice, GenericDevices.IBalance2 + { + /// + /// Info: StartMassMeasurement() and "Balnce response = .., Mass = ..." + /// Warn: Start measurement when busy is true + /// + private static readonly ILog log = LogManager.GetLogger(typeof(BalanceNewDev)); + public override string ToString() { return string.Format("Mettler-Toledo Balance with SN"); } + + public static void ResetStaticProperties() { } + + /// Serial number after GetSerialNumber() when MsrmntState == MsrmntState.Valid + public string SerialNumber + { + get { return serialNumber; } + } + string serialNumber; + + public BalanceNewDev(BalanceCfg cfg, IList components) + : base(cfg, components) + { + } + + /// + /// Get the serial number + /// + public void GetSerialNumber() + { + if (balanceCfg.DebugLevel == Entities.DebugMode.Simulate) return; + + if (msrmntState == MsrmntState.Busy) + { + log.Warn("GetSerialNumber() returns without getting the s/n because measurementState == MeasurementState.Busy"); + return; + } + + log.Info("GetSerialNumber()"); + + msrmntState = MsrmntState.Busy; + stringBuilder.Clear(); + serialPort.Write("I4\r\n"); + } + + /// + /// Parse characters received from the serial port + /// + public override void RunDeviceBefore() + { + if (balanceCfg.DebugLevel == Entities.DebugMode.Simulate) + { + mass = GetSimMass(balanceNr); + Masses[balanceNr] = mass; + serialNumber = "1234567890"; + msrmntState = MsrmntState.Valid; + msrmntTimeStamp = StateMachine.CurrentTime; + return; + } + + log.Debug("RunDevice()"); + + if (base.msrmntState != MsrmntState.Busy) return; /// No measurement in progress + + string justReceived = serialPort.ReadExisting(); + if (justReceived != null && justReceived.Length > 0) + { + log.Debug("RunDevice() received " + justReceived); + stringBuilder.Append(justReceived); + + if (stringBuilder.ToString().EndsWith("\r\n")) + { + msrmntTimeStamp = StateMachine.CurrentTime; + + string received = stringBuilder.ToString(); + + while (true) + { + string tmp = received.Replace(" ", " "); + if (tmp.Length == received.Length) break; + received = tmp; + } + + string[] fields = received.Substring(0, received.Length - 2).Split(new char[] { ' ' }); + if (fields.Length < 2) + { + msrmntState = MsrmntState.Failed; + log.WarnFormat("Balance response = {0}, Unexpected error !!!", + received.Replace("\r", "").Replace("\n", "")); + return; + } + + if (fields[0].Equals("I4")) /// Serial number + { + if (fields.Length == 3 && fields[1].Equals("A") && fields[2].Length >= 3) + { + serialNumber = fields[2].Substring(1, fields[2].Length - 2); + msrmntState = MsrmntState.Valid; + log.InfoFormat("Balance response = {0}, s/n = {1}", + received.Replace("\r", "").Replace("\n", ""), serialNumber); + } + else + { + msrmntState = MsrmntState.Failed; + log.WarnFormat("Balance response = {0}, error !!!", + received.Replace("\r", "").Replace("\n", "")); + } + } + else if (fields[0].Equals("Z")) /// Zero when stable + { + if (fields.Length == 2 && fields[1].Equals("A")) + { + mass = 0; + Masses[balanceNr] = mass; + msrmntState = MsrmntState.Valid; + log.InfoFormat("Balance response = {0}", + received.Replace("\r", "").Replace("\n", "")); + } + else + { + msrmntState = MsrmntState.Failed; + log.WarnFormat("Balance response = \"{0}\", error !!!", + received.Replace("\r", "").Replace("\n", "")); + } + } + else if (fields[0].Equals("S")) /// Stable (field[1] == "S") or dynamic (field[1] == "D") mass measurement + { + if (fields.Length == 4 && fields[1].Equals("S") && + float.TryParse(fields[2], NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign | NumberStyles.AllowLeadingWhite, + CultureInfo.InvariantCulture, out mass)) + { + if (fields[3].Equals("g")) mass /= 1000.0f; + if (fields[3].Equals("t")) mass *= 1000.0f; + Masses[balanceNr] = mass; + msrmntState = MsrmntState.Valid; + log.InfoFormat("Balance response = {0}, Mass = {1}", + received.Replace("\r", "").Replace("\n", ""), mass); + } + else if (fields.Length == 4 && fields[1].Equals("D") && + float.TryParse(fields[2], NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign | NumberStyles.AllowLeadingWhite, + CultureInfo.InvariantCulture, out mass)) + { + if (fields[3].Equals("g")) mass /= 1000.0f; + if (fields[3].Equals("t")) mass *= 1000.0f; + Masses[balanceNr] = mass; + msrmntState = MsrmntState.Valid; + log.InfoFormat("Balance response = {0}, Mass = {1}", + received.Replace("\r", "").Replace("\n", ""), mass); + } + else if (fields.Length == 2 && fields[1].Equals("-")) + { + mass = 0; + Masses[balanceNr] = mass; + msrmntState = MsrmntState.Valid; + log.InfoFormat("Balance response = {0}, Mass = {1}", + received.Replace("\r", "").Replace("\n", ""), mass); + } + else if (fields.Length >= 2 && fields[1].Equals("I")) + { + mass = balanceCfg.Capacity; + Masses[balanceNr] = mass; + msrmntState = MsrmntState.Overload; + log.InfoFormat("Balance response = {0}, Overload", + received.Replace("\r", "").Replace("\n", ""), mass); + } + else + { + msrmntState = MsrmntState.Failed; + log.WarnFormat("Balance response = \"{0}\", Overload or and unexpected error !!!", + received.Replace("\r", "").Replace("\n", "")); + } + } + else if (fields[0].Equals("T")) /// Taring + { + if (fields.Length == 4 && fields[1].Equals("S") && + float.TryParse(fields[2], NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign | NumberStyles.AllowLeadingWhite, + CultureInfo.InvariantCulture, out mass)) + { + if (fields[3].Equals("g")) mass /= 1000.0f; + if (fields[3].Equals("t")) mass *= 1000.0f; + msrmntState = MsrmntState.Valid; + log.InfoFormat("Balance response = {0}, Mass = {1}", + received.Replace("\r", "").Replace("\n", ""), mass); + } + else if (fields.Length >= 2 && fields[1].Equals("I")) + { + mass = mass = balanceCfg.Capacity; + msrmntState = MsrmntState.Overload; + log.InfoFormat("Balance response = {0}, Overload", + received.Replace("\r", "").Replace("\n", ""), mass); + } + else + { + msrmntState = MsrmntState.Failed; + log.WarnFormat("Balance response = \"{0}\", Overload or and unexpected error !!!", + received.Replace("\r", "").Replace("\n", "")); + } + } + else if (fields[0].Equals("U")) + { + if (fields.Length == 2 && fields[1].Equals("A")) + { + msrmntState = MsrmntState.Valid; + log.InfoFormat("Balance response = \"{0}\"", + received.Replace("\r", "").Replace("\n", "")); + } + else + { + msrmntState = MsrmntState.Failed; + log.WarnFormat("Balance response = \"{0}\", Unexpected error !!!", + received.Replace("\r", "").Replace("\n", "")); + } + } + else if (fields[0].Equals("SI")) /// "SI I" received in case of overload -> empty the tank + { + if (fields.Length >= 2 && fields[1].Equals("I")) + { + mass = balanceCfg.Capacity; + Masses[balanceNr] = mass; + msrmntState = MsrmntState.Valid; + //msrmntState = MsrmntState.Overload; + log.WarnFormat("Balance response = \"{0}\", Overload.", + received.Replace("\r", "").Replace("\n", "")); + } + } + } + } + } + + /// + /// Events: BalanceDone, Error + /// + /// Reference to the serialNumber + /// GetBalanceSNOp instance reference casted to IOperaton + public IOperation GetBalanceSNOp(ref string serialNumber) + { + return new GetBalanceSNOp(this, ref serialNumber); + } + + /// + /// Events: BalanceDone, Error + /// + /// + /// SetUnitsOp instance reference casted to IOperaton + public IOperation SetUnitsOp(Units units) + { + return new SetUnitsOp(this, units); + } + } +} diff --git a/TestBenchFramework/BenchControl/MettlerToledo/BalanceNewFactory.cs b/TestBenchFramework/BenchControl/MettlerToledo/BalanceNewFactory.cs new file mode 100644 index 000000000..7ff676ce5 --- /dev/null +++ b/TestBenchFramework/BenchControl/MettlerToledo/BalanceNewFactory.cs @@ -0,0 +1,41 @@ +using System.Collections.Generic; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.MettlerToledo +{ + public class BalanceNewFactory : IComponentFactory + { + public string ClassName { get { return "MettlerToledoBalanceSN"; } } + public bool HasProcedureParams { get { return false; } } + public bool HasTestParams { get { return false; } } + public IParamsProvider GetTestParams(Entities.ComponentTest testParams) { return null; } + public IParamsProvider GetProcedureParams(Entities.ComponentProcedure procedureParams) { return null; } + + /// Max. number of components of this class in the system + public int MaxCount { get { return 5; } } + + public IComponentCfg DefaultConfig(IList components) + { + return new BalanceCfg(this, "Balance1", 3, 2400, System.IO.Ports.Parity.Even, 7, + System.IO.Ports.StopBits.One, System.IO.Ports.Handshake.XOnXOff, + 200); // kg + } + + public IComponentCfgCtrl CreateCfgCtrl() + { + return new BalanceCfgCtrl(); + } + + public IComponent ComponentFromCmpntCfg(IComponentCfg config, IList components) + { + return new BalanceNewDev((BalanceCfg)config, components); + } + + public IComponentCfg CmpntCfgFromCmpntEntity(Entities.Component component) + { + return MettlerToledo.BalanceCfg.CreateFromDbEntity(component, this); + } + + public void ResetStaticProperties() { BalanceNewDev.ResetStaticProperties(); } + } +} diff --git a/TestBenchFramework/BenchControl/MettlerToledo/GetBalanceSNOp.cs b/TestBenchFramework/BenchControl/MettlerToledo/GetBalanceSNOp.cs new file mode 100644 index 000000000..159c6795a --- /dev/null +++ b/TestBenchFramework/BenchControl/MettlerToledo/GetBalanceSNOp.cs @@ -0,0 +1,59 @@ +using System; +using log4net; + +namespace TBF.BenchControl.MettlerToledo +{ + public class GetBalanceSNOp : IOperation + { + private static readonly ILog log = LogManager.GetLogger(typeof(GetBalanceSNOp)); + public override string ToString() { return string.Format("GetBalanceSNOp(.,.)"); } + + /// Set by the constructor + BalanceNewDev balanceDev; + string serialNumber; + + /// + /// Events: BalanceDone, Error + /// + /// Balance device instance + /// Reference to the serialNumber + public GetBalanceSNOp(BalanceNewDev balanceDev, ref string serialNumber) + { + if (balanceDev == null) throw new ArgumentNullException("balanceDev"); + this.balanceDev = balanceDev; + + this.serialNumber = serialNumber; + + log.Debug(this.ToString()); + } + + /// Start this operation + public void Start() + { + log.Debug("Start()"); + balanceDev.GetSerialNumber(); + } + + /// Run this operation + /// + /// Event.None + /// Event.BalanceDone + /// + public Event Run() + { + if (balanceDev.MsrmntState == MsrmntState.Valid) + { + serialNumber = balanceDev.SerialNumber; + return Event.BalanceDone; /// S/N read successful + } + if (balanceDev.MsrmntState == MsrmntState.Failed) return Event.Error; /// S/N read failed + return Event.None; /// No result yet + } + + /// Stop this operation + public void Stop() + { + log.Debug("Stop()"); + } + } +} diff --git a/TestBenchFramework/BenchControl/MettlerToledo/ReadMassOp.cs b/TestBenchFramework/BenchControl/MettlerToledo/ReadMassOp.cs new file mode 100644 index 000000000..7bfab0e04 --- /dev/null +++ b/TestBenchFramework/BenchControl/MettlerToledo/ReadMassOp.cs @@ -0,0 +1,68 @@ +using System; +using log4net; + +namespace TBF.BenchControl.MettlerToledo +{ + public class ReadMassOp : IOperation + { + private static readonly ILog log = LogManager.GetLogger(typeof(ReadMassOp)); + public override string ToString() { return string.Format("ReadMassOp(.,.)"); } + + bool done; + + /// Set by the constructor + BalanceDev balanceDev; + FloatBox result; + + /// + /// Events: BalanceDone, Error + /// + /// Balance device instance + /// Required mass readings count (>= 3) + /// Reference to the measured mass in kg + public ReadMassOp(BalanceDev balanceDev, ref FloatBox result) + { + if (balanceDev == null) throw new ArgumentNullException("balanceDev"); + this.balanceDev = balanceDev; + + this.result = result; + + log.Debug(this.ToString()); + } + + /// Start this operation + public void Start() + { + done = false; + balanceDev.GetImmediateMassMeasurement(); + } + + /// Run this operation + /// + /// Event.None + /// Event.BalanceDone + /// Event.Error . . . . . Current.Tick == null + /// + public Event Run() + { + if (done) return Event.BalanceDone; /// Mass has already been read + + if (balanceDev.MsrmntState == MsrmntState.Busy) return Event.None; + + if (balanceDev.MsrmntState == MsrmntState.Valid) + { + result.F = balanceDev.Mass; + done = true; + return Event.BalanceDone; /// Mass read OK + } + + balanceDev.GetImmediateMassMeasurement(); /// Failed -> repeat the measurement + return Event.None; + } + + /// Stop this operation + public void Stop() + { + } + } +} diff --git a/TestBenchFramework/BenchControl/MettlerToledo/ReadMassesOp.cs b/TestBenchFramework/BenchControl/MettlerToledo/ReadMassesOp.cs new file mode 100644 index 000000000..4d83e512f --- /dev/null +++ b/TestBenchFramework/BenchControl/MettlerToledo/ReadMassesOp.cs @@ -0,0 +1,60 @@ +using System; +using log4net; + +namespace TBF.BenchControl.MettlerToledo +{ + public class ReadMassesOp : IOperation + { + private static readonly ILog log = LogManager.GetLogger(typeof(ReadMassesOp)); + public override string ToString() { return string.Format("ReadMassesOp()"); } + + bool done; + + /// + /// Events: BalanceDone, Error + /// + /// Balance device instance + /// Required mass readings count (>= 3) + /// Reference to the measured mass in kg + public ReadMassesOp() + { + log.Debug(this.ToString()); + } + + /// Start this operation + public void Start() + { + done = false; + for (int i = 0; i < BalanceDev.BalancesCount; i++) + { + BalanceDev.Balances[i].GetImmediateMassMeasurement(); + } + } + + /// Run this operation + /// + /// Event.None + /// Event.BalanceDone + /// Event.Error . . . . . Current.Tick == null + /// + public Event Run() + { + if (done) return Event.BalanceDone; /// Mass has already been read + + for (int i = 0; i < BalanceDev.BalancesCount; i++) + { + if (BalanceDev.Balances[i].MsrmntState == MsrmntState.Busy) + { + return Event.None; + } + } + done = true; + return Event.BalanceDone; + } + + /// Stop this operation + public void Stop() + { + } + } +} diff --git a/TestBenchFramework/BenchControl/MettlerToledo/ReadStableMassOp.cs b/TestBenchFramework/BenchControl/MettlerToledo/ReadStableMassOp.cs new file mode 100644 index 000000000..31bc41f96 --- /dev/null +++ b/TestBenchFramework/BenchControl/MettlerToledo/ReadStableMassOp.cs @@ -0,0 +1,88 @@ +using System; +using log4net; + +namespace TBF.BenchControl.MettlerToledo +{ + /// + /// Operation to read more mass values and average them to obtain a more accurate result. + /// + public class ReadStableMassOp : IOperation + { + private static readonly ILog log = LogManager.GetLogger(typeof(ReadStableMassOp)); + public override string ToString() { return string.Format("ReadStableMassOp(.,{0},.)", totalReadingsCount); } + + /// Operation specific + float[] massReadings; + int currentReadingsCount; + + /// Set by the constructor + BalanceDev balanceDev; + int totalReadingsCount; + FloatBox result; + + /// + /// Events: BalanceDone, Error + /// + /// Balance device instance + /// Reference to the measured mass in kg + /// Required mass readings count (>= 3) + public ReadStableMassOp(BalanceDev balanceDev, ref FloatBox result, int readingsCount) + { + if (balanceDev == null) throw new ArgumentNullException("balanceDev"); + this.balanceDev = balanceDev; + + if (readingsCount < 3) throw new ArgumentOutOfRangeException("requiredReadingsCount"); + this.totalReadingsCount = readingsCount; + + this.result = result; + + log.Debug(this.ToString()); + } + + /// Start this operation + public void Start() + { + currentReadingsCount = 0; + massReadings = new float[totalReadingsCount]; + balanceDev.GetStableMassMeasurement(); + } + + /// Run this operation + /// + /// Event.None + /// Event.BalanceDone + /// Event.Error . . . . . Current.Tick == null + /// + public Event Run() + { + if (currentReadingsCount >= totalReadingsCount) return Event.BalanceDone; /// Mass has already been calculated + + if (balanceDev.MsrmntState == MsrmntState.Busy) return Event.None; + + if (balanceDev.MsrmntState == MsrmntState.Valid) + { + massReadings[currentReadingsCount++] = balanceDev.Mass; + + if (currentReadingsCount == totalReadingsCount) + { + /// calculate the average + float calcMass = 0; + Array.Sort(massReadings); + for (int i = 1; i < totalReadingsCount - 1; i++) calcMass += massReadings[i]; + calcMass = (calcMass / (totalReadingsCount - 2)); + + result.F = calcMass; + return Event.BalanceDone; /// Mass has just been calculated + } + } + + balanceDev.GetStableMassMeasurement(); + return Event.None; + } + + /// Stop this operation + public void Stop() + { + } + } +} diff --git a/TestBenchFramework/BenchControl/MettlerToledo/SetUnitsOp.cs b/TestBenchFramework/BenchControl/MettlerToledo/SetUnitsOp.cs new file mode 100644 index 000000000..848d1b634 --- /dev/null +++ b/TestBenchFramework/BenchControl/MettlerToledo/SetUnitsOp.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using log4net; + +namespace TBF.BenchControl.MettlerToledo +{ + public class SetUnitsOp : IOperation + { + private static readonly ILog log = LogManager.GetLogger(typeof(SetUnitsOp)); + public override string ToString() { return string.Format("SetUnitsOp({0})", units); } + + /// Set by the constructor + BalanceDev balanceDev; + BalanceDev.Units units; + + /// + /// Events: BalanceDone, Error + /// + /// Balance device instance + /// Reference to the serialNumber + public SetUnitsOp(BalanceDev balanceDev, BalanceDev.Units units) + { + if (balanceDev == null) throw new ArgumentNullException("balanceDev"); + this.balanceDev = balanceDev; + + this.units = units; + + log.Debug(this.ToString()); + } + + /// Start this operation + public void Start() + { + log.Debug("Start()"); + balanceDev.SetUnits(units); + } + + /// Run this operation + /// + /// Event.None + /// Event.BalanceDone + /// + public Event Run() + { + if (balanceDev.MsrmntState == MsrmntState.Valid) return Event.BalanceDone; /// Units set + if (balanceDev.MsrmntState == MsrmntState.Failed) return Event.Error; /// Failed + return Event.None; /// No result yet + } + + /// Stop this operation + public void Stop() + { + log.Debug("Stop()"); + } + } +} diff --git a/TestBenchFramework/BenchControl/MettlerToledo/TaringOp.cs b/TestBenchFramework/BenchControl/MettlerToledo/TaringOp.cs new file mode 100644 index 000000000..de7a435e9 --- /dev/null +++ b/TestBenchFramework/BenchControl/MettlerToledo/TaringOp.cs @@ -0,0 +1,74 @@ +using System; +using log4net; + +namespace TBF.BenchControl.MettlerToledo +{ + public class TaringOp : IOperation + { + private static readonly ILog log = LogManager.GetLogger(typeof(TaringOp)); + public override string ToString() { return string.Format("TaringOp(.,.)"); } + + bool done; + + /// Set by the constructor + BalanceDev balanceDev; + FloatBox tara; + + /// + /// Events: BalanceDone, Error + /// + /// Balance device instance + /// Reference to variable for 'tara' in kg + public TaringOp(BalanceDev balanceDev, ref FloatBox tara) + { + if (balanceDev == null) throw new ArgumentNullException("balanceDev"); + this.balanceDev = balanceDev; + + this.tara = tara; + + log.Debug(this.ToString()); + } + + /// Start this operation + public void Start() + { + done = false; + balanceDev.Taring(); + } + + /// Run this operation + /// + /// Event.None + /// Event.BalanceDone + /// Event.Error . . . . . Current.Tick == null + /// + public Event Run() + { + if (done) return Event.BalanceDone; /// Taring has been done already + + if (balanceDev.MsrmntState == MsrmntState.Busy) return Event.None; + + if (balanceDev.MsrmntState == MsrmntState.Overload) + { + tara.F = balanceDev.Capacity; + done = true; + return Event.BalanceOverload; + } + + if (balanceDev.MsrmntState == MsrmntState.Valid) + { + tara.F = balanceDev.Mass; + done = true; + return Event.BalanceDone; /// Taring completed + } + + balanceDev.Taring(); /// Failed -> repeat taring + return Event.None; + } + + /// Stop this operation + public void Stop() + { + } + } +} diff --git a/TestBenchFramework/BenchControl/Operations/AskYesNoForm.Designer.cs b/TestBenchFramework/BenchControl/Operations/AskYesNoForm.Designer.cs new file mode 100644 index 000000000..4517e6cd7 --- /dev/null +++ b/TestBenchFramework/BenchControl/Operations/AskYesNoForm.Designer.cs @@ -0,0 +1,94 @@ +namespace TBF.BenchControl.Operations +{ + partial class AskYesNoForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.yesButton = new System.Windows.Forms.Button(); + this.noButton = new System.Windows.Forms.Button(); + this.questionLabel = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // yesButton + // + this.yesButton.Font = new System.Drawing.Font("Verdana", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238))); + this.yesButton.ForeColor = System.Drawing.Color.Black; + this.yesButton.Location = new System.Drawing.Point(200, 96); + this.yesButton.Name = "yesButton"; + this.yesButton.Size = new System.Drawing.Size(98, 63); + this.yesButton.TabIndex = 1; + this.yesButton.Text = "Yes"; + this.yesButton.UseVisualStyleBackColor = true; + this.yesButton.Click += new System.EventHandler(this.yesButton_Click); + // + // noButton + // + this.noButton.Font = new System.Drawing.Font("Verdana", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238))); + this.noButton.ForeColor = System.Drawing.Color.Black; + this.noButton.Location = new System.Drawing.Point(65, 96); + this.noButton.Name = "noButton"; + this.noButton.Size = new System.Drawing.Size(98, 63); + this.noButton.TabIndex = 2; + this.noButton.Text = "No"; + this.noButton.UseVisualStyleBackColor = true; + this.noButton.Click += new System.EventHandler(this.noButton_Click); + // + // questionLabel + // + this.questionLabel.AutoSize = true; + this.questionLabel.Font = new System.Drawing.Font("Verdana", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238))); + this.questionLabel.Location = new System.Drawing.Point(34, 38); + this.questionLabel.Name = "questionLabel"; + this.questionLabel.Size = new System.Drawing.Size(300, 23); + this.questionLabel.TabIndex = 4; + this.questionLabel.Text = "Fill the test bench with water?"; + // + // AskYesNoForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.BackColor = System.Drawing.Color.Goldenrod; + this.ClientSize = new System.Drawing.Size(363, 201); + this.Controls.Add(this.questionLabel); + this.Controls.Add(this.noButton); + this.Controls.Add(this.yesButton); + this.Name = "AskYesNoForm"; + this.Text = "Question"; + this.TopMost = true; + this.Load += new System.EventHandler(this.AskYesNoForm_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Button yesButton; + private System.Windows.Forms.Button noButton; + private System.Windows.Forms.Label questionLabel; + } +} \ No newline at end of file diff --git a/TestBenchFramework/BenchControl/Operations/AskYesNoForm.cs b/TestBenchFramework/BenchControl/Operations/AskYesNoForm.cs new file mode 100644 index 000000000..974fe95c0 --- /dev/null +++ b/TestBenchFramework/BenchControl/Operations/AskYesNoForm.cs @@ -0,0 +1,38 @@ +using System; +using System.Windows.Forms; +using TBF.Resources; + +namespace TBF.BenchControl.Operations +{ + public partial class AskYesNoForm : Form + { + public string Question; + public bool CompletedYes; + public bool CompletedNo; + + public AskYesNoForm() + { + InitializeComponent(); + } + + private void AskYesNoForm_Load(object sender, EventArgs e) + { + Text = Strings.Question; + questionLabel.Text = Strings.Fill_with_water; + yesButton.Text = Strings.YesBtn; + noButton.Text = Strings.NoBtn; + } + + private void yesButton_Click(object sender, EventArgs e) + { + CompletedYes = true; + Close(); + } + + private void noButton_Click(object sender, EventArgs e) + { + CompletedNo = true; + Close(); + } + } +} diff --git a/TestBenchFramework/BenchControl/Operations/AskYesNoForm.resx b/TestBenchFramework/BenchControl/Operations/AskYesNoForm.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/TestBenchFramework/BenchControl/Operations/AskYesNoForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/BenchControl/Operations/AskYesNoOp.cs b/TestBenchFramework/BenchControl/Operations/AskYesNoOp.cs new file mode 100644 index 000000000..740f230e8 --- /dev/null +++ b/TestBenchFramework/BenchControl/Operations/AskYesNoOp.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using TBF.BenchControl; + +namespace TBF.BenchControl.Operations +{ + public class AskYesNoOp : IOperation + { + AskYesNoForm modelessDlg; + + string question; + + /// Reference to the operation + public AskYesNoOp() + { + } + + public AskYesNoOp(string question) + { + this.question = question; + } + + delegate void AskYesNoFormDlgt(AskYesNoOp myRef); + /// + void OpenFormDlg(AskYesNoOp myRef) + { + myRef.modelessDlg = new AskYesNoForm(); + myRef.modelessDlg.Question = this.question; + modelessDlg.Show(); + } + + /// Start this operation + public void Start() + { + Program.MainWnd.Invoke(new AskYesNoFormDlgt(OpenFormDlg), this); + } + + /// Run this operation + /// Event.ResultsPrinted + public Event Run() + { + if (modelessDlg.CompletedYes) return Event.Yes; + if (modelessDlg.CompletedNo) return Event.No; + return Event.None; + } + + /// Stop this operation + public void Stop() + { + modelessDlg = null; + } + } +} diff --git a/TestBenchFramework/BenchControl/Operations/CheckUIOp.cs b/TestBenchFramework/BenchControl/Operations/CheckUIOp.cs new file mode 100644 index 000000000..2ec7528d5 --- /dev/null +++ b/TestBenchFramework/BenchControl/Operations/CheckUIOp.cs @@ -0,0 +1,109 @@ +using log4net; +using TBF.UiBridge; + +namespace TBF.BenchControl.Operations +{ + /// + /// Implements User Interface input for the state machine. + /// UI inserts commands int a queue (FIFO buffer). + /// UiBridgeOp class reads the queue and generates events that + /// in turn control state transitions in the state machine. + /// + public class CheckUIOp : IOperation + { + private static readonly ILog log = LogManager.GetLogger(typeof(CheckUIOp)); + public override string ToString() { return "CheckUIOp(" + clearInputQueue.ToString() + ")"; } + + /// Set by constructors + bool clearInputQueue; + + /// + /// Check input from UI for the state machine. + /// Events: Start,Stop,Cycle,Purge,LetOutLine,LetOutBalance,TestOpticalHeads,ResetResults,Calibration,SensitivityTest + /// + /// true = clear queue on start + public CheckUIOp(bool clearInputQueue) + { + this.clearInputQueue = clearInputQueue; + } + public CheckUIOp() + : this(false) + { + } + + void UiEventHandlerMethod(UI2BenchCmd cmd) + { + lock (Bridge.Ui2MachineQueue) + { + Bridge.Ui2MachineQueue.Enqueue(cmd); + } + } + + public void Start() + { + if (clearInputQueue) + { + lock (Bridge.Ui2MachineQueue) + { + Bridge.Ui2MachineQueue.Clear(); + } + } + } + + public Event Run() + { + if (Bridge.Ui2MachineQueue.Count <= 0) return Event.None; + + UI2BenchCmd cmd; + + lock (Bridge.Ui2MachineQueue) + { + if (Bridge.Ui2MachineQueue.Contains(UI2BenchCmd.Stop)) + { + do { + cmd = Bridge.Ui2MachineQueue.Dequeue(); + } + while (cmd != UI2BenchCmd.Stop); + } + else + { + cmd = Bridge.Ui2MachineQueue.Dequeue(); + } + } + + switch (cmd) + { + /// Bench Control Panel buttons + case UI2BenchCmd.StartTest: return Event.UiCmdStartTest; + case UI2BenchCmd.StartQ1: return Event.UiCmdStartQ1; + case UI2BenchCmd.StartQ2: return Event.UiCmdStartQ2; + case UI2BenchCmd.StartQ3: return Event.UiCmdStartQ3; + case UI2BenchCmd.StartCycle: return Event.UiCmdStartCycle; + case UI2BenchCmd.Stop: return Event.UiCmdStop; + case UI2BenchCmd.PurgeBegin: return Event.UiCmdPurgeBegin; + case UI2BenchCmd.PurgeEnd: return Event.UiCmdPurgeEnd; + case UI2BenchCmd.EmptyTank1: return Event.UiCmdEmptyTank1; + case UI2BenchCmd.EmptyTank2: return Event.UiCmdEmptyTank2; + case UI2BenchCmd.TryOpticalHeads: return Event.UiCmdTestOpticalHeads; + case UI2BenchCmd.ResetResults: return Event.UiCmdResetResults; + case UI2BenchCmd.AcceptResults: return Event.UiCmdAcceptResults; + case UI2BenchCmd.Calibration: return Event.UiCmdCalibration; + case UI2BenchCmd.CameraTest: return Event.UiCmdCameraTest; + case UI2BenchCmd.SensitivityTest: return Event.UiCmdSensitivityTest; + + case UI2BenchCmd.Next: return Event.Next; + + /// Test buttons + case UI2BenchCmd.B1: return Event.UiCmdB1; + case UI2BenchCmd.B2: return Event.UiCmdB2; + case UI2BenchCmd.B3: return Event.UiCmdB3; + + default: return Event.None; + } + } + + public void Stop() + { + } + } +} diff --git a/TestBenchFramework/BenchControl/Operations/ClearResultsOp.cs b/TestBenchFramework/BenchControl/Operations/ClearResultsOp.cs new file mode 100644 index 000000000..b3a1c9c18 --- /dev/null +++ b/TestBenchFramework/BenchControl/Operations/ClearResultsOp.cs @@ -0,0 +1,25 @@ +using log4net; + +namespace TBF.BenchControl.Operations +{ + class ClearResultsOp : IOperation + { + private static readonly ILog log = LogManager.GetLogger(typeof(ClearResultsOp)); + public override string ToString() { return "ClearResultsOp"; } + + public void Start() + { + //Results.Clear(); + } + + public Event Run() + { + log.Info("Event.Done"); + return Event.Done; + } + + public void Stop() + { + } + } +} diff --git a/TestBenchFramework/BenchControl/Operations/EmptyBalanceTankOp.cs b/TestBenchFramework/BenchControl/Operations/EmptyBalanceTankOp.cs new file mode 100644 index 000000000..06fa5c3c4 --- /dev/null +++ b/TestBenchFramework/BenchControl/Operations/EmptyBalanceTankOp.cs @@ -0,0 +1,51 @@ +using log4net; + +namespace TBF.BenchControl.Operations +{ + /// + /// An empty operation. + /// + /// Constructors: + /// EmptyBalanceTank() + /// Start argument: + /// - + /// Events: + /// Event.None ... operation is in progress + /// + class EmptyBalanceTankOp : IOperation + { + private static readonly ILog log = LogManager.GetLogger(typeof(EmptyBalanceTankOp)); + public override string ToString() { return "EmptyBalanceTankOp"; } + + /// + /// Constructor + /// + public EmptyBalanceTankOp() + { + } + + /// + /// When started + /// + public void Start() + { + } + + /// + /// When running + /// + /// + public Event Run() + { + /// Must return some event + return Event.None; + } + + /// + /// When stopped + /// + public void Stop() + { + } + } +} diff --git a/TestBenchFramework/BenchControl/Operations/LoadProcedureOp.cs b/TestBenchFramework/BenchControl/Operations/LoadProcedureOp.cs new file mode 100644 index 000000000..d07274ad8 --- /dev/null +++ b/TestBenchFramework/BenchControl/Operations/LoadProcedureOp.cs @@ -0,0 +1,75 @@ +using System.Threading; +using log4net; +using NHibernate; + +namespace TBF.BenchControl.Operations +{ + public class LoadProcedureOp : IOperation + { + private static readonly ILog log = LogManager.GetLogger(typeof(LoadProcedureOp)); + + Thread loaderThread; + bool error; + bool completed; + + /// + /// Events: Wait, ProcedureLoaded or Error + /// + public LoadProcedureOp() + { + error = false; + completed = false; + } + + /// Start this operation + public void Start() + { + if (loaderThread != null) + { + error = true; + return; + } + + loaderThread = new Thread(Loader); + loaderThread.Start(); + } + + void Loader() + { + StateMachine.LoadProcedure(false); + StateMachine.LoadProcedureParams(StateMachine.Procedure); + + completed = true; + } + + /// Run this operation + /// + /// Event.Error, Event.ProcedureLoaded or Event.Wait + /// + public Event Run() + { + if (error) return Event.Error; + if (!completed) return Event.Wait; + + /// + /// Check for incomplete configuration mistakes + /// + if (StateMachine.Tests.Count == 0) return Event.ConfigurationError; + foreach (var test in StateMachine.Tests) + { + if (test.FeedingPath == null || test.BenchPath == null || + test.OutputPath == null || test.MetersPath == null) + { + return Event.ConfigurationError; + } + } + + return Event.ProcedureLoaded; + } + + /// Stop this operation + public void Stop() + { + } + } +} diff --git a/TestBenchFramework/BenchControl/Operations/OpTemplate.cs b/TestBenchFramework/BenchControl/Operations/OpTemplate.cs new file mode 100644 index 000000000..f759cdd12 --- /dev/null +++ b/TestBenchFramework/BenchControl/Operations/OpTemplate.cs @@ -0,0 +1,61 @@ +using log4net; +using System; +using System.Diagnostics; +using System.Collections.Generic; +using TBF.BenchControl; + +namespace TBF.BenchControl.Operations +{ + /// + /// An empty operation. + /// + /// Constructors: + /// OpTemplate() + /// + /// Start argument: + /// + /// Events: + /// Event.None ...... operation is in progress + /// + class OpTemplate : IOperation + { + private static readonly ILog log = LogManager.GetLogger(typeof(OpTemplate)); + public override string ToString() { return string.Format("OpTemplate({0})", someValue); } + + /// Set by the constructor + int someValue; + + /// + /// Constructor + /// + public OpTemplate(int someValue) + { + if (someValue < 0 || someValue > 5) throw new ArgumentOutOfRangeException("someValue"); + this.someValue = someValue; + } + + /// + /// When started + /// + public void Start() + { + } + + /// + /// When running + /// + /// + public Event Run() + { + /// Must return some event + return Event.None; + } + + /// + /// When stopped + /// + public void Stop() + { + } + } +} diff --git a/TestBenchFramework/BenchControl/Operations/ReadMoreRegistersOp.cs b/TestBenchFramework/BenchControl/Operations/ReadMoreRegistersOp.cs new file mode 100644 index 000000000..b5a47773e --- /dev/null +++ b/TestBenchFramework/BenchControl/Operations/ReadMoreRegistersOp.cs @@ -0,0 +1,134 @@ +using System; +using log4net; +using TBF.BenchControl; + +namespace TBF.BenchControl.Operations +{ + public class ReadMoreRegistersOp : IOperation + { + private static readonly ILog log = LogManager.GetLogger(typeof(ReadMoreRegistersOp)); + public override string ToString() { return string.Format("ReadAllRegistersOp()"); } + + /// Set by the constructor + int readersCount; + int[] iPulses; + int[] iRefPulses; + IntBox[] pulses; + IntBox[] refPulses; + IOperation[] readRegOps; + Event[] events; + + /// + /// Events: eventDone (default=Event.ReadRegisterDone) or Event.Error + /// + /// Register reader reference + /// Reference to the water meter register state in pulses + public ReadMoreRegistersOp(GenericDevices.IRegisterReader[] readers, ref int[] iPulses) + { + if (readers == null) throw new ArgumentNullException("readers"); + + readersCount = readers.Length; + + if (iPulses == null || iPulses.Length != readersCount) + { + throw new ArgumentException("iPulses"); + } + this.iPulses = iPulses; + + pulses = new IntBox[Program.WMsCount]; + + readRegOps = new IOperation[readersCount]; + for (int i = 0; i < readersCount; i++) + { + pulses[i] = new IntBox(iPulses[i]); + + if (readers[i] != null) + { + readRegOps[i] = readers[i].ReadRegisterOp(ref pulses[i]); + } + } + log.Debug(this.ToString()); + } + + /// + /// Events: eventDone (default=Event.ReadRegisterDone) or Event.Error + /// + /// Register reader reference + /// Reference to the water meter register state in pulses + public ReadMoreRegistersOp(GenericDevices.IRegisterReader[] readers, ref int[] iPulses, ref int[] iRefPulses) + : this(readers, ref iPulses) + { + if (readers == null) throw new ArgumentNullException("readers"); + + readersCount = readers.Length; + + if (iPulses == null || iPulses.Length != readersCount || + iRefPulses == null || iRefPulses.Length != readersCount) + { + throw new ArgumentException("iPulses or iRefPulses"); + } + this.iPulses = iPulses; + this.iRefPulses = iRefPulses; + + pulses = new IntBox[Program.WMsCount]; + refPulses = new IntBox[Program.WMsCount]; + + readRegOps = new IOperation[readersCount]; + for (int i = 0; i < readersCount; i++) + { + pulses[i] = new IntBox(iPulses[i]); + refPulses[i] = new IntBox(iRefPulses[i]); + + if (readers[i] != null) + { + readRegOps[i] = readers[i].ReadRegisterOp(ref pulses[i], ref refPulses[i]); + } + } + log.Debug(this.ToString()); + } + + /// Start this operation + public void Start() + { + for (int i = 0; i < readersCount; i++) + { + if (readRegOps[i] != null) readRegOps[i].Start(); + } + } + + /// Run this operation + public Event Run() + { + bool allDone = true; + bool anyError = false; + + for (int i = 0; i < readersCount; i++) + { + if (readRegOps[i] != null) + { + Event evnt = readRegOps[i].Run(); + iPulses[i] = pulses[i].N; + if (iRefPulses != null) + { + iRefPulses[i] = refPulses[i].N; + } + if (evnt == Event.Error) anyError = true; + if (evnt != Event.ReadRegisterDone) allDone = false; + } + } + + if (anyError) return Event.Error; + if (allDone) return Event.ReadAllRegistersDone; + return Event.None; + } + + /// Stop this operation + public void Stop() + { + for (int i = 0; i < readersCount; i++) + { + if (readRegOps[i] != null) readRegOps[i].Stop(); + } + } + } +} diff --git a/TestBenchFramework/BenchControl/Operations/SetAllRegulValvesOp.cs b/TestBenchFramework/BenchControl/Operations/SetAllRegulValvesOp.cs new file mode 100644 index 000000000..013ca6491 --- /dev/null +++ b/TestBenchFramework/BenchControl/Operations/SetAllRegulValvesOp.cs @@ -0,0 +1,76 @@ +using System; +using System.Collections.Generic; +using log4net; +using TBF.BenchControl.GenericDevices; + +namespace TBF.BenchControl.Operations +{ + public class SetAllRegulValvesOp : IOperation + { + private static readonly ILog log = LogManager.GetLogger(typeof(SetAllRegulValvesOp)); + public override string ToString() { return string.Format("SetAllRegulValvesOp()"); } + + IList regulValves; + int rvCount; + IOperation[] setRVPosOps; + + public SetAllRegulValvesOp(IList regulValves, string encodedPositions, int timeout) + { + if (regulValves == null) throw new ArgumentNullException("regulValves"); + this.regulValves = regulValves; + rvCount = regulValves.Count; + + // Parse the positions + float[] positions = new float[rvCount]; + string[] rvPosStr = (encodedPositions != null) ? encodedPositions.Split(new char[] { ';' }) : new string[0]; + for (int i = 0; i < Math.Min(rvCount, rvPosStr.Length); i++) + { + float posPct; + if (float.TryParse(rvPosStr[i], out posPct) && posPct >= 0 && posPct <= 100.0f) + { + positions[i] = posPct; + } + } + setRVPosOps = new IOperation[rvCount]; + for (int i = 0; i < rvCount; i++) + { + float posLo = Math.Max(positions[i] - 5.0f, 0); + float posHi = Math.Min(positions[i] + 5.0f, 100.0f); + setRVPosOps[i] = regulValves[i].SetRegulValvePositionOp(posLo, posHi, timeout); + } + } + + /// Start this operation + public void Start() + { + for (int i = 0; i < rvCount; i++) setRVPosOps[i].Start(); + } + + /// Run this operation + public Event Run() + { + bool allDone = true; + bool anyError = false; + bool anyTimeout = false; + + for (int i = 0; i < rvCount; i++) + { + Event evnt = setRVPosOps[i].Run(); + if (evnt == Event.Error) anyError = true; + else if (evnt == Event.RegulValveTimeOut) anyTimeout = true; + else if (evnt != Event.PositionReached) allDone = false; + } + + if (anyError) return Event.Error; + if (anyTimeout) return Event.Error; + if (allDone) return Event.AllPositionsReached; + return Event.None; + } + + /// Stop this operation + public void Stop() + { + for (int i = 0; i < rvCount; i++) setRVPosOps[i].Stop(); + } + } +} diff --git a/TestBenchFramework/BenchControl/Operations/TimerOp.cs b/TestBenchFramework/BenchControl/Operations/TimerOp.cs new file mode 100644 index 000000000..b93ce96f1 --- /dev/null +++ b/TestBenchFramework/BenchControl/Operations/TimerOp.cs @@ -0,0 +1,72 @@ +using log4net; + +namespace TBF.BenchControl.Operations +{ + /// + /// Implements timer function + /// + /// Constructors: + /// Timer(timerTimeMs) ................ use Event.TimerExpired as eventExpired + /// Timer(timerTimeMs, eventExpired) .. use constructor argument as eventExpired + /// + /// Start argument: + /// + /// Events: + /// Event.None ........ operation is in progress + /// eventExpired ...... timer expired + /// + public class TimerOp : IOperation + { + private static readonly ILog log = LogManager.GetLogger(typeof(TimerOp)); + public override string ToString() { return string.Format("TimerOp({0}s, Event.{1})", timerTime, eventExpired); } + + /// Private fields + bool timerStarted = false; + bool timeExpired = false; + int expireTime; + + /// Set by constructors + int timerTime; + Event eventExpired; + + /// + /// Constructors, optional argument is a timer name (you can create more then one timer) + /// + public TimerOp(int timerTime, Event eventExpired) + { + this.timerTime = timerTime; + this.eventExpired = eventExpired; + } + public TimerOp(int timerTime) + : this(timerTime, Event.TimerExpired) + { + } + + /// Time period (TimeSpan) + public void Start() + { + timeExpired = false; + timerStarted = true; + expireTime = StateMachine.CurrentTime + timerTime; + } + + public Event Run() + { + if (timerStarted && !timeExpired && StateMachine.CurrentTime >= expireTime) + { + timeExpired = true; + return eventExpired; + } + else + { + return Event.None; + } + } + + public void Stop() + { + timerStarted = false; + timeExpired = false; + } + } +} diff --git a/TestBenchFramework/BenchControl/OutputPath.cs b/TestBenchFramework/BenchControl/OutputPath.cs new file mode 100644 index 000000000..88291a666 --- /dev/null +++ b/TestBenchFramework/BenchControl/OutputPath.cs @@ -0,0 +1,52 @@ +using System.Collections.Generic; +using TBF.BenchControl.GenericDevices; + +namespace TBF.BenchControl +{ + public class OutputPath + { + public int ItemNr; + public string Name; + public float Qfrom; + public float Qto; + public IRegulValve RegulValve; + public IFlowMeter FlowMeter; + public IDiverter Diverter; + public ITempMeter TempDiv; + public IBalance Balance; + public IValve EmptyTankValve; + public IList ValvesOpen; + public IList ValvesClose; + + /// Constructor from name, the rest is empty + public OutputPath(string name, int itemNr) + { + ItemNr = itemNr; + Name = name; + ValvesOpen = new List(); + ValvesClose = new List(); + } + + /// Constructor from data entity + public OutputPath(Entities.OutputPath entity, IList components) + : this(entity.Name, entity.ItemNr) + { + Qfrom = entity.Qfrom; + Qto = entity.Qto; + RegulValve = (IRegulValve)TbfComponents.FindComponent(entity.RegulValve, components); + FlowMeter = (IFlowMeter)TbfComponents.FindComponent(entity.FlowMeter, components); + Diverter = (IDiverter)TbfComponents.FindComponent(entity.Diverter, components); + TempDiv = (ITempMeter)TbfComponents.FindComponent(entity.TempDiv, components); + Balance = (IBalance)TbfComponents.FindComponent(entity.Balance, components); + EmptyTankValve = (IValve)TbfComponents.FindComponent(entity.EmptyTankValve, components); + + string[] vOpen = entity.ValvesOpen.Split(new char[] { ';' }); + ValvesOpen = new List(); + foreach (var vName in vOpen) ValvesOpen.Add((IValve)TbfComponents.FindComponent(vName, components)); + + string[] vClose = entity.ValvesClose.Split(new char[] { ';' }); + ValvesClose = new List(); + foreach (var vName in vClose) ValvesClose.Add((IValve)TbfComponents.FindComponent(vName, components)); + } + } +} diff --git a/TestBenchFramework/BenchControl/ResultsPrinters/Basic/BasicPrintDocument.cs b/TestBenchFramework/BenchControl/ResultsPrinters/Basic/BasicPrintDocument.cs new file mode 100644 index 000000000..b4d4d2233 --- /dev/null +++ b/TestBenchFramework/BenchControl/ResultsPrinters/Basic/BasicPrintDocument.cs @@ -0,0 +1,111 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Printing; + +namespace TBF.BenchControl.ResultsPrinters.Basic +{ + public class BasicPrintDocument : PrintDocument + { + /// + /// Property variable for the Font the user wishes to use + /// + public Font Font + { + get { return font; } + set { font = value; } + } + Font font; + + /// + /// Data to print + /// + BenchControl.BenchId.Component benchId; + IList waterMeters; + IList results; + string title; + + /// + /// Constructor + /// + /// Text to be printed + public BasicPrintDocument(BenchControl.BenchId.Component benchId, + IList waterMeters, + IList results, + string title) + { + this.benchId = benchId; + this.waterMeters = waterMeters; + this.results = results; + this.title = title; + } + + /// + /// Override the default onbeginPrint method of the PrintDocument Object + /// + /// + /// + protected override void OnBeginPrint(System.Drawing.Printing.PrintEventArgs e) + { + base.OnBeginPrint(e); + if (font == null) { font = new Font("Times New Roman", 10); } + } + + /// + /// Override the default OnPrintPage method of the PrintDocument. + /// + /// + /// This provides the print logic for our document + protected override void OnPrintPage(System.Drawing.Printing.PrintPageEventArgs e) + { + // Run base code + base.OnPrintPage(e); + + /// Set print area size and margins (in dots using 80 dpi) + int printHeight = base.DefaultPageSettings.PaperSize.Height - base.DefaultPageSettings.Margins.Top - base.DefaultPageSettings.Margins.Bottom; + int printWidth = base.DefaultPageSettings.PaperSize.Width - base.DefaultPageSettings.Margins.Left - base.DefaultPageSettings.Margins.Right; + int leftMargin = base.DefaultPageSettings.Margins.Left; /// X + int topMargin = base.DefaultPageSettings.Margins.Top; /// Y + + /// Check if the user selected to print in Landscape mode + /// if they did then we need to swap height/width parameters + if (base.DefaultPageSettings.Landscape) + { + int tmp = printHeight; + printHeight = printWidth; + printWidth = tmp; + } + + int x = leftMargin; + int y = topMargin; + + /// Use the StringFormat class for the text layout of our document + StringFormat format = new StringFormat(StringFormatFlags.LineLimit); + + foreach (var testResults in results) + { + RectangleF printArea = new RectangleF(x, y, printWidth, printHeight); + e.Graphics.DrawString("Test: " + testResults.TestName, font, Brushes.Black, printArea); + y += 30; + + printArea = new RectangleF(x + 100, y, printWidth, printHeight); + e.Graphics.DrawString("Watermeter1: Error = " + testResults.Meters[0].VolumeErrorPct.ToString() + + "% Result = " + testResults.Meters[0].Passed.ToString(), + font, Brushes.Black, printArea); + y += 30; + + printArea = new RectangleF(x + 100, y, printWidth, printHeight); + e.Graphics.DrawString("Watermeter2: " + testResults.Meters[1].Passed.ToString(), + font, Brushes.Black, printArea); + y += 30; + + printArea = new RectangleF(x + 100, y, printWidth, printHeight); + e.Graphics.DrawString("Watermeter3: " + testResults.Meters[2].Passed.ToString(), + font, Brushes.Black, printArea); + y += 50; + } + + e.HasMorePages = false; + } + } +} diff --git a/TestBenchFramework/BenchControl/ResultsPrinters/Basic/Printer.cs b/TestBenchFramework/BenchControl/ResultsPrinters/Basic/Printer.cs new file mode 100644 index 000000000..e282b5565 --- /dev/null +++ b/TestBenchFramework/BenchControl/ResultsPrinters/Basic/Printer.cs @@ -0,0 +1,67 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Printing; +using TBF.BenchControl; + +namespace TBF.BenchControl.ResultsPrinters.Basic +{ + public class Printer : Generic.IComponent, IOperation, GenericDevices.IResultsPrinter + { + readonly PrinterCfg printerCfg; + public Generic.IComponentCfg Cfg { get { return printerCfg; } } + + public static void ResetStaticProperties() { } + + public string Name { get { return printerCfg.Name; } } + + /// + /// Data to print + /// + BenchControl.BenchId.Component benchId; + IList waterMeters; + IList results; + string title; + + public Printer(PrinterCfg cfg) + { + if (cfg == null) throw new ArgumentNullException("cfg"); + this.printerCfg = cfg; + } + + /// + /// Prints the test cycle results, Events: Event.ResultsPrinted + /// + /// Results to print + /// Reference to the operation + public IOperation PrintResultsOp(BenchControl.BenchId.Component benchId, + IList waterMeters, + IList results, + string title) + { + this.benchId = benchId; + this.waterMeters = waterMeters; + this.results = results; + this.title = title; + return this; + } + + /// Start this operation + public void Start() + { + new BasicPrintDocument(benchId, waterMeters, results, title).Print(); + } + + /// Run this operation + /// Event.ResultsPrinted + public Event Run() + { + return Event.ResultsPrinted; + } + + /// Stop this operation + public void Stop() + { + } + } +} diff --git a/TestBenchFramework/BenchControl/ResultsPrinters/Basic/PrinterCfg.cs b/TestBenchFramework/BenchControl/ResultsPrinters/Basic/PrinterCfg.cs new file mode 100644 index 000000000..892e15a28 --- /dev/null +++ b/TestBenchFramework/BenchControl/ResultsPrinters/Basic/PrinterCfg.cs @@ -0,0 +1,54 @@ +using System; +using System.IO; +using System.Xml.Serialization; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.ResultsPrinters.Basic +{ + public class PrinterCfg : ComponentCfgBase, Generic.IComponentCfg + { + /// Parameterless constructor + public PrinterCfg() + { + } + + /// + /// Basic results printer configuration parameters + /// + /// BasicPrinter factory + /// Printer name + public PrinterCfg(IComponentFactory factory, string name) + : base(factory, name) + { + } + + public IComponentCfg Clone() + { + return new PrinterCfg(Factory, Name); + } + + public string ToString(int i) + { + return string.Empty; + } + + public TBF.Entities.Component CreateDbEntity() + { + using (var writer = new StringWriter()) + { + (new XmlSerializer(GetType())).Serialize(writer, this); + return Entities.Component.CreateFromCfg(Name, Factory.ClassName, ParentName, ItemNr, DebugLevel, LogLevel, writer.ToString()); + } + } + + public static IComponentCfg CreateFromDbEntity(Entities.Component component, IComponentFactory factory) + { + using (var reader = new StringReader(component.Parameters)) + { + PrinterCfg config = (PrinterCfg)(new XmlSerializer(typeof(PrinterCfg))).Deserialize(reader); + config.InitCfgBaseFromEntity(component, factory); + return config; + } + } + } +} diff --git a/TestBenchFramework/BenchControl/ResultsPrinters/Basic/PrinterCfgCtrl.Designer.cs b/TestBenchFramework/BenchControl/ResultsPrinters/Basic/PrinterCfgCtrl.Designer.cs new file mode 100644 index 000000000..4db2db42a --- /dev/null +++ b/TestBenchFramework/BenchControl/ResultsPrinters/Basic/PrinterCfgCtrl.Designer.cs @@ -0,0 +1,83 @@ +namespace TBF.BenchControl.ResultsPrinters.Basic +{ + partial class PrinterCfgCtrl + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.nameTextBox = new System.Windows.Forms.TextBox(); + this.nameLabel = new System.Windows.Forms.Label(); + this.classNameLabel = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // nameTextBox + // + this.nameTextBox.Enabled = false; + this.nameTextBox.Location = new System.Drawing.Point(137, 57); + this.nameTextBox.Name = "nameTextBox"; + this.nameTextBox.Size = new System.Drawing.Size(130, 20); + this.nameTextBox.TabIndex = 5; + // + // nameLabel + // + this.nameLabel.AutoSize = true; + this.nameLabel.Location = new System.Drawing.Point(27, 60); + this.nameLabel.Name = "nameLabel"; + this.nameLabel.Size = new System.Drawing.Size(35, 13); + this.nameLabel.TabIndex = 4; + this.nameLabel.Text = "Name"; + // + // classNameLabel + // + this.classNameLabel.AutoSize = true; + this.classNameLabel.Location = new System.Drawing.Point(134, 33); + this.classNameLabel.Name = "classNameLabel"; + this.classNameLabel.Size = new System.Drawing.Size(83, 13); + this.classNameLabel.TabIndex = 3; + this.classNameLabel.Text = "ComonentName"; + // + // BasicPrinterCfgCtrl + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.nameTextBox); + this.Controls.Add(this.nameLabel); + this.Controls.Add(this.classNameLabel); + this.Name = "BasicPrinterCfgCtrl"; + this.Size = new System.Drawing.Size(300, 200); + this.Load += new System.EventHandler(this.PrinterCfgCtrl_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TextBox nameTextBox; + private System.Windows.Forms.Label nameLabel; + private System.Windows.Forms.Label classNameLabel; + } +} diff --git a/TestBenchFramework/BenchControl/ResultsPrinters/Basic/PrinterCfgCtrl.cs b/TestBenchFramework/BenchControl/ResultsPrinters/Basic/PrinterCfgCtrl.cs new file mode 100644 index 000000000..13d7d66d5 --- /dev/null +++ b/TestBenchFramework/BenchControl/ResultsPrinters/Basic/PrinterCfgCtrl.cs @@ -0,0 +1,58 @@ +using System; +using System.Windows.Forms; +using log4net; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.ResultsPrinters.Basic +{ + public partial class PrinterCfgCtrl : UserControl, IComponentCfgCtrl + { + static readonly ILog log = LogManager.GetLogger(typeof(PrinterCfgCtrl)); + + PrinterCfg config; + + public IComponentCfg Config + { + get { return config as IComponentCfg; } + set + { + config = value as PrinterCfg; + Redraw(); + } + } + + public PrinterCfgCtrl() + { + InitializeComponent(); + } + + private void PrinterCfgCtrl_Load(object sender, EventArgs e) + { + Redraw(); + } + + void Redraw() + { + if (config == null) return; /// Control was not loaded, settings were not changed + classNameLabel.Text = config.Factory.ClassName; + nameTextBox.Text = config.Name; + } + + public void Unlock() + { + nameTextBox.Enabled = true; + } + + public CfgVerifyFlags VerifyCfg(ref string message) + { + CfgVerifyFlags flags = CfgVerifyFlags.None; + return flags; + } + + public void UpdateCfg() + { + if (config == null) return; /// Control was not loaded, settings were not changed + config.Name = nameTextBox.Text; + } + } +} diff --git a/TestBenchFramework/BenchControl/ResultsPrinters/Basic/PrinterCfgCtrl.resx b/TestBenchFramework/BenchControl/ResultsPrinters/Basic/PrinterCfgCtrl.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/TestBenchFramework/BenchControl/ResultsPrinters/Basic/PrinterCfgCtrl.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/BenchControl/ResultsPrinters/Basic/PrinterFactory.cs b/TestBenchFramework/BenchControl/ResultsPrinters/Basic/PrinterFactory.cs new file mode 100644 index 000000000..3de5b5cf9 --- /dev/null +++ b/TestBenchFramework/BenchControl/ResultsPrinters/Basic/PrinterFactory.cs @@ -0,0 +1,40 @@ +using System.Collections.Generic; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.ResultsPrinters.Basic +{ + public class PrinterFactory : IComponentFactory + { + public string ClassName { get { return "BasicResultsPrinter"; } } + public bool HasProcedureParams { get { return false; } } + public bool HasTestParams { get { return false; } } + public IParamsProvider GetTestParams(Entities.ComponentTest testParams) { return null; } + public IParamsProvider GetProcedureParams(Entities.ComponentProcedure procedureParams) { return null; } + + /// Max. number of components of this class in the system + public int MaxCount { get { return 1; } } + + + public IComponentCfg DefaultConfig(IList components) + { + return new PrinterCfg(this, "BasicResultsPrinter"); + } + + public IComponentCfgCtrl CreateCfgCtrl() + { + return new PrinterCfgCtrl(); + } + + public IComponent ComponentFromCmpntCfg(IComponentCfg config, IList components) + { + return new Printer((PrinterCfg)config); + } + + public IComponentCfg CmpntCfgFromCmpntEntity(Entities.Component component) + { + return PrinterCfg.CreateFromDbEntity(component, this); + } + + public void ResetStaticProperties() { Printer.ResetStaticProperties(); } + } +} diff --git a/TestBenchFramework/BenchControl/ResultsPrinters/Munich/MunichPrintDocument.cs b/TestBenchFramework/BenchControl/ResultsPrinters/Munich/MunichPrintDocument.cs new file mode 100644 index 000000000..085db937a --- /dev/null +++ b/TestBenchFramework/BenchControl/ResultsPrinters/Munich/MunichPrintDocument.cs @@ -0,0 +1,325 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Printing; +using TBF.BenchControl; + +namespace TBF.BenchControl.ResultsPrinters.Munich +{ + public class MunichPrintDocument : PrintDocument + { + const int SpacingOne = 20; + const int SpacingOneAndHalf = (3 * SpacingOne) / 2; + const int TitleX = 240; + const int TitleY = 200; /// Depends on the size of the header + const int FirstLineNr = 14; /// Depends on the size of the header + const int Tab1 = 80; /// Positions of columns above the table + const int Tab2 = 240; + const int Tab3 = 430; + const int Tab4 = 590; + const int BorderW = 1; /// Table border line width + const int Margin = 7; /// Margins of the text from table lines + + /// Initialized in the constructor + readonly Printer prn; + readonly bool combined; /// true when MetersKind is MetersKind.Combined + readonly int secondTableOffset; /// Calculated in the constructor + + /// Top coordinate of the table + int top; + + /// + /// Property variable for the Font the user wishes to use + /// + public Font Font + { + get { return font; } + set { font = value; } + } + Font font; + Font fontTitle; + + /// + /// Constructor + /// + /// Text to be printed + public MunichPrintDocument(Printer printer) + { + prn = printer; + combined = (prn.Results[0].MetersKind == Entities.MetersKind.Combined); + secondTableOffset = (prn.Results.Count + 2) * SpacingOneAndHalf; + } + + /// + /// Override the default onbeginPrint method of the PrintDocument Object. + /// + /// + /// + protected override void OnBeginPrint(System.Drawing.Printing.PrintEventArgs e) + { + base.OnBeginPrint(e); + if (font == null) { font = new Font("Times New Roman", 10); } + if (fontTitle == null) { fontTitle = new Font("Times New Roman", 24); } + } + + /// + /// Override the default OnPrintPage method of the PrintDocument. + /// + /// + /// This provides the print logic for our document + protected override void OnPrintPage(System.Drawing.Printing.PrintPageEventArgs e) + { + // Run base code + base.OnPrintPage(e); + + e.Graphics.DrawImageUnscaled(Properties.Resources.Headpic, 0, 0); + + /// Set print area size and margins (in dots using 80 dpi) + int printHeight = base.DefaultPageSettings.PaperSize.Height - base.DefaultPageSettings.Margins.Top - base.DefaultPageSettings.Margins.Bottom; + int printWidth = base.DefaultPageSettings.PaperSize.Width - base.DefaultPageSettings.Margins.Left - base.DefaultPageSettings.Margins.Right; + int leftMargin = base.DefaultPageSettings.Margins.Left; /// X + int topMargin = base.DefaultPageSettings.Margins.Top; /// Y + + /// Check if the user selected to print in Landscape mode + /// if they did then we need to swap height/width parameters + if (base.DefaultPageSettings.Landscape) + { + int tmp = printHeight; + printHeight = printWidth; + printWidth = tmp; + } + + int x = leftMargin; + int y = topMargin; + + /// Use the StringFormat class for the text layout of our document + StringFormat format = new StringFormat(StringFormatFlags.LineLimit); + + RectangleF printArea = new RectangleF(TitleX, TitleY, 667, 50); + e.Graphics.DrawString(prn.Title, this.fontTitle, Brushes.Black, printArea); + + int lineNr = FirstLineNr; + PrintAt(e, Tab1, lineNr * SpacingOne, prn.Version); + lineNr++; + PrintAt(e, Tab1, lineNr * SpacingOne, "Prüfstand Nr :"); + PrintAt(e, Tab2, lineNr * SpacingOne, prn.BenchId.TestBenchNr.ToString()); + PrintAt(e, Tab3, lineNr * SpacingOne, "Datum :"); + PrintAt(e, Tab4, lineNr * SpacingOne, DateTime.Now.Date.ToString("d")); + lineNr++; + PrintAt(e, Tab1, lineNr * SpacingOne, "Zahlertyp :"); + PrintAt(e, Tab2, lineNr * SpacingOne, prn.Zaehlertyp); + PrintAt(e, Tab3, lineNr * SpacingOne, "Eichjahr :"); + PrintAt(e, Tab4, lineNr * SpacingOne, prn.Eichjahr); + lineNr++; + PrintAt(e, Tab1, lineNr * SpacingOne, "Prüfvorlage :"); + PrintAt(e, Tab2, lineNr * SpacingOne, prn.Pruefvorlage); + lineNr += 2; + + if (combined) + { + PrintAt(e, Tab1, lineNr * SpacingOne, "Hauptzahler"); + PrintAt(e, Tab3, lineNr * SpacingOne, "Nebenzahler"); + lineNr++; + } + + PrintAt(e, Tab1, lineNr * SpacingOne, "Hersteller :"); + PrintAt(e, Tab2, lineNr * SpacingOne, prn.WaterMeters[0].Producer); + if (combined) + { + PrintAt(e, Tab3, lineNr * SpacingOne, "Hersteller :"); + PrintAt(e, Tab4, lineNr * SpacingOne, prn.WaterMeters[1].Producer); + } + lineNr++; + + PrintAt(e, Tab1, lineNr * SpacingOne, "Seriennummer :"); + PrintAt(e, Tab2, lineNr * SpacingOne, prn.WaterMeters[0].SerialNr); + if (combined) + { + PrintAt(e, Tab3, lineNr * SpacingOne, "Seriennummer :"); + PrintAt(e, Tab4, lineNr * SpacingOne, prn.WaterMeters[1].SerialNr); + } + lineNr++; + + PrintAt(e, Tab1, lineNr * SpacingOne, "Qn :"); + PrintAt(e, Tab2, lineNr * SpacingOne, prn.WaterMeters[0].Qn.ToString()); + if (combined) + { + PrintAt(e, Tab3, lineNr * SpacingOne, "Qn :"); + PrintAt(e, Tab4, lineNr * SpacingOne, prn.WaterMeters[1].Qn.ToString()); + } + lineNr++; + + PrintAt(e, Tab1, lineNr * SpacingOne, "Zulassungszeichen :"); + PrintAt(e, Tab2, lineNr * SpacingOne, prn.WaterMeters[0].ApprovalInfo); + if (combined) + { + PrintAt(e, Tab3, lineNr * SpacingOne, "Zulassungszeichen :"); + PrintAt(e, Tab4, lineNr * SpacingOne, prn.WaterMeters[1].ApprovalInfo); + } + lineNr++; + + PrintAt(e, Tab1, lineNr * SpacingOne, "Metr. klasse :"); + PrintAt(e, Tab2, lineNr * SpacingOne, prn.WaterMeters[0].MetrologicalClass); + if (combined) + { + PrintAt(e, Tab3, lineNr * SpacingOne, "Metr. klasse :"); + PrintAt(e, Tab4, lineNr * SpacingOne, prn.WaterMeters[1].MetrologicalClass); + } + lineNr++; + + PrintAt(e, Tab1, lineNr * SpacingOne, "Stand :"); + PrintAt(e, Tab2, lineNr * SpacingOne, prn.WaterMeters[0].State); + if (combined) + { + PrintAt(e, Tab3, lineNr * SpacingOne, "Stand :"); + PrintAt(e, Tab4, lineNr * SpacingOne, prn.WaterMeters[1].State); + + lineNr += 2; + PrintAt(e, Tab1, lineNr * SpacingOne, "Umschaltpunkte :"); + lineNr++; + PrintAt(e, Tab1, lineNr * SpacingOne, "Qsteig"); + PrintAt(e, Tab2, lineNr * SpacingOne, (1000.0f * Sequences.SequenceBase.Qrise).ToString("F1") + " l/h"); + lineNr++; + PrintAt(e, Tab1, lineNr * SpacingOne, "Qfall"); + PrintAt(e, Tab2, lineNr * SpacingOne, (1000.0f * Sequences.SequenceBase.Qfall).ToString("F1") + " l/h"); + } + + lineNr += 2; + top = SpacingOne * lineNr; + + PrintTable(e); + DrawTable(e); + + lineNr += (secondTableOffset * 2) / SpacingOne; + PrintAt(e, Tab1, lineNr * SpacingOne, "Temperatur"); + PrintAt(e, Tab2, lineNr * SpacingOne, prn.Results[0].AmbientTempAve.ToString("F1") + " \x00b0C"); + lineNr++; + PrintAt(e, Tab1, lineNr * SpacingOne, "Feuchtigkeit"); + PrintAt(e, Tab2, lineNr * SpacingOne, prn.Results[0].AmbientHumiAve.ToString("F0") + " %"); + lineNr++; + PrintAt(e, Tab1, lineNr * SpacingOne, "Luftdruck"); + PrintAt(e, Tab2, lineNr * SpacingOne, prn.Results[0].AmbientPressAve.ToString("F0") + " mbar"); + + lineNr++; + PrintAt(e, Tab3, lineNr * SpacingOne, DateTime.Now.Date.ToString("d")); + lineNr ++; + PrintAt(e, Tab3, lineNr * SpacingOne, "Datum"); + PrintAt(e, Tab4, lineNr * SpacingOne, "Unterschrift"); + } + + /// + /// Print table texts. + /// + void PrintTable(System.Drawing.Printing.PrintPageEventArgs e) + { + PrintAt(e, FromTest(-1, -1), "Prüflauf"); + PrintAt(e, FromTest(-1, 0), "Q [l/h]"); + PrintAt(e, FromTest(-1, 1), "Prüf-Vol.[l]"); + PrintAt(e, FromTest(-1, 2), combined ? "HZ-Vol.[l]" : "Z-Vol.[l]"); + PrintAt(e, FromTest(-1, 3), combined ? "NZ-Vol.[l]" : "-"); + PrintAt(e, FromTest(-1, 4), "Fehler [%]"); + PrintAt(e, FromTest(-1, 5), "Ergebnis"); + + PrintAt(e, FromTest(-1, 6), "Q [l/h]"); + PrintAt(e, FromTest(-1, 7), "Temperatur"); + PrintAt(e, FromTest(-1, 8), "Dichte"); + PrintAt(e, FromTest(-1, 9), "Prüfzeit"); + PrintAt(e, FromTest(-1, 10), "Druck Eing."); + PrintAt(e, FromTest(-1, 11), "Druck Ausg."); + + for (int i = 0; i < prn.Results.Count; i++) + { + Point p = FromTest(i, -1); + PrintAt(e, p.X, p.Y, prn.Results[i].Name); + PrintAt(e, p.X, p.Y + (prn.Results.Count + 2) * SpacingOneAndHalf, prn.Results[i].Name); + + PrintAt(e, FromTest(i, 0), prn.Results[i].FlowMass.ToString("F1")); + PrintAt(e, FromTest(i, 1), prn.Results[i].VolumeCTV.ToString("F2")); + PrintAt(e, FromTest(i, 2), prn.Results[i].Meters[0].VolumeMeter.ToString("F2")); + if (combined) + { + PrintAt(e, FromTest(i, 3), prn.Results[i].Meters[1].VolumeMeter.ToString("F2")); + PrintAt(e, FromTest(i, 4), prn.Results[i].CombinedMeters[0].VolumeErrorPct.ToString("F2")); + PrintAt(e, FromTest(i, 5), prn.Results[i].CombinedMeters[0].Passed ? "iO" : "NiO"); + } + else + { + PrintAt(e, FromTest(i, 3), "-"); + PrintAt(e, FromTest(i, 4), prn.Results[i].Meters[0].VolumeErrorPct.ToString("F2")); + PrintAt(e, FromTest(i, 5), prn.Results[i].Meters[0].Passed ? "iO" : "NiO"); + } + PrintAt(e, FromTest(i, 6), prn.Results[i].FlowMass.ToString("F1")); + PrintAt(e, FromTest(i, 7), prn.Results[i].TempOutAvrg.ToString("F2")); + PrintAt(e, FromTest(i, 8), prn.Results[i].DensityDiv.ToString("F2")); + PrintAt(e, FromTest(i, 9), prn.Results[i].Time.ToString("F1")); + PrintAt(e, FromTest(i, 10), prn.Results[i].PressInAvrg.ToString("F2")); + PrintAt(e, FromTest(i, 11), prn.Results[i].PressOutAvrg.ToString("F2")); + } + } + + /// + /// Draw table lines. + /// + void DrawTable(System.Drawing.Printing.PrintPageEventArgs e) + { + int mid = top + SpacingOneAndHalf; + int bot = top + (prn.Results.Count + 1) * SpacingOneAndHalf; + + int top2 = top + secondTableOffset; + int mid2 = mid + secondTableOffset; + int bot2 = bot + secondTableOffset; + + // Horizontal lines + e.Graphics.DrawLine(new Pen(Color.Black, BorderW), new Point(80, top), new Point(747, top)); + e.Graphics.DrawLine(new Pen(Color.Black, BorderW), new Point(80, mid), new Point(747, mid)); + e.Graphics.DrawLine(new Pen(Color.Black, BorderW), new Point(80, bot), new Point(747, bot)); + + e.Graphics.DrawLine(new Pen(Color.Black, BorderW), new Point(80, top2), new Point(747, top2)); + e.Graphics.DrawLine(new Pen(Color.Black, BorderW), new Point(80, mid2), new Point(747, mid2)); + e.Graphics.DrawLine(new Pen(Color.Black, BorderW), new Point(80, bot2), new Point(747, bot2)); + + // Vertical lines + e.Graphics.DrawLine(new Pen(Color.Black, BorderW), new Point( 80, top), new Point( 80, bot)); + e.Graphics.DrawLine(new Pen(Color.Black, BorderW), new Point(267, top), new Point(267, bot)); + e.Graphics.DrawLine(new Pen(Color.Black, BorderW), new Point(347, top), new Point(347, bot)); + e.Graphics.DrawLine(new Pen(Color.Black, BorderW), new Point(427, top), new Point(427, bot)); + e.Graphics.DrawLine(new Pen(Color.Black, BorderW), new Point(507, top), new Point(507, bot)); + e.Graphics.DrawLine(new Pen(Color.Black, BorderW), new Point(587, top), new Point(587, bot)); + e.Graphics.DrawLine(new Pen(Color.Black, BorderW), new Point(667, top), new Point(667, bot)); + e.Graphics.DrawLine(new Pen(Color.Black, BorderW), new Point(747, top), new Point(747, bot)); + + e.Graphics.DrawLine(new Pen(Color.Black, BorderW), new Point( 80, top2), new Point( 80, bot2)); + e.Graphics.DrawLine(new Pen(Color.Black, BorderW), new Point(267, top2), new Point(267, bot2)); + e.Graphics.DrawLine(new Pen(Color.Black, BorderW), new Point(347, top2), new Point(347, bot2)); + e.Graphics.DrawLine(new Pen(Color.Black, BorderW), new Point(427, top2), new Point(427, bot2)); + e.Graphics.DrawLine(new Pen(Color.Black, BorderW), new Point(507, top2), new Point(507, bot2)); + e.Graphics.DrawLine(new Pen(Color.Black, BorderW), new Point(587, top2), new Point(587, bot2)); + e.Graphics.DrawLine(new Pen(Color.Black, BorderW), new Point(667, top2), new Point(667, bot2)); + e.Graphics.DrawLine(new Pen(Color.Black, BorderW), new Point(747, top2), new Point(747, bot2)); + } + + void PrintAt(System.Drawing.Printing.PrintPageEventArgs e, Point p, string text) + { + PrintAt(e, p.X, p.Y, text); + } + + void PrintAt(System.Drawing.Printing.PrintPageEventArgs e, int x, int y, string text) + { + RectangleF printArea = new RectangleF(x, y, 667, SpacingOne); + e.Graphics.DrawString(text, this.font, Brushes.Black, printArea); + } + + Point FromTest(int testNr, int parNr) + { + const int NrParamsInOneTableRow = 6; + + int x = 267 + (parNr % NrParamsInOneTableRow) * 80 + Margin; + int y = top + SpacingOneAndHalf + Margin + testNr * SpacingOneAndHalf + + ((parNr >= NrParamsInOneTableRow) ? secondTableOffset : 0); + + if (parNr < 0) x = 80 + Margin; /// When parNr == -1 return the left column x coordinate + + return new Point(x, y); + } + } +} diff --git a/TestBenchFramework/BenchControl/ResultsPrinters/Munich/Printer.cs b/TestBenchFramework/BenchControl/ResultsPrinters/Munich/Printer.cs new file mode 100644 index 000000000..72eb449d4 --- /dev/null +++ b/TestBenchFramework/BenchControl/ResultsPrinters/Munich/Printer.cs @@ -0,0 +1,86 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Printing; +using TBF.BenchControl; + +namespace TBF.BenchControl.ResultsPrinters.Munich +{ + public class Printer : ComponentBase, Generic.IComponent, IOperation, GenericDevices.IResultsPrinter + { + readonly PrinterCfg printerCfg; + + public static void ResetStaticProperties() { } + + /// + /// Data to print + /// + public BenchControl.BenchId.Component BenchId; + public IList WaterMeters; + public IList Results; + public string Title; + + public string Version + { + get { return (ProcedureParams is ProcParams) ? (ProcedureParams as ProcParams).Version : ""; } + } + + public string Zaehlertyp + { + get { return (ProcedureParams is ProcParams) ? (ProcedureParams as ProcParams).Zaehlertyp : ""; } + } + + public string Pruefvorlage + { + get { return (ProcedureParams is ProcParams) ? (ProcedureParams as ProcParams).Pruefvorlage : ""; } + } + + public string Eichjahr + { + get { return (ProcedureParams is ProcParams) ? (ProcedureParams as ProcParams).Eichjahr : ""; } + } + + public Printer(PrinterCfg cfg) + : base(cfg) + { + if (cfg == null) throw new ArgumentNullException("cfg"); + this.printerCfg = cfg; + } + + /// Events: ResultsPrinted + /// Results to print + /// Reference to the operation + public IOperation PrintResultsOp(BenchControl.BenchId.Component benchId, + IList waterMeters, + IList results, + string title) + { + this.BenchId = benchId; + this.WaterMeters = waterMeters; + this.Results = results; + this.Title = title; + return this; + } + + /// Start this operation + public void Start() + { + if (Results != null && Results.Count >= 1) + { + new MunichPrintDocument(this).Print(); + } + } + + /// Run this operation + /// Event.ResultsPrinted + public Event Run() + { + return Event.ResultsPrinted; + } + + /// Stop this operation + public void Stop() + { + } + } +} diff --git a/TestBenchFramework/BenchControl/ResultsPrinters/Munich/PrinterCfg.cs b/TestBenchFramework/BenchControl/ResultsPrinters/Munich/PrinterCfg.cs new file mode 100644 index 000000000..977fa051a --- /dev/null +++ b/TestBenchFramework/BenchControl/ResultsPrinters/Munich/PrinterCfg.cs @@ -0,0 +1,54 @@ +using System; +using System.IO; +using System.Xml.Serialization; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.ResultsPrinters.Munich +{ + public class PrinterCfg : ComponentCfgBase, Generic.IComponentCfg + { + /// Parameterless constructor + public PrinterCfg() + { + } + + /// + /// Basic results printer configuration parameters + /// + /// BasicPrinter factory + /// Printer name + public PrinterCfg(IComponentFactory factory, string name) + : base(factory, name) + { + } + + public IComponentCfg Clone() + { + return new PrinterCfg(Factory, Name); + } + + public string ToString(int i) + { + return string.Empty; + } + + public TBF.Entities.Component CreateDbEntity() + { + using (var writer = new StringWriter()) + { + (new XmlSerializer(GetType())).Serialize(writer, this); + return Entities.Component.CreateFromCfg(Name, Factory.ClassName, ParentName, ItemNr, DebugLevel, LogLevel, writer.ToString()); + } + } + + public static IComponentCfg CreateFromDbEntity(Entities.Component component, IComponentFactory factory) + { + using (var reader = new StringReader(component.Parameters)) + { + PrinterCfg config = (PrinterCfg)(new XmlSerializer(typeof(PrinterCfg))).Deserialize(reader); + config.InitCfgBaseFromEntity(component, factory); + return config; + } + } + } +} diff --git a/TestBenchFramework/BenchControl/ResultsPrinters/Munich/PrinterCfgCtrl.cs b/TestBenchFramework/BenchControl/ResultsPrinters/Munich/PrinterCfgCtrl.cs new file mode 100644 index 000000000..1169bf8b6 --- /dev/null +++ b/TestBenchFramework/BenchControl/ResultsPrinters/Munich/PrinterCfgCtrl.cs @@ -0,0 +1,58 @@ +using System; +using System.Windows.Forms; +using log4net; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.ResultsPrinters.Munich +{ + public partial class PrinterCfgCtrl : UserControl, IComponentCfgCtrl + { + static readonly ILog log = LogManager.GetLogger(typeof(PrinterCfgCtrl)); + + PrinterCfg config; + + public IComponentCfg Config + { + get { return config as IComponentCfg; } + set + { + config = value as PrinterCfg; + Redraw(); + } + } + + public PrinterCfgCtrl() + { + InitializeComponent(); + } + + private void PrinterCfgCtrl_Load(object sender, EventArgs e) + { + Redraw(); + } + + void Redraw() + { + if (config == null) return; /// Control was not loaded, settings were not changed + classNameLabel.Text = config.Factory.ClassName; + nameTextBox.Text = config.Name; + } + + public void Unlock() + { + nameTextBox.Enabled = true; + } + + public CfgVerifyFlags VerifyCfg(ref string message) + { + CfgVerifyFlags flags = CfgVerifyFlags.None; + return flags; + } + + public void UpdateCfg() + { + if (config == null) return; /// Control was not loaded, settings were not changed + config.Name = nameTextBox.Text; + } + } +} diff --git a/TestBenchFramework/BenchControl/ResultsPrinters/Munich/PrinterCfgCtrl.designer.cs b/TestBenchFramework/BenchControl/ResultsPrinters/Munich/PrinterCfgCtrl.designer.cs new file mode 100644 index 000000000..dce5ccb71 --- /dev/null +++ b/TestBenchFramework/BenchControl/ResultsPrinters/Munich/PrinterCfgCtrl.designer.cs @@ -0,0 +1,83 @@ +namespace TBF.BenchControl.ResultsPrinters.Munich +{ + partial class PrinterCfgCtrl + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.nameTextBox = new System.Windows.Forms.TextBox(); + this.nameLabel = new System.Windows.Forms.Label(); + this.classNameLabel = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // nameTextBox + // + this.nameTextBox.Enabled = false; + this.nameTextBox.Location = new System.Drawing.Point(137, 57); + this.nameTextBox.Name = "nameTextBox"; + this.nameTextBox.Size = new System.Drawing.Size(130, 20); + this.nameTextBox.TabIndex = 5; + // + // nameLabel + // + this.nameLabel.AutoSize = true; + this.nameLabel.Location = new System.Drawing.Point(27, 60); + this.nameLabel.Name = "nameLabel"; + this.nameLabel.Size = new System.Drawing.Size(35, 13); + this.nameLabel.TabIndex = 4; + this.nameLabel.Text = "Name"; + // + // classNameLabel + // + this.classNameLabel.AutoSize = true; + this.classNameLabel.Location = new System.Drawing.Point(134, 33); + this.classNameLabel.Name = "classNameLabel"; + this.classNameLabel.Size = new System.Drawing.Size(83, 13); + this.classNameLabel.TabIndex = 3; + this.classNameLabel.Text = "ComonentName"; + // + // BasicPrinterCfgCtrl + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.nameTextBox); + this.Controls.Add(this.nameLabel); + this.Controls.Add(this.classNameLabel); + this.Name = "BasicPrinterCfgCtrl"; + this.Size = new System.Drawing.Size(300, 200); + this.Load += new System.EventHandler(this.PrinterCfgCtrl_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TextBox nameTextBox; + private System.Windows.Forms.Label nameLabel; + private System.Windows.Forms.Label classNameLabel; + } +} diff --git a/TestBenchFramework/BenchControl/ResultsPrinters/Munich/PrinterCfgCtrl.resx b/TestBenchFramework/BenchControl/ResultsPrinters/Munich/PrinterCfgCtrl.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/TestBenchFramework/BenchControl/ResultsPrinters/Munich/PrinterCfgCtrl.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/BenchControl/ResultsPrinters/Munich/PrinterFactory.cs b/TestBenchFramework/BenchControl/ResultsPrinters/Munich/PrinterFactory.cs new file mode 100644 index 000000000..c9bf43481 --- /dev/null +++ b/TestBenchFramework/BenchControl/ResultsPrinters/Munich/PrinterFactory.cs @@ -0,0 +1,43 @@ +using System.Collections.Generic; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.ResultsPrinters.Munich +{ + public class PrinterFactory : IComponentFactory + { + public string ClassName { get { return "ResultsPrinter4Munich"; } } + public bool HasProcedureParams { get { return true; } } + public bool HasTestParams { get { return false; } } + public IParamsProvider GetTestParams(Entities.ComponentTest testParams) { return null; } + public IParamsProvider GetProcedureParams(Entities.ComponentProcedure procedureParams) + { + return ProcParams.GetProcedureParams(procedureParams); + } + + /// Max. number of components of this class in the system + public int MaxCount { get { return 1; } } + + + public IComponentCfg DefaultConfig(IList components) + { + return new PrinterCfg(this, "PrintedProtocol"); + } + + public IComponentCfgCtrl CreateCfgCtrl() + { + return new PrinterCfgCtrl(); + } + + public IComponent ComponentFromCmpntCfg(IComponentCfg config, IList components) + { + return new Printer((PrinterCfg)config); + } + + public IComponentCfg CmpntCfgFromCmpntEntity(Entities.Component component) + { + return PrinterCfg.CreateFromDbEntity(component, this); + } + + public void ResetStaticProperties() { Printer.ResetStaticProperties(); } + } +} diff --git a/TestBenchFramework/BenchControl/ResultsPrinters/Munich/ProcParams.cs b/TestBenchFramework/BenchControl/ResultsPrinters/Munich/ProcParams.cs new file mode 100644 index 000000000..c5b75ba30 --- /dev/null +++ b/TestBenchFramework/BenchControl/ResultsPrinters/Munich/ProcParams.cs @@ -0,0 +1,163 @@ +using System.IO; +using System.Text; +using System.Xml.Serialization; +using TBF.BenchControl.Generic; +using TBF.Resources; + +namespace TBF.BenchControl.ResultsPrinters.Munich +{ + public class ProcParams : IParamsProvider, IProcedureParams + { + public string Version; + public string Zaehlertyp; + public string Pruefvorlage; + public string Eichjahr; + + string[] paramNames = new string[] + { + Strings.Version, + "Zählertyp", + "Prüfvorlage", + "Eichjahr", + }; + public string ParamName(int i) { return paramNames[i]; } + + public string ToString(int i) + { + switch (i) + { + case 0: return Version; + case 1: return Zaehlertyp; + case 2: return Pruefvorlage; + case 3: return Eichjahr; + default: return string.Empty; + } + } + + public void UpdateParam(int i, string strValue) + { + switch (i) + { + case 0: Version = strValue; return; + case 1: Zaehlertyp = strValue; return; + case 2: Pruefvorlage = strValue; return; + case 3: Eichjahr = strValue; return; + default: return; + } + } + + public bool ValidateParam(int i, string strValue, out string message) + { + message = string.Empty; + + switch (i) + { + case 0: + case 1: + case 2: + case 3: + return true; + default: + message = "Invalid index"; + return false; + } + } + + #region Boilerplate code + + public int ParamsCount() { return paramNames.Length; } + + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < ParamsCount(); i++) + { + if (i != 0) sb.Append("; "); + sb.Append(ParamName(i)); + sb.Append("="); + sb.Append(ToString(i)); + } + return sb.ToString(); + } + + [XmlIgnore] + public Entities.ComponentProcedure ProcedureParamsEntity { get { return procParamsEntity; } } + Entities.ComponentProcedure procParamsEntity; + + [XmlIgnore] + public string ComponentName { get { return componentName; } } + string componentName; + + [XmlIgnore] + public Entities.Procedure Test { get { return test; } } + Entities.Procedure test; + + /// Parameterless constructor + public ProcParams() + { + Version = "4/13"; + Zaehlertyp = ""; + Pruefvorlage = ""; + Eichjahr = "2014"; + } + + public ProcParams(Entities.ComponentProcedure procParamsEntity, string componentName, Entities.Procedure test) + : this() + { + this.procParamsEntity = procParamsEntity; + this.componentName = componentName; + this.test = test; + } + + public TBF.Entities.ComponentProcedure ToDbEntity(IComponent component, Entities.Procedure procedure) + { + using (var writer = new StringWriter()) + { + /// Serialize this class with parameters + (new XmlSerializer(GetType())).Serialize(writer, this); + + /// Create and return the ComponentProcedure entity + TBF.Entities.ComponentProcedure entity = new TBF.Entities.ComponentProcedure(); + entity.CmpntName = component.Cfg.Name; + entity.Parameters = writer.ToString(); + entity.Procedure = procedure; + return entity; + } + } + + public void UpdateDbEntity() + { + using (var writer = new StringWriter()) + { + /// Serialize this class and update the entity + (new XmlSerializer(GetType())).Serialize(writer, this); + procParamsEntity.Parameters = writer.ToString(); + procParamsEntity.CmpntName = componentName; + procParamsEntity.Procedure = test; + + } + } + + public static IParamsProvider GetProcedureParams(Entities.ComponentProcedure procParamsEntity) + { + if (procParamsEntity == null) return new ProcParams(); + + ProcParams procParams; + try + { + procParams = (ProcParams)(new XmlSerializer(typeof(ProcParams))) + .Deserialize(new StringReader(procParamsEntity.Parameters)); + } + catch + { + procParams = new ProcParams(); + } + procParams.procParamsEntity = procParamsEntity; + procParams.componentName = procParamsEntity.CmpntName; + procParams.test = procParamsEntity.Procedure; + return procParams; + } + + #endregion + } +} diff --git a/TestBenchFramework/BenchControl/ResultsWriters/Basic/Writer.cs b/TestBenchFramework/BenchControl/ResultsWriters/Basic/Writer.cs new file mode 100644 index 000000000..58fd852d1 --- /dev/null +++ b/TestBenchFramework/BenchControl/ResultsWriters/Basic/Writer.cs @@ -0,0 +1,140 @@ +using System; +using System.Collections.Generic; +using System.IO; +using TBF.BenchControl; + +namespace TBF.BenchControl.ResultsWriters.Basic +{ + public class Writer : Generic.IComponent, IOperation, GenericDevices.IResultsWriter + { + readonly WriterCfg writerCfg; + public Generic.IComponentCfg Cfg { get { return writerCfg; } } + + public static void ResetStaticProperties() { } + + public string Name { get { return writerCfg.Name; } } + + /// + /// Results to print + /// + IList results; + DateTime now; + Stream stream; + StreamWriter writer; + + public Writer(WriterCfg cfg) + { + if (cfg == null) throw new ArgumentNullException("cfg"); + this.writerCfg = cfg; + } + + /// + /// Writes the test cycle results into a file, Events: Event.ResultsWritten + /// + /// Results to write into the file + /// Reference to the operation + public IOperation WriteResultsOp(IList results) + { + this.results = results; + this.now = DateTime.Now; + this.stream = System.IO.File.Create(string.Format("{0}Results\\{1}-{2}-{3}\\{4}-{5}.txt", + Program.HomeDir, + now.Year, now.Month, now.Date, + now.Hour, now.Minute)); + this.writer = new StreamWriter(stream); + + return this; + } + + /// Start this operation + public void Start() + { + writer.WriteLine("Staatlich anerkante Prüfstelle für Meßgeräte für Wasser WB2"); + writer.WriteLine(""); + writer.WriteLine(string.Format(" PROTOKOLL Nummer {0}", 0)); + writer.WriteLine(""); + writer.WriteLine("Ver. 3/13"); + writer.WriteLine(string.Format("Datum / Zeit : {0}.{1}.{2} / {3}:{4} Seite : 1/ 1 / 1", + now.Date, now.Month, now.Year, now.Hour, now.Minute)); + writer.WriteLine("Wasserzähler Type : 110338"); + writer.WriteLine("Gerät Nr. : 1"); + writer.WriteLine("Benutzer : Bauer"); + writer.WriteLine("Impulsrate : 1 67.422 1"); + writer.WriteLine("Bereich : 22,9 °C 947 mbar 43 %"); + writer.WriteLine(""); + writer.WriteLine("Test Metode MIDFehler Durchfluss Test Zeit T1 T2 Dichte Masse Druck Volume Bor"); + writer.WriteLine(" [%] [m3/h] [s] [°C] [°C] [kg/m3] [kg] [MPa] [L] [m3/h]"); + writer.WriteLine("---------------------------------------------------------------------------------------------------------------------------------------"); + + foreach (var tr in results) + { + if (tr.MetersKind == Entities.MetersKind.Single) + { + writer.WriteLine(string.Format("{0} {1} {2} {3} {4} {5} {6} {7} {8} {9} {10} {11}"), + tr.Name, + tr.Method, + tr.Meters[0].VolumeErrorPct, + tr.FlowMass, + tr.Time, + tr.TempInAvrg, + tr.TempDivAvrg, + tr.DensityOut, + tr.MassDiff, + tr.PressInAvrg, + tr.PressOutAvrg, + tr.VolumeCTV); + } + else if (tr.MetersKind == Entities.MetersKind.Combined) + { + writer.WriteLine(string.Format("{0} {1} {2} {3} {4} {5} {6} {7} {8} {9} {10} {11}"), + tr.Name, + tr.Method, + tr.CombinedMeters[0].VolumeErrorPct, + tr.FlowMass, + tr.Time, + tr.TempInAvrg, + tr.TempDivAvrg, + tr.DensityOut, + tr.MassDiff, + tr.PressInAvrg, + tr.PressOutAvrg, + tr.VolumeCTV); + } + } + + writer.WriteLine("---------------------------------------------------------------------------------------------------------------------------------------"); + writer.WriteLine("No| Zähler Nr| Test. Volume [L] | Zählerabweichung [%] | Messunsicherheit k=2 |Prüfergebnis"); + writer.WriteLine("---------------------------------------------------------------------------------------------------------------------------------------"); + writer.WriteLine(" Qmin Qt Qmax Qmin Qt Qmax Qmin Qt Qmax"); + writer.WriteLine("---------------------------------------------------------------------------------------------------------------------------------------"); + } + + /// Run this operation + /// Event.ResultsWritten + public Event Run() + { + + return Event.ResultsWritten; + } + + /// Stop this operation + public void Stop() + { + writer.WriteLine("---------------------------------------------------------------------------------------------------------------------------------------"); + writer.WriteLine(""); + writer.WriteLine("Hersteller : Bemerkung : M - Prüfung gegen Waage"); + writer.WriteLine(" V - Prüfung gegen MID"); + writer.WriteLine(" P - Start / Stopp"); + writer.WriteLine(" F - Fliegender Start"); + writer.WriteLine(" S - Impulskompensation"); + writer.WriteLine(" C - Impulszählung"); + writer.WriteLine(""); + writer.WriteLine("---------------------------------------------------------------------------------------------------------------------------------------"); + + if (writer != null) writer.Close(); + if (stream != null) stream.Close(); + writer = null; + stream = null; + } + } +} diff --git a/TestBenchFramework/BenchControl/ResultsWriters/Basic/WriterCfg.cs b/TestBenchFramework/BenchControl/ResultsWriters/Basic/WriterCfg.cs new file mode 100644 index 000000000..83ea2e5cf --- /dev/null +++ b/TestBenchFramework/BenchControl/ResultsWriters/Basic/WriterCfg.cs @@ -0,0 +1,54 @@ +using System; +using System.IO; +using System.Xml.Serialization; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.ResultsWriters.Basic +{ + public class WriterCfg : ComponentCfgBase, Generic.IComponentCfg + { + /// Parameterless constructor + public WriterCfg() + { + } + + /// + /// Basic results printer configuration parameters + /// + /// BasicPrinter factory + /// Printer name + public WriterCfg(IComponentFactory factory, string name) + : base(factory, name) + { + } + + public IComponentCfg Clone() + { + return new WriterCfg(Factory, Name); + } + + public string ToString(int i) + { + return string.Empty; + } + + public TBF.Entities.Component CreateDbEntity() + { + using (var writer = new StringWriter()) + { + (new XmlSerializer(GetType())).Serialize(writer, this); + return Entities.Component.CreateFromCfg(Name, Factory.ClassName, ParentName, ItemNr, DebugLevel, LogLevel, writer.ToString()); + } + } + + public static IComponentCfg CreateFromDbEntity(Entities.Component component, IComponentFactory factory) + { + using (var reader = new StringReader(component.Parameters)) + { + WriterCfg config = (WriterCfg)(new XmlSerializer(typeof(WriterCfg))).Deserialize(reader); + config.InitCfgBaseFromEntity(component, factory); + return config; + } + } + } +} diff --git a/TestBenchFramework/BenchControl/ResultsWriters/Basic/WriterCfgCtrl.cs b/TestBenchFramework/BenchControl/ResultsWriters/Basic/WriterCfgCtrl.cs new file mode 100644 index 000000000..ac2b59074 --- /dev/null +++ b/TestBenchFramework/BenchControl/ResultsWriters/Basic/WriterCfgCtrl.cs @@ -0,0 +1,58 @@ +using System; +using System.Windows.Forms; +using log4net; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.ResultsWriters.Basic +{ + public partial class WriterCfgCtrl : UserControl, IComponentCfgCtrl + { + static readonly ILog log = LogManager.GetLogger(typeof(WriterCfgCtrl)); + + WriterCfg config; + + public IComponentCfg Config + { + get { return config as IComponentCfg; } + set + { + config = value as WriterCfg; + Redraw(); + } + } + + public WriterCfgCtrl() + { + InitializeComponent(); + } + + private void WriterCfgCtrl_Load(object sender, EventArgs e) + { + Redraw(); + } + + void Redraw() + { + if (config == null) return; /// Control was not loaded, settings were not changed + classNameLabel.Text = config.Factory.ClassName; + nameTextBox.Text = config.Name; + } + + public void Unlock() + { + nameTextBox.Enabled = true; + } + + public CfgVerifyFlags VerifyCfg(ref string message) + { + CfgVerifyFlags flags = CfgVerifyFlags.None; + return flags; + } + + public void UpdateCfg() + { + if (config == null) return; /// Control was not loaded, settings were not changed + config.Name = nameTextBox.Text; + } + } +} diff --git a/TestBenchFramework/BenchControl/ResultsWriters/Basic/WriterCfgCtrl.designer.cs b/TestBenchFramework/BenchControl/ResultsWriters/Basic/WriterCfgCtrl.designer.cs new file mode 100644 index 000000000..a4907d37d --- /dev/null +++ b/TestBenchFramework/BenchControl/ResultsWriters/Basic/WriterCfgCtrl.designer.cs @@ -0,0 +1,83 @@ +namespace TBF.BenchControl.ResultsWriters.Basic +{ + partial class WriterCfgCtrl + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.nameTextBox = new System.Windows.Forms.TextBox(); + this.nameLabel = new System.Windows.Forms.Label(); + this.classNameLabel = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // nameTextBox + // + this.nameTextBox.Enabled = false; + this.nameTextBox.Location = new System.Drawing.Point(137, 57); + this.nameTextBox.Name = "nameTextBox"; + this.nameTextBox.Size = new System.Drawing.Size(130, 20); + this.nameTextBox.TabIndex = 5; + // + // nameLabel + // + this.nameLabel.AutoSize = true; + this.nameLabel.Location = new System.Drawing.Point(27, 60); + this.nameLabel.Name = "nameLabel"; + this.nameLabel.Size = new System.Drawing.Size(35, 13); + this.nameLabel.TabIndex = 4; + this.nameLabel.Text = "Name"; + // + // classNameLabel + // + this.classNameLabel.AutoSize = true; + this.classNameLabel.Location = new System.Drawing.Point(134, 33); + this.classNameLabel.Name = "classNameLabel"; + this.classNameLabel.Size = new System.Drawing.Size(83, 13); + this.classNameLabel.TabIndex = 3; + this.classNameLabel.Text = "ComonentName"; + // + // BasicPrinterCfgCtrl + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.nameTextBox); + this.Controls.Add(this.nameLabel); + this.Controls.Add(this.classNameLabel); + this.Name = "BasicPrinterCfgCtrl"; + this.Size = new System.Drawing.Size(300, 200); + this.Load += new System.EventHandler(this.WriterCfgCtrl_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TextBox nameTextBox; + private System.Windows.Forms.Label nameLabel; + private System.Windows.Forms.Label classNameLabel; + } +} diff --git a/TestBenchFramework/BenchControl/ResultsWriters/Basic/WriterCfgCtrl.resx b/TestBenchFramework/BenchControl/ResultsWriters/Basic/WriterCfgCtrl.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/TestBenchFramework/BenchControl/ResultsWriters/Basic/WriterCfgCtrl.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/BenchControl/ResultsWriters/Basic/WriterFactory.cs b/TestBenchFramework/BenchControl/ResultsWriters/Basic/WriterFactory.cs new file mode 100644 index 000000000..0517275ef --- /dev/null +++ b/TestBenchFramework/BenchControl/ResultsWriters/Basic/WriterFactory.cs @@ -0,0 +1,40 @@ +using System.Collections.Generic; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.ResultsWriters.Basic +{ + public class WriterFactory : IComponentFactory + { + public string ClassName { get { return "BasicResultsWriter"; } } + public bool HasProcedureParams { get { return false; } } + public bool HasTestParams { get { return false; } } + public IParamsProvider GetTestParams(Entities.ComponentTest testParams) { return null; } + public IParamsProvider GetProcedureParams(Entities.ComponentProcedure procedureParams) { return null; } + + /// Max. number of components of this class in the system + public int MaxCount { get { return 1; } } + + + public IComponentCfg DefaultConfig(IList components) + { + return new WriterCfg(this, "BasicResultsWriter"); + } + + public IComponentCfgCtrl CreateCfgCtrl() + { + return new WriterCfgCtrl(); + } + + public IComponent ComponentFromCmpntCfg(IComponentCfg config, IList components) + { + return new Writer((WriterCfg)config); + } + + public IComponentCfg CmpntCfgFromCmpntEntity(Entities.Component component) + { + return WriterCfg.CreateFromDbEntity(component, this); + } + + public void ResetStaticProperties() { Writer.ResetStaticProperties(); } + } +} diff --git a/TestBenchFramework/BenchControl/Sequences/MainSeq.cs b/TestBenchFramework/BenchControl/Sequences/MainSeq.cs new file mode 100644 index 000000000..c5a6dca7b --- /dev/null +++ b/TestBenchFramework/BenchControl/Sequences/MainSeq.cs @@ -0,0 +1,533 @@ +using System; +using System.Collections.Generic; +using log4net; +using TBF.UiBridge; +using TBF.BenchControl.Operations; +using TBF.BenchControl.GenericDevices; +using TBF.Resources; + +namespace TBF.BenchControl.Sequences +{ + public class MainSeq : SequenceBase, ISequence + { + private static readonly ILog log = LogManager.GetLogger(typeof(MainSeq)); + private static readonly ILog allResults = LogManager.GetLogger("AllResults"); + private static readonly ILog summaryResults = LogManager.GetLogger("SummaryResults"); + + public override string ToString() { return "Sequences.MainSeq"; } + + /// + /// Specifies the selection done in the main sequence + /// + public enum Selection + { + None, + Cycle, + Test, + Q1, + Q2, + Q3, + PurgeBegin, + PurgeEnd, + EmptyTank1, + EmptyTank2, + } + + public MainSeq() + { + } + + public IList Execute(Entities.Test dummyArg) + { + Elde.ControlBoardDev cBrd = StateMachine.ControlBoard; + + /// Operations running in more then one state + IOperation checkUiOp = new CheckUIOp(true); + + IList e; + Selection selection; + bool benchFilled = false; + + Entities.TransitionSequence purgeBegin; + Entities.TransitionSequence purgeEnd; + + StateMachine.LoadProcedure(true); + + Bridge.Bench2UI(ButtonsEtc.StopBtnEn); + + //------------------------------------------------ + Bridge.OnActivity(this, Strings.Measuring_the_weight); + //------------------------------------------------ + State.Create(Strings.Set_route) + .AddOperation(new MettlerToledo.ReadMassesOp()) + .AddOperation(cBrd.SetValvesOp(StateMachine.DefaultValvesOpen, StateMachine.DefaultValvesClose)) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.Error)) goto error; + if (e.Contains(Event.UiCmdStop)) goto stop; + } + while (!(e.Contains(Event.ValvesSet) && e.Contains(Event.BalanceDone))); + + //------------------------------------------------ + Bridge.OnActivity(this, Strings.Starting_the_cameras); + //------------------------------------------------ + State startNew = State.Create("MainSeq : Starting the cameras") + .AddOperation(checkUiOp); + foreach (var cmpnt in StateMachine.Components) + { + Cameras.IdcCamera.IdcCamera camera = cmpnt as Cameras.IdcCamera.IdcCamera; + if ((camera != null) && (camera.Cfg.DebugLevel != Entities.DebugMode.DetectedOff)) + { + startNew.AddOperation(camera.StartNewOp()); + } + } + startNew.EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.Error)) goto error; + if (e.Contains(Event.UiCmdStop)) goto stop; + } + while (e.Contains(Event.CameraBusy)); + + if (e.Contains(Event.CameraOpFailed)) goto error; /// TODO: resolve in some other way + + idle: + + Bridge.Bench2UI(ButtonsEtc.ProcedureCmbBoxEn | ButtonsEtc.TestCmbBoxEn | ButtonsEtc.StopBtnEn | + ButtonsEtc.StartCycleBtnEn | ButtonsEtc.StartTestBtnsEn | + ButtonsEtc.EmptyTankBtnsEn | ButtonsEtc.PurgeBeginBtnEn | + ButtonsEtc.CalibrationBtnEn); + //--------------------------------------------------------- + Bridge.OnActivity(this, Strings.Please_select_a_procedure); + //--------------------------------------------------------- + selection = Selection.None; + State.Create("MainSeq : Select a procedure") + .AddOperation(cBrd.UpdateTankWeightOp()) + .AddOperation(checkUiOp) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.Error)) goto error; + if (e.Contains(Event.UiCmdPurgeBegin)) selection = Selection.PurgeBegin; + if (e.Contains(Event.UiCmdStartTest)) selection = Selection.Test; + if (e.Contains(Event.UiCmdStartQ1)) selection = Selection.Q1; + if (e.Contains(Event.UiCmdStartQ2)) selection = Selection.Q2; + if (e.Contains(Event.UiCmdStartQ3)) selection = Selection.Q3; + if (e.Contains(Event.UiCmdStartCycle)) selection = Selection.Cycle; + if (e.Contains(Event.UiCmdEmptyTank1)) goto empty_tank1_idle; + if (e.Contains(Event.UiCmdEmptyTank2)) goto empty_tank2_idle; + if (e.Contains(Event.UiCmdCameraTest)) goto camera_test; + } + while (selection == Selection.None); + + //-------------------------------- + Bridge.Bench2UI(ButtonsEtc.StopBtnEn); + StateMachine.LoadProcedure(false); + if (StateMachine.Procedure == null) + { + goto idle; + } + StateMachine.LoadProcedureParams(StateMachine.Procedure); + ResetResults(); + Bridge.OnProcedureSelected(this, new ProcedureSelectedEventArgs(StateMachine.Procedure)); + + + purgeBegin = null; + purgeEnd = null; + foreach (var transition in StateMachine.TransitionSequences) + { + if (transition.Name == StateMachine.Procedure.TransitionStart) purgeBegin = transition; + if (transition.Name == StateMachine.Procedure.TransitionEnd) purgeEnd = transition; + } + + + if (selection == Selection.Q1 || selection == Selection.Q2 || + selection == Selection.Q3 || selection == Selection.Test) + { + goto assume_bench_filled; + } + else if (selection == Selection.Cycle && benchFilled) + { + //-------------------------------- + State.Create("MainSeq : Answer a question") + .AddOperation(new Operations.AskYesNoOp()) + .AddOperation(checkUiOp) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.No)) goto assume_bench_filled; + if (e.Contains(Event.UiCmdStop)) goto idle; + } + while (!e.Contains(Event.Yes)); + } + + fill_the_bench: + + /// Purge - Begin + switch (Transition(purgeBegin, Strings.Purging_i_n)) + { + case Event.Error: goto error; + case Event.UiCmdStop: goto stop; + } + + //-------------------------------- + Generic.IComponent dataEntryCmpnt = TbfComponents.FindComponent(StateMachine.Procedure.DataEntry); + if ((dataEntryCmpnt as GenericDevices.IDataEntry) != null) + { + Bridge.OnActivity(this, "Enter the water meter data"); + State.Create("MainSeq : Enter begin data") + .AddOperation((dataEntryCmpnt as GenericDevices.IDataEntry).ShowFormAtCycleBeginningOp(WaterMeters)) + .AddOperation(checkUiOp) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.UiCmdStop)) goto stop; + } + while (!e.Contains(Event.Done)); + } + + assume_bench_filled: + + benchFilled = true; + Bridge.Bench2UI(ButtonsEtc.ShowBenchFilled); + + if (selection != Selection.PurgeBegin) goto cycle_or_test; + + ready: + //--------------------------------------------------------- + Bridge.OnActivity(this, Strings.Please_select_a_cycle_a_test_or_empty); + //--------------------------------------------------------- + Bridge.Bench2UI(ButtonsEtc.TestCmbBoxEn | ButtonsEtc.StopBtnEn | ButtonsEtc.StartCycleBtnEn | + ButtonsEtc.StartTestBtnsEn | ButtonsEtc.PurgeBeginBtnEn | ButtonsEtc.PurgeEndBtnEn | + ButtonsEtc.EmptyTankBtnsEn | ((Cameras.Count > 0) ? ButtonsEtc.CalibrationBtnEn : 0) | + ButtonsEtc.SensitivityTestBtnEn | ButtonsEtc.TryOpticalHeadsBtnEn); + selection = Selection.None; + State.Create("MainSeq : Select an activity for the selected procedure") + .AddOperation(checkUiOp) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.Error)) goto error; + if (e.Contains(Event.UiCmdStop)) goto stop; + if (e.Contains(Event.UiCmdStartTest)) selection = Selection.Test; + if (e.Contains(Event.UiCmdStartQ1)) selection = Selection.Q1; + if (e.Contains(Event.UiCmdStartQ2)) selection = Selection.Q2; + if (e.Contains(Event.UiCmdStartQ3)) selection = Selection.Q3; + if (e.Contains(Event.UiCmdStartCycle)) selection = Selection.Cycle; + if (e.Contains(Event.UiCmdPurgeBegin)) { selection = Selection.PurgeBegin; goto fill_the_bench; } + if (e.Contains(Event.UiCmdPurgeEnd)) goto purge_end; + if (e.Contains(Event.UiCmdEmptyTank1)) goto empty_tank1; + if (e.Contains(Event.UiCmdEmptyTank2)) goto empty_tank2; + if (e.Contains(Event.UiCmdAcceptResults)) goto save_results; + } + while (selection == Selection.None); + + cycle_or_test: + + Bridge.Bench2UI(ButtonsEtc.StopBtnEn); /// Hide buttons + + if (selection == Selection.Cycle) + { + TimeEstimateTotal = 0; + foreach (var test in StateMachine.Tests) TimeEstimateTotal += (test.Repeats * (test.TstTime + 10.0f)); + + TimeEstimateBeginRpts = 0; + foreach (var test in StateMachine.Tests) + { + transitionStart = null; + transitionStop = null; + foreach (var transition in StateMachine.TransitionSequences) + { + if (transition.Name == test.TransitionStart) transitionStart = transition; + if (transition.Name == test.TransitionEnd) transitionStop = transition; + } + + TimeEstimateOneTest = test.TstTime + 10.0f; + //-------------------------------------------------------------- + ISequence testMethodSequence = TbfComponents.FindComponent(test.Method) as ISequence; + if (testMethodSequence != null) + { + //-------------------------------------------------------------- + var events = testMethodSequence.Execute(test); + + if (events.Contains(Event.Error)) goto error; + if (events.Contains(Event.UiCmdStop)) goto stop; + } + + TimeEstimateBeginRpts += (test.Repeats * TimeEstimateOneTest); + } + } + else + { + Entities.Test test = StateMachine.GetTest(selection); + + TimeEstimateTotal = test.Repeats * (test.TstTime + 10.0f); + TimeEstimateOneTest = test.TstTime + 10.0f; + TimeEstimateBeginRpts = 0; + + transitionStart = null; + transitionStop = null; + foreach (var transition in StateMachine.TransitionSequences) + { + if (transition.Name == test.TransitionStart) transitionStart = transition; + if (transition.Name == test.TransitionEnd) transitionStop = transition; + } + + ISequence testMethodSequence = TbfComponents.FindComponent(test.Method) as ISequence; + if (testMethodSequence != null) + { + //-------------------------------------------------------------- + var events = testMethodSequence.Execute(test); + + if (events.Contains(Event.Error)) goto error; + if (events.Contains(Event.UiCmdStop)) goto stop; + } + } + + if (ResultsAreComplete(StateMachine.Tests)) + { + Bridge.Bench2UI(ButtonsEtc.AcceptResultsBtnEn | ButtonsEtc.ResetResultsBtnEn); + } + else + { + Bridge.Bench2UI(ButtonsEtc.ResetResultsBtnEn); + } + + goto ready; + + empty_tank1: + + switch (EmptyTheTank(StateMachine.EmptyTankValve1, StateMachine.Balance1)) + { + case Event.Error: goto error; + case Event.UiCmdStop: goto stop; + default: goto ready; + } + + empty_tank2: + + switch (EmptyTheTank(StateMachine.EmptyTankValve2, StateMachine.Balance2)) + { + case Event.Error: goto error; + case Event.UiCmdStop: goto stop; + default: goto ready; + } + + empty_tank1_idle: + + switch (EmptyTheTank(StateMachine.EmptyTankValve1, StateMachine.Balance1)) + { + case Event.Error: goto error; + case Event.UiCmdStop: goto stop; + default: goto idle; + } + + empty_tank2_idle: + + switch (EmptyTheTank(StateMachine.EmptyTankValve2, StateMachine.Balance2)) + { + case Event.Error: goto error; + case Event.UiCmdStop: goto stop; + default: goto idle; + } + + purge_end: + save_results: + + Bridge.Bench2UI(ButtonsEtc.StopBtnEn); // Hide the most of buttons + + //-------------------------------- + string protocolTitle = string.Empty; + dataEntryCmpnt = TbfComponents.FindComponent(StateMachine.Procedure.DataEntry); + if ((dataEntryCmpnt as GenericDevices.IDataEntry) != null) + { + Bridge.OnActivity(this, "Enter the protokoll data"); + State.Create("MainSeq : Enter end data") + .AddOperation((dataEntryCmpnt as GenericDevices.IDataEntry).ShowFormAtCycleEndOp(WaterMeters)) + .AddOperation(checkUiOp) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.UiCmdStop)) goto stop; + } + while (!e.Contains(Event.Done)); + + if (dataEntryCmpnt is IHasProtocolTitle) + { + protocolTitle = (dataEntryCmpnt as IHasProtocolTitle).ProtocolTitle; + } + } + + //-------------------------------- + IResultsWriter writer = TbfComponents.FindComponent(StateMachine.Procedure.ResultsWriter) as IResultsWriter; + if (writer != null) + { + State.Create("MainSeq : Saving results") + .AddOperation(writer.WriteResultsOp(results)) + .AddOperation(checkUiOp) + .EnterState(); + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.Error)) goto error; + if (e.Contains(Event.UiCmdStop)) goto stop; + } + } + + //-------------------------------- + IResultsPrinter printer = TbfComponents.FindComponent(StateMachine.Procedure.ResultsPrinter) as IResultsPrinter; + if (printer != null) + { + State.Create("MainSeq : Printing results") + .AddOperation(printer.PrintResultsOp(BenchId, WaterMeters, results, protocolTitle)) + .AddOperation(checkUiOp) + .EnterState(); + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.Error)) goto error; + if (e.Contains(Event.UiCmdStop)) goto stop; + } + } + + /// Purge - End + switch (Transition(purgeEnd, Strings.Emptying_i_n)) + { + case Event.Error: goto error; + case Event.UiCmdStop: goto stop; + } + + benchFilled = false; + Bridge.Bench2UI(ButtonsEtc.ShowBenchEmpty); + + goto idle; + + camera_test: + + Bridge.OnActivity(this, "Camera test"); + //--------------------------------------------------------- + Bridge.Bench2UI(ButtonsEtc.StartTestBtnsEn | ButtonsEtc.StopBtnEn); + selection = Selection.None; + State.Create("MainSeq : 1 = Grab, 2 = Live, 3 = Focus, Stop = Quit camera test") + .AddOperation(checkUiOp) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.Error)) goto error; + if (e.Contains(Event.UiCmdStop)) + { + goto idle; + } + if (e.Contains(Event.UiCmdStartQ1)) goto grab; + if (e.Contains(Event.UiCmdStartQ2)) goto live; + if (e.Contains(Event.UiCmdStartQ3)) goto focus; + } + while (true); + + grab: + Bridge.Bench2UI(ButtonsEtc.StopBtnEn); + selection = Selection.None; + State.Create("MainSeq : Press 'Stop' to continue") + .AddOperation(checkUiOp) + .AddOperation((Cameras.Count > 0 && Cameras[0] != null && (Cameras[0].Cfg.DebugLevel != Entities.DebugMode.DetectedOff)) ? Cameras[0].GrabOp() : null) + .AddOperation((Cameras.Count > 1 && Cameras[1] != null && (Cameras[1].Cfg.DebugLevel != Entities.DebugMode.DetectedOff)) ? Cameras[1].GrabOp() : null) + .AddOperation((Cameras.Count > 2 && Cameras[2] != null && (Cameras[2].Cfg.DebugLevel != Entities.DebugMode.DetectedOff)) ? Cameras[2].GrabOp() : null) + .AddOperation((Cameras.Count > 3 && Cameras[3] != null && (Cameras[3].Cfg.DebugLevel != Entities.DebugMode.DetectedOff)) ? Cameras[3].GrabOp() : null) + .AddOperation((Cameras.Count > 4 && Cameras[4] != null && (Cameras[4].Cfg.DebugLevel != Entities.DebugMode.DetectedOff)) ? Cameras[4].GrabOp() : null) + .AddOperation((Cameras.Count > 5 && Cameras[5] != null && (Cameras[5].Cfg.DebugLevel != Entities.DebugMode.DetectedOff)) ? Cameras[5].GrabOp() : null) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.Error)) goto error; + if (e.Contains(Event.UiCmdStop)) goto camera_test; + } + while (true); + + live: + Bridge.Bench2UI(ButtonsEtc.StopBtnEn); + selection = Selection.None; + State.Create("MainSeq : Press 'Stop' to stop.") + .AddOperation(checkUiOp) + .AddOperation((Cameras.Count > 0 && Cameras[0] != null && (Cameras[0].Cfg.DebugLevel != Entities.DebugMode.DetectedOff)) ? Cameras[0].LiveOp() : null) + .AddOperation((Cameras.Count > 1 && Cameras[1] != null && (Cameras[1].Cfg.DebugLevel != Entities.DebugMode.DetectedOff)) ? Cameras[1].LiveOp() : null) + .AddOperation((Cameras.Count > 2 && Cameras[2] != null && (Cameras[2].Cfg.DebugLevel != Entities.DebugMode.DetectedOff)) ? Cameras[2].LiveOp() : null) + .AddOperation((Cameras.Count > 3 && Cameras[3] != null && (Cameras[3].Cfg.DebugLevel != Entities.DebugMode.DetectedOff)) ? Cameras[3].LiveOp() : null) + .AddOperation((Cameras.Count > 4 && Cameras[4] != null && (Cameras[4].Cfg.DebugLevel != Entities.DebugMode.DetectedOff)) ? Cameras[4].LiveOp() : null) + .AddOperation((Cameras.Count > 5 && Cameras[5] != null && (Cameras[5].Cfg.DebugLevel != Entities.DebugMode.DetectedOff)) ? Cameras[5].LiveOp() : null) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.Error)) goto error; + if (e.Contains(Event.UiCmdStop)) goto camera_test; + } + while (true); + + focus: + Bridge.Bench2UI(ButtonsEtc.StopBtnEn); + selection = Selection.None; + State.Create("MainSeq : Press 'Stop' to stop.") + .AddOperation(checkUiOp) + .AddOperation((Cameras.Count > 0 && Cameras[0] != null && (Cameras[0].Cfg.DebugLevel != Entities.DebugMode.DetectedOff)) ? Cameras[0].FocusOp() : null) + .AddOperation((Cameras.Count > 1 && Cameras[1] != null && (Cameras[1].Cfg.DebugLevel != Entities.DebugMode.DetectedOff)) ? Cameras[1].FocusOp() : null) + .AddOperation((Cameras.Count > 2 && Cameras[2] != null && (Cameras[2].Cfg.DebugLevel != Entities.DebugMode.DetectedOff)) ? Cameras[2].FocusOp() : null) + .AddOperation((Cameras.Count > 3 && Cameras[3] != null && (Cameras[3].Cfg.DebugLevel != Entities.DebugMode.DetectedOff)) ? Cameras[3].FocusOp() : null) + .AddOperation((Cameras.Count > 4 && Cameras[4] != null && (Cameras[4].Cfg.DebugLevel != Entities.DebugMode.DetectedOff)) ? Cameras[4].FocusOp() : null) + .AddOperation((Cameras.Count > 5 && Cameras[5] != null && (Cameras[5].Cfg.DebugLevel != Entities.DebugMode.DetectedOff)) ? Cameras[5].FocusOp() : null) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.Error)) goto error; + if (e.Contains(Event.UiCmdStop)) goto camera_test; + } + while (true); + + stop: + //-------------------------------- + State.Create("MainSeq : Turning IDLE -> Closing the valves") + .AddOperation(checkUiOp) + .AddOperation(cBrd.SetValvesOp(StateMachine.DefaultValvesOpen, StateMachine.DefaultValvesClose)) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.Error)) goto error; + } + while (!e.Contains(Event.ValvesSet)); + + goto idle; + + config_error: + //-------------------------------- + State.Create("MainSeq : Procedure configuration error") + .EnterState(); + while (true) StateMachine.WaitRunDevsRunOps(); + + error: + //-------------------------------- + State.Create("MainSeq : ERROR -> Closing the valves") + .AddOperation(checkUiOp) + .AddOperation(cBrd.SetValvesOp(StateMachine.DefaultValvesOpen, StateMachine.DefaultValvesClose)) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + } + while (!e.Contains(Event.ValvesSet) && !e.Contains(Event.Error)); + + //-------------------------------- + State.Create("MainSeq : ERROR state") + .EnterState(); + while (true) StateMachine.WaitRunDevsRunOps(); + } + } +} diff --git a/TestBenchFramework/BenchControl/Sequences/SequenceBase.cs b/TestBenchFramework/BenchControl/Sequences/SequenceBase.cs new file mode 100644 index 000000000..1921f9257 --- /dev/null +++ b/TestBenchFramework/BenchControl/Sequences/SequenceBase.cs @@ -0,0 +1,589 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using TBF.BenchControl.GenericDevices; +using TBF.UiBridge; +using TBF.Resources; +using TBF.BenchControl.Operations; +using log4net; + +namespace TBF.BenchControl.Sequences +{ + /// + /// Sequence is a group of states that can be dynamically added to + /// and removed from the state machine + /// + public class SequenceBase + { + private static readonly ILog log = LogManager.GetLogger(typeof(SequenceBase)); + + ///------------------------------------------------------------ + /// Global static variables set only once. + ///------------------------------------------------------------ + public static BenchId.Component BenchId; + public static IList RegulValves; /// list of regulation valves + public static IList WaterMeters; /// list of water meters + public static IList Cameras; /// list of cameras + + ///------------------------------------------------------------ + /// Procedure related (static) variables. + /// They are re-initialized when LoadProcedure() is called + ///------------------------------------------------------------ + protected static IList results; + public static float Qrise; + public static float Qfall; + + /// + /// Clear all test results. + /// + protected static void ResetResults() + { + results = new List(); + Qrise = 0; + Qfall = 0; + } + + /// + /// Add result to the list of results. + /// Overwrite (=delete) any previous result with the same name. + /// + /// New test result + protected static void AddOrOverwriteResult(Entities.TestResult newTestResult) + { + try + { + Entities.TestResult toDelete = + results.First(x => x.Name.Equals(newTestResult.Name)); + results.Remove(toDelete); + } + catch { }; + + results.Add(newTestResult); + } + + /// + /// Check whether the results are complete, whether there is a result for each test. + /// + /// All tests + /// true = The results are complete + protected static bool ResultsAreComplete(IList tests) + { + foreach (var test in tests) + { + if (!test.Method.Contains("RoiDetection")) + { + for (int r = 1; r <= test.Repeats; r++) + { + bool resultExists = false; + foreach (var tr in results) + { + if ((tr.DoNotEvaluate == false) && (tr.RepetitionNr == r) && (tr.TestName == test.Name)) + { + resultExists = true; + break; + } + } + if (!resultExists) return false; + } + } + } + return true; + } + + protected static float TimeEstimateTotal; /// Time estimate of the selected cycle or test + protected static float TimeEstimateBeginRpts; /// Time estimate at the beginning of all repetitions of the current tests + protected static float TimeEstimateOneTest; /// Time estimate of the current test (one repetition) + + static SequenceBase() + { + results = new List(); + } + + ///------------------------------------------------------------ + /// Test related (instance) variables. + /// Created when test sequence is open. + /// They persist during all repetitions of the same test + ///------------------------------------------------------------ + protected BenchControl.FeedingPath inPath; + protected BenchControl.BenchPath benchPath; + protected BenchControl.OutputPath outPath; + protected BenchControl.MetersPath sensPath; + + protected Entities.TransitionSequence transitionStart; + protected Entities.TransitionSequence transitionStop; + + #region Temperature_Pressure_Humidity + + protected FloatBox tempIn = new FloatBox(20.0f); + protected FloatBox tempOut = new FloatBox(20.0f); + protected FloatBox tempDiv = new FloatBox(20.0f); + protected FloatBox pressIn = new FloatBox(); + protected FloatBox pressOut = new FloatBox(); + protected FloatBox airTemperature = new FloatBox(20.0f); + protected FloatBox airPressure = new FloatBox(1.0f); + protected FloatBox airHumidity = new FloatBox(40.0f); + /// + protected float tempInSum; + protected float tempOutSum; + protected float tempDivSum; + protected float pressInSum; + protected float pressOutSum; + protected float ambientTempSum; + protected float ambientPressSum; + protected float ambientHumiSum; + /// + protected int averagedDataCount; + /// + protected void ResetAveragedData() + { + tempInSum = 0; + tempOutSum = 0; + tempDivSum = 0; + pressInSum = 0; + pressOutSum = 0; + ambientTempSum = 0; + ambientPressSum = 0; + ambientHumiSum = 0; + /// + averagedDataCount = 0; + } + /// + protected void AccumulateAveragedData() + { + tempInSum += tempIn.F; + tempOutSum += tempOut.F; + tempDivSum += tempDiv.F; + pressInSum += pressIn.F; + pressOutSum += pressOut.F; + ambientTempSum += airTemperature.F; + ambientPressSum += airPressure.F; + ambientHumiSum += airHumidity.F; + /// + averagedDataCount++; + } + /// + protected void UpdateTestRsltWithAveragedData(Entities.TestResult tstRslt) + { + if (averagedDataCount != 0) + { + float denominator = (float)averagedDataCount; + tstRslt.AmbientTempAve = ambientTempSum / denominator; + tstRslt.AmbientPressAve = ambientPressSum / denominator; + tstRslt.AmbientHumiAve = ambientHumiSum / denominator; + tstRslt.PressInAvrg = pressInSum / denominator; + tstRslt.PressOutAvrg = pressOutSum / denominator; + tstRslt.TempInAvrg = tempInSum / denominator; + tstRslt.TempOutAvrg = tempOutSum / denominator; + tstRslt.TempDivAvrg = tempDivSum / denominator; + } + } + + #endregion + + protected FloatBox measuredFlow = new FloatBox(); + + protected FloatBox mass = new FloatBox(); + protected FloatBox stableMass = new FloatBox(); + + protected bool ticTac = false; + protected int[] WMPulses = new int[Program.WMsCount]; + protected int[] WMRefPulses = new int[Program.WMsCount]; + + + protected IOperation readRegisters1; + protected IOperation readRegisters2; + protected IOperation queryEnd1; + protected IOperation queryEnd2; + protected IOperation checkUiOp; + + /// + /// Empties the tank: opens the emptying valve and measures the weight. + /// + /// Valve to empty the tank + /// Balance underneath the tank + /// Event.Done or Event.Error + protected Event EmptyTheTank(IValve EmptyTankValve, IBalance Balance) + { + //------------------------------------------------ + Bridge.OnActivity(this, TBF.Resources.Strings.Emptying_tank); + //------------------------------------------------ + + IList e; + Bridge.Bench2UI(ButtonsEtc.StopBtnEn); + + State.Create("SequenceBase : Opening the emptying valve") + .AddOperation(checkUiOp) + .AddOperation(StateMachine.ControlBoard.SetValvesOp(EmptyTankValve, null)) + .EnterState(); + do { e = StateMachine.WaitRunDevsRunOps(); } + while (!e.Contains(Event.ValvesSet)); + + do + { + //-------------------------------- + State.Create("SequenceBase : Emptying the tank") + .AddOperation(checkUiOp) + .AddOperation(Balance.ReadMassOp(ref mass)) + .AddOperation(StateMachine.ControlBoard.UpdateTankWeightOp()) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.Error)) return Event.Error; + if (e.Contains(Event.UiCmdStop)) goto quit_emptying; + if (e.Contains(Event.BalanceOverload)) { }; /// Tank should be emptying now + } + while (!e.Contains(Event.BalanceDone)); + } + while (mass.F > (Balance.Capacity / 100.0f + 20.0f)); + + quit_emptying: + //-------------------------------- + State.Create("SequenceBase : Closing the emptying valve") + .AddOperation(checkUiOp) + .AddOperation(Balance.ReadMassOp(ref mass)) + .AddOperation(StateMachine.ControlBoard.UpdateTankWeightOp()) + .AddOperation(StateMachine.ControlBoard.SetValvesOp(null, EmptyTankValve)) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.Error)) return Event.Error; + } + while (!e.Contains(Event.ValvesSet) || !e.Contains(Event.BalanceDone)); + + State.Create("SequenceBase : Updating the weight") + .AddOperation(checkUiOp) + .AddOperation(Balance.ReadMassOp(ref mass)) + .AddOperation(new Operations.TimerOp(5)) + .AddOperation(StateMachine.ControlBoard.UpdateTankWeightOp()) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.Error)) return Event.Error; + } + while (!e.Contains(Event.BalanceDone) || !e.Contains(Event.TimerExpired)); + + return Event.Done; + } + + /// + /// Executes steps of a transition sequence. + /// + /// TransitionSequence entity + /// Event.Done, Event.Error or Event.UiCmdStop + protected Event Transition(Entities.TransitionSequence transitionSequence, string message) + { + if (transitionSequence == null) return Event.None; + + IList transitionSteps = StateMachine.WtSession + .CreateQuery("FROM TransitionStep WHERE TransitionSequence = :tsId ORDER BY ItemNr") + .SetParameter("tsId", transitionSequence.Id) + .List(); + + IList e; + int stepsCount = transitionSteps.Count; + foreach (var step in transitionSteps) + { + //------------------------------------------------ + Bridge.OnActivity(this, string.Format(message, transitionSequence.Name, step.ItemNr + 1, stepsCount)); + //------------------------------------------------ + + /// Get new regulation valve positions and calculate the number of valves to change + float[] allRegvPositions = Utils.RegulValvesPositions(step); + /// + IList rvPosOperations = new List(); + for (int i = 0; i < allRegvPositions.Length; i++) + { + if (allRegvPositions[i] >= 0) /// Negative value means no position change + { + rvPosOperations.Add(RegulValves[i].SetRegulValvePositionOp( + Math.Max(0, allRegvPositions[i] - 0.05f), Math.Min(100.0f, allRegvPositions[i] + 0.05f), 60)); + } + } + int changingRVsCount = rvPosOperations.Count; /// Number of RV-s with changing position in this step + + /// Duration must be at least the number of regulation valves to change seconds + int duration = Math.Max(step.Duration, changingRVsCount); + + /// + /// The first state updates all (regular) valves and the 1st regulation valve to be changed + /// Max. one regulation valve may be controlled in each sub-step (in each state) + /// + State oneStep = State.Create(string.Format("SequenceBase.Transition() : Step {0}.1/{1}", step.ItemNr + 1, stepsCount)) + .AddOperation(checkUiOp) + .AddOperation(StateMachine.ControlBoard.SetValvesOp(Utils.ValvesOpen(step), Utils.ValvesClose(step))) + .AddOperation(new TimerOp((changingRVsCount <= 1) ? step.Duration : 1)); + + if (changingRVsCount > 0) + { + oneStep.AddOperation(rvPosOperations[0]); + } + oneStep.EnterState(); + + do { + e = StateMachine.WaitRunDevsRunOps(); + log.InfoFormat("RV1={0}% RV2={1}% RV3={2}% RV4={3}% RV5={4}%", StateMachine.ControlBoard.RValvePosition(1), + StateMachine.ControlBoard.RValvePosition(2), StateMachine.ControlBoard.RValvePosition(3), + StateMachine.ControlBoard.RValvePosition(4), StateMachine.ControlBoard.RValvePosition(5)); + if (e.Contains(Event.Error)) return Event.Error; + if (e.Contains(Event.RegulValveTimeOut)) return Event.Error; + if (e.Contains(Event.UiCmdStop)) return Event.UiCmdStop; + } + while (!e.Contains(Event.TimerExpired)); + + /// + /// Additional extra states the 2nd and all subsequent regulation valves to be changed + /// Max. one regulation valve may be controlled in each sub-step (in each state) + /// + for (int j = 1; j < changingRVsCount; j++) + { + /// The first state updating all plain valves and the 1st regulation valve + /// Max. one regulation valve may change in each step + State oneStepContinued = State.Create(string.Format("SequenceBase.Transition() : Step {0}.{2}/{1}", step.ItemNr + 1, stepsCount, j+1)) + .AddOperation(checkUiOp) + .AddOperation(new TimerOp((j == changingRVsCount - 1) ? (step.Duration - changingRVsCount + 1) : 1)); + for (int k = 0; k <= j; k++) { oneStepContinued.AddOperation(rvPosOperations[k]); } + oneStepContinued.EnterState(); + + do + { + e = StateMachine.WaitRunDevsRunOps(); + log.InfoFormat("RV1={0}% RV2={1}% RV3={2}% RV4={3}% RV5={4}%", StateMachine.ControlBoard.RValvePosition(1), + StateMachine.ControlBoard.RValvePosition(2), StateMachine.ControlBoard.RValvePosition(3), + StateMachine.ControlBoard.RValvePosition(4), StateMachine.ControlBoard.RValvePosition(5)); + if (e.Contains(Event.Error)) return Event.Error; + if (e.Contains(Event.RegulValveTimeOut)) return Event.Error; + if (e.Contains(Event.UiCmdStop)) return Event.UiCmdStop; + } + while (!e.Contains(Event.TimerExpired)); + } + } + + return Event.Done; + } + + + /// + /// Main loop where measurements are collected. + /// + /// false = a flow setting or a switching flow detection, true = measurement + /// Event.MeasurementCompleted, Event.UiCmdStop, Event.Error or Event.Done + protected Event ReadRegistersTempPressAmbient(IList measureOperations, bool realTest) + { + IList e; + ticTac = !ticTac; + State.Create("Read water meters") + .AddOperation(checkUiOp) + .AddOperations(measureOperations) + .AddOperation(ticTac ? readRegisters1 : readRegisters2) + .AddOperation(benchPath.TempIn.ReadTempOp(ref tempIn, Event.TempInDone)) + .AddOperation(benchPath.TempOut.ReadTempOp(ref tempOut, Event.TempOutDone)) + .AddOperation(outPath.TempDiv.ReadTempOp(ref tempDiv, Event.TempDivDone)) + .AddOperation(benchPath.PressIn.ReadPressureOp(ref pressIn, Event.PressureInDone)) + .AddOperation(benchPath.PressOut.ReadPressureOp(ref pressOut, Event.PressureOutDone)) + .AddOperation(realTest ? outPath.Balance.ReadMassOp(ref mass) : null) + .AddOperation(StateMachine.ControlBoard.UpdateTankWeightOp()) + .AddOperation((StateMachine.Ambient != null) + ? StateMachine.Ambient.ReadAmbientOp(airTemperature, airPressure, airHumidity) + : null) + .AddOperation(realTest ? (ticTac ? queryEnd1 : queryEnd2) : null) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.Error)) return Event.Error; + if (e.Contains(Event.UiCmdStop)) return Event.UiCmdStop; + if (e.Contains(Event.MeasurementCompleted)) return Event.MeasurementCompleted; + } + while ( !e.Contains(Event.TempInDone) || + !e.Contains(Event.TempOutDone) || + !e.Contains(Event.TempDivDone) || + !e.Contains(Event.PressureInDone) || + !e.Contains(Event.PressureOutDone) || + (realTest && !e.Contains(Event.BalanceDone)) || + !e.Contains(Event.ReadAllRegistersDone)); + + return Event.Done; + } + + /// + /// Prepares 'TestProgressEventArgs' object that update screens during the test + /// + /// Current 'Test' entity + /// Current 'TestResult' entity + /// Current number of reference pulses + /// Curent reference frequency in [Hz] + /// Current test time in [s] + /// Current progress 0 .. 1.0f + /// Data for the UI + protected TestProgressEventArgs GetTestProgressData(Entities.Test test, Entities.TestResult tstRslt, + int currentRefPulses, float time, float progress) + { + TestProgressEventArgs data = new TestProgressEventArgs(); + + data.TestResult = tstRslt; + + //float ltrPerRefPulse = outPath.FlowMeter.NominalFlow / 7200.0f; /// [ltr/pulse] + float refPulsesPerLtr = 7200.0f / outPath.FlowMeter.NominalFlow; /// [pulse/ltr] + + data.RefPulses = currentRefPulses; + data.Flow = measuredFlow.F; + data.Volume = Formulas.VolumeFromPulses(currentRefPulses, refPulsesPerLtr); + data.Time = time; + + data.Progress = progress; + float estCurrentTime = TimeEstimateBeginRpts + ((float)(tstRslt.RepetitionNr - 1) + progress) * TimeEstimateOneTest; + data.OveralProgress = estCurrentTime / TimeEstimateTotal; + + data.Tin = tempIn.F; + data.Tout = tempOut.F; + data.Tdiv = tempDiv.F; + data.Pin = pressIn.F; + data.Pout = pressOut.F; + data.AmbientTemp = airTemperature.F; + data.AmbientPressure = airPressure.F; + data.AmbientHumidity = airHumidity.F; + + for (int i = 0; i < Program.WMsCount; i++) + { + if (sensPath.RegisterReaders[i] != null) + { + data.WmPulses[i] = WMPulses[i]; + data.WmRefPulses[i] = WMRefPulses[i]; + data.WmVolume[i] = Formulas.VolumeFromPulses(WMPulses[i], sensPath.RegisterReaders[i].PulsesPerLtr); + data.WmErrPct[i] = Formulas.ErrorFromVolumes(data.WmVolume[i], data.Volume); + } + } + + return data; + } + + protected string TestResult2CsvLine(Entities.TestResult tstRslt, int currentRefPulses) + { + System.Text.StringBuilder sb = new System.Text.StringBuilder(); + + sb.Append(tstRslt.TimeStart); + sb.Append(";"); sb.Append(tstRslt.TestName); + sb.Append(";"); sb.Append(tstRslt.RepetitionNr); + sb.Append(";"); sb.Append("1"); + sb.Append(";"); sb.Append(tstRslt.Method); + sb.Append(";"); sb.Append(tstRslt.Volume); + sb.Append(";"); sb.Append(tstRslt.Qfrom); + sb.Append(";"); sb.Append(tstRslt.Qto); + sb.Append(";"); sb.Append(tstRslt.ErrLimLo); + sb.Append(";"); sb.Append(tstRslt.ErrLimHi); + sb.Append(";"); sb.Append("0"); + sb.Append(";"); sb.Append("60"); + sb.Append(";"); sb.Append("0"); + sb.Append(";"); sb.Append("0"); + sb.Append(";"); sb.Append("2"); + sb.Append(";"); sb.Append(" "); + sb.Append(";"); sb.Append(outPath.Balance.Cfg.Name); + sb.Append(";"); sb.Append(tstRslt.AmbientTempAve); + sb.Append(";"); sb.Append(tstRslt.AmbientPressAve); + sb.Append(";"); sb.Append(tstRslt.AmbientHumiAve); + sb.Append(";"); sb.Append(tstRslt.PressInAvrg); + sb.Append(";"); sb.Append(tstRslt.PressOutAvrg); + sb.Append(";"); sb.Append(tstRslt.PressInStart); + sb.Append(";"); sb.Append(tstRslt.PressOutStart); + sb.Append(";"); sb.Append(tstRslt.PressInEnd); + sb.Append(";"); sb.Append(tstRslt.PressOutEnd); + sb.Append(";"); sb.Append(tstRslt.TempInAvrg); + sb.Append(";"); sb.Append(tstRslt.TempOutAvrg); + sb.Append(";"); sb.Append(tstRslt.TempDivAvrg); + sb.Append(";"); sb.Append(tstRslt.TempInStart); + sb.Append(";"); sb.Append(tstRslt.TempOutStart); + sb.Append(";"); sb.Append(tstRslt.TempDivStart); + sb.Append(";"); sb.Append(tstRslt.TempInEnd); + sb.Append(";"); sb.Append(tstRslt.TempOutEnd); + sb.Append(";"); sb.Append(tstRslt.TempDivEnd); + sb.Append(";"); sb.Append(tstRslt.MassStartRaw); + sb.Append(";"); sb.Append(tstRslt.MassStart); + sb.Append(";"); sb.Append(tstRslt.MassEndRaw); + sb.Append(";"); sb.Append(tstRslt.MassEnd); + sb.Append(";"); sb.Append(tstRslt.MassDiff); + sb.Append(";"); sb.Append(tstRslt.DensityDiv); + sb.Append(";"); sb.Append(tstRslt.DensityIn); + sb.Append(";"); sb.Append(tstRslt.DensityOut); + sb.Append(";"); sb.Append(" "); /// d_air: Hustota vzduchu: Sheet1 - K9 + sb.Append(";"); sb.Append(" "); /// Buoyancy: Sheet1 - X9 + sb.Append(";"); sb.Append(" "); /// Exp T: teraz vynechat + sb.Append(";"); sb.Append(" "); /// Exp P: teraz vynechat + sb.Append(";"); sb.Append(" "); /// pipe expansion: teraz vynechat + sb.Append(";"); sb.Append(tstRslt.FlowMass); /// Qm [kg/h] + sb.Append(";"); sb.Append(tstRslt.FlowVolume); /// Qv [l/h] + sb.Append(";"); sb.Append(tstRslt.VolumeCTV); /// Vet . . . komercne prava hodnota - podla vahy + sb.Append(";"); sb.Append(tstRslt.VolumeMaster); /// Velm . . . . objem podla etalonu + sb.Append(";"); sb.Append(" "); /// Vmass . . . objem podla druheho etalonu / prietokomeru pred tratou (teraz vynechavame) + sb.Append(";"); sb.Append(tstRslt.Time); /// t + sb.Append(";"); sb.Append(tstRslt.ErrorMaster); /// Eelm . . . chyba etalonu voci komercne pravej hodnote + sb.Append(";"); sb.Append(" "); /// Emass . . . chyba druheho etalonu voci komercne pravej hodnote (teraz vynechavame) + sb.Append(";"); sb.Append(7200.0f / outPath.FlowMeter.NominalFlow); + /// Const.MID . konstanta eatlonu + sb.Append(";"); sb.Append(" "); /// Const.MA . . konstanta druheho etalonu + sb.Append(";"); sb.Append(tstRslt.TimeDivStart0); /// Time Div Start celkovy cas v [ms] + sb.Append(";"); sb.Append(tstRslt.TimeDivStart1); /// Time Div Start1 + sb.Append(";"); sb.Append(tstRslt.TimeDivStart2); /// Time Div Start2 + sb.Append(";"); sb.Append(tstRslt.TimeDivStart3); /// Time Div Start3 + sb.Append(";"); sb.Append(tstRslt.TimeDivStart4); /// Time Div Start4 + sb.Append(";"); sb.Append(tstRslt.TimeDivStart5); /// Time Div Start5 + sb.Append(";"); sb.Append(tstRslt.TimeDivEnd0); /// Time Div End celkovy cas v [ms] + sb.Append(";"); sb.Append(tstRslt.TimeDivEnd1); /// Time Div End1 + sb.Append(";"); sb.Append(tstRslt.TimeDivEnd2); /// Time Div End2 + sb.Append(";"); sb.Append(tstRslt.TimeDivEnd3); /// Time Div End3 + sb.Append(";"); sb.Append(tstRslt.TimeDivEnd4); /// Time Div End4 + sb.Append(";"); sb.Append(tstRslt.TimeDivEnd5); /// Time Div End5 + sb.Append(";"); sb.Append(currentRefPulses); /// Celkovy pocet et. pulzov skusky + sb.Append(";"); sb.Append(" "); /// - '' - pre druhy + for (int i = 0; i < tstRslt.Meters.Count; i++) + { + Entities.MeterTestResult mtrRslt = tstRslt.Meters[i]; + + sb.Append(";"); sb.Append(mtrRslt.SerialNr); /// WM Ser.No. + sb.Append(";"); sb.Append(mtrRslt.VolumeStart); /// WM Vinit - pri pevnom starte pociatocny stav natukany alebo cez inteligentny system + sb.Append(";"); sb.Append(mtrRslt.VolumeEnd); /// WM Vfin - pri pevnom starte konecny stav natukany alebo cez inteligentny system + sb.Append(";"); sb.Append(mtrRslt.VolumeMeter); /// WM Vmer - objem namerany vodomerom + sb.Append(";"); sb.Append(mtrRslt.VolumeRef); /// WM Vet - objem namerany stanicou + sb.Append(";"); sb.Append(mtrRslt.VolumeErrorPct); /// WM Emt - chyba vodomerom nameraneho objemu + sb.Append(";"); sb.Append(" "); /// WM U - neistota (zatial nechat prazdne) + sb.Append(";"); sb.Append(mtrRslt.PulsesMeter); /// WM Np met - pocet impulzov zo skusaneho meradla + sb.Append(";"); sb.Append(mtrRslt.PulsesMaster); /// WM Np elm - pocet impulzov etalonu pocas merania pre prislusny vodomer + sb.Append(";"); sb.Append(mtrRslt.Time); /// WM Tmet - cas merania (obmedzany pri synchro skuske) + bool ok = (mtrRslt.VolumeErrorPct >= tstRslt.ErrLimLo) && (mtrRslt.VolumeErrorPct <= tstRslt.ErrLimHi); + sb.Append(";"); sb.Append(ok ? "OK" : "NOK"); /// WM Vysledok (t.j. ci je v hraniciach chyb) - OK/NOK + sb.Append(";"); sb.Append(" "); /// WM AN value - hodnota z analogoveho prevodnika (teraz nic) + sb.Append(";"); sb.Append(" "); /// WM Vinit - pri datastreamovych hodnotach (alebo kamera) + sb.Append(";"); sb.Append(" "); /// WM Time init ??? + sb.Append(";"); sb.Append(" "); /// WM Vend ??? + sb.Append(";"); sb.Append(" "); /// WM Time end ??? + } + for (int i = 0; i < tstRslt.CombinedMeters.Count; i++) + { + Entities.MeterTestResult mtrRslt = tstRslt.CombinedMeters[i]; + + sb.Append(";"); sb.Append(mtrRslt.SerialNr); /// WM Ser.No. + sb.Append(";"); sb.Append(mtrRslt.VolumeStart); /// WM Vinit - pri pevnom starte pociatocny stav natukany alebo cez inteligentny system + sb.Append(";"); sb.Append(mtrRslt.VolumeEnd); /// WM Vfin - pri pevnom starte konecny stav natukany alebo cez inteligentny system + sb.Append(";"); sb.Append(mtrRslt.VolumeMeter); /// WM Vmer - objem namerany vodomerom + sb.Append(";"); sb.Append(mtrRslt.VolumeRef); /// WM Vet - objem namerany stanicou + sb.Append(";"); sb.Append(mtrRslt.VolumeErrorPct); /// WM Emt - chyba vodomerom nameraneho objemu + sb.Append(";"); sb.Append(" "); /// WM U - neistota (zatial nechat prazdne) + sb.Append(";"); sb.Append(mtrRslt.PulsesMeter); /// WM Np met - pocet impulzov zo skusaneho meradla + sb.Append(";"); sb.Append(mtrRslt.PulsesMaster); /// WM Np elm - pocet impulzov etalonu pocas merania pre prislusny vodomer + sb.Append(";"); sb.Append(mtrRslt.Time); /// WM Tmet - cas merania (obmedzany pri synchro skuske) + bool ok = (mtrRslt.VolumeErrorPct >= tstRslt.ErrLimLo) && (mtrRslt.VolumeErrorPct <= tstRslt.ErrLimHi); + sb.Append(";"); sb.Append(ok ? "OK" : "NOK"); /// WM Vysledok (t.j. ci je v hraniciach chyb) - OK/NOK + sb.Append(";"); sb.Append(" "); /// WM AN value - hodnota z analogoveho prevodnika (teraz nic) + sb.Append(";"); sb.Append(" "); /// WM Vinit - pri datastreamovych hodnotach (alebo kamera) + sb.Append(";"); sb.Append(" "); /// WM Time init ??? + sb.Append(";"); sb.Append(" "); /// WM Vend ??? + sb.Append(";"); sb.Append(" "); /// WM Time end ??? + } + sb.Append(";"); + + return sb.ToString(); + } + } +} diff --git a/TestBenchFramework/BenchControl/State.cs b/TestBenchFramework/BenchControl/State.cs new file mode 100644 index 000000000..9966ea70a --- /dev/null +++ b/TestBenchFramework/BenchControl/State.cs @@ -0,0 +1,199 @@ +using System; +using System.Collections.Generic; +using System.Text; +using log4net; + +namespace TBF.BenchControl +{ + public class State + { + /// + /// DEBUG: all state changes and all operations + /// INFO: all state changes and operations that returned evnt != Event.None + /// WARN: only state changes + /// + private static readonly ILog log = LogManager.GetLogger(typeof(State)); + public override string ToString() { return Name + (Label==null ? "" : ", label=" + Label); } + + /// Current state (static) + public static State CurrentState + { + get { return currentState; } + } + static State currentState; + + /// State with an empty list of operations + /// Useful when entering the first state and leaving the last one + public static State Empty + { + get { return new State("empty"); } + } + + /// + /// Static constructor that initializes CurrentState + /// + static State() + { + currentState = State.Empty; + } + + /// + /// Instance fields set or initialized by the constructor + /// + public readonly IList Operations; + public readonly IList Transitions; + public readonly string Name; + public readonly string Label; + + + /// + /// Constructor with a label + /// + public State(string name, string label) + { + this.Name = name; + this.Label = label; + Operations = new List(); + Transitions = new List(); + log.Debug(this.ToString()); + } + + /// + /// Default constructor + /// + public State(string name) + : this(name, null) + { + } + + + /// + /// Create a new state without a label + /// + public static State Create(string name) + { + return new State(name); + } + + /// + /// Create a new state with a label + /// + public static State Create(string name, string label) + { + return new State(name, label); + } + + /// + /// Add an operation to this state + /// + /// operation + public State AddOperation(IOperation operation) + { + if (operation != null) Operations.Add(operation); + return this; + } + + /// + /// Add a list of operations to this state + /// + /// operation + public State AddOperations(IList operations) + { + if (operations != null) + { + foreach (var op in operations) { if (op != null) Operations.Add(op); } + } + return this; + } + + /// + /// Add a state transition to the state + /// + /// transition + public State AddTransition(Transition transition) + { + if (transition != null) Transitions.Add(transition); + return this; + } + + /// + /// Enter a new state + /// + public State EnterState() + { + ChangeState(State.currentState, this); + State.currentState = this; + UiBridge.Bridge.OnStateChanged(this, State.currentState.ToString()); + return this; + } + + // ----------------------------------- Run time ----------------------------------------- + + /// + /// Execute Run() methods of all operations of the current state. + /// + /// List of Event-s returned from the state operations + public static IList RunOperations() + { + IList events = new List(); + + foreach (IOperation operation in currentState.Operations) + { + Event evnt = operation.Run(); + if (evnt != Event.None) + { + log.InfoFormat("Operation {0} returned {1}", operation, evnt); + events.Add(evnt); + } + else + { + log.DebugFormat("Operation {0} returned {1}", operation, evnt); + } + } + + return events; + } + + /// + /// Execute Stop() methods of all operations of the current state. + /// + public static void StopOperations() + { + foreach (IOperation operation in currentState.Operations) + { + log.DebugFormat("stopping {0}", operation); + operation.Stop(); + } + } + + /// + /// Run Stop() and Start() methods of operations when changing the state. + /// + /// Stopping state + /// Starting state + static void ChangeState(State previousState, State newState) + { + /// Stop() the previous state operations, which are not in the next state + foreach (IOperation operation in previousState.Operations) + { + if (!newState.Operations.Contains(operation)) + { + log.DebugFormat("stopping {0}", operation); + operation.Stop(); + } + } + + log.WarnFormat("ChangeState( {0} -> {1} )", previousState.ToString(), newState.ToString()); + + /// Start() the operations that are in the current (new) state, but aren't in the previous state. + foreach (IOperation operation in newState.Operations) + { + if (!previousState.Operations.Contains(operation)) + { + log.DebugFormat("starting {0}", operation); + operation.Start(); + } + } + } + } +} diff --git a/TestBenchFramework/BenchControl/StateMachine.cs b/TestBenchFramework/BenchControl/StateMachine.cs new file mode 100644 index 000000000..8da8c28fb --- /dev/null +++ b/TestBenchFramework/BenchControl/StateMachine.cs @@ -0,0 +1,513 @@ +using System; +using System.Text; +using System.Threading; +using System.Diagnostics; +using System.Collections.Generic; +using System.Windows.Forms; +using log4net; +using NHibernate; + +using TBF.BenchControl.Generic; +using TBF.BenchControl.GenericDevices; +using TBF.BenchControl.Sequences; + +namespace TBF.BenchControl +{ + public class QuitStateMachineException : Exception + { + } + + /// + /// This class controls real test bench behavior. + /// It is based on a state machine + /// + public static class StateMachine + { + private static readonly ILog log = LogManager.GetLogger(typeof(StateMachine)); + private static readonly ILog wlog = LogManager.GetLogger(typeof(StateMachine)); + + /// Private devices and components + static IList components; /// list of all components + static IList devices; /// list of devices + /// + /// Bench paths + static IList feedingPaths; + static IList benchPaths; + static IList outputPaths; + static IList metersPaths; + public static IList TransitionSequences; + + /// Public components + public static Elde.ControlBoardDev ControlBoard; + public static GenericDevices.IAmbient Ambient; + public static GenericDevices.IBalance Balance1; + public static GenericDevices.IBalance Balance2; + public static GenericDevices.IValve EmptyTankValve1; + public static GenericDevices.IValve EmptyTankValve2; + public static IList MasterValves; /// list of directly controlled valves + public static IList CoupledValves; /// list of coupled valves + + + /// Time and synchronization + public const int Period = 1; /// State machine period in sec. + static DateTime startDateTime; /// DateTime of time instance when the state machine worker thread starts + static int currentTimeSec; /// Time from the start of the state machine in seconds + static bool quitStateMachine; /// flag to stop the worker thread + + /// true when the state machine is running + static bool stateMachineRunning; + public static bool Running { get { return stateMachineRunning; } } + + /// Worker thread and database session + static Thread workerThread; + public static ISession WtSession; + + static IList states; /// list of states + + + public static IList DefaultValvesOpen + { + get + { + return GenericDevices.ValveBase.Merge( + Utils.ValvesOpen((feedingPaths != null && feedingPaths.Count > 0) ? feedingPaths[0] : null), + Utils.ValvesOpen((benchPaths != null && benchPaths.Count > 0) ? benchPaths[0] : null), + Utils.ValvesOpen((outputPaths != null && outputPaths.Count > 0) ? outputPaths[0] : null) + ); + } + } + + public static IList DefaultValvesClose + { + get + { + return GenericDevices.ValveBase.Merge( + Utils.ValvesClose((feedingPaths != null && feedingPaths.Count > 0) ? feedingPaths[0] : null), + Utils.ValvesClose((benchPaths != null && benchPaths.Count > 0) ? benchPaths[0] : null), + Utils.ValvesClose((outputPaths != null && outputPaths.Count > 0) ? outputPaths[0] : null) + ); + } + } + + /// + /// Loaded by LoadProcedure() or IOperation LoadProcedureOp(...) + /// + public static Entities.Procedure Procedure; /// Procedure + public static IList Tests; /// Tests + + + /// Hardware devices connected to the PC controlling the bench. + public static IList Components { get { return components; } } + public static IList Devices { get { return devices; } } + + /// + /// DateTime of time instance when the state machine worker thread starts + /// + public static DateTime StartDateTime { get { return startDateTime; } } + + /// + /// Current state name + /// + public static int CurrentTime { get { return currentTimeSec; } } + + /// + /// Constructor + /// + static StateMachine() + { + devices = new List(); + states = new List(); + + currentTimeSec = 0; + quitStateMachine = false; + } + + /// + /// Add a device to the state machine. + /// + /// Device + public static void AddDevice(IDevice device) + { + if (device != null && !devices.Contains(device)) devices.Add(device); + } + + /// + /// Add a state to the state machine. + /// In this way a sequence can be created programtically. + /// + /// State + public static void AddState(State state) + { + if (state != null && !states.Contains(state)) states.Add(state); + } + + /// + /// Remove the state from the state machine. + /// + /// State + public static void RemoveState(State state) + { + if (state != null && state != State.CurrentState && states.Contains(state)) states.Remove(state); + } + + /// + /// Get a state from a label + /// + /// + /// The matching state or null + static State GetStateFromLabel(string label) + { + if (label == null) return null; + + foreach (State state in states) + { + if (state.Label != null && state.Label.Equals(label)) return state; + } + return null; + } + + /// + /// Start the state machine in the state 'label' in a desired mode of operation. + /// This method is called in the UI thread and creates a new state machine thread. + /// This method call should be embedded in: try { StateMachine.Start(...); } catch { } + /// to handle configuration problems. Calls CreateDevices(mode) and CreateStates(). + /// + /// Mode of operation + /// A copy of bench data used by the state machine + /// Identifies the initial state +#if DN100 + public static void InitializeBoardEtc(ControlCom2VB.ControlCom2panel ctrlBrdComponent) +#elif MUNICH + public static void InitializeBoardEtc(ControlComponent3Munich.UserControl1 ctrlBrdComponent) +#elif FUZHOU150 + public static void InitializeBoardEtc(ControlComponent3Munich.UserControl1 ctrlBrdComponent) +#endif + { + /// Load the list of components (entities) from the database. + /// Then create the components (derived from IComponent). + components = BenchControl.TbfComponents.LoadComponentsFromDB(FluentCommon.CreateSession(Database.Bench)); + MasterValves = GenericDevices.ValveBase.MasterValves(components); + CoupledValves = GenericDevices.ValveBase.CoupledValves(components); + + /// Find all balances (to initialize tank capacities in the control board) + /// Find the control board + IList balances = new List(); + SequenceBase.RegulValves = new List(); + SequenceBase.WaterMeters = new List(); + SequenceBase.Cameras = new List(); + foreach (var cmpnt in components) + { + if (cmpnt is Elde.ControlBoardDev) ControlBoard = cmpnt as Elde.ControlBoardDev; + if (cmpnt is BenchId.Component) SequenceBase.BenchId = cmpnt as BenchId.Component; + if (cmpnt is IRegulValve) SequenceBase.RegulValves.Add(cmpnt as IRegulValve); + if (cmpnt is IWaterMeter) SequenceBase.WaterMeters.Add(cmpnt as IWaterMeter); + if (cmpnt is ICamera) SequenceBase.Cameras.Add(cmpnt as ICamera); + if (cmpnt is GenericDevices.IAmbient) Ambient = cmpnt as GenericDevices.IAmbient; + if (cmpnt is IBalance) + { + IBalance balance = cmpnt as IBalance; + balances.Add(balance); + + if (balance.BalanceNr == 0) Balance1 = balance; + else if (balance.BalanceNr == 1) Balance2 = balance; + } + } + + /// Create an array with tank capacities + float[] tankCapacities = new float[balances.Count]; + for (int i = 0; i < tankCapacities.Length; i++) tankCapacities[i] = balances[i].Capacity; + + /// Pre-initialize the control board (= buffer the arguments ctrlBrdComponent, tankCapacities) + ControlBoard.InitializeComponent(ctrlBrdComponent, tankCapacities); + } + + public static void InitializeDevices() + { + /// Add all devices to the state machine and initialize them + foreach (var cmpnt in components) + { + if (cmpnt is IDevice) + { + AddDevice(cmpnt as IDevice); + (cmpnt as IDevice).Initialize(); + } + } + + /// Propagate debug levels from parents to children when necessary + foreach (var cmpnt in components) + { + if (cmpnt.Cfg is IChildComponentCfg && !string.IsNullOrEmpty(cmpnt.Cfg.ParentName) && + (cmpnt.Cfg.DebugLevel == Entities.DebugMode.Inherit || cmpnt.Cfg.DebugLevel == Entities.DebugMode.AutoDetect)) + { + foreach (var par in components) + { + if (par.Cfg.Name.Equals(cmpnt.Cfg.ParentName)) { cmpnt.Cfg.DebugLevel = par.Cfg.DebugLevel; break; } + } + } + } + } + + /// + /// Start the state machine + /// + public static void Start() + { + if (stateMachineRunning) return; + + workerThread = new Thread(Worker); + workerThread.CurrentCulture = Thread.CurrentThread.CurrentCulture; + workerThread.CurrentUICulture = Thread.CurrentThread.CurrentUICulture; + workerThread.Start(); + stateMachineRunning = true; + } + + public static void LoadProcedure(bool loadPathsOnly) + { + ISession session = FluentCommon.CreateSession(Database.Procedures); + WtSession = session; + + feedingPaths = session.CreateQuery("FROM FeedingPath ORDER BY ItemNr").List(); + benchPaths = session.CreateQuery("FROM BenchPath ORDER BY ItemNr").List(); + outputPaths = session.CreateQuery("FROM OutputPath ORDER BY ItemNr").List(); + metersPaths = session.CreateQuery("FROM MetersPath ORDER BY ItemNr").List(); + TransitionSequences = session.CreateQuery("FROM TransitionSequence ORDER BY ItemNr").List(); + + // Automatic detection of empty tank valves + foreach (var opath in outputPaths) + { + if (opath.Balance == Balance1.Cfg.Name) + { + EmptyTankValve1 = TbfComponents.FindComponent(opath.EmptyTankValve) as IValve; + break; + } + } + foreach (var opath in outputPaths) + { + if (opath.Balance == Balance2.Cfg.Name) + { + EmptyTankValve2 = TbfComponents.FindComponent(opath.EmptyTankValve) as IValve; + break; + } + } + + if (loadPathsOnly) return; + + IList selectedProcs = session + .CreateQuery("FROM Procedure WHERE Name = :name") + .SetParameter("name", TBF.UiBridge.Bridge.SelectedProcedureName) + .List(); + + if (selectedProcs.Count != 1) return; + + Procedure = selectedProcs[0]; + Tests = selectedProcs[0].Tests; + } + + public static void LoadProcedureParams(Entities.Procedure procedure) + { + foreach (var cmpnt in components) + { + if (cmpnt is ComponentBase) (cmpnt as ComponentBase).GetProcedureParams(procedure); + } + } + + public static void LoadTestParams(Entities.Test test) + { + foreach (var cmpnt in components) + { + if (cmpnt is ComponentBase) (cmpnt as ComponentBase).GetTestParams(test); + } + } + + /// + /// Processes the selection done by the bench control panel in the main sequence. + /// + /// Selection.Q1, .Q2, .Q3 or .Test + /// The selected test or null + public static Entities.Test GetTest(Sequences.MainSeq.Selection selection) + { + if ((selection == Sequences.MainSeq.Selection.Q1) && (Tests.Count >= 1)) + { + return Tests[0]; + } + else if ((selection == Sequences.MainSeq.Selection.Q2) && (Tests.Count >= 2)) + { + return Tests[1]; + } + else if ((selection == Sequences.MainSeq.Selection.Q3) && (Tests.Count >= 3)) + { + return Tests[2]; + } + else if (selection == Sequences.MainSeq.Selection.Test) + { + foreach (var test in Tests) if (test.Name.Contains(TBF.UiBridge.Bridge.SelectedTestName)) return test; + } + return null; + } + + /// + /// Called from the sequence to update paths based on the selected test + /// + /// Selected test + /// + /// + /// + /// + /// true when all four paths are defined (non null) + public static bool GetPaths(Entities.Test test, + out FeedingPath pfeed, out BenchPath pben, out OutputPath pout, out MetersPath pmtrs, + out Entities.TransitionSequence transitionStart, out Entities.TransitionSequence transitionEnd) + { + pfeed = null; + pben = null; + pout = null; + pmtrs = null; + transitionStart = null; + transitionEnd = null; + + foreach (var path in feedingPaths) + { + if (test.FeedingPath == path.Name) { pfeed = new FeedingPath(path, components); break; } + } + + foreach (var path in benchPaths) + { + if (test.BenchPath == path.Name) { pben = new BenchPath(path, components); break; } + } + + foreach (var path in outputPaths) + { + if (test.OutputPath == path.Name) { pout = new OutputPath(path, components); break; } + } + + foreach (var path in metersPaths) + { + if (test.MetersPath == path.Name) { pmtrs = new MetersPath(path, components); break; } + } + if (pmtrs != null) + { + for (int i = 0; i < Program.WMsCount; i++) + { + if ((pmtrs.RegisterReaders[i] != null) && + (pmtrs.RegisterReaders[i].Cfg.DebugLevel == Entities.DebugMode.DetectedOff)) + { + pmtrs.RegisterReaders[i] = null; + } + } + } + + foreach (var transition in TransitionSequences) + { + if (transition.Name == test.TransitionStart) transitionStart = transition; + if (transition.Name == test.TransitionEnd) transitionEnd = transition; + } + + return (pfeed != null) && (pben != null) && (pout != null) && (pmtrs != null); + } + + /// + /// Stops the state machine (and the worker thread) + /// + public static void Stop() + { + if (stateMachineRunning) quitStateMachine = true; + } + + + /* + * This is and example sequence of RunDeviceBefore() / RunOperations() / RunDeviceAfter() calls + * as they are executed during normal run from the progran start to the end. + * + foreach (var device in devices) device.RunDeviceBefore(); . . . . . . in StateMachine.Worker() + State.Create(...).AddOperation(...).AddOperation(...).EnterState() . . in the sequence in Execute(...) + + foreach (var device in devices) device.RunDeviceAfter(); . . . . . . . in WaitRunDevsRunOps() + WaitNextTick() (may throw QuitStateMachineException) . . . . . . . . in WaitRunDevsRunOps() + foreach (var device in devices) device.RunDeviceBefore(); . . . . . . in WaitRunDevsRunOps() + IList events = State.RunOperations(); . . . . . . . . . . . . . in WaitRunDevsRunOps() + + foreach (var device in devices) device.RunDeviceAfter(); . . . . . . . in WaitRunDevsRunOps() + WaitNextTick() (may throw QuitStateMachineException) . . . . . . . . in WaitRunDevsRunOps() + foreach (var device in devices) device.RunDeviceBefore(); . . . . . . in WaitRunDevsRunOps() + IList events = State.RunOperations(); . . . . . . . . . . . . . in WaitRunDevsRunOps() + + State.Create(...).AddOperation(...).AddOperation(...).EnterState() . . in the sequence in Execute(...) + + foreach (var device in devices) device.RunDeviceAfter(); . . . . . . . in WaitRunDevsRunOps() + WaitNextTick() (may throw QuitStateMachineException) . . . . . . . . in WaitRunDevsRunOps() + foreach (var device in devices) device.RunDeviceBefore(); . . . . . . in WaitRunDevsRunOps() + IList events = State.RunOperations(); . . . . . . . . . . . . . in WaitRunDevsRunOps() + + foreach (var device in devices) device.RunDeviceAfter(); . . . . . . . in WaitRunDevsRunOps() + WaitNextTick() (assume QuitStateMachineException thrown) . . . . . . in WaitRunDevsRunOps() + State.StopOperations(); . . . . . . . . . . . . . . . . . . . . . . . in StateMachine.Worker() catch() + foreach (var device in devices) device.StopDevice(); . . . . . . . . . in StateMachine.Worker() catch() + */ + + /// + /// Worker thread: calls Start(), Run() and Stop() methods of operations. + /// It uses 'currentState', 'nextState' and 'quitStateMachine' static fields. + /// + static void Worker() + { + startDateTime = DateTime.Now; + wlog.InfoFormat(" currentTime = {0}s startDateTime = {1}", currentTimeSec.ToString(), startDateTime.ToString()); + + /// Run all devices for the first time + foreach (var device in devices) device.RunDeviceBefore(); + + try + { + (new Sequences.MainSeq()).Execute(null); + } + catch (QuitStateMachineException) + { + State.StopOperations(); + foreach (var device in devices) device.StopDevice(); + + quitStateMachine = false; + stateMachineRunning = false; + } + } + + + /// + /// Do stuff that is repeated in the state execution loops most often + /// + /// List of Event-s returned from the state operations + public static IList WaitRunDevsRunOps() + { + foreach (var device in devices) device.RunDeviceAfter(); + WaitNextTick(); + foreach (var device in devices) device.RunDeviceBefore(); + IList events = State.RunOperations(); + return events; + /// This is followed by a state change in the sequence + } + + + /// + /// Wait time period - synchronize + /// + /// true when interrupted by 'quitStateMachine', otherwise false + public static void WaitNextTick() + { + currentTimeSec += Period; + + TimeSpan timeFromStart = TimeSpan.FromSeconds(currentTimeSec); + DateTime nextLoopDateTime = startDateTime + timeFromStart; + while (DateTime.Now < nextLoopDateTime) + { + if (quitStateMachine) + { + quitStateMachine = false; + wlog.Info("quitStateMachine == true ... going to stop the StateMachine()"); + throw new QuitStateMachineException(); + } + Thread.Sleep(100); + } + + wlog.DebugFormat(" currentTime = {0}s", currentTimeSec); + } + } +} diff --git a/TestBenchFramework/BenchControl/TbfComponents.cs b/TestBenchFramework/BenchControl/TbfComponents.cs new file mode 100644 index 000000000..f68a0484b --- /dev/null +++ b/TestBenchFramework/BenchControl/TbfComponents.cs @@ -0,0 +1,150 @@ +using System.Collections.Generic; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl +{ + public static class TbfComponents + { + public static IList Factories; + + static TbfComponents() + { + Factories = new List(); + + Factories.Add(new BenchId.ComponentFactory()); + Factories.Add(new Cameras.IdcCamera.IdcCameraFactory()); + Factories.Add(new Cameras.CameraRoi.CameraRoiFactory()); + Factories.Add(new DataEntry.Munich.EntryFormFactory()); + Factories.Add(new Elde.ControlBoardFactory()); + Factories.Add(new Elde.Diverter.DiverterFactory()); + Factories.Add(new Elde.FlowMeter.FlowMeterFactory()); + Factories.Add(new Elde.PressureMeter.PressureMeterFactory()); + Factories.Add(new Elde.Pump.PumpFactory()); + Factories.Add(new Elde.PumpWithFM.PumpFactory()); + Factories.Add(new Elde.RegisterReader.RegisterReaderFactory()); + Factories.Add(new Elde.RegulValve.RegulValveFactory()); + Factories.Add(new Elde.TempMeter.TempMeterFactory()); + Factories.Add(new Elde.Valve.ValveFactory()); + Factories.Add(new Greco.AmbientFactory()); + Factories.Add(new MettlerToledo.BalanceFactory()); + Factories.Add(new MettlerToledo.BalanceNewFactory()); + Factories.Add(new ResultsPrinters.Basic.PrinterFactory()); + Factories.Add(new ResultsPrinters.Munich.PrinterFactory()); + Factories.Add(new ResultsWriters.Basic.WriterFactory()); + Factories.Add(new TestMethods.CameraRoiDetection.RoiDetectionFactory()); + Factories.Add(new TestMethods.CombinedMeters.TestMethodFactory()); + Factories.Add(new TestMethods.CombinedWithDetection.TestMethodFactory()); + Factories.Add(new TestMethods.FlyingStartCollectionMethod.TestMethodFactory()); + Factories.Add(new WaterMeter.WaterMeterFactory()); + } + + /// + /// Get a component factory given the component name + /// + /// Component class name + /// Component factory instance + public static IComponentFactory CmpntFactoryFromClassName(string className) + { + foreach (var factory in Factories) + { + if (factory.ClassName.Equals(className)) return factory; + } + return null; + } + + public static IComponentCfg CmpntCfgFromCmpntEntity(Entities.Component entity) + { + return CmpntFactoryFromClassName(entity.ClassName).CmpntCfgFromCmpntEntity(entity); + } + + /// + /// Load component entities from the database and convert them to TBF components + /// derived from IComponent with mutual references. + /// + /// NHibernate DB session + /// A list of TBF Components + public static IList LoadComponentsFromDB(NHibernate.ISession session) + { + foreach (var factory in Factories) factory.ResetStaticProperties(); + + /// Load the list of components from the database + IList cmptnEntities = session + .CreateQuery("FROM Component ORDER BY ItemNr") + .List(); + + /// Convert database entities to TBF components + IList components = new List(); + foreach (var entity in cmptnEntities) + { + IComponent cmpnt = BenchControl.TbfComponents + .CmpntFactoryFromClassName(entity.ClassName) + .ComponentFromCmpntCfg(BenchControl.TbfComponents.CmpntCfgFromCmpntEntity(entity), components); + + /// Inherit DebugMode from the parent (if any) + if (cmpnt.Cfg.DebugLevel != Entities.DebugMode.Inherit && cmpnt.Cfg is IChildComponentCfg && + !string.IsNullOrEmpty(cmpnt.Cfg.ParentName)) + { + foreach (var par in components) + { + if (par.Cfg.Name.Equals(cmpnt.Cfg.ParentName)) { cmpnt.Cfg.DebugLevel = par.Cfg.DebugLevel; break; } + } + } + + if (cmpnt.Cfg.DebugLevel != Entities.DebugMode.Off) components.Add(cmpnt); + } + + return components; + } + + /// + /// Get a reference to a component with a given name from a list of components. + /// + /// Component name + /// A list of components + /// Matching component or null + public static IComponent FindComponent(string name, IList components) + { + if (name == null) return null; + foreach (var cmpnt in components) if (cmpnt.Cfg.Name.Equals(name)) return cmpnt; + return null; + } + public static IComponent FindComponent(string name) + { + return FindComponent(name, StateMachine.Components); + } + + + public static IParamsProvider GetTestParams(IComponent cmpnt, Entities.Test test) + { + if (cmpnt == null || cmpnt.Cfg == null || !cmpnt.Cfg.Factory.HasTestParams) return null; + + /// Search for an existing matching entity + foreach (var tstPrms in test.MoreParams) + { + if (tstPrms.CmpntName.Equals(cmpnt.Cfg.Name)) return cmpnt.Cfg.Factory.GetTestParams(tstPrms); + } + + /// Create a new entity and add it to the list test.MoreParams + Entities.ComponentTest testParams = new Entities.ComponentTest { CmpntName = cmpnt.Cfg.Name, Test = test }; + test.MoreParams.Add(testParams); + return cmpnt.Cfg.Factory.GetTestParams(testParams); + } + + + public static IParamsProvider GetProcedureParams(IComponent cmpnt, Entities.Procedure procedure) + { + if (cmpnt == null || cmpnt.Cfg == null || !cmpnt.Cfg.Factory.HasProcedureParams) return null; + + /// Search for an existing matching entity + foreach (var procPrms in procedure.MoreParams) + { + if (procPrms.CmpntName.Equals(cmpnt.Cfg.Name)) return cmpnt.Cfg.Factory.GetProcedureParams(procPrms); + } + + /// Create a new entity and add it to the list procedure.MoreParams + Entities.ComponentProcedure procParams = new Entities.ComponentProcedure { CmpntName = cmpnt.Cfg.Name, Procedure = procedure }; + procedure.MoreParams.Add(procParams); + return cmpnt.Cfg.Factory.GetProcedureParams(procParams); + } + } +} diff --git a/TestBenchFramework/BenchControl/TestBenchSim.cs b/TestBenchFramework/BenchControl/TestBenchSim.cs new file mode 100644 index 000000000..779194aea --- /dev/null +++ b/TestBenchFramework/BenchControl/TestBenchSim.cs @@ -0,0 +1,377 @@ +using System; +using log4net; + +namespace TBF.BenchControl +{ + /// + /// Test bench model inherited by all classes for the simulation of devices. + /// Define DN100, MUNICH or nothing. + /// + public class TestBenchSim + { + private static readonly ILog log = LogManager.GetLogger(typeof(TestBenchSim)); + + /// + /// Incremented in RunDevice() depending on diverters and valves + /// + public static float Mass1sim; /// Volume in [ltr] or mass in [kg] in the tank1 on the balance1, filled by the diverter1 + public static float Mass2sim; /// Volume in [ltr] or mass in [kg] in the tank2 on the balance2, filled by the diverter2 + + /// + /// Set by regulation valves + /// + public static float Flow1sim; /// flow in [m3/h] through RV1 + public static float Flow2sim; /// flow in [m3/h] through RV2 + public static float Flow3sim; /// flow in [m3/h] through RV3 + public static float Flow4sim; /// flow in [m3/h] through RV4 + public static float Flow5sim; /// flow in [m3/h] through RV5 + + /// + /// Valves and diverters + /// + public static ulong RouteSim; + public static bool Div1sim; + public static bool Div2sim; + public static bool Div3sim; + + int regulValveNo; /// 0=undefined, 1..5 + int refFlowmtrNo; /// 0=undefined, 1..4 + + public void Initialize() + { + Mass1sim = 0.0f; /// Initialize tanks + Mass2sim = 0.0f; + Flow1sim = 0.0f; /// Initialize regulation valves + Flow2sim = 0.0f; + Flow3sim = 0.0f; + Flow4sim = 0.0f; + Flow5sim = 0.0f; + RouteSim = 0; /// Initialize other valves + Div1sim = false; + Div2sim = false; + Div3sim = false; + } + +#if DN100 + /// Paths modulating the flows + const ulong K5 = (1 << 0); + const ulong K7 = (1 << 1); + const ulong K10 = (1 << 2); + const ulong K13 = (1 << 3); + const ulong K16 = (1 << 4); + const ulong K2 = (1 << 5); + const ulong EmptyValve1 = (1 << 17); + const ulong EmptyValve2 = (1 << 18); + const ulong Vl5 = (1 << 21); + const ulong Path1 = K2 | K5 | K7; + const ulong Path2 = K2 | K5 | K10; + const ulong Path3 = K2 | K5 | K13; + const ulong Path4 = K2 | K5 | K16; + const ulong Path5 = K2 | K5 | Vl5; +#elif MUNICH + const ulong VL11 = (1 << 0); + const ulong VL13 = (1 << 1); + const ulong VL21 = (1 << 2); + const ulong VL23 = (1 << 3); + const ulong VZ1 = (1 << 4); + const ulong VP2 = (1 << 5); + const ulong VP4 = (1 << 6); + const ulong VP5 = (1 << 7); + const ulong VP6 = (1 << 8); + const ulong VL12 = (1 << 9); + const ulong VL22 = (1 << 10); + const ulong VI11 = (1 << 11); + const ulong VI12 = (1 << 12); + const ulong VI13 = (1 << 13); + const ulong VI21 = (1 << 14); + const ulong VI22 = (1 << 15); + const ulong VI2P = (1 << 16); + const ulong VI31 = (1 << 17); + const ulong VI32 = (1 << 18); + const ulong VI3P = (1 << 19); + const ulong VI41 = (1 << 20); + const ulong VI42 = (1 << 21); + const ulong VI43 = (1 << 22); + const ulong VI4P = (1 << 23); + const ulong VB1 = (1 << 24); + const ulong VB1a = (1 << 25); + const ulong VB2 = (1 << 26); + const ulong VB2a = (1 << 27); + const ulong VM1 = (1 << 28); + const ulong VM2 = (1 << 29); + const ulong VM3 = (1 << 30); + const ulong VM4 = ((ulong)1 << 31); + const ulong Pump1 = ((ulong)1 << 32); + const ulong Block = ((ulong)1 << 33); + const ulong VZ8 = ((ulong)1 << 37); + const ulong EmptyValve1 = VB1 | VB1a; + const ulong EmptyValve2 = VB2 | VB2a; + const ulong Path1 = VZ1 | VL12 | VI11 | VI13; + const ulong Path2 = VZ1 | VL11 | VL12 | VI21 | VI22 | VI13; + const ulong Path3 = VZ1 | VL11 | VL12 | VI31 | VI32; + const ulong Path4 = VZ1 | VL11 | VL12 | VI41 | VI42; + const ulong Path5 = VZ1 | VL11 | VL12 | VI41 | VI43; +#elif FUZHOU150 + const ulong VL11 = (1 << 2); + const ulong VL13 = (1 << 3); + const ulong VL4 = (1 << 4); + const ulong VZ6 = (1 << 5); + const ulong VZ7 = (1 << 6); + const ulong VP5 = (1 << 7); + + const ulong VP6 = (1 << 8); + const ulong VL12 = (1 << 9); + const ulong VZ14 = (1 << 10); + const ulong VI11 = (1 << 11); + const ulong VI12 = (1 << 12); + const ulong VI13 = (1 << 13); + const ulong VI21 = (1 << 14); + const ulong VI22 = (1 << 15); + + const ulong VI2p = (1 << 16); + const ulong VI31 = (1 << 17); + const ulong VI32 = (1 << 18); + const ulong VI3p = (1 << 19); + const ulong VI41 = (1 << 20); + const ulong VI42 = (1 << 21); + const ulong VI43 = (1 << 22); + const ulong VI4p = (1 << 23); + + const ulong VB1 = (1 << 24); + const ulong VB1a = (1 << 25); + const ulong VB2 = (1 << 26); + const ulong VB2a = (1 << 27); + const ulong VM1 = (1 << 28); + const ulong VM2 = (1 << 29); + const ulong VM3 = (1 << 20); + + const ulong Pump1 = ((ulong)1 << 32); + const ulong Pump4 = ((ulong)1 << 33); + const ulong Pump2 = ((ulong)1 << 37); + const ulong Pump3 = ((ulong)1 << 38); + const ulong Pump5 = ((ulong)1 << 39); + + const ulong EmptyValve1 = VB1 | VB1a; + const ulong EmptyValve2 = VB2 | VB2a; + + const ulong Path1 = VL12 | VI11 | VI13; + const ulong Path2 = VL12 | VI21 | VI22 | VI13; + const ulong Path3 = VL12 | VI31 | VI32; + const ulong Path4 = VL12 | VI41 | VI42; + const ulong Path5 = VL12 | VI41 | VI43; +#else + /// Paths modulating the flows + const ulong V1 = (1 << 1); + const ulong V2 = (1 << 2); + const ulong V3 = (1 << 3); + const ulong V3b = (1 << 4); + const ulong V4 = (1 << 5); + const ulong V4b = (1 << 6); + const ulong V5 = (1 << 7); + const ulong V5b = (1 << 8); + const ulong EmptyValve1 = (1 << 9); // =Ve1 + const ulong EmptyValve2 = (1 << 10); // =Ve2 + const ulong Path1 = V1 | V3 | V3b | V4 | V4b; + const ulong Path2 = V2 | V3 | V3b | V5 | V5b; + const ulong Path3 = 0; + const ulong Path4 = 0; + const ulong Path5 = 0; +#endif + /// Run this device + public void RunDevice(int regulValveNo, int refFlowmtrNo, Elde.StatusP statusP) + { + this.regulValveNo = regulValveNo; + this.refFlowmtrNo = refFlowmtrNo; + float time = 1.0f; + +#if DN100 + if (Div1sim && (RouteSim & Path1) == Path1) Mass1sim += DiffKg(Flow1sim, time); + if (Div1sim && (RouteSim & Path2) == Path2) Mass1sim += DiffKg(Flow2sim, time); + if (Div2sim && (RouteSim & Path3) == Path3) Mass2sim += DiffKg(Flow3sim, time); + if (Div2sim && (RouteSim & Path4) == Path4) Mass2sim += DiffKg(Flow4sim, time); + if (Div1sim && (RouteSim & Path5) == Path5) Mass1sim += DiffKg(Flow5sim, time); +#elif MUNICH || FUZHOU150 + if (Div1sim && (RouteSim & Path1) == Path1) Mass1sim += DiffKg(Flow1sim, time); + if (Div1sim && (RouteSim & Path2) == Path2) Mass1sim += DiffKg(Flow2sim, time); + if (Div2sim && (RouteSim & Path3) == Path3) + { + Mass2sim += DiffKg(Flow3sim, time); + } + if (Div3sim && (RouteSim & Path4) == Path4) Mass2sim += DiffKg(Flow4sim, time); + if (Div3sim && (RouteSim & Path5) == Path5) Mass2sim += DiffKg(Flow5sim, time); +#else + if (Div1sim && (RouteSim & Path1) == Path1) Mass1sim += DiffKg(Flow1sim, time); + if (Div2sim && (RouteSim & Path2) == Path2) Mass2sim += DiffKg(Flow2sim, time); +#endif + + if ((RouteSim & EmptyValve1) == EmptyValve1) Mass1sim -= DiffKg(100.0f, time); + if (Mass1sim < 0) Mass1sim = 0; + + if ((RouteSim & EmptyValve2) == EmptyValve2) Mass2sim -= DiffKg(10.0f, time); + if (Mass2sim < 0) Mass2sim = 0; + + UiBridge.Bridge.OnLog(this, string.Format("I{1}/RV{2}: q1={3}, q2={4}, q3={5}, q4={6}, q5={7}, D123={8}{9}{10}, m1={11}, m2={12}, S={13}\r\n", + time, + refFlowmtrNo, regulValveNo, + Flow1sim.ToString("F1"), Flow2sim.ToString("F1"), Flow3sim.ToString("F1"), Flow4sim.ToString("F1"), Flow5sim.ToString("F1"), + (Div1sim ? "o" : "x"), (Div2sim ? "o" : "x"), (Div3sim ? "o" : "x"), + Mass1sim.ToString("F1"), Mass2sim.ToString("F1"), ((ulong)statusP).ToString("X"))); + } + + /// + /// Calculate the mass change from the flow and the time period + /// + /// Flow in [m3/h] + /// Time period in [s] + /// Mass change in [kg] + float DiffKg(float flowM3H, float timeSec) + { + return timeSec * flowM3H / 3.6f; + } + + /// + /// Get the simulated mass. Use the balance range to distinguish the balances. + /// + /// 0-based balance number + /// Simulated mass reading [kg] + public float GetSimMass(int balanceNr) + { + if (balanceNr == 0) return Mass1sim; + else if (balanceNr == 1) return Mass2sim; + else return 0; + } + + /// + /// Set the simulated diverter. Use the nominal flow to distinguish the path. + /// + /// Diverter state: true = to the tank + /// Nominal flow of the path [m3/h] + public void SetSimDiverter(bool toTank) + { +#if DN100 + switch (regulValveNo) + { + case 1: + case 2: + case 5: + Div1sim = toTank; + break; + case 3: + case 4: + Div2sim = toTank; + break; + default: + if (toTank) { throw (new Exception()); } + break; + } +#elif MUNICH || FUZHOU150 + switch (regulValveNo) + { + case 1: + case 2: + Div1sim = toTank; + break; + case 3: + Div2sim = toTank; + break; + case 4: + case 5: + Div3sim = toTank; + break; + default: + if (toTank) { throw (new Exception()); } + break; + } +#else + switch (regulValveNo) + { + case 1: Div1sim = toTank; break; + case 2: Div2sim = toTank; break; + default: + if (toTank) { throw (new Exception()); } + break; + } +#endif + return; + } + + /// + /// Determine which autput section is used + /// + /// + /// + int OutputPathId(float nominalFlow) + { +#if DN100 + // + // Qn1=0.3, Qn2=2.5, Qn3=25, Qn4=250, Qn5=0.2 + // + if (nominalFlow < 0.25f) return 5; + else if (nominalFlow < 1.0f) return 1; + else if (nominalFlow < 10.0f) return 2; + else if (nominalFlow < 100.0f) return 3; + else return 4; +#elif MUNICH + // + // Qn1=200, Qn2=20, Qn3=3, Qn4=0.25 + // + if (nominalFlow <= 0.25f) return 4; + else if (nominalFlow <= 3.0f) return 3; + else if (nominalFlow <= 20.0f) return 2; + else return 1; +#elif FUZHOU150 + // + // Qn1=350, Qn2=50, Qn3=7, Qn4=0.5 + // + if (nominalFlow <= 0.5f) return 4; + else if (nominalFlow <= 7.0f) return 3; + else if (nominalFlow <= 50.0f) return 2; + else return 1; +#else + // + // Qn1=1, Qn2=10 + // + if (nominalFlow < 3.0f) return 1; + else return 2; +#endif + } + + /// + /// Get the simulated flow in [m3/h]. + /// + /// Simulated flow [m3/h] + public float GetSimFlow() + { + switch (refFlowmtrNo) + { + case 1: return ((RouteSim & Path1) == Path1) ? Flow1sim : 0; + case 2: return ((RouteSim & Path2) == Path2) ? Flow2sim : 0; + case 3: return ((RouteSim & Path3) == Path3) ? Flow3sim : 0; + case 4: return (((RouteSim & Path4) == Path4) ? Flow4sim : 0) + + (((RouteSim & Path5) == Path5) ? Flow5sim : 0); + default: return 0; + } + } + + /// + /// Update simulated flow. Use the nominal flow to distinguish the path. + /// + /// Target flow [m3/h] + /// Nominal flow of the path [m3/h] + public void UpdateSimFlow(float targetFlow) + { + float A = 0.7f; /// higher value -> slower regulation + float B = 1.0f - A; + + switch (regulValveNo) + { + case 1: Flow1sim = A * Flow1sim + B * targetFlow; break; + case 2: Flow2sim = A * Flow2sim + B * targetFlow; break; + case 3: Flow3sim = A * Flow3sim + B * targetFlow; break; + case 4: Flow4sim = A * Flow4sim + B * targetFlow; break; + case 5: Flow5sim = A * Flow5sim + B * targetFlow; break; + default: break; + } + } + } +} diff --git a/TestBenchFramework/BenchControl/TestMethods/CameraRoiDetection/RoiDetection.cs b/TestBenchFramework/BenchControl/TestMethods/CameraRoiDetection/RoiDetection.cs new file mode 100644 index 000000000..c8e272785 --- /dev/null +++ b/TestBenchFramework/BenchControl/TestMethods/CameraRoiDetection/RoiDetection.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using TBF.BenchControl; + +namespace TBF.BenchControl.TestMethods.CameraRoiDetection +{ + public class RoiDetection : Generic.IComponent, GenericDevices.ITestMethod, ISequence + { + readonly RoiDetectionCfg roiDetectionCfg; + public Generic.IComponentCfg Cfg { get { return roiDetectionCfg; } } + + public static void ResetStaticProperties() { } + + public string Name { get { return roiDetectionCfg.Name; } } + + public RoiDetection(RoiDetectionCfg cfg) + { + if (cfg == null) throw new ArgumentNullException("cfg"); + this.roiDetectionCfg = cfg; + } + + public IList Execute(Entities.Test test) + { + return (new RoiDetectionSeq()).Execute(test); + } + } +} diff --git a/TestBenchFramework/BenchControl/TestMethods/CameraRoiDetection/RoiDetectionCfg.cs b/TestBenchFramework/BenchControl/TestMethods/CameraRoiDetection/RoiDetectionCfg.cs new file mode 100644 index 000000000..5b9a19d3e --- /dev/null +++ b/TestBenchFramework/BenchControl/TestMethods/CameraRoiDetection/RoiDetectionCfg.cs @@ -0,0 +1,54 @@ +using System; +using System.IO; +using System.Xml.Serialization; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.TestMethods.CameraRoiDetection +{ + public class RoiDetectionCfg : ComponentCfgBase, Generic.IComponentCfg + { + /// Parameterless constructor + public RoiDetectionCfg() + { + } + + /// + /// Data entry form configuration parameters + /// + /// Data entry form factory + /// Component name + public RoiDetectionCfg(IComponentFactory factory, string name) + : base(factory, name) + { + } + + public IComponentCfg Clone() + { + return new RoiDetectionCfg(Factory, Name); + } + + public string ToString(int i) + { + return string.Format("ROI-s detection {0}", Name); + } + + public TBF.Entities.Component CreateDbEntity() + { + using (var writer = new StringWriter()) + { + (new XmlSerializer(GetType())).Serialize(writer, this); + return Entities.Component.CreateFromCfg(Name, Factory.ClassName, ParentName, ItemNr, DebugLevel, LogLevel, writer.ToString()); + } + } + + public static IComponentCfg CreateFromDbEntity(Entities.Component component, IComponentFactory factory) + { + using (var reader = new StringReader(component.Parameters)) + { + RoiDetectionCfg config = (RoiDetectionCfg)(new XmlSerializer(typeof(RoiDetectionCfg))).Deserialize(reader); + config.InitCfgBaseFromEntity(component, factory); + return config; + } + } + } +} diff --git a/TestBenchFramework/BenchControl/TestMethods/CameraRoiDetection/RoiDetectionCfgCtrl.cs b/TestBenchFramework/BenchControl/TestMethods/CameraRoiDetection/RoiDetectionCfgCtrl.cs new file mode 100644 index 000000000..311a39b34 --- /dev/null +++ b/TestBenchFramework/BenchControl/TestMethods/CameraRoiDetection/RoiDetectionCfgCtrl.cs @@ -0,0 +1,58 @@ +using System; +using System.Windows.Forms; +using log4net; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.TestMethods.CameraRoiDetection +{ + public partial class RoiDetectionCfgCtrl : UserControl, IComponentCfgCtrl + { + static readonly ILog log = LogManager.GetLogger(typeof(RoiDetectionCfgCtrl)); + + RoiDetectionCfg config; + + public IComponentCfg Config + { + get { return config as IComponentCfg; } + set + { + config = value as RoiDetectionCfg; + Redraw(); + } + } + + public RoiDetectionCfgCtrl() + { + InitializeComponent(); + } + + private void EntryFormCfgCtrl_Load(object sender, EventArgs e) + { + Redraw(); + } + + void Redraw() + { + if (config == null) return; /// Control was not loaded, settings were not changed + classNameLabel.Text = config.Factory.ClassName; + nameTextBox.Text = config.Name; + } + + public void Unlock() + { + nameTextBox.Enabled = true; + } + + public CfgVerifyFlags VerifyCfg(ref string message) + { + CfgVerifyFlags flags = CfgVerifyFlags.None; + return flags; + } + + public void UpdateCfg() + { + if (config == null) return; /// Control was not loaded, settings were not changed + config.Name = nameTextBox.Text; + } + } +} diff --git a/TestBenchFramework/BenchControl/TestMethods/CameraRoiDetection/RoiDetectionCfgCtrl.designer.cs b/TestBenchFramework/BenchControl/TestMethods/CameraRoiDetection/RoiDetectionCfgCtrl.designer.cs new file mode 100644 index 000000000..41ff98eb1 --- /dev/null +++ b/TestBenchFramework/BenchControl/TestMethods/CameraRoiDetection/RoiDetectionCfgCtrl.designer.cs @@ -0,0 +1,79 @@ +namespace TBF.BenchControl.TestMethods.CameraRoiDetection +{ + partial class RoiDetectionCfgCtrl + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.nameTextBox = new System.Windows.Forms.TextBox(); + this.nameLabel = new System.Windows.Forms.Label(); + this.classNameLabel = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // nameTextBox + // + this.nameTextBox.Enabled = false; + this.nameTextBox.Location = new System.Drawing.Point(134, 69); + this.nameTextBox.Name = "nameTextBox"; + this.nameTextBox.Size = new System.Drawing.Size(130, 20); + this.nameTextBox.TabIndex = 7; + // + // nameLabel + // + this.nameLabel.AutoSize = true; + this.nameLabel.Location = new System.Drawing.Point(24, 72); + this.nameLabel.Name = "nameLabel"; + this.nameLabel.Size = new System.Drawing.Size(35, 13); + this.nameLabel.TabIndex = 6; + this.nameLabel.Text = "Name"; + // + // classNameLabel + // + this.classNameLabel.AutoSize = true; + this.classNameLabel.Location = new System.Drawing.Point(131, 43); + this.classNameLabel.Name = "classNameLabel"; + this.classNameLabel.Size = new System.Drawing.Size(83, 13); + this.classNameLabel.TabIndex = 5; + this.classNameLabel.Text = "ComonentName"; + // + // RoiDetectionCfgCtrl + // + this.Controls.Add(this.nameTextBox); + this.Controls.Add(this.nameLabel); + this.Controls.Add(this.classNameLabel); + this.Name = "RoiDetectionCfgCtrl"; + this.Size = new System.Drawing.Size(300, 240); + this.ResumeLayout(false); + this.PerformLayout(); + } + + #endregion + + private System.Windows.Forms.TextBox nameTextBox; + private System.Windows.Forms.Label nameLabel; + private System.Windows.Forms.Label classNameLabel; + } +} diff --git a/TestBenchFramework/BenchControl/TestMethods/CameraRoiDetection/RoiDetectionCfgCtrl.resx b/TestBenchFramework/BenchControl/TestMethods/CameraRoiDetection/RoiDetectionCfgCtrl.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/TestBenchFramework/BenchControl/TestMethods/CameraRoiDetection/RoiDetectionCfgCtrl.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/BenchControl/TestMethods/CameraRoiDetection/RoiDetectionFactory.cs b/TestBenchFramework/BenchControl/TestMethods/CameraRoiDetection/RoiDetectionFactory.cs new file mode 100644 index 000000000..c5e4f5a77 --- /dev/null +++ b/TestBenchFramework/BenchControl/TestMethods/CameraRoiDetection/RoiDetectionFactory.cs @@ -0,0 +1,40 @@ +using System.Collections.Generic; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.TestMethods.CameraRoiDetection +{ + public class RoiDetectionFactory : IComponentFactory + { + public string ClassName { get { return "ROI Detection"; } } + public bool HasProcedureParams { get { return false; } } + public bool HasTestParams { get { return false; } } + public IParamsProvider GetTestParams(Entities.ComponentTest testParams) { return null; } + public IParamsProvider GetProcedureParams(Entities.ComponentProcedure procedureParams) { return null; } + + /// Max. number of components of this class in the system + public int MaxCount { get { return 1; } } + + + public IComponentCfg DefaultConfig(IList components) + { + return new RoiDetectionCfg(this, "RoiDetection"); + } + + public IComponentCfgCtrl CreateCfgCtrl() + { + return new RoiDetectionCfgCtrl(); + } + + public IComponent ComponentFromCmpntCfg(IComponentCfg config, IList components) + { + return new RoiDetection((RoiDetectionCfg)config); + } + + public IComponentCfg CmpntCfgFromCmpntEntity(Entities.Component component) + { + return RoiDetectionCfg.CreateFromDbEntity(component, this); + } + + public void ResetStaticProperties() { RoiDetection.ResetStaticProperties(); } + } +} diff --git a/TestBenchFramework/BenchControl/TestMethods/CameraRoiDetection/RoiDetectionSeq.cs b/TestBenchFramework/BenchControl/TestMethods/CameraRoiDetection/RoiDetectionSeq.cs new file mode 100644 index 000000000..f0658dc37 --- /dev/null +++ b/TestBenchFramework/BenchControl/TestMethods/CameraRoiDetection/RoiDetectionSeq.cs @@ -0,0 +1,245 @@ +using System; +using System.Collections.Generic; +using System.Text; +using log4net; +using TBF.Resources; +using TBF.UiBridge; + +namespace TBF.BenchControl.TestMethods.CameraRoiDetection +{ + public class RoiDetectionSeq : Sequences.SequenceBase + { + private static readonly ILog log = LogManager.GetLogger(typeof(RoiDetectionSeq)); + private static readonly ILog allResults = LogManager.GetLogger("AllResults"); + private static readonly ILog summaryResults = LogManager.GetLogger("SummaryResults"); + + + public IList Execute(Entities.Test test) + { + Elde.ControlBoardDev cBrd = StateMachine.ControlBoard; + + /// Operations running in more then one state + checkUiOp = new Operations.CheckUIOp(true); + + IList e; /// Events from currently running operations + + //-------------------------------- + State.Create("RoiDetection : Starting the detection sequence") + .AddOperation(checkUiOp) + .AddOperation(cBrd.StopPreviousOp()) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.UiCmdStop)) goto stop; + } + while (!e.Contains(Event.PreviousStopped)); + + /// Fetch the test, the paths + bool success = StateMachine.GetPaths(test, out inPath, out benchPath, out outPath, out sensPath, + out transitionStart, out transitionStop); + if (!success) goto error; + + //==================================== + /// Start the test, initialize test results + Bridge.OnTestSelected(this, new TestSelectedEventArgs(test, 1, inPath, benchPath, outPath, sensPath, 0)); + Entities.TestResult tstRslt = new Entities.TestResult(test, 1, Entities.MetersKind.Single); + tstRslt.DoNotEvaluate = true; + tstRslt.DoNotPublish = true; + + //==================================== + // Transition or SetRoute - Start + //==================================== + if (transitionStart != null) + { + switch (Transition(transitionStart, "RoiDetection : " + Strings.Test_start_sequence_i_n)) + { + case Event.Error: goto error; + case Event.UiCmdStop: goto stop; + } + } + else + { + //-------------------------------- + State.Create("RoiDetection : Setting the route") + .AddOperation(checkUiOp) + .AddOperation(cBrd.SetValvesOp(GenericDevices.ValveBase.Merge(inPath.ValvesOpen, benchPath.ValvesOpen, outPath.ValvesOpen), + GenericDevices.ValveBase.Merge(inPath.ValvesClose, benchPath.ValvesClose, outPath.ValvesClose))) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.UiCmdStop)) goto stop; + } + while (!e.Contains(Event.ValvesSet)); + } + + //------------------------------------------------ + Bridge.OnActivity(this, Strings.Setting_the_flow); + //------------------------------------------------ + State.Create("RoiDetection : Starting the pump") + .AddOperation(checkUiOp) + .AddOperation((inPath != null && inPath.Pump is GenericDevices.IPumpFM) ? (inPath.Pump as GenericDevices.IPumpFM).TurnOn() : null) + .AddOperation(cBrd.SetValvesOp(inPath.Pump, null)) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.UiCmdStop)) goto stop; + } + while (!e.Contains(Event.ValvesSet)); + + //-------------------------------- + State.Create("RoiDetection : Setting the flow") + .AddOperation(checkUiOp) + .AddOperation(outPath.RegulValve.SetFlowOp(outPath.FlowMeter, test.Qfrom, test.Qto, measuredFlow, 600)) /// timeout = 10 min. + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.UiCmdStop)) goto stop; + if (e.Contains(Event.RegulValveTimeOut)) goto error; + if (e.Contains(Event.Next)) goto flow_set; + } + while (!e.Contains(Event.FlowReached)); + + flow_set: + int time = StateMachine.CurrentTime; + float currentFlow = measuredFlow.F; + + //------------------------------------------------ + Bridge.OnActivity(this, Strings.ROI_Detection_in_Progress); + //------------------------------------------------ + State detection = State.Create("RoiDetection : Detection of ROI-s") + .AddOperation(checkUiOp); + /// Extract cameras from the current sensors path, add operations to the detection state + for (int i = 0; i < sensPath.RegisterReaders.Length; i++) + { + GenericDevices.ICameraRoi cameraRoi = sensPath.RegisterReaders[i] as GenericDevices.ICameraRoi; + if (cameraRoi != null) + { + detection.AddOperation(cameraRoi.DetectOp()); + } + } + detection.EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.Error)) goto error; + if (e.Contains(Event.UiCmdStop)) goto stop; + } + while (e.Contains(Event.CameraBusy)); + + if (e.Contains(Event.CameraOpFailed)) goto error; /// TODO: resolve in some other way + + //------------------------------------------------ + Bridge.OnActivity(this, Strings.Detection_completed); + //------------------------------------------------ + State.Create("RoiDetection : Stopping the pump") + .AddOperation(checkUiOp) + .AddOperation((inPath != null && inPath.Pump is GenericDevices.IPumpFM) ? (inPath.Pump as GenericDevices.IPumpFM).TurnOff() : null) + .AddOperation(cBrd.SetValvesOp(null, inPath.Pump)) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.UiCmdStop)) goto stop; + } + while (!e.Contains(Event.ValvesSet)); + + + //-------------------------------- + State.Create("RoiDetection : Stopping diverter, gate, etc.") + .AddOperation(checkUiOp) + .AddOperation(cBrd.StopPreviousOp()) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.UiCmdStop)) goto stop; + } + while (!e.Contains(Event.PreviousStopped)); + + ///----------------------/// + /// Quit this sequence /// + ///----------------------/// + + /// Stop the pump + State.Create("RoiDetection : Detection of ROI-s completed -> Stopping the pump") + .AddOperation(checkUiOp) + .AddOperation(cBrd.SetValvesOp(null, inPath.Pump)) + .AddOperation((inPath != null && inPath.Pump is GenericDevices.IPumpFM) ? (inPath.Pump as GenericDevices.IPumpFM).TurnOff() : null) + .EnterState(); + do { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.Error)) goto error; + } + while (!e.Contains(Event.ValvesSet) || ((inPath.Pump is GenericDevices.IPumpFM) && !e.Contains(Event.TurnPumpOnOffDone))); + + /// Transition or SetRoute - End + if (transitionStop != null) + { + switch (Transition(transitionStop, "RoiDetection : " + Strings.Test_stop_sequence_i_n)) + { + case Event.Error: goto error; + case Event.UiCmdStop: goto stop; + } + } + else + { + State.Create("RoiDetection : Detection completed -> Closing the valves") + .AddOperation(checkUiOp) + .AddOperation(cBrd.SetValvesOp(StateMachine.DefaultValvesOpen, StateMachine.DefaultValvesClose)) + .EnterState(); + do { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.Error)) goto error; + } + while (!e.Contains(Event.ValvesSet)); + } + + /// Create the return value: a list with one event Event.Done + IList retval = new List(); + retval.Add(Event.Done); + return retval; + + //==================================== + stop: + cBrd.SetFMFreq(0, 0); /// Stop FM controlled pumps + State.Create("RoiDetection : User selected STOP -> Closing the valves") + .AddOperation(checkUiOp) + .AddOperation((inPath != null && inPath.Pump is GenericDevices.IPumpFM) ? (inPath.Pump as GenericDevices.IPumpFM).TurnOff() : null) + .AddOperation(cBrd.SetValvesOp(StateMachine.DefaultValvesOpen, StateMachine.DefaultValvesClose)) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.Error)) goto error; + } + while (!e.Contains(Event.ValvesSet)); + + IList retval2 = new List(); + retval2.Add(Event.UiCmdStop); + return retval2; + + //==================================== + error: + cBrd.SetFMFreq(0, 0); /// Stop FM controlled pumps + State.Create("RoiDetection : ERROR -> Closing the valves") + .AddOperation(checkUiOp) + .AddOperation((inPath != null && inPath.Pump is GenericDevices.IPumpFM) ? (inPath.Pump as GenericDevices.IPumpFM).TurnOff() : null) + .AddOperation(cBrd.SetValvesOp(StateMachine.DefaultValvesOpen, StateMachine.DefaultValvesClose)) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.Error)) goto error; + } + while (!e.Contains(Event.ValvesSet)); + + IList retval3 = new List(); + retval3.Add(Event.Error); + return retval3; + } + } +} diff --git a/TestBenchFramework/BenchControl/TestMethods/CombinedMeters/CombinedMetersSeq.cs b/TestBenchFramework/BenchControl/TestMethods/CombinedMeters/CombinedMetersSeq.cs new file mode 100644 index 000000000..5c4e54218 --- /dev/null +++ b/TestBenchFramework/BenchControl/TestMethods/CombinedMeters/CombinedMetersSeq.cs @@ -0,0 +1,483 @@ +using System; +using System.Collections.Generic; +using System.Text; +using log4net; +using TBF.UiBridge; +using TBF.BenchControl; +using TBF.Resources; + +namespace TBF.BenchControl.TestMethods.CombinedMeters +{ + public class CombinedMetersSeq : Sequences.SequenceBase + { + private static readonly ILog log = LogManager.GetLogger(typeof(CombinedMetersSeq)); + private static readonly ILog allResults = LogManager.GetLogger("AllResults"); + private static readonly ILog summaryResults = LogManager.GetLogger("SummaryResults"); + + + public IList Execute(Entities.Test test) + { + Elde.ControlBoardDev cBrd = StateMachine.ControlBoard; + + /// Specific for combined meters + int[] lastWMPulses = new int[Program.WMsCount]; + + /// Operations running in more then one state + checkUiOp = new Operations.CheckUIOp(true); + + IList e; /// Events from currently running operations + + //-------------------------------- + State.Create("CombinedMeters : Stopping diverter, gate, etc.") + .AddOperation(checkUiOp) + .AddOperation(cBrd.StopPreviousOp()) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.UiCmdStop)) goto stop; + } + while (!e.Contains(Event.PreviousStopped)); + + /// Fetch the test, the paths + bool success = StateMachine.GetPaths(test, out inPath, out benchPath, out outPath, out sensPath, + out transitionStart, out transitionStop); + if (!success) goto error; + + /// Notes: + /// float timeHr = volumeLtr / (1000.0f * targetFlow); + /// float timeSec = 3600.0f * timeHr; + /// uint refPulses = (uint)(timeSec * (2000.0f * targetFlow / pOut.FlowMeter.NominalFlow)); + int totalPulses = (int)(7200.0f * test.Volume / outPath.FlowMeter.NominalFlow); /// Nominal flow in [m3/h] + + float ltrPerRefPulse = outPath.FlowMeter.NominalFlow / 7200.0f; /// [ltr/pulse] + /// + /// Meters path is required for the following: + readRegisters1 = new Operations.ReadMoreRegistersOp(sensPath.RegisterReaders, ref WMPulses, ref WMRefPulses); + readRegisters2 = new Operations.ReadMoreRegistersOp(sensPath.RegisterReaders, ref WMPulses, ref WMRefPulses); + + int repetitionNr = 1; /// First test: repetitionNr=1 + + //==================================== + // Transition or SetRoute - Start + //==================================== + if (transitionStart != null) + { + switch (Transition(transitionStart, "CombinedMeters : " + Strings.Test_start_sequence_i_n)) + { + case Event.Error: goto error; + case Event.UiCmdStop: goto stop; + } + } + else + { + //-------------------------------- + State.Create("CombinedMeters : Setting the route") + .AddOperation(checkUiOp) + .AddOperation(cBrd.SetValvesOp(GenericDevices.ValveBase.Merge(inPath.ValvesOpen, benchPath.ValvesOpen, outPath.ValvesOpen), + GenericDevices.ValveBase.Merge(inPath.ValvesClose, benchPath.ValvesClose, outPath.ValvesClose))) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.UiCmdStop)) goto stop; + } + while (!e.Contains(Event.ValvesSet)); + } + + //==================================== + loop: + /// Start the test, initialize test results + Bridge.OnTestSelected(this, new TestSelectedEventArgs(test, repetitionNr, inPath, benchPath, outPath, sensPath, (int)totalPulses)); + Entities.TestResult tstRslt = new Entities.TestResult(test, repetitionNr, Entities.MetersKind.Combined); + + + if (!test.Emptying) /// Do not skip emptying if test.Emptying==true + { + //-------------------------------- + State.Create("CombinedMeters : Measuring the mass of water in the tank") + .AddOperation(checkUiOp) + .AddOperation(outPath.Balance.ReadMassOp(ref mass)) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.Error)) goto error; + if (e.Contains(Event.UiCmdStop)) goto stop; + } + while (!e.Contains(Event.BalanceDone)); + + float estimatedEndMass = mass.F + test.Volume; + if (estimatedEndMass < outPath.Balance.Capacity * Constants.TankFullFactor) + { + goto set_flow; /// Enough room in the tank -> skip emptying + } + } + + // Empty the water tank + switch (EmptyTheTank(outPath.EmptyTankValve, outPath.Balance)) + { + case Event.Error: goto error; + case Event.UiCmdStop: goto stop; + } + + set_flow: + + //------------------------------------------------ + Bridge.OnActivity(this, Strings.Setting_the_flow); + //------------------------------------------------ + State.Create("CombinedMeters : Starting the pump") + .AddOperation(checkUiOp) + .AddOperation((inPath != null && inPath.Pump is GenericDevices.IPumpFM) ? (inPath.Pump as GenericDevices.IPumpFM).TurnOn() : null) + .AddOperation(cBrd.SetValvesOp(inPath.Pump, null)) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.UiCmdStop)) goto stop; + } + while (!e.Contains(Event.ValvesSet)); + + //-------------------------------- + State.Create("CombinedMeters : Setting the flow") + .AddOperation(checkUiOp) + .AddOperation(outPath.RegulValve.SetFlowOp(outPath.FlowMeter, test.Qfrom, test.Qto, measuredFlow, 600)) /// timeout = 10 min. + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.UiCmdStop)) goto stop; + if (e.Contains(Event.RegulValveTimeOut)) goto error; + } + while (!e.Contains(Event.FlowReached)); + + int time = StateMachine.CurrentTime; + float currentFlow = measuredFlow.F; + + /// Extract cameras from the current sensors path, add operations to the detection state + IList measureOperations = new List(); + for (int i = 0; i < sensPath.RegisterReaders.Length; i++) + { + GenericDevices.ICameraRoi cameraRoi = sensPath.RegisterReaders[i] as GenericDevices.ICameraRoi; + if (cameraRoi != null) measureOperations.Add(cameraRoi.MeasureOp()); + } + + //------------------------------------------------ + Bridge.OnActivity(this, Strings.Measuring_the_weight); + //------------------------------------------------ + State.Create("CombinedMeters : Measuring the start mass") + .AddOperation(checkUiOp) + .AddOperations(measureOperations) + .AddOperation(outPath.Balance.ReadStableMassOp(ref stableMass, 5)) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.Error)) goto error; + if (e.Contains(Event.UiCmdStop)) goto stop; + } + while (!e.Contains(Event.BalanceDone)); + + tstRslt.TimeStart = DateTime.Now; + tstRslt.MassStartRaw = stableMass.F; + mass.F = stableMass.F; + + //------------------------------------------------ + Bridge.OnActivity(this, Strings.Test_in_progress); + //------------------------------------------------ + State.Create("CombinedMeters : Starting the test") + .AddOperation(checkUiOp) + .AddOperations(measureOperations) + .AddOperation(cBrd.StartMeasurementOp(outPath.FlowMeter, totalPulses, Elde.TestMethods.Diverter | Elde.TestMethods.Synchro)) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.Error)) goto error; + if (e.Contains(Event.UiCmdStop)) goto stop; + } + while (!e.Contains(Event.MeasurementStarted)); + + /// + /// Measurement loop - preparation + /// + queryEnd1 = cBrd.QueryMeasurementEndOp(); + queryEnd2 = cBrd.QueryMeasurementEndOp(); + + bool firstTime = true; /// Used to reset sums for averaging + ResetAveragedData(); + + /// Measurement loop - begin + while (true) + { + //-------------------------------- + switch(ReadRegistersTempPressAmbient(measureOperations, true)) + { + case Event.Error: goto error; + case Event.UiCmdStop: goto stop; + case Event.MeasurementCompleted: goto measurement_completed; + } + + if (firstTime) + { + firstTime = false; /// Do the following only once + tstRslt.TempInStart = tempIn.F; + tstRslt.TempOutStart = tempOut.F; + tstRslt.TempDivStart = tempDiv.F; + tstRslt.PressInStart = pressIn.F; + tstRslt.PressOutStart = pressOut.F; + } + + tstRslt.TempInEnd = tempIn.F; + tstRslt.TempOutEnd = tempOut.F; + tstRslt.TempDivEnd = tempDiv.F; + tstRslt.PressInEnd = pressIn.F; + tstRslt.PressOutEnd = pressOut.F; + tstRslt.MassEndRaw = mass.F; + + AccumulateAveragedData(); + + + string logstr = string.Format("E={0} f={1} q={2}", cBrd.EtPulses(0), cBrd.ReferenceFreq, + cBrd.ReferenceFlow * outPath.FlowMeter.NominalFlow); + for (int i = 0; i < Program.WMsCount; i++) + { + logstr += string.Format(" M{0}=({1},{2})", i + 1, WMRefPulses[i], WMPulses[i]); + } + log.Info(logstr); + + + float progress = Formulas.TestProgress(cBrd.EtPulses(0), totalPulses, 10.0f, test.TstTime); + TestProgressEventArgs data = GetTestProgressData(test, tstRslt, cBrd.EtPulses(0), cBrd.TTime, progress); + data.WmVolume[2] = data.WmVolume[0] + data.WmVolume[1]; + data.WmErrPct[2] = Formulas.ErrorFromVolumes(data.WmVolume[2], data.Volume); + Bridge.OnTestProgress(this, data); + } + /// Measurement loop - end + + + measurement_completed: + + //------------------------------------------------ + Bridge.OnActivity(this, Strings.Measuring_the_weight); + //------------------------------------------------ + State.Create("CombinedMeters : Measuring the end mass") + .AddOperation(checkUiOp) + .AddOperation(outPath.Balance.ReadStableMassOp(ref stableMass, 5)) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.Error)) goto error; + if (e.Contains(Event.UiCmdStop)) goto stop; + } + while (!e.Contains(Event.BalanceDone)); + /// + tstRslt.MassEndRaw = stableMass.F; + tstRslt.TimeEnd = DateTime.Now; + + //------------------------------------------------ + Bridge.OnActivity(this, Strings.Test_completed); + //------------------------------------------------ + State.Create("CombinedMeters : Stopping the pump") + .AddOperation(checkUiOp) + .AddOperation((inPath != null && inPath.Pump is GenericDevices.IPumpFM) ? (inPath.Pump as GenericDevices.IPumpFM).TurnOff() : null) + .AddOperation(cBrd.SetValvesOp(null, inPath.Pump)) + .AddOperation(cBrd.UpdateTankWeightOp()) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.UiCmdStop)) goto stop; + } + while (!e.Contains(Event.ValvesSet)); + + + //-------------------------------- + State.Create("CombinedMeters : Stopping diverter, gate, etc.") + .AddOperation(checkUiOp) + .AddOperation(cBrd.StopPreviousOp()) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.UiCmdStop)) goto stop; + } + while (!e.Contains(Event.PreviousStopped)); + + /// + /// Populate TestRasult data entity with data + /// + tstRslt.TimeEnd = DateTime.Now; + UpdateTestRsltWithAveragedData(tstRslt); + tstRslt.MassStart = Formulas.CorrectedValue(tstRslt.MassStartRaw, outPath.Balance.Corrections); + tstRslt.MassEnd = Formulas.CorrectedValue(tstRslt.MassEndRaw, outPath.Balance.Corrections); + tstRslt.MassDiff = tstRslt.MassEnd - tstRslt.MassStart; + tstRslt.DensityIn = Formulas.WaterDensityFromTemp(tstRslt.TempInAvrg); /// [kg/m3] + tstRslt.DensityOut = Formulas.WaterDensityFromTemp(tstRslt.TempOutAvrg); /// [kg/m3] + tstRslt.DensityDiv = Formulas.WaterDensityFromTemp(tstRslt.TempDivAvrg); /// [kg/m3] + tstRslt.Time = cBrd.TTime; /// [s] measurement time + tstRslt.FlowMass = 3600.0f * tstRslt.MassDiff / tstRslt.Time; /// [kg/h] + tstRslt.FlowVolume = 3600.0f * ltrPerRefPulse * cBrd.EtPulses(0) / tstRslt.Time; /// [l/h] + tstRslt.VolumeCTV = 1.00103f * 1000.0f * tstRslt.MassDiff / tstRslt.DensityOut; /// [l] 1000.0f is because density is in [kg/m3] + tstRslt.VolumeMaster = ltrPerRefPulse * cBrd.EtPulses(0); /// [l] volume from the master flow meter + tstRslt.PulsesMaster = cBrd.EtPulses(0); /// Pulses of the master flow meter (test total) + tstRslt.ConstMaster = ltrPerRefPulse * tstRslt.VolumeCTV / tstRslt.VolumeMaster; + /// Corrected master pulses per liter + if (tstRslt.VolumeCTV <= float.Epsilon) + { + tstRslt.ErrorMaster = 0.1f; + } + else + { + tstRslt.ErrorMaster = 100 * (tstRslt.VolumeMaster - tstRslt.VolumeCTV) / tstRslt.VolumeCTV; + } + tstRslt.TimeDivStart0 = 0; + tstRslt.TimeDivStart1 = 0; + tstRslt.TimeDivStart2 = 0; + tstRslt.TimeDivStart3 = 0; + tstRslt.TimeDivStart4 = 0; + tstRslt.TimeDivStart5 = 0; + tstRslt.TimeDivEnd0 = 0; + tstRslt.TimeDivEnd1 = 0; + tstRslt.TimeDivEnd2 = 0; + tstRslt.TimeDivEnd3 = 0; + tstRslt.TimeDivEnd4 = 0; + tstRslt.TimeDivEnd5 = 0; + + for (int iCmbnd = 0; iCmbnd < Program.WMsCount / 2; iCmbnd++) + { + for (int i = 2 * iCmbnd; i < 2 * iCmbnd + 2; i++) + { + if (sensPath.RegisterReaders[i] == null || sensPath.RegisterReaders[i].PulsesPerLtr <= float.Epsilon) + { + tstRslt.Meters[i].VolumeMeter = 0; + } + else + { + tstRslt.Meters[i].VolumeMeter = Convert.ToSingle(WMPulses[i]) / sensPath.RegisterReaders[i].PulsesPerLtr; + } + + tstRslt.Meters[i].SerialNr = "wm" + (i + 1).ToString(); + tstRslt.Meters[i].VolumeStart = 0; /// liter + tstRslt.Meters[i].VolumeEnd = 0; /// liter + + tstRslt.Meters[i].VolumeRef = tstRslt.VolumeCTV; /// liter + if (WMRefPulses[i] != 0) + { + tstRslt.Meters[i].VolumeMeter *= ((float)cBrd.EtPulses(0) / (float)WMRefPulses[i]); + } + + tstRslt.Meters[i].PulsesMeter = WMPulses[i]; + tstRslt.Meters[i].PulsesMaster = WMRefPulses[i]; + tstRslt.Meters[i].Time = cBrd.TTime; + + tstRslt.Meters[i].VolumeErrorPct = 0; /// Not used + } + + tstRslt.CombinedMeters[iCmbnd].VolumeRef = tstRslt.VolumeCTV; /// liter + tstRslt.CombinedMeters[iCmbnd].VolumeMeter = tstRslt.Meters[2 * iCmbnd].VolumeMeter + tstRslt.Meters[2 * iCmbnd + 1].VolumeMeter; + + tstRslt.CombinedMeters[iCmbnd].PulsesMaster = cBrd.EtPulses(0); + tstRslt.CombinedMeters[iCmbnd].Time = cBrd.TTime; + tstRslt.CombinedMeters[iCmbnd].VolumeErrorPct = Formulas.ErrorFromVolumes(tstRslt.CombinedMeters[iCmbnd].VolumeMeter, tstRslt.CombinedMeters[iCmbnd].VolumeRef); + tstRslt.CombinedMeters[iCmbnd].Passed = (tstRslt.ErrLimLo <= tstRslt.CombinedMeters[iCmbnd].VolumeErrorPct) && (tstRslt.CombinedMeters[iCmbnd].VolumeErrorPct <= tstRslt.ErrLimHi); + } + /// Add data - end + + AddOrOverwriteResult(tstRslt); + + Bridge.OnTestCompleted(this, new TestCompletedEventArgs(tstRslt)); + + /// Append the results to the CSV-file + allResults.Info(TestResult2CsvLine(tstRslt, cBrd.EtPulses(0))); + + FluentCommon.SaveToDb(StateMachine.WtSession, tstRslt); + + if (++repetitionNr <= test.Repeats) + { + goto loop; + } + + ///----------------------/// + /// Quit this sequence /// + ///----------------------/// + + /// Stop the pump + State.Create("CombinedMeters : Test(s) completed -> Closing the valves") + .AddOperation(checkUiOp) + .AddOperation(cBrd.SetValvesOp(null, inPath.Pump)) + .AddOperation((inPath != null && inPath.Pump is GenericDevices.IPumpFM) ? (inPath.Pump as GenericDevices.IPumpFM).TurnOff() : null) + .EnterState(); + do { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.Error)) goto error; + } + while (!e.Contains(Event.ValvesSet) || ((inPath.Pump is GenericDevices.IPumpFM) && !e.Contains(Event.TurnPumpOnOffDone))); + + /// Transition or SetRoute - End + if (transitionStop != null) + { + switch (Transition(transitionStop, "CombinedMeters : " + Strings.Test_stop_sequence_i_n)) + { + case Event.Error: goto error; + case Event.UiCmdStop: goto stop; + } + } + else + { + State.Create("CombinedMeters : Test(s) completed -> Closing the valves") + .AddOperation(checkUiOp) + .AddOperation(cBrd.SetValvesOp(StateMachine.DefaultValvesOpen, StateMachine.DefaultValvesClose)) + .EnterState(); + do { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.Error)) goto error; + } + while (!e.Contains(Event.ValvesSet)); + } + + /// Create the return value - a list with one event Event.Done - and return + IList retval = new List(); + retval.Add(Event.Done); + return retval; + + //==================================== + stop: + + State.Create("CombinedMeters : User selected STOP -> Closing the valves") + .AddOperation(checkUiOp) + .AddOperation((inPath != null && inPath.Pump is GenericDevices.IPumpFM) ? (inPath.Pump as GenericDevices.IPumpFM).TurnOff() : null) + .AddOperation(cBrd.SetValvesOp(StateMachine.DefaultValvesOpen, StateMachine.DefaultValvesClose)) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.Error)) goto error; + } + while (!e.Contains(Event.ValvesSet)); + + IList retval2 = new List(); + retval2.Add(Event.UiCmdStop); + return retval2; + + //==================================== + error: + State.Create("CombinedMeters : ERROR -> Closing the valves") + .AddOperation(checkUiOp) + .AddOperation((inPath != null && inPath.Pump is GenericDevices.IPumpFM) ? (inPath.Pump as GenericDevices.IPumpFM).TurnOff() : null) + .AddOperation(cBrd.SetValvesOp(StateMachine.DefaultValvesOpen, StateMachine.DefaultValvesClose)) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.Error)) goto error; + } + while (!e.Contains(Event.ValvesSet)); + + IList retval3 = new List(); + retval3.Add(Event.Error); + return retval3; + } + } +} diff --git a/TestBenchFramework/BenchControl/TestMethods/CombinedMeters/TestMethod.cs b/TestBenchFramework/BenchControl/TestMethods/CombinedMeters/TestMethod.cs new file mode 100644 index 000000000..7d3d5c3b7 --- /dev/null +++ b/TestBenchFramework/BenchControl/TestMethods/CombinedMeters/TestMethod.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using TBF.BenchControl; + +namespace TBF.BenchControl.TestMethods.CombinedMeters +{ + public class TestMethod : Generic.IComponent, GenericDevices.ITestMethod, ISequence + { + readonly TestMethodCfg testMethodCfg; + public Generic.IComponentCfg Cfg { get { return testMethodCfg; } } + + public static void ResetStaticProperties() { } + + public string Name { get { return testMethodCfg.Name; } } + + public TestMethod(TestMethodCfg cfg) + { + if (cfg == null) throw new ArgumentNullException("cfg"); + this.testMethodCfg = cfg; + } + + public IList Execute(Entities.Test test) + { + return (new CombinedMetersSeq()).Execute(test); + } + } +} diff --git a/TestBenchFramework/BenchControl/TestMethods/CombinedMeters/TestMethodCfg.cs b/TestBenchFramework/BenchControl/TestMethods/CombinedMeters/TestMethodCfg.cs new file mode 100644 index 000000000..39d12cff6 --- /dev/null +++ b/TestBenchFramework/BenchControl/TestMethods/CombinedMeters/TestMethodCfg.cs @@ -0,0 +1,54 @@ +using System; +using System.IO; +using System.Xml.Serialization; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.TestMethods.CombinedMeters +{ + public class TestMethodCfg : ComponentCfgBase, Generic.IComponentCfg + { + /// Parameterless constructor + public TestMethodCfg() + { + } + + /// + /// Data entry form configuration parameters + /// + /// Data entry form factory + /// Component name + public TestMethodCfg(IComponentFactory factory, string name) + : base(factory, name) + { + } + + public IComponentCfg Clone() + { + return new TestMethodCfg(Factory, Name); + } + + public string ToString(int i) + { + return string.Empty; + } + + public TBF.Entities.Component CreateDbEntity() + { + using (var writer = new StringWriter()) + { + (new XmlSerializer(GetType())).Serialize(writer, this); + return Entities.Component.CreateFromCfg(Name, Factory.ClassName, ParentName, ItemNr, DebugLevel, LogLevel, writer.ToString()); + } + } + + public static IComponentCfg CreateFromDbEntity(Entities.Component component, IComponentFactory factory) + { + using (var reader = new StringReader(component.Parameters)) + { + TestMethodCfg config = (TestMethodCfg)(new XmlSerializer(typeof(TestMethodCfg))).Deserialize(reader); + config.InitCfgBaseFromEntity(component, factory); + return config; + } + } + } +} diff --git a/TestBenchFramework/BenchControl/TestMethods/CombinedMeters/TestMethodCfgCtrl.cs b/TestBenchFramework/BenchControl/TestMethods/CombinedMeters/TestMethodCfgCtrl.cs new file mode 100644 index 000000000..b75f0a6ed --- /dev/null +++ b/TestBenchFramework/BenchControl/TestMethods/CombinedMeters/TestMethodCfgCtrl.cs @@ -0,0 +1,58 @@ +using System; +using System.Windows.Forms; +using log4net; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.TestMethods.CombinedMeters +{ + public partial class TestMethodCfgCtrl : UserControl, IComponentCfgCtrl + { + static readonly ILog log = LogManager.GetLogger(typeof(TestMethodCfgCtrl)); + + TestMethodCfg config; + + public IComponentCfg Config + { + get { return config as IComponentCfg; } + set + { + config = value as TestMethodCfg; + Redraw(); + } + } + + public TestMethodCfgCtrl() + { + InitializeComponent(); + } + + private void EntryFormCfgCtrl_Load(object sender, EventArgs e) + { + Redraw(); + } + + void Redraw() + { + if (config == null) return; /// Control was not loaded, settings were not changed + classNameLabel.Text = config.Factory.ClassName; + nameTextBox.Text = config.Name; + } + + public void Unlock() + { + nameTextBox.Enabled = true; + } + + public CfgVerifyFlags VerifyCfg(ref string message) + { + CfgVerifyFlags flags = CfgVerifyFlags.None; + return flags; + } + + public void UpdateCfg() + { + if (config == null) return; /// Control was not loaded, settings were not changed + config.Name = nameTextBox.Text; + } + } +} diff --git a/TestBenchFramework/BenchControl/TestMethods/CombinedMeters/TestMethodCfgCtrl.designer.cs b/TestBenchFramework/BenchControl/TestMethods/CombinedMeters/TestMethodCfgCtrl.designer.cs new file mode 100644 index 000000000..d67a0f394 --- /dev/null +++ b/TestBenchFramework/BenchControl/TestMethods/CombinedMeters/TestMethodCfgCtrl.designer.cs @@ -0,0 +1,83 @@ +namespace TBF.BenchControl.TestMethods.CombinedMeters +{ + partial class TestMethodCfgCtrl + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.nameTextBox = new System.Windows.Forms.TextBox(); + this.nameLabel = new System.Windows.Forms.Label(); + this.classNameLabel = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // nameTextBox + // + this.nameTextBox.Enabled = false; + this.nameTextBox.Location = new System.Drawing.Point(137, 57); + this.nameTextBox.Name = "nameTextBox"; + this.nameTextBox.Size = new System.Drawing.Size(130, 20); + this.nameTextBox.TabIndex = 5; + // + // nameLabel + // + this.nameLabel.AutoSize = true; + this.nameLabel.Location = new System.Drawing.Point(27, 60); + this.nameLabel.Name = "nameLabel"; + this.nameLabel.Size = new System.Drawing.Size(35, 13); + this.nameLabel.TabIndex = 4; + this.nameLabel.Text = "Name"; + // + // classNameLabel + // + this.classNameLabel.AutoSize = true; + this.classNameLabel.Location = new System.Drawing.Point(134, 33); + this.classNameLabel.Name = "classNameLabel"; + this.classNameLabel.Size = new System.Drawing.Size(83, 13); + this.classNameLabel.TabIndex = 3; + this.classNameLabel.Text = "ComonentName"; + // + // BasicPrinterCfgCtrl + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.nameTextBox); + this.Controls.Add(this.nameLabel); + this.Controls.Add(this.classNameLabel); + this.Name = "BasicPrinterCfgCtrl"; + this.Size = new System.Drawing.Size(300, 200); + this.Load += new System.EventHandler(this.EntryFormCfgCtrl_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TextBox nameTextBox; + private System.Windows.Forms.Label nameLabel; + private System.Windows.Forms.Label classNameLabel; + } +} diff --git a/TestBenchFramework/BenchControl/TestMethods/CombinedMeters/TestMethodCfgCtrl.resx b/TestBenchFramework/BenchControl/TestMethods/CombinedMeters/TestMethodCfgCtrl.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/TestBenchFramework/BenchControl/TestMethods/CombinedMeters/TestMethodCfgCtrl.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/BenchControl/TestMethods/CombinedMeters/TestMethodFactory.cs b/TestBenchFramework/BenchControl/TestMethods/CombinedMeters/TestMethodFactory.cs new file mode 100644 index 000000000..68030affa --- /dev/null +++ b/TestBenchFramework/BenchControl/TestMethods/CombinedMeters/TestMethodFactory.cs @@ -0,0 +1,41 @@ +using System.Collections.Generic; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.TestMethods.CombinedMeters +{ + public class TestMethodFactory : IComponentFactory + { + public string ClassName { get { return "CombinedMeters"; } } + + public bool HasProcedureParams { get { return false; } } + public IParamsProvider GetProcedureParams(Entities.ComponentProcedure procedureParams) { return null; } + public bool HasTestParams { get { return false; } } + public IParamsProvider GetTestParams(Entities.ComponentTest testParams) { return null; } + + /// Max. number of components of this class in the system + public int MaxCount { get { return 1; } } + + + public IComponentCfg DefaultConfig(IList components) + { + return new TestMethodCfg(this, "CombinedMeters"); + } + + public IComponentCfgCtrl CreateCfgCtrl() + { + return new TestMethodCfgCtrl(); + } + + public IComponent ComponentFromCmpntCfg(IComponentCfg config, IList components) + { + return new TestMethod((TestMethodCfg)config); + } + + public IComponentCfg CmpntCfgFromCmpntEntity(Entities.Component component) + { + return TestMethodCfg.CreateFromDbEntity(component, this); + } + + public void ResetStaticProperties() { TestMethod.ResetStaticProperties(); } + } +} diff --git a/TestBenchFramework/BenchControl/TestMethods/CombinedWithDetection/CombinedWithDetTestParams.cs b/TestBenchFramework/BenchControl/TestMethods/CombinedWithDetection/CombinedWithDetTestParams.cs new file mode 100644 index 000000000..24f1c776d --- /dev/null +++ b/TestBenchFramework/BenchControl/TestMethods/CombinedWithDetection/CombinedWithDetTestParams.cs @@ -0,0 +1,177 @@ +using System; +using System.IO; +using System.Text; +using System.Xml.Serialization; +using TBF.BenchControl.Generic; +using TBF.Resources; + +namespace TBF.BenchControl.TestMethods.CombinedWithDetection +{ + public class CombinedWithDetTestParams : IParamsProvider, ITestParams + { + public float TargetQ; /// Target=terminal flow durning detection when increasing or decreasing the flow + public float RelativeQfrom; /// Tested flow low range related to the detected flow + public float RelativeQto; /// Tested flow high range related to the detected flow + public float RateOfChange; /// Each step is calculated as (TargetQfrom - Qfrom) * RateOfChange, text form is displayed in % (*100) + public float DetectionThreshold;/// Drop of frequency for the detection, text form is displayed in % (*100) + + string[] paramNames = new string[] + { + Strings.TargetQ, + Strings.RelativeQfrom, + Strings.RelativeQto, + Strings.RateOfChangePct, + Strings.DetectionThresholdPct, + }; + public string ParamName(int i) { return paramNames[i]; } + + public string ToString(int i) + { + switch (i) + { + case 0: return TargetQ.ToString(); + case 1: return RelativeQfrom.ToString(); + case 2: return RelativeQto.ToString(); + case 3: return (100.0f * RateOfChange).ToString(); + case 4: return (100.0f * DetectionThreshold).ToString(); + default: return string.Empty; + } + } + + public void UpdateParam(int i, string strValue) + { + switch (i) + { + case 0: TargetQ = Utils.ParseUFloat(strValue); return; + case 1: RelativeQfrom = Utils.ParseSFloat(strValue); return; + case 2: RelativeQto = Utils.ParseSFloat(strValue); return; + case 3: RateOfChange = Utils.ParseUFloat(strValue) / 100.0f; return; + case 4: DetectionThreshold = Utils.ParseUFloat(strValue) / 100.0f; return; + default: return; + } + } + + public bool ValidateParam(int i, string strValue, out string message) + { + message = string.Empty; + + float dummy; + switch (i) + { + case 0: + case 3: + case 4: + if (Utils.TryParseUFloat(strValue, out dummy)) return true; + break; + case 1: + case 2: + if (Utils.TryParseSFloat(strValue, out dummy)) return true; + break; + default: + message = "Invalid index"; + return false; + } + + message = ParamName(i) + " is invalid"; + return false; + } + + #region Boilerplate code + + public int ParamsCount() { return paramNames.Length; } + + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < ParamsCount(); i++) + { + if (i != 0) sb.Append("; "); + sb.Append(ParamName(i)); + sb.Append("="); + sb.Append(ToString(i)); + } + return sb.ToString(); + } + + [XmlIgnore] + public Entities.ComponentTest TestParamsEntity { get { return testParamsEntity; } } + Entities.ComponentTest testParamsEntity; + + [XmlIgnore] + public string ComponentName { get { return componentName; } } + string componentName; + + [XmlIgnore] + public Entities.Test Test { get { return test; } } + Entities.Test test; + + /// Parameterless constructor + public CombinedWithDetTestParams() + { + TargetQ = 3.0f; + RelativeQfrom = -0.4f; + RelativeQto = -0.2f; + RateOfChange = 0.05f; + DetectionThreshold = 0.25f; + } + + public CombinedWithDetTestParams(Entities.ComponentTest testParamsEntity, string componentName, Entities.Test test) + : this() + { + this.testParamsEntity = testParamsEntity; + this.componentName = componentName; + this.test = test; + } + + public TBF.Entities.ComponentTest ToDbEntity(IComponent component, Entities.Test test) + { + using (var writer = new StringWriter()) + { + /// Serialize this class with parameters + (new XmlSerializer(GetType())).Serialize(writer, this); + + /// Create and return the ComponentTest entity + TBF.Entities.ComponentTest entity = new TBF.Entities.ComponentTest(); + entity.CmpntName = component.Cfg.Name; + entity.Parameters = writer.ToString(); + entity.Test = test; + return entity; + } + } + + public void UpdateDbEntity() + { + using (var writer = new StringWriter()) + { + /// Serialize this class and update the entity + (new XmlSerializer(GetType())).Serialize(writer, this); + testParamsEntity.Parameters = writer.ToString(); + testParamsEntity.CmpntName = componentName; + testParamsEntity.Test = test; + + } + } + + public static IParamsProvider GetTestParams(Entities.ComponentTest testParamsEntity) + { + if (testParamsEntity == null) return new CombinedWithDetTestParams(); + + CombinedWithDetTestParams testParams; + try + { + testParams = (CombinedWithDetTestParams)(new XmlSerializer(typeof(CombinedWithDetTestParams))) + .Deserialize(new StringReader(testParamsEntity.Parameters)); + } + catch + { + testParams = new CombinedWithDetTestParams(); + } + testParams.testParamsEntity = testParamsEntity; + testParams.componentName = testParamsEntity.CmpntName; + testParams.test = testParamsEntity.Test; + return testParams; + } + + #endregion + } +} diff --git a/TestBenchFramework/BenchControl/TestMethods/CombinedWithDetection/CombinedWithDetectionSeq.cs b/TestBenchFramework/BenchControl/TestMethods/CombinedWithDetection/CombinedWithDetectionSeq.cs new file mode 100644 index 000000000..8ce8d0993 --- /dev/null +++ b/TestBenchFramework/BenchControl/TestMethods/CombinedWithDetection/CombinedWithDetectionSeq.cs @@ -0,0 +1,668 @@ +using System; +using System.Collections.Generic; +using System.Text; +using log4net; +using TBF.UiBridge; +using TBF.BenchControl; +using TBF.Resources; + +namespace TBF.BenchControl.TestMethods.CombinedWithDetection +{ + public class CombinedWithDetectionSeq : Sequences.SequenceBase + { + private static readonly ILog log = LogManager.GetLogger(typeof(CombinedWithDetectionSeq)); + private static readonly ILog allResults = LogManager.GetLogger("AllResults"); + private static readonly ILog summaryResults = LogManager.GetLogger("SummaryResults"); + + const int DetectionBufferSize = 9; + const int DetectionKernelSize = 5; + + public IList Execute(Entities.Test test, CombinedWithDetTestParams testParams) + { + Elde.ControlBoardDev cBrd = StateMachine.ControlBoard; + + /// Specific for combined meters + int[] lastWMPulses = new int[Program.WMsCount]; + + /// Operations running in more then one state + checkUiOp = new Operations.CheckUIOp(true); + + IList e; /// Events from currently running operations + + //-------------------------------- + State.Create("CombinedWithDetection : stop diverter gate etc") + .AddOperation(checkUiOp) + .AddOperation(cBrd.StopPreviousOp()) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.UiCmdStop)) goto stop; + } + while (!e.Contains(Event.PreviousStopped)); + + /// Fetch the test, the paths + bool success = StateMachine.GetPaths(test, out inPath, out benchPath, out outPath, out sensPath, + out transitionStart, out transitionStop); + if (!success) goto error; + + /// Notes: + /// float timeHr = volumeLtr / (1000.0f * targetFlow); + /// float timeSec = 3600.0f * timeHr; + /// uint refPulses = (uint)(timeSec * (2000.0f * targetFlow / pOut.FlowMeter.NominalFlow)); + int totalPulses = (int)(7200.0f * test.Volume / outPath.FlowMeter.NominalFlow); /// Nominal flow in [m3/h] + + float ltrPerRefPulse = outPath.FlowMeter.NominalFlow / 7200.0f; /// [ltr/pulse] + /// + /// Meters path is required for the following: + readRegisters1 = new Operations.ReadMoreRegistersOp(sensPath.RegisterReaders, ref WMPulses, ref WMRefPulses); + readRegisters2 = new Operations.ReadMoreRegistersOp(sensPath.RegisterReaders, ref WMPulses, ref WMRefPulses); + + int repetitionNr = 1; /// First test: repetitionNr=1 + + //==================================== + // Transition or SetRoute - Start + //==================================== + if (transitionStart != null) + { + switch (Transition(transitionStart, "CombinedWithDetection : " + Strings.Test_start_sequence_i_n)) + { + case Event.Error: goto error; + case Event.UiCmdStop: goto stop; + } + } + else + { + //-------------------------------- + State.Create("CombinedWithDetection : Setting the route") + .AddOperation(checkUiOp) + .AddOperation(cBrd.SetValvesOp(GenericDevices.ValveBase.Merge(inPath.ValvesOpen, benchPath.ValvesOpen, outPath.ValvesOpen), + GenericDevices.ValveBase.Merge(inPath.ValvesClose, benchPath.ValvesClose, outPath.ValvesClose))) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.UiCmdStop)) goto stop; + } + while (!e.Contains(Event.ValvesSet)); + } + + //==================================== + loop: + /// Start the test, initialize test results + Bridge.OnTestSelected(this, new TestSelectedEventArgs(test, repetitionNr, inPath, benchPath, outPath, sensPath, (int)totalPulses)); + Entities.TestResult tstRslt = new Entities.TestResult(test, repetitionNr, Entities.MetersKind.Combined); + + + if (!test.Emptying) /// Do not skip emptying if test.Emptying==true + { + //-------------------------------- + State.Create("CombinedWithDetection : Get the mass of water in the tank") + .AddOperation(checkUiOp) + .AddOperation(outPath.Balance.ReadMassOp(ref mass)) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.Error)) goto error; + if (e.Contains(Event.UiCmdStop)) goto stop; + } + while (!e.Contains(Event.BalanceDone)); + + float estimatedEndMass = mass.F + test.Volume; + if (estimatedEndMass < outPath.Balance.Capacity * Constants.TankFullFactor) + { + goto switching_flow_detection; /// Enough room in the tank -> skip emptying + } + } + + // Empty the water tank + switch (EmptyTheTank(outPath.EmptyTankValve, outPath.Balance)) + { + case Event.Error: goto error; + case Event.UiCmdStop: goto stop; + } + + switching_flow_detection: + + /// Extract cameras from the current sensors path, add operations to the detection state + IList measureOperations = new List(); + for (int i = 0; i < sensPath.RegisterReaders.Length; i++) + { + GenericDevices.ICameraRoi cameraRoi = sensPath.RegisterReaders[i] as GenericDevices.ICameraRoi; + if (cameraRoi != null) measureOperations.Add(cameraRoi.MeasureOp()); + } + + //------------------------------------------------ + Bridge.OnActivity(this, Strings.Switching_flow_detection); + //------------------------------------------------ + State.Create("CombinedWithDetection : Start the pump") + .AddOperation(checkUiOp) + .AddOperations(measureOperations) + .AddOperation((inPath != null && inPath.Pump is GenericDevices.IPumpFM) ? (inPath.Pump as GenericDevices.IPumpFM).TurnOn() : null) + .AddOperation(cBrd.SetValvesOp(inPath.Pump, null)) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.UiCmdStop)) goto stop; + } + while (!e.Contains(Event.ValvesSet)); + + //-------------------------------- + State.Create("CombinedWithDetection : Set the initial flow") + .AddOperation(checkUiOp) + .AddOperations(measureOperations) + .AddOperation(outPath.RegulValve.SetFlowAndMeasureOp(outPath.FlowMeter, test.Qfrom, test.Qto, measuredFlow, 600)) /// timeout = 10 min. + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.UiCmdStop)) goto stop; + if (e.Contains(Event.RegulValveTimeOut)) goto error; + } + while (!e.Contains(Event.FlowReached)); + + //-------------------------------- + switch (ReadRegistersTempPressAmbient(measureOperations, false)) + { + case Event.Error: goto error; + case Event.UiCmdStop: goto stop; + } + + //==================================== + // Find the switching flow + //==================================== + + /// Allocate detection buffers + float[] flowsForDetection = new float[DetectionBufferSize]; + float[] pulseFreqsForDetection = new float[DetectionBufferSize]; + + /// Current values + flowsForDetection[0] = measuredFlow.F; + pulseFreqsForDetection[0] = 0.0f; + int startTime = StateMachine.CurrentTime; + int lastTime = StateMachine.CurrentTime; + + /// Detection parameters + float rvPulse = (testParams.TargetQ > (test.Qfrom + test.Qto) / 2.0f) ? 0.05f : -0.05f; // rise or fall? + rvPulse *= (100.0f * testParams.RateOfChange); + + bool detected = false; + bool targetReached = false; + float detectedFlow = 0; + + do + { + //-------------------------------- + State.Create("CombinedWithDetection : Change the RV position") + .AddOperation(checkUiOp) + .AddOperations(measureOperations) + .AddOperation(outPath.RegulValve.ChangeRegulValvePositionOp(rvPulse)) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.UiCmdStop)) goto stop; + } + while (!e.Contains(Event.PositionReached)); + + // Last pulses are kept to calculate differences + for (int i = 0; i < Program.WMsCount; i++) lastWMPulses[i] = WMPulses[i]; + + // Shift data in the detection buffers + for (int i = DetectionBufferSize - 2; i >= 0; i--) + { + flowsForDetection[i+1] = flowsForDetection[i]; + pulseFreqsForDetection[i+1] = pulseFreqsForDetection[i]; + } + + switch (ReadRegistersTempPressAmbient(measureOperations, false)) + { + case Event.Error: goto error; + case Event.UiCmdStop: goto stop; + } + + int time = StateMachine.CurrentTime; + int diff = WMPulses[1] - lastWMPulses[1]; + flowsForDetection[0] = cBrd.ReferenceFreq * outPath.FlowMeter.NominalFlow / 2000.0f; + pulseFreqsForDetection[0] = (float)diff / (float)(time - lastTime); + lastTime = StateMachine.CurrentTime; + + if ((flowsForDetection[0] > 0) && (flowsForDetection[DetectionBufferSize - 1] > 0)) + { + float[] flowBefore = new float[DetectionKernelSize]; + float[] flowAfter = new float[DetectionKernelSize]; + float[] freqBefore = new float[DetectionKernelSize]; + float[] freqAfter = new float[DetectionKernelSize]; + for (int i = 0; i < DetectionKernelSize; i++) + { + flowBefore[i] = flowsForDetection[DetectionBufferSize - DetectionKernelSize + i]; + freqBefore[i] = pulseFreqsForDetection[DetectionBufferSize - DetectionKernelSize + i]; + flowAfter[i] = flowsForDetection[i]; + freqAfter[i] = pulseFreqsForDetection[i]; + } + Array.Sort(flowBefore); + Array.Sort(flowAfter); + Array.Sort(freqBefore); + Array.Sort(freqAfter); + flowBefore[0] = 0; + flowAfter[0] = 0; + //freqBefore[0] = 0; + //freqAfter[0] = 0; + flowBefore[DetectionKernelSize - 1] = 0; + flowAfter[DetectionKernelSize - 1] = 0; + //freqBefore[DetectionKernelSize - 1] = 0; + //freqAfter[DetectionKernelSize - 1] = 0; + float aveFlowBefore = 0; + float aveFlowAfter = 0; + float aveFreqBefore = 0; + float aveFreqAfter = 0; + foreach (var f in flowBefore) aveFlowBefore += f; + foreach (var f in flowAfter) aveFlowAfter += f; + foreach (var f in freqBefore) aveFreqBefore += f; + foreach (var f in freqAfter) aveFreqAfter += f; + aveFlowBefore /= (float)(DetectionKernelSize - 2); + aveFlowAfter /= (float)(DetectionKernelSize - 2); + aveFreqBefore /= (float)(DetectionKernelSize); + aveFreqAfter /= (float)(DetectionKernelSize); + + UiBridge.Bridge.OnLog(this, string.Format("time={0}, flow{1}, aveFlowB={2}, aveFlowA={3}, pulseFreq={4}, aveFreqB={5}, aveFreqA={6}\r\n", + time - startTime, + flowsForDetection[0].ToString("F2"), + aveFlowBefore.ToString("F2"), + aveFlowAfter.ToString("F2"), + pulseFreqsForDetection[0].ToString("F2"), + aveFreqBefore.ToString("F2"), + aveFreqAfter.ToString("F2"))); + + //detectedFlow = (aveFlowBefore + aveFlowAfter) / 2.0f; + detectedFlow = aveFlowBefore; + + if (rvPulse > 0) + { + detected = (aveFreqAfter < aveFreqBefore * (1.0f - testParams.DetectionThreshold)); + targetReached = ((aveFlowAfter + aveFlowBefore) / 2.0f) > testParams.TargetQ; + } + else + { + detected = (aveFreqAfter > aveFreqBefore * (1.0f + testParams.DetectionThreshold)); + targetReached = ((aveFlowAfter + aveFlowBefore) / 2.0f) < testParams.TargetQ; + } + } + } + while (!detected && !targetReached); + + if (rvPulse > 0) + { + Qrise = detectedFlow; + } + else + { + Qfall = detectedFlow; + } + + UiBridge.Bridge.OnLog(this, string.Format("detected flow={0}\r\n", detectedFlow.ToString("F2"))); + + float qfrom_test = detectedFlow + testParams.RelativeQfrom; + float qto_test = detectedFlow + testParams.RelativeQto; + + /// Update test results with the test flow determined from the detected switching flow + tstRslt.Qfrom = qfrom_test; + tstRslt.Qto = qto_test; + float Qave_lps = (qfrom_test + qto_test) / 7.2f; + tstRslt.TstTime = tstRslt.Volume / Qave_lps; + + + //-------------------------------- + State.Create("CombinedWithDetection : Switching flow detected, going back") + .AddOperation(checkUiOp) + .AddOperations(measureOperations) + .AddOperation(outPath.RegulValve.SetFlowOp(outPath.FlowMeter, test.Qfrom, test.Qto, measuredFlow, 600)) /// timeout = 10 min. + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.UiCmdStop)) goto stop; + if (e.Contains(Event.RegulValveTimeOut)) goto error; + } + while (!e.Contains(Event.FlowReached)); + + //-------------------------------- + State.Create("CombinedWithDetection : Going to the test flow") + //State.Create("set_RV_position", + .AddOperation(checkUiOp) + .AddOperations(measureOperations) + .AddOperation(outPath.RegulValve.SetFlowOp(outPath.FlowMeter, qfrom_test, qto_test, measuredFlow, 10)) /// timeout = 10 sec. + //.AddOp(pOut.RegulValve.SetPositionOp(35.0f, 38.0f, uint.MaxValue)) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.UiCmdStop)) goto stop; + //if (e.Contains(Event.FlowTimeOut)) goto do_detection; + } + while (!e.Contains(Event.FlowReached)); + + + start_measurement: + + //------------------------------------------------ + Bridge.OnActivity(this, Strings.Measuring_the_weight); + //------------------------------------------------ + State.Create(Strings.Measure_the_mass) + .AddOperation(checkUiOp) + .AddOperations(measureOperations) + .AddOperation(outPath.Balance.ReadStableMassOp(ref stableMass, 5)) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.Error)) goto error; + if (e.Contains(Event.UiCmdStop)) goto stop; + } + while (!e.Contains(Event.BalanceDone)); + + tstRslt.TimeStart = DateTime.Now; + tstRslt.MassStartRaw = stableMass.F; + mass.F = stableMass.F; + + //------------------------------------------------ + Bridge.OnActivity(this, Strings.Test_in_progress); + //------------------------------------------------ + State.Create(Strings.Start_the_test) + .AddOperation(checkUiOp) + .AddOperations(measureOperations) + .AddOperation(cBrd.StartMeasurementOp(outPath.FlowMeter, totalPulses, Elde.TestMethods.Diverter | Elde.TestMethods.Synchro)) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.Error)) goto error; + if (e.Contains(Event.UiCmdStop)) goto stop; + } + while (!e.Contains(Event.MeasurementStarted)); + + /// + /// Measurement loop - preparation + /// + queryEnd1 = cBrd.QueryMeasurementEndOp(); + queryEnd2 = cBrd.QueryMeasurementEndOp(); + + bool firstTime = true; /// Used to reset sums for averaging + ResetAveragedData(); + + /// Measurement loop - begin + while (true) + { + //-------------------------------- + switch (ReadRegistersTempPressAmbient(measureOperations, true)) + { + case Event.Error: goto error; + case Event.UiCmdStop: goto stop; + case Event.MeasurementCompleted: goto measurement_completed; + } + + if (firstTime) + { + firstTime = false; /// Do the following only once + tstRslt.TempInStart = tempIn.F; + tstRslt.TempOutStart = tempOut.F; + tstRslt.TempDivStart = tempDiv.F; + tstRslt.PressInStart = pressIn.F; + tstRslt.PressOutStart = pressOut.F; + } + + tstRslt.TempInEnd = tempIn.F; + tstRslt.TempOutEnd = tempOut.F; + tstRslt.TempDivEnd = tempDiv.F; + tstRslt.PressInEnd = pressIn.F; + tstRslt.PressOutEnd = pressOut.F; + tstRslt.MassEndRaw = mass.F; + + AccumulateAveragedData(); + + + string logstr = string.Format("E={0} f={1} q={2}", cBrd.EtPulses(0), cBrd.ReferenceFreq, + cBrd.ReferenceFlow * outPath.FlowMeter.NominalFlow); + for (int i = 0; i < Program.WMsCount; i++) + { + logstr += string.Format(" M{0}=({1},{2})", i + 1, WMRefPulses[i], WMPulses[i]); + } + log.Info(logstr); + + + float progress = Formulas.TestProgress(cBrd.EtPulses(0), totalPulses, 10.0f, test.TstTime); + TestProgressEventArgs data = GetTestProgressData(test, tstRslt, cBrd.EtPulses(0), cBrd.TTime, progress); + data.WmVolume[2] = data.WmVolume[0] + data.WmVolume[1]; + data.WmErrPct[2] = Formulas.ErrorFromVolumes(data.WmVolume[2], data.Volume); + Bridge.OnTestProgress(this, data); + } + /// Measurement loop - end + + + measurement_completed: + + //------------------------------------------------ + Bridge.OnActivity(this, Strings.Measuring_the_weight); + //------------------------------------------------ + State.Create(Strings.Measure_the_mass) + .AddOperation(checkUiOp) + .AddOperation(outPath.Balance.ReadStableMassOp(ref stableMass, 5)) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.Error)) goto error; + if (e.Contains(Event.UiCmdStop)) goto stop; + } + while (!e.Contains(Event.BalanceDone)); + /// + tstRslt.MassEndRaw = stableMass.F; + tstRslt.TimeEnd = DateTime.Now; + + //------------------------------------------------ + Bridge.OnActivity(this, Strings.Test_completed); + //------------------------------------------------ + State.Create(Strings.Stop_the_pump) + .AddOperation(checkUiOp) + .AddOperation((inPath != null && inPath.Pump is GenericDevices.IPumpFM) ? (inPath.Pump as GenericDevices.IPumpFM).TurnOff() : null) + .AddOperation(cBrd.SetValvesOp(null, inPath.Pump)) + .AddOperation(cBrd.UpdateTankWeightOp()) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.UiCmdStop)) goto stop; + } + while (!e.Contains(Event.ValvesSet)); + + + //-------------------------------- + State.Create("stop_diverter_gate_etc") + .AddOperation(checkUiOp) + .AddOperation(cBrd.StopPreviousOp()) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.UiCmdStop)) goto stop; + } + while (!e.Contains(Event.PreviousStopped)); + + /// + /// Populate TestRasult data entity with data + /// + tstRslt.TimeEnd = DateTime.Now; + UpdateTestRsltWithAveragedData(tstRslt); + tstRslt.MassStart = Formulas.CorrectedValue(tstRslt.MassStartRaw, outPath.Balance.Corrections); + tstRslt.MassEnd = Formulas.CorrectedValue(tstRslt.MassEndRaw, outPath.Balance.Corrections); + tstRslt.MassDiff = tstRslt.MassEnd - tstRslt.MassStart; + tstRslt.DensityIn = Formulas.WaterDensityFromTemp(tstRslt.TempInAvrg); /// [kg/m3] + tstRslt.DensityOut = Formulas.WaterDensityFromTemp(tstRslt.TempOutAvrg); /// [kg/m3] + tstRslt.DensityDiv = Formulas.WaterDensityFromTemp(tstRslt.TempDivAvrg); /// [kg/m3] + tstRslt.Time = cBrd.TTime; /// [s] measurement time + tstRslt.FlowMass = 3600.0f * tstRslt.MassDiff / tstRslt.Time; /// [kg/h] + tstRslt.FlowVolume = 3600.0f * ltrPerRefPulse * cBrd.EtPulses(0) / tstRslt.Time; /// [l/h] + tstRslt.VolumeCTV = 1.00103f * 1000.0f * tstRslt.MassDiff / tstRslt.DensityOut; /// [l] 1000.0f is because density is in [kg/m3] + tstRslt.VolumeMaster = ltrPerRefPulse * cBrd.EtPulses(0); /// [l] volume from the master flow meter + tstRslt.PulsesMaster = cBrd.EtPulses(0); /// Pulses of the master flow meter (test total) + tstRslt.ConstMaster = ltrPerRefPulse * tstRslt.VolumeCTV / tstRslt.VolumeMaster; + /// Corrected master pulses per liter + if (tstRslt.VolumeCTV <= float.Epsilon) + { + tstRslt.ErrorMaster = 0.1f; + } + else + { + tstRslt.ErrorMaster = 100 * (tstRslt.VolumeMaster - tstRslt.VolumeCTV) / tstRslt.VolumeCTV; + } + tstRslt.TimeDivStart0 = 0; + tstRslt.TimeDivStart1 = 0; + tstRslt.TimeDivStart2 = 0; + tstRslt.TimeDivStart3 = 0; + tstRslt.TimeDivStart4 = 0; + tstRslt.TimeDivStart5 = 0; + tstRslt.TimeDivEnd0 = 0; + tstRslt.TimeDivEnd1 = 0; + tstRslt.TimeDivEnd2 = 0; + tstRslt.TimeDivEnd3 = 0; + tstRslt.TimeDivEnd4 = 0; + tstRslt.TimeDivEnd5 = 0; + + for (int iCmbnd = 0; iCmbnd < Program.WMsCount / 2; iCmbnd++) + { + for (int i = 2 * iCmbnd; i < 2 * iCmbnd + 2; i++) + { + if (sensPath.RegisterReaders[i] == null || sensPath.RegisterReaders[i].PulsesPerLtr <= float.Epsilon) + { + tstRslt.Meters[i].VolumeMeter = 0; + } + else + { + tstRslt.Meters[i].VolumeMeter = Convert.ToSingle(WMPulses[i]) / sensPath.RegisterReaders[i].PulsesPerLtr; + } + + tstRslt.Meters[i].SerialNr = "wm" + (i + 1).ToString(); + tstRslt.Meters[i].VolumeStart = 0; /// liter + tstRslt.Meters[i].VolumeEnd = 0; /// liter + + tstRslt.Meters[i].VolumeRef = tstRslt.VolumeCTV; /// liter + if (WMRefPulses[i] != 0) + { + tstRslt.Meters[i].VolumeMeter *= ((float)cBrd.EtPulses(0) / (float)WMRefPulses[i]); + } + + tstRslt.Meters[i].PulsesMeter = WMPulses[i]; + tstRslt.Meters[i].PulsesMaster = WMRefPulses[i]; + tstRslt.Meters[i].Time = cBrd.TTime; + + tstRslt.Meters[i].VolumeErrorPct = 0; /// Not used + } + + tstRslt.CombinedMeters[iCmbnd].VolumeRef = tstRslt.VolumeCTV; /// liter + tstRslt.CombinedMeters[iCmbnd].VolumeMeter = tstRslt.Meters[2 * iCmbnd].VolumeMeter + tstRslt.Meters[2 * iCmbnd + 1].VolumeMeter; + + tstRslt.CombinedMeters[iCmbnd].PulsesMaster = cBrd.EtPulses(0); + tstRslt.CombinedMeters[iCmbnd].Time = cBrd.TTime; + tstRslt.CombinedMeters[iCmbnd].VolumeErrorPct = Formulas.ErrorFromVolumes(tstRslt.CombinedMeters[iCmbnd].VolumeMeter, tstRslt.CombinedMeters[iCmbnd].VolumeRef); + tstRslt.CombinedMeters[iCmbnd].Passed = (tstRslt.ErrLimLo <= tstRslt.CombinedMeters[iCmbnd].VolumeErrorPct) && (tstRslt.CombinedMeters[iCmbnd].VolumeErrorPct <= tstRslt.ErrLimHi); + } + /// Add data - end + + Bridge.OnTestCompleted(this, new TestCompletedEventArgs(tstRslt)); + + AddOrOverwriteResult(tstRslt); + + /// Append the results to the CSV-file + allResults.Info(TestResult2CsvLine(tstRslt, cBrd.EtPulses(0))); + + FluentCommon.SaveToDb(StateMachine.WtSession, tstRslt); + + if (++repetitionNr <= test.Repeats) + { + goto loop; + } + + ///----------------------/// + /// Quit this sequence /// + ///----------------------/// + + /// Stop the pump + State.Create("CombinedWithDetection : Test(s) completed -> Stopping the pump") + .AddOperation(checkUiOp) + .AddOperation(cBrd.SetValvesOp(null, inPath.Pump)) + .AddOperation((inPath != null && inPath.Pump is GenericDevices.IPumpFM) ? (inPath.Pump as GenericDevices.IPumpFM).TurnOff() : null) + .EnterState(); + do { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.Error)) goto error; + } + while (!e.Contains(Event.ValvesSet) || ((inPath.Pump is GenericDevices.IPumpFM) && !e.Contains(Event.TurnPumpOnOffDone))); + + /// Transition or SetRoute - End + if (transitionStop != null) + { + switch (Transition(transitionStop, "CombinedWithDetection : " + Strings.Test_stop_sequence_i_n)) + { + case Event.Error: goto error; + case Event.UiCmdStop: goto stop; + } + } + else + { + State.Create("CombinedWithDetection : Test(s) completed -> Closing the valves") + .AddOperation(checkUiOp) + .AddOperation(cBrd.SetValvesOp(StateMachine.DefaultValvesOpen, StateMachine.DefaultValvesClose)) + .EnterState(); + do { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.Error)) goto error; + } + while (!e.Contains(Event.ValvesSet)); + } + + /// Create the return value - a list with one event Event.Done - and return + IList retval = new List(); + retval.Add(Event.Done); + return retval; + + //==================================== + stop: + + State.Create("CombinedWithDetection : User selected STOP -> Closing the valves") + .AddOperation(checkUiOp) + .AddOperation((inPath != null && inPath.Pump is GenericDevices.IPumpFM) ? (inPath.Pump as GenericDevices.IPumpFM).TurnOff() : null) + .AddOperation(cBrd.SetValvesOp(StateMachine.DefaultValvesOpen, StateMachine.DefaultValvesClose)) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.Error)) goto error; + } + while (!e.Contains(Event.ValvesSet)); + + IList retval2 = new List(); + retval2.Add(Event.UiCmdStop); + return retval2; + + //==================================== + error: + State.Create("close_before_error") + .AddOperation(checkUiOp) + .AddOperation((inPath != null && inPath.Pump is GenericDevices.IPumpFM) ? (inPath.Pump as GenericDevices.IPumpFM).TurnOff() : null) + .AddOperation(cBrd.SetValvesOp(StateMachine.DefaultValvesOpen, StateMachine.DefaultValvesClose)) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.Error)) goto error; + } + while (!e.Contains(Event.ValvesSet)); + + IList retval3 = new List(); + retval3.Add(Event.Error); + return retval3; + } + } +} diff --git a/TestBenchFramework/BenchControl/TestMethods/CombinedWithDetection/TestMethod.cs b/TestBenchFramework/BenchControl/TestMethods/CombinedWithDetection/TestMethod.cs new file mode 100644 index 000000000..5ab52ad41 --- /dev/null +++ b/TestBenchFramework/BenchControl/TestMethods/CombinedWithDetection/TestMethod.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using TBF.BenchControl; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.TestMethods.CombinedWithDetection +{ + public class TestMethod : Generic.IComponent, GenericDevices.ITestMethod, ISequence + { + readonly TestMethodCfg testMethodCfg; + public Generic.IComponentCfg Cfg { get { return testMethodCfg; } } + + public static void ResetStaticProperties() { } + + public string Name { get { return testMethodCfg.Name; } } + + public TestMethod(TestMethodCfg cfg) + { + if (cfg == null) throw new ArgumentNullException("cfg"); + this.testMethodCfg = cfg; + } + + public IList Execute(Entities.Test test) + { + IParamsProvider testParams = BenchControl.TbfComponents.GetTestParams(this, test); + return (new CombinedWithDetectionSeq()).Execute(test, testParams as CombinedWithDetTestParams); + } + } +} diff --git a/TestBenchFramework/BenchControl/TestMethods/CombinedWithDetection/TestMethodCfg.cs b/TestBenchFramework/BenchControl/TestMethods/CombinedWithDetection/TestMethodCfg.cs new file mode 100644 index 000000000..b15932913 --- /dev/null +++ b/TestBenchFramework/BenchControl/TestMethods/CombinedWithDetection/TestMethodCfg.cs @@ -0,0 +1,54 @@ +using System; +using System.IO; +using System.Xml.Serialization; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.TestMethods.CombinedWithDetection +{ + public class TestMethodCfg : ComponentCfgBase, Generic.IComponentCfg + { + /// Parameterless constructor + public TestMethodCfg() + { + } + + /// + /// Data entry form configuration parameters + /// + /// Data entry form factory + /// Component name + public TestMethodCfg(IComponentFactory factory, string name) + : base(factory, name) + { + } + + public IComponentCfg Clone() + { + return new TestMethodCfg(Factory, Name); + } + + public string ToString(int i) + { + return string.Empty; + } + + public TBF.Entities.Component CreateDbEntity() + { + using (var writer = new StringWriter()) + { + (new XmlSerializer(GetType())).Serialize(writer, this); + return Entities.Component.CreateFromCfg(Name, Factory.ClassName, ParentName, ItemNr, DebugLevel, LogLevel, writer.ToString()); + } + } + + public static IComponentCfg CreateFromDbEntity(Entities.Component component, IComponentFactory factory) + { + using (var reader = new StringReader(component.Parameters)) + { + TestMethodCfg config = (TestMethodCfg)(new XmlSerializer(typeof(TestMethodCfg))).Deserialize(reader); + config.InitCfgBaseFromEntity(component, factory); + return config; + } + } + } +} diff --git a/TestBenchFramework/BenchControl/TestMethods/CombinedWithDetection/TestMethodCfgCtrl.cs b/TestBenchFramework/BenchControl/TestMethods/CombinedWithDetection/TestMethodCfgCtrl.cs new file mode 100644 index 000000000..eeb70fc60 --- /dev/null +++ b/TestBenchFramework/BenchControl/TestMethods/CombinedWithDetection/TestMethodCfgCtrl.cs @@ -0,0 +1,58 @@ +using System; +using System.Windows.Forms; +using log4net; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.TestMethods.CombinedWithDetection +{ + public partial class TestMethodCfgCtrl : UserControl, IComponentCfgCtrl + { + static readonly ILog log = LogManager.GetLogger(typeof(TestMethodCfgCtrl)); + + TestMethodCfg config; + + public IComponentCfg Config + { + get { return config as IComponentCfg; } + set + { + config = value as TestMethodCfg; + Redraw(); + } + } + + public TestMethodCfgCtrl() + { + InitializeComponent(); + } + + private void EntryFormCfgCtrl_Load(object sender, EventArgs e) + { + Redraw(); + } + + void Redraw() + { + if (config == null) return; /// Control was not loaded, settings were not changed + classNameLabel.Text = config.Factory.ClassName; + nameTextBox.Text = config.Name; + } + + public void Unlock() + { + nameTextBox.Enabled = true; + } + + public CfgVerifyFlags VerifyCfg(ref string message) + { + CfgVerifyFlags flags = CfgVerifyFlags.None; + return flags; + } + + public void UpdateCfg() + { + if (config == null) return; /// Control was not loaded, settings were not changed + config.Name = nameTextBox.Text; + } + } +} diff --git a/TestBenchFramework/BenchControl/TestMethods/CombinedWithDetection/TestMethodCfgCtrl.designer.cs b/TestBenchFramework/BenchControl/TestMethods/CombinedWithDetection/TestMethodCfgCtrl.designer.cs new file mode 100644 index 000000000..af1af3fed --- /dev/null +++ b/TestBenchFramework/BenchControl/TestMethods/CombinedWithDetection/TestMethodCfgCtrl.designer.cs @@ -0,0 +1,83 @@ +namespace TBF.BenchControl.TestMethods.CombinedWithDetection +{ + partial class TestMethodCfgCtrl + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.nameTextBox = new System.Windows.Forms.TextBox(); + this.nameLabel = new System.Windows.Forms.Label(); + this.classNameLabel = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // nameTextBox + // + this.nameTextBox.Enabled = false; + this.nameTextBox.Location = new System.Drawing.Point(137, 57); + this.nameTextBox.Name = "nameTextBox"; + this.nameTextBox.Size = new System.Drawing.Size(130, 20); + this.nameTextBox.TabIndex = 5; + // + // nameLabel + // + this.nameLabel.AutoSize = true; + this.nameLabel.Location = new System.Drawing.Point(27, 60); + this.nameLabel.Name = "nameLabel"; + this.nameLabel.Size = new System.Drawing.Size(35, 13); + this.nameLabel.TabIndex = 4; + this.nameLabel.Text = "Name"; + // + // classNameLabel + // + this.classNameLabel.AutoSize = true; + this.classNameLabel.Location = new System.Drawing.Point(134, 33); + this.classNameLabel.Name = "classNameLabel"; + this.classNameLabel.Size = new System.Drawing.Size(83, 13); + this.classNameLabel.TabIndex = 3; + this.classNameLabel.Text = "ComonentName"; + // + // BasicPrinterCfgCtrl + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.nameTextBox); + this.Controls.Add(this.nameLabel); + this.Controls.Add(this.classNameLabel); + this.Name = "BasicPrinterCfgCtrl"; + this.Size = new System.Drawing.Size(300, 200); + this.Load += new System.EventHandler(this.EntryFormCfgCtrl_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TextBox nameTextBox; + private System.Windows.Forms.Label nameLabel; + private System.Windows.Forms.Label classNameLabel; + } +} diff --git a/TestBenchFramework/BenchControl/TestMethods/CombinedWithDetection/TestMethodCfgCtrl.resx b/TestBenchFramework/BenchControl/TestMethods/CombinedWithDetection/TestMethodCfgCtrl.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/TestBenchFramework/BenchControl/TestMethods/CombinedWithDetection/TestMethodCfgCtrl.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/BenchControl/TestMethods/CombinedWithDetection/TestMethodFactory.cs b/TestBenchFramework/BenchControl/TestMethods/CombinedWithDetection/TestMethodFactory.cs new file mode 100644 index 000000000..5847e137a --- /dev/null +++ b/TestBenchFramework/BenchControl/TestMethods/CombinedWithDetection/TestMethodFactory.cs @@ -0,0 +1,45 @@ +using System.Collections.Generic; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.TestMethods.CombinedWithDetection +{ + public class TestMethodFactory : IComponentFactory + { + public string ClassName { get { return "CombinedWithDetection"; } } + + /// Max. number of components of this class in the system + public int MaxCount { get { return 1; } } + + + public IComponentCfg DefaultConfig(IList components) + { + return new TestMethodCfg(this, "CombinedWithDetection"); + } + + public IComponentCfgCtrl CreateCfgCtrl() + { + return new TestMethodCfgCtrl(); + } + + public IComponent ComponentFromCmpntCfg(IComponentCfg config, IList components) + { + return new TestMethod((TestMethodCfg)config); + } + + public IComponentCfg CmpntCfgFromCmpntEntity(Entities.Component component) + { + return TestMethodCfg.CreateFromDbEntity(component, this); + } + + public bool HasProcedureParams { get { return false; } } + public IParamsProvider GetProcedureParams(Entities.ComponentProcedure procedureParams) { return null; } + + public bool HasTestParams { get { return true; } } + public IParamsProvider GetTestParams(Entities.ComponentTest testParams) + { + return CombinedWithDetTestParams.GetTestParams(testParams); + } + + public void ResetStaticProperties() { TestMethod.ResetStaticProperties(); } + } +} diff --git a/TestBenchFramework/BenchControl/TestMethods/FlyingStartCollectionMethod/FlyingStartCollectionMethodSeq.cs b/TestBenchFramework/BenchControl/TestMethods/FlyingStartCollectionMethod/FlyingStartCollectionMethodSeq.cs new file mode 100644 index 000000000..a0cc95483 --- /dev/null +++ b/TestBenchFramework/BenchControl/TestMethods/FlyingStartCollectionMethod/FlyingStartCollectionMethodSeq.cs @@ -0,0 +1,466 @@ +using System; +using System.Collections.Generic; +using System.Text; +using log4net; +using TBF.Resources; +using TBF.UiBridge; + +namespace TBF.BenchControl.TestMethods.FlyingStartCollectionMethod +{ + public class FlyingStartCollectionMethodSeq : Sequences.SequenceBase + { + private static readonly ILog log = LogManager.GetLogger(typeof(FlyingStartCollectionMethodSeq)); + private static readonly ILog allResults = LogManager.GetLogger("AllResults"); + private static readonly ILog summaryResults = LogManager.GetLogger("SummaryResults"); + + + public IList Execute(Entities.Test test) + { + Elde.ControlBoardDev cBrd = StateMachine.ControlBoard; + + /// Operations running in more then one state + checkUiOp = new Operations.CheckUIOp(true); + + IList e; /// Events from currently running operations + + //-------------------------------- + State.Create("FlyingStartCollectionMethod : Stopping diverter, gate, etc.") + .AddOperation(checkUiOp) + .AddOperation(cBrd.StopPreviousOp()) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.UiCmdStop)) goto stop; + } + while (!e.Contains(Event.PreviousStopped)); + + /// Fetch the test, the paths + bool success = StateMachine.GetPaths(test, out inPath, out benchPath, out outPath, out sensPath, + out transitionStart, out transitionStop); + if (!success) goto error; + + /// Notes: + /// float timeHr = volumeLtr / (1000.0f * targetFlow); + /// float timeSec = 3600.0f * timeHr; + /// int refPulses = (int)(timeSec * (2000.0f * targetFlow / pOut.FlowMeter.NominalFlow)); + int totalPulses = (int)(7200.0f * test.Volume / outPath.FlowMeter.NominalFlow); /// Nominal flow in [m3/h] + + float ltrPerRefPulse = outPath.FlowMeter.NominalFlow / 7200.0f; /// [ltr/pulse] + + int repetitionNr = 1; /// First test: repetitionNr=1 + + //==================================== + // Transition or SetRoute - Start + //==================================== + if (transitionStart != null) + { + switch (Transition(transitionStart, "FlyingStartCollectionMethod : " + Strings.Test_start_sequence_i_n)) + { + case Event.Error: goto error; + case Event.UiCmdStop: goto stop; + } + } + else + { + //-------------------------------- + State.Create("FlyingStartCollectionMethod : Setting the route") + .AddOperation(checkUiOp) + .AddOperation(cBrd.SetValvesOp(GenericDevices.ValveBase.Merge(inPath.ValvesOpen, benchPath.ValvesOpen, outPath.ValvesOpen), + GenericDevices.ValveBase.Merge(inPath.ValvesClose, benchPath.ValvesClose, outPath.ValvesClose))) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.UiCmdStop)) goto stop; + } + while (!e.Contains(Event.ValvesSet)); + } + + //==================================== + loop: + /// Start the test, initialize test results + Bridge.OnTestSelected(this, new TestSelectedEventArgs(test, repetitionNr, inPath, benchPath, outPath, sensPath, totalPulses)); + Entities.TestResult tstRslt = new Entities.TestResult(test, repetitionNr, Entities.MetersKind.Single); + + + if (!test.Emptying) /// Do not skip emptying if test.Emptying==true + { + //-------------------------------- + State.Create("FlyingStartCollectionMethod : Measuring the mass of water in the tank") + .AddOperation(checkUiOp) + .AddOperation(outPath.Balance.ReadMassOp(ref mass)) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.Error)) goto error; + if (e.Contains(Event.UiCmdStop)) goto stop; + } + while (!e.Contains(Event.BalanceDone)); + + float estimatedEndMass = mass.F + test.Volume; + if (estimatedEndMass < outPath.Balance.Capacity * Constants.TankFullFactor) + { + goto set_flow; /// Enough room in the tank -> skip emptying + } + } + + // Empty the water tank + switch (EmptyTheTank(outPath.EmptyTankValve, outPath.Balance)) + { + case Event.Error: goto error; + case Event.UiCmdStop: goto stop; + } + + set_flow: + + //------------------------------------------------ + Bridge.OnActivity(this, Strings.Setting_the_flow); + //------------------------------------------------ + State.Create("FlyingStartCollectionMethod : Starting the pump") + .AddOperation(checkUiOp) + .AddOperation((inPath != null && inPath.Pump is GenericDevices.IPumpFM) ? (inPath.Pump as GenericDevices.IPumpFM).TurnOn() : null) + .AddOperation(cBrd.SetValvesOp(inPath.Pump, null)) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.UiCmdStop)) goto stop; + } + while (!e.Contains(Event.ValvesSet)); + + //-------------------------------- + State.Create("FlyingStartCollectionMethod : Setting the flow") + .AddOperation(checkUiOp) + .AddOperation(outPath.RegulValve.SetFlowOp(outPath.FlowMeter, test.Qfrom, test.Qto, measuredFlow, 600)) /// timeout = 10 min. + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.UiCmdStop)) goto stop; + if (e.Contains(Event.RegulValveTimeOut)) goto error; + if (e.Contains(Event.Next)) goto flow_set; + } + while (!e.Contains(Event.FlowReached)); + + flow_set: + int time = StateMachine.CurrentTime; + float currentFlow = measuredFlow.F; + + /// Extract cameras from the current sensors path, add operations to the detection state + IList measureOperations = new List(); + for (int i = 0; i < sensPath.RegisterReaders.Length; i++) + { + GenericDevices.ICameraRoi cameraRoi = sensPath.RegisterReaders[i] as GenericDevices.ICameraRoi; + if (cameraRoi != null) measureOperations.Add(cameraRoi.MeasureOp()); + } + + //------------------------------------------------ + Bridge.OnActivity(this, Strings.Measuring_the_weight); + //------------------------------------------------ + State.Create("FlyingStartCollectionMethod : Measuring the start mass") + .AddOperation(checkUiOp) + .AddOperations(measureOperations) + .AddOperation(outPath.Balance.ReadStableMassOp(ref stableMass, 5)) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.Error)) goto error; + if (e.Contains(Event.UiCmdStop)) goto stop; + } + while (!e.Contains(Event.BalanceDone)); + + tstRslt.TimeStart = DateTime.Now; + tstRslt.MassStartRaw = stableMass.F; + mass.F = stableMass.F; + + //------------------------------------------------ + Bridge.OnActivity(this, Strings.Test_in_progress); + //------------------------------------------------ + State.Create("FlyingStartCollectionMethod : Starting the test") + .AddOperation(checkUiOp) + .AddOperations(measureOperations) + .AddOperation(cBrd.StartMeasurementOp(outPath.FlowMeter, totalPulses, Elde.TestMethods.Diverter | Elde.TestMethods.Synchro)) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.Error)) goto error; + if (e.Contains(Event.UiCmdStop)) goto stop; + } + while (!e.Contains(Event.MeasurementStarted)); + + /// Measurement loop - preparation + readRegisters1 = new Operations.ReadMoreRegistersOp(sensPath.RegisterReaders, ref WMPulses, ref WMRefPulses); + readRegisters2 = new Operations.ReadMoreRegistersOp(sensPath.RegisterReaders, ref WMPulses, ref WMRefPulses); + queryEnd1 = cBrd.QueryMeasurementEndOp(); + queryEnd2 = cBrd.QueryMeasurementEndOp(); + + bool firstTime = true; + ResetAveragedData(); + + /// Measurement loop - begin + while (true) + { + //-------------------------------- + switch (ReadRegistersTempPressAmbient(measureOperations, true)) + { + case Event.Error: goto error; + case Event.UiCmdStop: goto stop; + case Event.MeasurementCompleted: goto measurement_completed; + } + + if (firstTime) + { + firstTime = false; /// Do the following only once + tstRslt.TempInStart = tempIn.F; + tstRslt.TempOutStart = tempOut.F; + tstRslt.TempDivStart = tempDiv.F; + tstRslt.PressInStart = pressIn.F; + tstRslt.PressOutStart = pressOut.F; + } + + tstRslt.TempInEnd = tempIn.F; + tstRslt.TempOutEnd = tempOut.F; + tstRslt.TempDivEnd = tempDiv.F; + tstRslt.PressInEnd = pressIn.F; + tstRslt.PressOutEnd = pressOut.F; + tstRslt.MassEndRaw = mass.F; + + AccumulateAveragedData(); + + tstRslt.AmbientTempAve = airTemperature.F; + tstRslt.AmbientPressAve = airPressure.F; + tstRslt.AmbientHumiAve = airHumidity.F; + + + string logstr = string.Format("E={0} f={1} q={2}", cBrd.EtPulses(0), cBrd.ReferenceFreq, + cBrd.ReferenceFlow * outPath.FlowMeter.NominalFlow); + for (int i = 0; i < Program.WMsCount; i++) + { + logstr += string.Format(" M{0}=({1},{2})", i + 1, WMRefPulses[i], WMPulses[i]); + } + log.Info(logstr); + + + float progress = Formulas.TestProgress(cBrd.EtPulses(0), totalPulses, 10.0f, test.TstTime); + Bridge.OnTestProgress(this, GetTestProgressData(test, tstRslt, cBrd.EtPulses(0), cBrd.TTime, progress)); + } + /// Measurement loop - end + + measurement_completed: + + //------------------------------------------------ + Bridge.OnActivity(this, Strings.Measuring_the_weight); + //------------------------------------------------ + State.Create("FlyingStartCollectionMethod : Measuring the end mass") + .AddOperation(checkUiOp) + .AddOperation(outPath.Balance.ReadStableMassOp(ref stableMass, 5)) + .AddOperation(cBrd.UpdateTankWeightOp()) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.Error)) goto error; + if (e.Contains(Event.UiCmdStop)) goto stop; + } + while (!e.Contains(Event.BalanceDone)); + /// + tstRslt.MassEndRaw = stableMass.F; + tstRslt.TimeEnd = DateTime.Now; + + //------------------------------------------------ + Bridge.OnActivity(this, Strings.Test_completed); + //------------------------------------------------ + cBrd.SetFMFreq(0, 0); /// Stop FM controlled pumps + State.Create("FlyingStartCollectionMethod : Stopping the pump") + .AddOperation(checkUiOp) + .AddOperation((inPath != null && inPath.Pump is GenericDevices.IPumpFM) ? (inPath.Pump as GenericDevices.IPumpFM).TurnOff() : null) + .AddOperation(cBrd.SetValvesOp(null, inPath.Pump)) + .AddOperation(cBrd.UpdateTankWeightOp()) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.UiCmdStop)) goto stop; + } + while (!e.Contains(Event.ValvesSet)); + + + //-------------------------------- + State.Create("FlyingStartCollectionMethod : Stopping diverter, gate, etc.") + .AddOperation(checkUiOp) + .AddOperation(cBrd.StopPreviousOp()) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.UiCmdStop)) goto stop; + } + while (!e.Contains(Event.PreviousStopped)); + + /// + /// Populate TestResult data entity with data + /// + tstRslt.TimeEnd = DateTime.Now; + UpdateTestRsltWithAveragedData(tstRslt); + tstRslt.MassStart = Formulas.CorrectedValue(tstRslt.MassStartRaw, outPath.Balance.Corrections); + tstRslt.MassEnd = Formulas.CorrectedValue(tstRslt.MassEndRaw, outPath.Balance.Corrections); + tstRslt.MassDiff = tstRslt.MassEnd - tstRslt.MassStart; + tstRslt.DensityIn = Formulas.WaterDensityFromTemp(tstRslt.TempInAvrg); /// [kg/m3] + tstRslt.DensityOut = Formulas.WaterDensityFromTemp(tstRslt.TempOutAvrg); /// [kg/m3] + tstRslt.DensityDiv = Formulas.WaterDensityFromTemp(tstRslt.TempDivAvrg); /// [kg/m3] + tstRslt.Time = cBrd.TTime; /// [s] measurement time + tstRslt.FlowMass = 3600.0f * tstRslt.MassDiff / tstRslt.Time; /// [kg/h] + tstRslt.FlowVolume = 3600.0f * ltrPerRefPulse * cBrd.EtPulses(0) / tstRslt.Time; /// [l/h] + tstRslt.VolumeCTV = 1.00103f * 1000.0f * tstRslt.MassDiff / tstRslt.DensityOut; /// [l] 1000.0f is because density is in [kg/m3] + tstRslt.VolumeMaster = ltrPerRefPulse * cBrd.EtPulses(0); /// [l] volume from the master flow meter + tstRslt.PulsesMaster = cBrd.EtPulses(0); /// Pulses of the master flow meter (test total) + tstRslt.ConstMaster = ltrPerRefPulse * tstRslt.VolumeCTV / tstRslt.VolumeMaster; + /// Corrected master pulses per liter + if (tstRslt.VolumeCTV <= float.Epsilon) + { + tstRslt.ErrorMaster = 0.1f; + } + else + { + tstRslt.ErrorMaster = 100 * (tstRslt.VolumeMaster - tstRslt.VolumeCTV) / tstRslt.VolumeCTV; + } + tstRslt.TimeDivStart0 = 0; + tstRslt.TimeDivStart1 = 0; + tstRslt.TimeDivStart2 = 0; + tstRslt.TimeDivStart3 = 0; + tstRslt.TimeDivStart4 = 0; + tstRslt.TimeDivStart5 = 0; + tstRslt.TimeDivEnd0 = 0; + tstRslt.TimeDivEnd1 = 0; + tstRslt.TimeDivEnd2 = 0; + tstRslt.TimeDivEnd3 = 0; + tstRslt.TimeDivEnd4 = 0; + tstRslt.TimeDivEnd5 = 0; + for (int i = 0; i < Program.WMsCount; i++) + { + if (sensPath.RegisterReaders[i] != null) + { + tstRslt.Meters[i].SerialNr = "wm" + (i + 1).ToString(); + tstRslt.Meters[i].VolumeStart = 0; /// liter + tstRslt.Meters[i].VolumeEnd = 0; /// liter + if (sensPath.RegisterReaders[i].PulsesPerLtr <= float.Epsilon) tstRslt.Meters[i].VolumeMeter = 0; + else tstRslt.Meters[i].VolumeMeter = Convert.ToSingle(WMPulses[i]) / sensPath.RegisterReaders[i].PulsesPerLtr; + tstRslt.Meters[i].VolumeRef = tstRslt.ConstMaster * WMRefPulses[i]; /// liter + tstRslt.Meters[i].PulsesMeter = WMPulses[i]; + tstRslt.Meters[i].PulsesMaster = WMRefPulses[i]; + tstRslt.Meters[i].Time = cBrd.TTime; + if (WMPulses[i] > 0 && tstRslt.Meters[i].VolumeRef > 0) + { + tstRslt.Meters[i].VolumeErrorPct = + 100 * (tstRslt.Meters[i].VolumeMeter - tstRslt.Meters[i].VolumeRef) / tstRslt.Meters[i].VolumeRef; + /// % + } + else + { + tstRslt.Meters[i].VolumeErrorPct = -100; + } + tstRslt.Meters[i].Passed = (tstRslt.ErrLimLo <= tstRslt.Meters[i].VolumeErrorPct) && (tstRslt.Meters[i].VolumeErrorPct <= tstRslt.ErrLimHi); + } + } + /// Add data - end + + AddOrOverwriteResult(tstRslt); + + Bridge.OnTestCompleted(this, new TestCompletedEventArgs(tstRslt)); + + /// Append the results to the CSV-file + allResults.Info(TestResult2CsvLine(tstRslt, cBrd.EtPulses(0))); + + FluentCommon.SaveToDb(StateMachine.WtSession, tstRslt); + + if (++repetitionNr <= test.Repeats) + { + goto loop; + } + + ///----------------------/// + /// Quit this sequence /// + ///----------------------/// + + /// Stop the pump + State.Create("FlyingStartCollectionMethod : Test(s) completed -> Stopping the pump") + .AddOperation(checkUiOp) + .AddOperation(cBrd.SetValvesOp(null, inPath.Pump)) + .AddOperation((inPath.Pump is GenericDevices.IPumpFM) ? (inPath.Pump as GenericDevices.IPumpFM).TurnOff() : null) + .EnterState(); + do { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.Error)) goto error; + } + while (!e.Contains(Event.ValvesSet) || ((inPath.Pump is GenericDevices.IPumpFM) && !e.Contains(Event.TurnPumpOnOffDone))); + + /// Transition or SetRoute - End + if (transitionStop != null) + { + switch (Transition(transitionStop, "FlyingStartCollectionMethod : " + Strings.Test_stop_sequence_i_n)) + { + case Event.Error: goto error; + case Event.UiCmdStop: goto stop; + } + } + else + { + State.Create("FlyingStartCollectionMethod : Test(s) completed -> Closing the valves") + .AddOperation(checkUiOp) + .AddOperation(cBrd.SetValvesOp(StateMachine.DefaultValvesOpen, StateMachine.DefaultValvesClose)) + .EnterState(); + do { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.Error)) goto error; + } + while (!e.Contains(Event.ValvesSet)); + } + + /// Create the return value - a list with one event Event.Done - and return + IList retval = new List(); + retval.Add(Event.Done); + return retval; + + //==================================== + stop: + State.Create("FlyingStartCollectionMethod : User selected STOP -> Closing the valves") + .AddOperation(checkUiOp) + .AddOperation((inPath != null && inPath.Pump is GenericDevices.IPumpFM) ? (inPath.Pump as GenericDevices.IPumpFM).TurnOff() : null) + .AddOperation(cBrd.SetValvesOp(StateMachine.DefaultValvesOpen, StateMachine.DefaultValvesClose)) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.Error)) goto error; + } + while (!e.Contains(Event.ValvesSet)); + + IList retval2 = new List(); + retval2.Add(Event.UiCmdStop); + return retval2; + + //==================================== + error: + cBrd.SetFMFreq(0, 0); /// Stop FM controlled pumps + State.Create("FlyingStartCollectionMethod : ERROR -> Closing the valves") + .AddOperation(checkUiOp) + .AddOperation((inPath != null && inPath.Pump is GenericDevices.IPumpFM) ? (inPath.Pump as GenericDevices.IPumpFM).TurnOff() : null) + .AddOperation(cBrd.SetValvesOp(StateMachine.DefaultValvesOpen, StateMachine.DefaultValvesClose)) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.Error)) goto error; + } + while (!e.Contains(Event.ValvesSet)); + + IList retval3 = new List(); + retval3.Add(Event.Error); + return retval3; + } + } +} diff --git a/TestBenchFramework/BenchControl/TestMethods/FlyingStartCollectionMethod/TestMethod.cs b/TestBenchFramework/BenchControl/TestMethods/FlyingStartCollectionMethod/TestMethod.cs new file mode 100644 index 000000000..8439cad6d --- /dev/null +++ b/TestBenchFramework/BenchControl/TestMethods/FlyingStartCollectionMethod/TestMethod.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using TBF.BenchControl; + +namespace TBF.BenchControl.TestMethods.FlyingStartCollectionMethod +{ + public class TestMethod : Generic.IComponent, GenericDevices.ITestMethod, ISequence + { + readonly TestMethodCfg testMethodCfg; + public Generic.IComponentCfg Cfg { get { return testMethodCfg; } } + + public static void ResetStaticProperties() { } + + public string Name { get { return testMethodCfg.Name; } } + + public TestMethod(TestMethodCfg cfg) + { + if (cfg == null) throw new ArgumentNullException("cfg"); + this.testMethodCfg = cfg; + } + + public IList Execute(Entities.Test test) + { + return (new FlyingStartCollectionMethodSeq()).Execute(test); + } + } +} diff --git a/TestBenchFramework/BenchControl/TestMethods/FlyingStartCollectionMethod/TestMethodCfg.cs b/TestBenchFramework/BenchControl/TestMethods/FlyingStartCollectionMethod/TestMethodCfg.cs new file mode 100644 index 000000000..1bc6c5ded --- /dev/null +++ b/TestBenchFramework/BenchControl/TestMethods/FlyingStartCollectionMethod/TestMethodCfg.cs @@ -0,0 +1,54 @@ +using System; +using System.IO; +using System.Xml.Serialization; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.TestMethods.FlyingStartCollectionMethod +{ + public class TestMethodCfg : ComponentCfgBase, Generic.IComponentCfg + { + /// Parameterless constructor + public TestMethodCfg() + { + } + + /// + /// Data entry form configuration parameters + /// + /// Data entry form factory + /// Component name + public TestMethodCfg(IComponentFactory factory, string name) + : base(factory, name) + { + } + + public IComponentCfg Clone() + { + return new TestMethodCfg(Factory, Name); + } + + public string ToString(int i) + { + return string.Empty; + } + + public TBF.Entities.Component CreateDbEntity() + { + using (var writer = new StringWriter()) + { + (new XmlSerializer(GetType())).Serialize(writer, this); + return Entities.Component.CreateFromCfg(Name, Factory.ClassName, ParentName, ItemNr, DebugLevel, LogLevel, writer.ToString()); + } + } + + public static IComponentCfg CreateFromDbEntity(Entities.Component component, IComponentFactory factory) + { + using (var reader = new StringReader(component.Parameters)) + { + TestMethodCfg config = (TestMethodCfg)(new XmlSerializer(typeof(TestMethodCfg))).Deserialize(reader); + config.InitCfgBaseFromEntity(component, factory); + return config; + } + } + } +} diff --git a/TestBenchFramework/BenchControl/TestMethods/FlyingStartCollectionMethod/TestMethodCfgCtrl.cs b/TestBenchFramework/BenchControl/TestMethods/FlyingStartCollectionMethod/TestMethodCfgCtrl.cs new file mode 100644 index 000000000..152f606c5 --- /dev/null +++ b/TestBenchFramework/BenchControl/TestMethods/FlyingStartCollectionMethod/TestMethodCfgCtrl.cs @@ -0,0 +1,58 @@ +using System; +using System.Windows.Forms; +using log4net; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.TestMethods.FlyingStartCollectionMethod +{ + public partial class TestMethodCfgCtrl : UserControl, IComponentCfgCtrl + { + static readonly ILog log = LogManager.GetLogger(typeof(TestMethodCfgCtrl)); + + TestMethodCfg config; + + public IComponentCfg Config + { + get { return config as IComponentCfg; } + set + { + config = value as TestMethodCfg; + Redraw(); + } + } + + public TestMethodCfgCtrl() + { + InitializeComponent(); + } + + private void EntryFormCfgCtrl_Load(object sender, EventArgs e) + { + Redraw(); + } + + void Redraw() + { + if (config == null) return; /// Control was not loaded, settings were not changed + classNameLabel.Text = config.Factory.ClassName; + nameTextBox.Text = config.Name; + } + + public void Unlock() + { + nameTextBox.Enabled = true; + } + + public CfgVerifyFlags VerifyCfg(ref string message) + { + CfgVerifyFlags flags = CfgVerifyFlags.None; + return flags; + } + + public void UpdateCfg() + { + if (config == null) return; /// Control was not loaded, settings were not changed + config.Name = nameTextBox.Text; + } + } +} diff --git a/TestBenchFramework/BenchControl/TestMethods/FlyingStartCollectionMethod/TestMethodCfgCtrl.designer.cs b/TestBenchFramework/BenchControl/TestMethods/FlyingStartCollectionMethod/TestMethodCfgCtrl.designer.cs new file mode 100644 index 000000000..a912e3ac8 --- /dev/null +++ b/TestBenchFramework/BenchControl/TestMethods/FlyingStartCollectionMethod/TestMethodCfgCtrl.designer.cs @@ -0,0 +1,83 @@ +namespace TBF.BenchControl.TestMethods.FlyingStartCollectionMethod +{ + partial class TestMethodCfgCtrl + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.nameTextBox = new System.Windows.Forms.TextBox(); + this.nameLabel = new System.Windows.Forms.Label(); + this.classNameLabel = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // nameTextBox + // + this.nameTextBox.Enabled = false; + this.nameTextBox.Location = new System.Drawing.Point(137, 57); + this.nameTextBox.Name = "nameTextBox"; + this.nameTextBox.Size = new System.Drawing.Size(130, 20); + this.nameTextBox.TabIndex = 5; + // + // nameLabel + // + this.nameLabel.AutoSize = true; + this.nameLabel.Location = new System.Drawing.Point(27, 60); + this.nameLabel.Name = "nameLabel"; + this.nameLabel.Size = new System.Drawing.Size(35, 13); + this.nameLabel.TabIndex = 4; + this.nameLabel.Text = "Name"; + // + // classNameLabel + // + this.classNameLabel.AutoSize = true; + this.classNameLabel.Location = new System.Drawing.Point(134, 33); + this.classNameLabel.Name = "classNameLabel"; + this.classNameLabel.Size = new System.Drawing.Size(83, 13); + this.classNameLabel.TabIndex = 3; + this.classNameLabel.Text = "ComonentName"; + // + // BasicPrinterCfgCtrl + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.nameTextBox); + this.Controls.Add(this.nameLabel); + this.Controls.Add(this.classNameLabel); + this.Name = "BasicPrinterCfgCtrl"; + this.Size = new System.Drawing.Size(300, 200); + this.Load += new System.EventHandler(this.EntryFormCfgCtrl_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TextBox nameTextBox; + private System.Windows.Forms.Label nameLabel; + private System.Windows.Forms.Label classNameLabel; + } +} diff --git a/TestBenchFramework/BenchControl/TestMethods/FlyingStartCollectionMethod/TestMethodCfgCtrl.resx b/TestBenchFramework/BenchControl/TestMethods/FlyingStartCollectionMethod/TestMethodCfgCtrl.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/TestBenchFramework/BenchControl/TestMethods/FlyingStartCollectionMethod/TestMethodCfgCtrl.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/BenchControl/TestMethods/FlyingStartCollectionMethod/TestMethodFactory.cs b/TestBenchFramework/BenchControl/TestMethods/FlyingStartCollectionMethod/TestMethodFactory.cs new file mode 100644 index 000000000..4575b6ac8 --- /dev/null +++ b/TestBenchFramework/BenchControl/TestMethods/FlyingStartCollectionMethod/TestMethodFactory.cs @@ -0,0 +1,40 @@ +using System.Collections.Generic; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.TestMethods.FlyingStartCollectionMethod +{ + public class TestMethodFactory : IComponentFactory + { + public string ClassName { get { return "Flying-Start-Collection"; } } + public bool HasProcedureParams { get { return false; } } + public bool HasTestParams { get { return false; } } + public IParamsProvider GetTestParams(Entities.ComponentTest testParams) { return null; } + public IParamsProvider GetProcedureParams(Entities.ComponentProcedure procedureParams) { return null; } + + /// Max. number of components of this class in the system + public int MaxCount { get { return 1; } } + + + public IComponentCfg DefaultConfig(IList components) + { + return new TestMethodCfg(this, "FlyingStartCollection"); + } + + public IComponentCfgCtrl CreateCfgCtrl() + { + return new TestMethodCfgCtrl(); + } + + public IComponent ComponentFromCmpntCfg(IComponentCfg config, IList components) + { + return new TestMethod((TestMethodCfg)config); + } + + public IComponentCfg CmpntCfgFromCmpntEntity(Entities.Component component) + { + return TestMethodCfg.CreateFromDbEntity(component, this); + } + + public void ResetStaticProperties() { TestMethod.ResetStaticProperties(); } + } +} diff --git a/TestBenchFramework/BenchControl/Transition.cs b/TestBenchFramework/BenchControl/Transition.cs new file mode 100644 index 000000000..62721f6f3 --- /dev/null +++ b/TestBenchFramework/BenchControl/Transition.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; + +namespace TBF.BenchControl +{ + public class Transition + { + public Event Evnt; + public State NextState; /// if not null, nextState reference is used + public string NextStateLabel; /// otherwise nextStateLabel is used + + /// + /// Constructor using a next state reference + /// + public Transition(Event evnt, State nextState) + { + this.Evnt = evnt; + this.NextState = nextState; + this.NextStateLabel = null; + } + + /// + /// Constructor using a next state label + /// + public Transition(Event evnt, string nextStateLabel) + { + this.Evnt = evnt; + this.NextState = null; + this.NextStateLabel = nextStateLabel; + } + } +} diff --git a/TestBenchFramework/BenchControl/WaterMeter/ProcParams.cs b/TestBenchFramework/BenchControl/WaterMeter/ProcParams.cs new file mode 100644 index 000000000..daea4f125 --- /dev/null +++ b/TestBenchFramework/BenchControl/WaterMeter/ProcParams.cs @@ -0,0 +1,170 @@ +using System; +using System.IO; +using System.Text; +using System.Xml.Serialization; +using TBF.BenchControl.Generic; +using TBF.Resources; + +namespace TBF.BenchControl.WaterMeter +{ + public class ProcParams : IParamsProvider, IProcedureParams + { + public string Producer; + public float Qn; + public string ApprovalInfo; + public string MetrologicalClass; + + string[] paramNames = new string[] + { + Strings.Producer, + Strings.Qn, + Strings.Approval_info, + Strings.Metrological_class, + }; + public string ParamName(int i) { return paramNames[i]; } + + public string ToString(int i) + { + switch (i) + { + case 0: return Producer; + case 1: return Qn.ToString(); + case 2: return ApprovalInfo; + case 3: return MetrologicalClass; + default: return string.Empty; + } + } + + public void UpdateParam(int i, string strValue) + { + switch (i) + { + case 0: Producer = strValue; return; + case 1: Qn = Utils.ParseUFloat(strValue); return; + case 2: ApprovalInfo = strValue; return; + case 3: MetrologicalClass = strValue; return; + default: return; + } + } + + public bool ValidateParam(int i, string strValue, out string message) + { + message = string.Empty; + + float dummy; + switch (i) + { + case 1: + if (Utils.TryParseUFloat(strValue, out dummy)) return true; + break; + case 0: + case 2: + case 3: + return true; + default: + message = "Invalid index"; + return false; + } + + message = ParamName(i) + " is invalid"; + return false; + } + + #region Boilerplate code + + public int ParamsCount() { return paramNames.Length; } + + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < ParamsCount(); i++) + { + if (i != 0) sb.Append("; "); + sb.Append(ParamName(i)); + sb.Append("="); + sb.Append(ToString(i)); + } + return sb.ToString(); + } + + [XmlIgnore] + public Entities.ComponentProcedure ProcedureParamsEntity { get { return procParamsEntity; } } + Entities.ComponentProcedure procParamsEntity; + + [XmlIgnore] + public string ComponentName { get { return componentName; } } + string componentName; + + [XmlIgnore] + public Entities.Procedure Test { get { return test; } } + Entities.Procedure test; + + /// Parameterless constructor + public ProcParams() + { + Producer = ""; + Qn = 2.5f; + ApprovalInfo = ""; + MetrologicalClass = "A"; + } + + public ProcParams(Entities.ComponentProcedure procParamsEntity, string componentName, Entities.Procedure test) + : this() + { + this.procParamsEntity = procParamsEntity; + this.componentName = componentName; + this.test = test; + } + + public TBF.Entities.ComponentProcedure ToDbEntity(IComponent component, Entities.Procedure procedure) + { + using (var writer = new StringWriter()) + { + /// Serialize this class with parameters + (new XmlSerializer(GetType())).Serialize(writer, this); + + /// Create and return the ComponentProcedure entity + TBF.Entities.ComponentProcedure entity = new TBF.Entities.ComponentProcedure(); + entity.CmpntName = component.Cfg.Name; + entity.Parameters = writer.ToString(); + entity.Procedure = procedure; + return entity; + } + } + + public void UpdateDbEntity() + { + using (var writer = new StringWriter()) + { + /// Serialize this class and update the entity + (new XmlSerializer(GetType())).Serialize(writer, this); + procParamsEntity.Parameters = writer.ToString(); + procParamsEntity.CmpntName = componentName; + procParamsEntity.Procedure = test; + + } + } + + public static IParamsProvider GetProcedureParams(Entities.ComponentProcedure procParamsEntity) + { + if (procParamsEntity == null) return new ProcParams(); + + ProcParams procParams; + try + { + procParams = (ProcParams)(new XmlSerializer(typeof(ProcParams))) + .Deserialize(new StringReader(procParamsEntity.Parameters)); + } + catch + { + procParams = new ProcParams(); + } + procParams.procParamsEntity = procParamsEntity; + procParams.componentName = procParamsEntity.CmpntName; + procParams.test = procParamsEntity.Procedure; + return procParams; + } + + #endregion + } +} diff --git a/TestBenchFramework/BenchControl/WaterMeter/WaterMeter.cs b/TestBenchFramework/BenchControl/WaterMeter/WaterMeter.cs new file mode 100644 index 000000000..5835456d9 --- /dev/null +++ b/TestBenchFramework/BenchControl/WaterMeter/WaterMeter.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections.Generic; +using TBF.BenchControl; + +namespace TBF.BenchControl.WaterMeter +{ + /// + /// This component = instance of this class is a placeholder for a combined main watermeter + /// + public class WaterMeter : ComponentBase, Generic.IComponent, GenericDevices.IWaterMeter + { + readonly WaterMeterCfg combinedMainCfg; + + public static void ResetStaticProperties() { } + + /// WaterMeter producer + public string Producer + { + get { return (ProcedureParams is ProcParams) ? (ProcedureParams as ProcParams).Producer : ""; } + } + + /// Nominal water flow in [m3/h] + public float Qn + { + get { return (ProcedureParams is ProcParams) ? (ProcedureParams as ProcParams).Qn : 0; } + } + + /// WaterMeter approval information or signature + public string ApprovalInfo + { + get { return (ProcedureParams is ProcParams) ? (ProcedureParams as ProcParams).ApprovalInfo : ""; } + } + + /// Metrological class + public string MetrologicalClass + { + get { return (ProcedureParams is ProcParams) ? (ProcedureParams as ProcParams).MetrologicalClass : ""; } + } + + /// Properties set by the Begin and the End form + public string SerialNr + { + get { return serialNr; } + set { serialNr = value; } + } + string serialNr; + + public string State + { + get { return endState; } + set { endState = value; } + } + string endState; + + public string BeginState + { + get { return beginState; } + set { beginState = value; } + } + string beginState; + + public WaterMeter(WaterMeterCfg cfg) + : base(cfg) + { + if (cfg == null) throw new ArgumentNullException("cfg"); + this.combinedMainCfg = cfg; + } + } +} diff --git a/TestBenchFramework/BenchControl/WaterMeter/WaterMeterCfg.cs b/TestBenchFramework/BenchControl/WaterMeter/WaterMeterCfg.cs new file mode 100644 index 000000000..5b0a43b9b --- /dev/null +++ b/TestBenchFramework/BenchControl/WaterMeter/WaterMeterCfg.cs @@ -0,0 +1,66 @@ +using System; +using System.IO; +using System.Xml.Serialization; +using TBF.BenchControl.Generic; +using TBF.Resources; + +namespace TBF.BenchControl.WaterMeter +{ + public class WaterMeterCfg : ComponentCfgBase, Generic.IComponentCfg + { + public string Producer; /// Hersteller + public float Qn; + public string ApprovalInfo; /// Zulassungszeichen + public string MetrologicalClass; /// Metr. Klasse + + /// Parameterless constructor + public WaterMeterCfg() + { + } + + /// + /// Data entry form configuration parameters + /// + /// Data entry form factory + /// Component name + public WaterMeterCfg(IComponentFactory factory, string name, string producer, + float qn, string approvalInfo, string metrologicalClass) + : base(factory, name) + { + Producer = producer; + Qn = qn; + ApprovalInfo = approvalInfo; + MetrologicalClass = metrologicalClass; + } + + public IComponentCfg Clone() + { + return new WaterMeterCfg(Factory, Name, Producer, + Qn, ApprovalInfo, MetrologicalClass); + } + + public string ToString(int i) + { + return string.Format(Strings.nothing_to_configure); + } + + public TBF.Entities.Component CreateDbEntity() + { + using (var writer = new StringWriter()) + { + (new XmlSerializer(GetType())).Serialize(writer, this); + return Entities.Component.CreateFromCfg(Name, Factory.ClassName, ParentName, ItemNr, DebugLevel, LogLevel, writer.ToString()); + } + } + + public static IComponentCfg CreateFromDbEntity(Entities.Component component, IComponentFactory factory) + { + using (var reader = new StringReader(component.Parameters)) + { + WaterMeterCfg config = (WaterMeterCfg)(new XmlSerializer(typeof(WaterMeterCfg))).Deserialize(reader); + config.InitCfgBaseFromEntity(component, factory); + return config; + } + } + } +} diff --git a/TestBenchFramework/BenchControl/WaterMeter/WaterMeterCfgCtrl.cs b/TestBenchFramework/BenchControl/WaterMeter/WaterMeterCfgCtrl.cs new file mode 100644 index 000000000..fbc48564f --- /dev/null +++ b/TestBenchFramework/BenchControl/WaterMeter/WaterMeterCfgCtrl.cs @@ -0,0 +1,60 @@ +using System; +using System.Windows.Forms; +using log4net; +using TBF.BenchControl.Generic; +using TBF.Resources; + +namespace TBF.BenchControl.WaterMeter +{ + public partial class WaterMeterCfgCtrl : UserControl, IComponentCfgCtrl + { + static readonly ILog log = LogManager.GetLogger(typeof(WaterMeterCfgCtrl)); + + WaterMeterCfg config; + + public IComponentCfg Config + { + get { return config as IComponentCfg; } + set + { + config = value as WaterMeterCfg; + Redraw(); + } + } + + public WaterMeterCfgCtrl() + { + InitializeComponent(); + } + + private void EntryFormCfgCtrl_Load(object sender, EventArgs e) + { + nameLabel.Text = Strings.Name; + Redraw(); + } + + void Redraw() + { + if (config == null) return; /// Control was not loaded, settings were not changed + classNameLabel.Text = config.Factory.ClassName; + nameTextBox.Text = config.Name; + } + + public void Unlock() + { + nameTextBox.Enabled = true; + } + + public CfgVerifyFlags VerifyCfg(ref string message) + { + CfgVerifyFlags flags = CfgVerifyFlags.None; + return flags; + } + + public void UpdateCfg() + { + if (config == null) return; /// Control was not loaded, settings were not changed + config.Name = nameTextBox.Text; + } + } +} diff --git a/TestBenchFramework/BenchControl/WaterMeter/WaterMeterCfgCtrl.designer.cs b/TestBenchFramework/BenchControl/WaterMeter/WaterMeterCfgCtrl.designer.cs new file mode 100644 index 000000000..4b556a607 --- /dev/null +++ b/TestBenchFramework/BenchControl/WaterMeter/WaterMeterCfgCtrl.designer.cs @@ -0,0 +1,83 @@ +namespace TBF.BenchControl.WaterMeter +{ + partial class WaterMeterCfgCtrl + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.nameTextBox = new System.Windows.Forms.TextBox(); + this.nameLabel = new System.Windows.Forms.Label(); + this.classNameLabel = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // nameTextBox + // + this.nameTextBox.Enabled = false; + this.nameTextBox.Location = new System.Drawing.Point(135, 55); + this.nameTextBox.Name = "nameTextBox"; + this.nameTextBox.Size = new System.Drawing.Size(130, 20); + this.nameTextBox.TabIndex = 5; + // + // nameLabel + // + this.nameLabel.AutoSize = true; + this.nameLabel.Location = new System.Drawing.Point(25, 58); + this.nameLabel.Name = "nameLabel"; + this.nameLabel.Size = new System.Drawing.Size(35, 13); + this.nameLabel.TabIndex = 4; + this.nameLabel.Text = "Name"; + // + // classNameLabel + // + this.classNameLabel.AutoSize = true; + this.classNameLabel.Location = new System.Drawing.Point(132, 31); + this.classNameLabel.Name = "classNameLabel"; + this.classNameLabel.Size = new System.Drawing.Size(60, 13); + this.classNameLabel.TabIndex = 3; + this.classNameLabel.Text = "ClassName"; + // + // WaterMeterCfgCtrl + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.nameTextBox); + this.Controls.Add(this.nameLabel); + this.Controls.Add(this.classNameLabel); + this.Name = "WaterMeterCfgCtrl"; + this.Size = new System.Drawing.Size(300, 200); + this.Load += new System.EventHandler(this.EntryFormCfgCtrl_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TextBox nameTextBox; + private System.Windows.Forms.Label nameLabel; + private System.Windows.Forms.Label classNameLabel; + } +} diff --git a/TestBenchFramework/BenchControl/WaterMeter/WaterMeterCfgCtrl.resx b/TestBenchFramework/BenchControl/WaterMeter/WaterMeterCfgCtrl.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/TestBenchFramework/BenchControl/WaterMeter/WaterMeterCfgCtrl.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/BenchControl/WaterMeter/WaterMeterFactory.cs b/TestBenchFramework/BenchControl/WaterMeter/WaterMeterFactory.cs new file mode 100644 index 000000000..bffb95501 --- /dev/null +++ b/TestBenchFramework/BenchControl/WaterMeter/WaterMeterFactory.cs @@ -0,0 +1,43 @@ +using System.Collections.Generic; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.WaterMeter +{ + public class WaterMeterFactory : IComponentFactory + { + public string ClassName { get { return "WaterMeter"; } } + public bool HasProcedureParams { get { return true; } } + public bool HasTestParams { get { return false; } } + public IParamsProvider GetTestParams(Entities.ComponentTest testParams) { return null; } + public IParamsProvider GetProcedureParams(Entities.ComponentProcedure procedureParams) + { + return ProcParams.GetProcedureParams(procedureParams); + } + + /// Max. number of components of this class in the system + public int MaxCount { get { return int.MaxValue; } } + + + public IComponentCfg DefaultConfig(IList components) + { + return new WaterMeterCfg(this, "WaterMeter", "", 2.5f, "", "A"); + } + + public IComponentCfgCtrl CreateCfgCtrl() + { + return new WaterMeterCfgCtrl(); + } + + public IComponent ComponentFromCmpntCfg(IComponentCfg config, IList components) + { + return new WaterMeter((WaterMeterCfg)config); + } + + public IComponentCfg CmpntCfgFromCmpntEntity(Entities.Component component) + { + return WaterMeterCfg.CreateFromDbEntity(component, this); + } + + public void ResetStaticProperties() { WaterMeter.ResetStaticProperties(); } + } +} diff --git a/TestBenchFramework/BenchesDlg.Designer.cs b/TestBenchFramework/BenchesDlg.Designer.cs new file mode 100644 index 000000000..145f5d053 --- /dev/null +++ b/TestBenchFramework/BenchesDlg.Designer.cs @@ -0,0 +1,137 @@ +namespace TBF +{ + partial class BenchesDlg + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(BenchesDlg)); + this.okButton = new System.Windows.Forms.Button(); + this.cancelButton = new System.Windows.Forms.Button(); + this.testBenchesListBox = new System.Windows.Forms.ListBox(); + this.label1 = new System.Windows.Forms.Label(); + this.editButton = new System.Windows.Forms.Button(); + this.addButton = new System.Windows.Forms.Button(); + this.removeButton = new System.Windows.Forms.Button(); + this.copyButton = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // okButton + // + resources.ApplyResources(this.okButton, "okButton"); + this.okButton.DialogResult = System.Windows.Forms.DialogResult.OK; + this.okButton.ImageKey = global::TBF.Resources.Strings.String1; + this.okButton.Name = "okButton"; + this.okButton.UseVisualStyleBackColor = true; + this.okButton.Click += new System.EventHandler(this.okButton_Click); + // + // cancelButton + // + resources.ApplyResources(this.cancelButton, "cancelButton"); + this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.cancelButton.ImageKey = global::TBF.Resources.Strings.String1; + this.cancelButton.Name = "cancelButton"; + this.cancelButton.UseVisualStyleBackColor = true; + this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click); + // + // testBenchesListBox + // + resources.ApplyResources(this.testBenchesListBox, "testBenchesListBox"); + this.testBenchesListBox.FormattingEnabled = true; + this.testBenchesListBox.Name = "testBenchesListBox"; + this.testBenchesListBox.DoubleClick += new System.EventHandler(this.testBenchesListBox_DoubleClick); + // + // label1 + // + resources.ApplyResources(this.label1, "label1"); + this.label1.ImageKey = global::TBF.Resources.Strings.String1; + this.label1.Name = "label1"; + // + // editButton + // + resources.ApplyResources(this.editButton, "editButton"); + this.editButton.ImageKey = global::TBF.Resources.Strings.String1; + this.editButton.Name = "editButton"; + this.editButton.UseVisualStyleBackColor = true; + this.editButton.Click += new System.EventHandler(this.editButton_Click); + // + // addButton + // + resources.ApplyResources(this.addButton, "addButton"); + this.addButton.ImageKey = global::TBF.Resources.Strings.String1; + this.addButton.Name = "addButton"; + this.addButton.UseVisualStyleBackColor = true; + this.addButton.Click += new System.EventHandler(this.addButton_Click); + // + // removeButton + // + resources.ApplyResources(this.removeButton, "removeButton"); + this.removeButton.ImageKey = global::TBF.Resources.Strings.String1; + this.removeButton.Name = "removeButton"; + this.removeButton.UseVisualStyleBackColor = true; + this.removeButton.Click += new System.EventHandler(this.removeButton_Click); + // + // copyButton + // + resources.ApplyResources(this.copyButton, "copyButton"); + this.copyButton.ImageKey = global::TBF.Resources.Strings.String1; + this.copyButton.Name = "copyButton"; + this.copyButton.UseVisualStyleBackColor = true; + this.copyButton.Click += new System.EventHandler(this.copyButton_Click); + // + // BenchesDlg + // + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.copyButton); + this.Controls.Add(this.removeButton); + this.Controls.Add(this.addButton); + this.Controls.Add(this.editButton); + this.Controls.Add(this.label1); + this.Controls.Add(this.testBenchesListBox); + this.Controls.Add(this.okButton); + this.Controls.Add(this.cancelButton); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.Name = "BenchesDlg"; + this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide; + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Button okButton; + private System.Windows.Forms.Button cancelButton; + private System.Windows.Forms.ListBox testBenchesListBox; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Button editButton; + private System.Windows.Forms.Button addButton; + private System.Windows.Forms.Button removeButton; + private System.Windows.Forms.Button copyButton; + } +} \ No newline at end of file diff --git a/TestBenchFramework/BenchesDlg.cs b/TestBenchFramework/BenchesDlg.cs new file mode 100644 index 000000000..7bf6f1269 --- /dev/null +++ b/TestBenchFramework/BenchesDlg.cs @@ -0,0 +1,199 @@ +using System; +using System.Windows.Forms; + +namespace TBF +{ + /// + /// Dialog to edit local settings that specify database parameters (S1.2) + /// + public partial class BenchesDlg : Form + { + // Local copy of 'local settings' initialized to Program.localSettings. + // Dialog modifies this copy and updates Program.localSettings just + // when 'OK' is pressed. + LocalSettings localSettings; + + /// + /// Constructor, initializes the dialog + /// + public BenchesDlg() + { + localSettings = new LocalSettings(); + localSettings.Assign(Program.LocalSettings); + + InitializeComponent(); + RedrawTestBenchesListBox(); + } + + void RedrawTestBenchesListBox() + { + testBenchesListBox.Items.Clear(); + if (localSettings.testBenches != null) + { + int nrBenches = localSettings.testBenches.GetLength(0); + for (int i = 0; i < nrBenches; i++) + { + testBenchesListBox.Items.Add(localSettings.testBenches[i].BenchName); + } + } + } + + /// + /// Create a new test bench DB specification and append it to the list + /// + /// Not used + /// Not used + private void addButton_Click(object sender, EventArgs e) + { + DatabaseSettings bench = new DatabaseSettings(); + DatabaseSettingsDlg dlg = new DatabaseSettingsDlg(bench); + DialogResult dr = dlg.ShowDialog(); + if (dr == DialogResult.OK) + { + int nrBenches = + (localSettings.testBenches == null) ? 0 : localSettings.testBenches.GetLength(0); + + if (nrBenches == 0) + { + localSettings.testBenches = new DatabaseSettings[1]; + localSettings.testBenches[0] = bench; + } + else + { + DatabaseSettings[] newTestBenches = new DatabaseSettings[nrBenches + 1]; + for (int i = 0; i < nrBenches; i++) + { + newTestBenches[i] = localSettings.testBenches[i]; + } + newTestBenches[nrBenches] = bench; + localSettings.testBenches = newTestBenches; + } + + testBenchesListBox.Items.Add(bench.BenchName); + } + } + + /// + /// Create a new test bench DB specification,which is a copy of the + /// selected bench, and append it to the list + /// + /// Not used + /// Not used + private void copyButton_Click(object sender, EventArgs e) + { + if (testBenchesListBox.SelectedIndex >= 0) + { + DatabaseSettings ori = localSettings.testBenches[testBenchesListBox.SelectedIndex]; + DatabaseSettings bench = (DatabaseSettings)ori.Clone(); + + DatabaseSettingsDlg dlg = new DatabaseSettingsDlg(bench); + DialogResult dr = dlg.ShowDialog(); + if (dr == DialogResult.OK) + { + int nrBenches = + (localSettings.testBenches == null) ? 0 : localSettings.testBenches.GetLength(0); + + DatabaseSettings[] newTestBenches = new DatabaseSettings[nrBenches + 1]; + for (int i = 0; i < nrBenches; i++) + { + newTestBenches[i] = localSettings.testBenches[i]; + } + newTestBenches[nrBenches] = bench; + localSettings.testBenches = newTestBenches; + + testBenchesListBox.Items.Add(bench.BenchName); + } + } + } + + /// + /// Edit selected test bench DB specification + /// + /// Not used + /// Not used + private void editButton_Click(object sender, EventArgs e) + { + if (testBenchesListBox.SelectedIndex >= 0) + { + DatabaseSettingsDlg dlg = new DatabaseSettingsDlg(localSettings.testBenches[testBenchesListBox.SelectedIndex]); + DialogResult dr = dlg.ShowDialog(); + if (dr == DialogResult.OK) + { + // Update the item name + testBenchesListBox.Items[testBenchesListBox.SelectedIndex] = + localSettings.testBenches[testBenchesListBox.SelectedIndex].BenchName; + } + } + } + + /// + /// Remove selected test bench DB specification from the list + /// + /// Not used + /// Not used + private void removeButton_Click(object sender, EventArgs e) + { + int selectedIx = testBenchesListBox.SelectedIndex; + if (selectedIx >= 0) + { + int nrBenches = + (localSettings.testBenches == null) ? 0 : localSettings.testBenches.GetLength(0); + + if (nrBenches == 1) + { + localSettings.testBenches = null; + } + else + { + DatabaseSettings[] newTestBenches = new DatabaseSettings[nrBenches - 1]; + for (int i = 0; i < selectedIx; i++) + { + newTestBenches[i] = localSettings.testBenches[i]; + } + for (int i = selectedIx + 1; i < nrBenches; i++) + { + newTestBenches[i - 1] = localSettings.testBenches[i]; + } + localSettings.testBenches = newTestBenches; + } + + RedrawTestBenchesListBox(); + } + } + + /// + /// Update setting, return 'OK' + /// + /// Not used + /// Not used + private void okButton_Click(object sender, EventArgs e) + { + Program.LocalSettings.Assign(localSettings); // Update Program.localSettings + DialogResult = DialogResult.OK; + Close(); + return; + } + + /// + /// Throw away changes, return 'Cancel' + /// + /// Not used + /// Not used + private void cancelButton_Click(object sender, EventArgs e) + { + DialogResult = DialogResult.Cancel; + Close(); + return; + } + + /// + /// Double click on an item = edit item + /// + /// Not used + /// Not used + private void testBenchesListBox_DoubleClick(object sender, EventArgs e) + { + editButton_Click(sender, e); + } + } +} \ No newline at end of file diff --git a/TestBenchFramework/BenchesDlg.de.resx b/TestBenchFramework/BenchesDlg.de.resx new file mode 100644 index 000000000..da230a148 --- /dev/null +++ b/TestBenchFramework/BenchesDlg.de.resx @@ -0,0 +1,148 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + &OK + + + &Abbrechen + + + + 58, 13 + + + Prüfstände + + + &Bearbeiten... + + + &Neu... + + + &Löschen + + + &Kopieren + + + Datenbank Einstellungen + + \ No newline at end of file diff --git a/TestBenchFramework/BenchesDlg.resx b/TestBenchFramework/BenchesDlg.resx new file mode 100644 index 000000000..139fa0b04 --- /dev/null +++ b/TestBenchFramework/BenchesDlg.resx @@ -0,0 +1,339 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 13 + + + + 192, 105 + + + $this + + + 105, 28 + + + 192, 37 + + + 164, 134 + + + &Add + + + 1 + + + 15 + + + $this + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + BenchesDlg + + + 5 + + + label1 + + + &Remove + + + 344, 71 + + + $this + + + Cancel + + + testBenchesListBox + + + 192, 71 + + + okButton + + + $this + + + System.Windows.Forms.ListBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 105, 28 + + + 0 + + + 14 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 79, 13 + + + 105, 28 + + + $this + + + 459, 185 + + + 11 + + + 6, 13 + + + 105, 28 + + + &Edit + + + addButton + + + + CenterParent + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 192, 139 + + + 7 + + + 344, 37 + + + 105, 28 + + + 17 + + + removeButton + + + &Copy + + + 12, 37 + + + 4 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 6 + + + $this + + + copyButton + + + 105, 28 + + + True + + + 3 + + + editButton + + + cancelButton + + + 12, 15 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 2 + + + OK + + + Database Settings + + + $this + + + System.Windows.Forms.Form, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 0 + + + 12 + + + 16 + + + Test Benches : + + + True + + + de + + \ No newline at end of file diff --git a/TestBenchFramework/ComponentParametersDlg.Designer.cs b/TestBenchFramework/ComponentParametersDlg.Designer.cs new file mode 100644 index 000000000..e161715ed --- /dev/null +++ b/TestBenchFramework/ComponentParametersDlg.Designer.cs @@ -0,0 +1,86 @@ +namespace TBF +{ + partial class ComponentParametersDlg + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.splitContainer = new System.Windows.Forms.SplitContainer(); + this.sharedButtons = new TBF.UiControls.SharedButtons(); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).BeginInit(); + this.splitContainer.Panel2.SuspendLayout(); + this.splitContainer.SuspendLayout(); + this.SuspendLayout(); + // + // splitContainer + // + this.splitContainer.Dock = System.Windows.Forms.DockStyle.Fill; + this.splitContainer.FixedPanel = System.Windows.Forms.FixedPanel.Panel2; + this.splitContainer.Location = new System.Drawing.Point(0, 0); + this.splitContainer.Name = "splitContainer"; + // + // splitContainer.Panel2 + // + this.splitContainer.Panel2.Controls.Add(this.sharedButtons); + this.splitContainer.Size = new System.Drawing.Size(459, 254); + this.splitContainer.SplitterDistance = 355; + this.splitContainer.TabIndex = 1; + // + // sharedButtons + // + this.sharedButtons.Location = new System.Drawing.Point(0, 0); + this.sharedButtons.Name = "sharedButtons"; + this.sharedButtons.Size = new System.Drawing.Size(100, 521); + this.sharedButtons.TabIndex = 0; + // + // ComponentConfigForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(459, 254); + this.Controls.Add(this.splitContainer); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.HelpButton = true; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "ComponentConfigForm"; + this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "Properties"; + this.Load += new System.EventHandler(this.ComponentCfgForm_Load); + this.splitContainer.Panel2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).EndInit(); + this.splitContainer.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.SplitContainer splitContainer; + private UiControls.SharedButtons sharedButtons; + } +} \ No newline at end of file diff --git a/TestBenchFramework/ComponentParametersDlg.cs b/TestBenchFramework/ComponentParametersDlg.cs new file mode 100644 index 000000000..f8513c720 --- /dev/null +++ b/TestBenchFramework/ComponentParametersDlg.cs @@ -0,0 +1,87 @@ +using System; +using System.Collections.Generic; +using System.Windows.Forms; +using TBF.BenchControl; +using TBF.BenchControl.Generic; +using TBF.UiControls; +using TBF.Resources; + +namespace TBF +{ + public partial class ComponentParametersDlg : Form + { + public IComponentCfgCtrl ComponentCfgCtrl; + + public IComponentCfg Config + { + get + { + if (ComponentCfgCtrl == null) return null; + return ComponentCfgCtrl.Config; + } + } + + /// + /// List of components (=component configuration instances) + /// + public IList TbfComponents; + + public ComponentParametersDlg() + { + InitializeComponent(); + + /// SharedDlgButtons configuration + sharedButtons.RequiredGroupMembership = Grp.GID.Metrologists; + sharedButtons.OptionalButtons = SharedButtons.Buttons.None; + sharedButtons.Unlocked += Unlock; + sharedButtons.OKClicked += okButton_Click; + sharedButtons.CancelClicked += cancelButton_Click; + } + + private void ComponentCfgForm_Load(object sender, EventArgs e) + { + Text = Strings.Properties; + + if (ComponentCfgCtrl != null) + { + splitContainer.Panel1.Controls.Add((UserControl)ComponentCfgCtrl); + } + } + + private void Unlock(object sender, EventArgs e) + { + ComponentCfgCtrl.Unlock(); + } + + public CfgVerifyFlags VerifyCfg(ref string message) + { + if (ComponentCfgCtrl == null) return CfgVerifyFlags.None; /// Nothing to verify -> OK + return ComponentCfgCtrl.VerifyCfg(ref message); + } + + private void okButton_Click(object sender, EventArgs e) + { + string message = string.Empty; + CfgVerifyFlags flags = VerifyCfg(ref message); + if ((flags & CfgVerifyFlags.Error) == CfgVerifyFlags.Error) + { + MessageBox.Show(Strings.Please_change_the_following_settings + message, + Strings.Error, MessageBoxButtons.OK, MessageBoxIcon.Error); + return; + } + + if (ComponentCfgCtrl != null) ComponentCfgCtrl.UpdateCfg(); + + DialogResult = DialogResult.OK; + Close(); + return; + } + + private void cancelButton_Click(object sender, EventArgs e) + { + DialogResult = DialogResult.Cancel; + Close(); + return; + } + } +} diff --git a/TestBenchFramework/ComponentParametersDlg.de.resx b/TestBenchFramework/ComponentParametersDlg.de.resx new file mode 100644 index 000000000..b344df0f9 --- /dev/null +++ b/TestBenchFramework/ComponentParametersDlg.de.resx @@ -0,0 +1,130 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 357, 243 + + + &OK + + + &Abbrechen + + \ No newline at end of file diff --git a/TestBenchFramework/ComponentParametersDlg.resx b/TestBenchFramework/ComponentParametersDlg.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/TestBenchFramework/ComponentParametersDlg.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/ComponentsManagerDlg.Designer.cs b/TestBenchFramework/ComponentsManagerDlg.Designer.cs new file mode 100644 index 000000000..e89dede25 --- /dev/null +++ b/TestBenchFramework/ComponentsManagerDlg.Designer.cs @@ -0,0 +1,95 @@ +namespace TBF +{ + partial class ComponentsManagerDlg + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ComponentsManagerDlg)); + this.splitContainer = new System.Windows.Forms.SplitContainer(); + this.listViewEx = new TBF.UiControls.ListViewEx(); + this.sharedButtons = new TBF.UiControls.SharedButtons(); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).BeginInit(); + this.splitContainer.Panel1.SuspendLayout(); + this.splitContainer.Panel2.SuspendLayout(); + this.splitContainer.SuspendLayout(); + this.SuspendLayout(); + // + // splitContainer + // + resources.ApplyResources(this.splitContainer, "splitContainer"); + this.splitContainer.FixedPanel = System.Windows.Forms.FixedPanel.Panel2; + this.splitContainer.Name = "splitContainer"; + // + // splitContainer.Panel1 + // + this.splitContainer.Panel1.Controls.Add(this.listViewEx); + // + // splitContainer.Panel2 + // + this.splitContainer.Panel2.Controls.Add(this.sharedButtons); + // + // listViewEx + // + this.listViewEx.AllowColumnReorder = true; + resources.ApplyResources(this.listViewEx, "listViewEx"); + this.listViewEx.DoubleClickActivation = false; + this.listViewEx.FullRowSelect = true; + this.listViewEx.GridLines = true; + this.listViewEx.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable; + this.listViewEx.Name = "listViewEx"; + this.listViewEx.UseCompatibleStateImageBehavior = false; + this.listViewEx.View = System.Windows.Forms.View.Details; + this.listViewEx.SelectedIndexChanged += new System.EventHandler(this.componentsListView_SelectedIndexChanged); + this.listViewEx.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.listViewEx_MouseDoubleClick); + // + // sharedButtons + // + resources.ApplyResources(this.sharedButtons, "sharedButtons"); + this.sharedButtons.Name = "sharedButtons"; + // + // ComponentsManagerDlg + // + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.splitContainer); + this.Name = "ComponentsManagerDlg"; + this.Load += new System.EventHandler(this.ComponentsManagerDlg_Load); + this.splitContainer.Panel1.ResumeLayout(false); + this.splitContainer.Panel2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).EndInit(); + this.splitContainer.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private TBF.UiControls.ListViewEx listViewEx; + private System.Windows.Forms.SplitContainer splitContainer; + private UiControls.SharedButtons sharedButtons; + } +} \ No newline at end of file diff --git a/TestBenchFramework/ComponentsManagerDlg.cs b/TestBenchFramework/ComponentsManagerDlg.cs new file mode 100644 index 000000000..fb03011c6 --- /dev/null +++ b/TestBenchFramework/ComponentsManagerDlg.cs @@ -0,0 +1,313 @@ +using System; +using System.Collections.Generic; +using System.Windows.Forms; +using log4net; + +using TBF.BenchControl; +using TBF.BenchControl.Generic; +using TBF.Entities; +using TBF.Resources; +using TBF.UiControls; + +namespace TBF +{ + public partial class ComponentsManagerDlg : Form, IParentOfListViewEx + { + static readonly ILog log = LogManager.GetLogger(typeof(ComponentsManagerDlg)); + + /// + /// List of components (=component configuration instances) + /// + IList cmpntEntities; + + IList toBeDeletedEntities; + + NHibernate.ISession session; + + SelectComponentClassDlg selectComponentTypeDlg; /// Constructed once, the selection is kept between dialog usages + + /// + /// ListViewEx columns + /// + enum Column + { + Name, + ClassName, + ParentName, + DebugMode, + Logging, + Parameters, + ColumnsCount, + } + readonly int columnsCount = (int)Column.ColumnsCount; + + /// Editors used by listViewEx + ComboBox debugCB; + ComboBox logCB; + + bool unlocked; + + public ComponentsManagerDlg() + { + toBeDeletedEntities = new List(); + + InitializeComponent(); + + selectComponentTypeDlg = new SelectComponentClassDlg(); + + /// SharedDlgButtons configuration + sharedButtons.RequiredGroupMembership = Grp.GID.Metrologists; + sharedButtons.OptionalButtons = SharedButtons.Buttons.Add | + SharedButtons.Buttons.Remove | + //SharedButtons.Buttons.Up | + //SharedButtons.Buttons.Down | + SharedButtons.Buttons.Edit; + sharedButtons.Unlocked += Unlocked; + sharedButtons.OKClicked += okButton_Click; + sharedButtons.CancelClicked += cancelButton_Click; + sharedButtons.AddClicked += addButton_Click; + sharedButtons.RemoveClicked += removeButton_Click; + //sharedButtons.UpClicked += upButton_Click; + //sharedButtons.DownClicked += downButton_Click; + sharedButtons.EditClicked += editButton_Click; + } + + private void ComponentsManagerDlg_Load(object sender, EventArgs e) + { + Text = Strings.Test_Bench_Components_Configuration; + listViewEx.Columns.Add(Strings.Name, 80); + listViewEx.Columns.Add(Strings.Type, 120); + listViewEx.Columns.Add(Strings.Parent, 55); + listViewEx.Columns.Add(Strings.Mode, 55); + listViewEx.Columns.Add(Strings.Logging, 55); + listViewEx.Columns.Add(Strings.Parameters, 600); + + debugCB = new ComboBox(); + for (DebugMode level = 0; level < DebugMode.Count; level++) debugCB.Items.Add(level.ToString()); + splitContainer.Panel1.Controls.Add(debugCB); + + logCB = new ComboBox(); + for (LogLevel level = 0; level < LogLevel.Count; level++) logCB.Items.Add(level.ToString()); + splitContainer.Panel1.Controls.Add(logCB); + + listViewEx.SubItemClicked += new SubItemEventHandler(listViewEx_SubItemClicked); + listViewEx.SubItemEndEditing += new SubItemEndEditingEventHandler(listViewEx_SubItemEndEditing); + + sharedButtons.DisableButtons(UiControls.SharedButtons.Buttons.Remove | UiControls.SharedButtons.Buttons.Edit); + + session = FluentCommon.CreateSession(Database.Bench); + cmpntEntities = session + .CreateQuery("FROM Component ORDER BY ItemNr") + .List(); + + RedrawAll(); + } + + void listViewEx_SubItemClicked(object sender, SubItemEventArgs e) + { + if (unlocked && e.SubItem == (int)Column.DebugMode) + { + listViewEx.StartEditing(debugCB, e.Item, e.SubItem); + } + else if (unlocked && e.SubItem == (int)Column.Logging) + { + listViewEx.StartEditing(logCB, e.Item, e.SubItem); + } + } + + void listViewEx_SubItemEndEditing(object sender, SubItemEndEditingEventArgs e) + { + Entities.Component cmpnt = (Entities.Component)e.Item.Tag; + + if (e.SubItem == (int)Column.DebugMode) + { + for (DebugMode level = 0; level < DebugMode.Count; level++) + { + if (debugCB.Text.Equals(level.ToString())) + { + cmpnt.Mode = level; + return; + } + } + e.DisplayText = cmpnt.Mode.ToString(); + } + else if (e.SubItem == (int)Column.Logging) + { + for (LogLevel level = 0; level < LogLevel.Count; level++) + { + if (logCB.Text.Equals(level.ToString())) + { + cmpnt.Logging = level; + return; + } + } + e.DisplayText = cmpnt.Logging.ToString(); + } + } + + private void Unlocked(object sender, EventArgs e) + { + unlocked = true; + } + + void RedrawAll() + { + listViewEx.Items.Clear(); + foreach (var cmpnt in cmpntEntities) DrawOne(cmpnt); + } + + void DrawOne(Entities.Component cmpnt) + { + IComponentCfg cmpCfg = TbfComponents.CmpntCfgFromCmpntEntity(cmpnt); + + ListViewItem lvi = new ListViewItem(cmpCfg.Name); + lvi.SubItems.Add(cmpCfg.Factory.ClassName); + lvi.SubItems.Add(cmpCfg.ParentName); + lvi.SubItems.Add(cmpCfg.DebugLevel.ToString()); + lvi.SubItems.Add(cmpCfg.LogLevel.ToString()); + lvi.SubItems.Add(cmpCfg.ToString(1)); + + lvi.Tag = cmpnt; + + listViewEx.Items.Add(lvi); + } + + /// OK + private void okButton_Click(object sender, EventArgs e) + { + foreach (var cmpnt in toBeDeletedEntities) + { + FluentCommon.DeleteFromDb(session, cmpnt); + } + foreach (var cmpnt in cmpntEntities) + { + FluentCommon.SaveToDb(session, cmpnt); + } + + DialogResult = DialogResult.OK; + Close(); + return; + } + + /// Cancel + private void cancelButton_Click(object sender, EventArgs e) + { + DialogResult = DialogResult.Cancel; + Close(); + return; + } + + /// Add a new component + private void addButton_Click(object sender, EventArgs e) + { + DialogResult dr = selectComponentTypeDlg.ShowDialog(); + if (dr != DialogResult.OK) return; + + IComponentFactory factory = selectComponentTypeDlg.SlctdCmpntFactory; + IComponentCfgCtrl cfgControl = factory.CreateCfgCtrl(); + cfgControl.Config = factory.DefaultConfig(cmpntEntities); + cfgControl.Config.ItemNr = listViewEx.Items.Count; + + ComponentParametersDlg cfgForm = new ComponentParametersDlg(); + cfgForm.TbfComponents = cmpntEntities; + cfgForm.ComponentCfgCtrl = cfgControl; + dr = cfgForm.ShowDialog(); + if (dr != DialogResult.OK) return; + + AddOne(cfgForm.Config.CreateDbEntity()); + } + + void AddOne(Entities.Component cmpnt) + { + cmpntEntities.Add(cmpnt); + DrawOne(cmpnt); + } + + /// Delete the component + private void removeButton_Click(object sender, EventArgs e) + { + if (listViewEx.SelectedIndices.Count != 1) return; + int ix = listViewEx.SelectedIndices[0]; + if (ix < 0) return; + + Entities.Component selectedCmpnt = (Entities.Component)listViewEx.Items[ix].Tag; + if (selectedCmpnt.Id != 0) toBeDeletedEntities.Add(selectedCmpnt); + listViewEx.Items.RemoveAt(ix); + RedrawAll(); + } + + /// DoubleClick -> Edit the component + private void listViewEx_MouseDoubleClick(object sender, MouseEventArgs e) + { + editButton_Click(sender, e); + } + + /// Edit the component + private void editButton_Click(object sender, EventArgs e) + { + if (listViewEx.SelectedIndices.Count != 1) return; + ListViewItem lvi = listViewEx.SelectedItems[0]; + + ComponentParametersDlg cfgForm = new ComponentParametersDlg(); + cfgForm.TbfComponents = cmpntEntities; + cfgForm.ComponentCfgCtrl = TbfComponents.CmpntFactoryFromClassName(((Entities.Component)lvi.Tag).ClassName).CreateCfgCtrl(); + cfgForm.ComponentCfgCtrl.Config = TbfComponents.CmpntCfgFromCmpntEntity((Entities.Component)lvi.Tag); + DialogResult dr = cfgForm.ShowDialog(); + if (dr != DialogResult.OK) return; + + sharedButtons.UnlockButtons(); /// Unlock this dialog buttons as changes were enabled + unlocked = true; /// in the ComponentParametersDlg. + + Entities.Component modified = cfgForm.Config.CreateDbEntity(); + Entities.Component original = (Entities.Component)lvi.Tag; + + original.Name = modified.Name; + original.ClassName = modified.ClassName; + original.ParentName = modified.ParentName; + original.Mode = modified.Mode; + original.Logging = modified.Logging; + original.Parameters = modified.Parameters; + + RedrawAll(); + } + + private void componentsListView_SelectedIndexChanged(object sender, EventArgs e) + { + if (listViewEx.SelectedIndices.Count == 1) + { + sharedButtons.EnableButtons(UiControls.SharedButtons.Buttons.Remove | UiControls.SharedButtons.Buttons.Edit); + } + else + { + sharedButtons.DisableButtons(UiControls.SharedButtons.Buttons.Remove | UiControls.SharedButtons.Buttons.Edit); + } + } + + public void UpdateButtonStates(SharedButtons.SelectedItemPos selectedItemPos) + { + if (selectedItemPos == SharedButtons.SelectedItemPos.None) + { + sharedButtons.DisableButtons(SharedButtons.Buttons.Remove | SharedButtons.Buttons.Up | SharedButtons.Buttons.Down); + } + else if (selectedItemPos == SharedButtons.SelectedItemPos.First) + { + sharedButtons.EnableButtons(SharedButtons.Buttons.Remove | SharedButtons.Buttons.Down); + sharedButtons.DisableButtons(SharedButtons.Buttons.Up); + } + else if (selectedItemPos == SharedButtons.SelectedItemPos.Last) + { + sharedButtons.EnableButtons(SharedButtons.Buttons.Remove | SharedButtons.Buttons.Up); + sharedButtons.DisableButtons(SharedButtons.Buttons.Down); + } + else if (selectedItemPos == SharedButtons.SelectedItemPos.FirstAndLast) + { + sharedButtons.EnableButtons(SharedButtons.Buttons.Remove); + sharedButtons.DisableButtons(SharedButtons.Buttons.Up | SharedButtons.Buttons.Down); + } + else + { + sharedButtons.EnableButtons(SharedButtons.Buttons.Remove | SharedButtons.Buttons.Up | SharedButtons.Buttons.Down); + } + } + } +} diff --git a/TestBenchFramework/ComponentsManagerDlg.resx b/TestBenchFramework/ComponentsManagerDlg.resx new file mode 100644 index 000000000..982aa26ca --- /dev/null +++ b/TestBenchFramework/ComponentsManagerDlg.resx @@ -0,0 +1,243 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + Fill + + + + True + + + + 0, 0 + + + Fill + + + 0, 0 + + + 520, 346 + + + 7 + + + listViewEx + + + TBF.UiControls.ListViewEx, TBF, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + + splitContainer.Panel1 + + + 0 + + + splitContainer.Panel1 + + + System.Windows.Forms.SplitterPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + splitContainer + + + 0 + + + 1, 0 + + + 100, 521 + + + 0 + + + sharedButtons + + + TBF.UiControls.SharedButtons, TBF, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + + splitContainer.Panel2 + + + 0 + + + splitContainer.Panel2 + + + System.Windows.Forms.SplitterPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + splitContainer + + + 1 + + + 625, 346 + + + 520 + + + 8 + + + splitContainer + + + System.Windows.Forms.SplitContainer, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 0 + + + True + + + 6, 13 + + + 625, 346 + + + CenterParent + + + Test Bench Components Configuration + + + ComponentsManagerDlg + + + System.Windows.Forms.Form, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/CustomStyle.cs b/TestBenchFramework/CustomStyle.cs new file mode 100644 index 000000000..d98c9e806 --- /dev/null +++ b/TestBenchFramework/CustomStyle.cs @@ -0,0 +1,83 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace TBF +{ + /// + /// This static class maintains a set of text box styles at one place, it is then sufficient + /// to use the static method CustomStyle.Apply(id, textBox(es)) to apply this style to text box(es). + /// + public static class CustomStyle + { + const int setsCount = 20; /// Number of styles / attribute sets + + static DockStyle[] dockStyles; /// Docking style + static System.Drawing.Color[] backColors; /// Background color + static BorderStyle[] borderStyles; /// Border style + static bool[] readOnly; /// Read only + static System.Drawing.Font[] fonts; /// Font + + static CustomStyle() + { + dockStyles = new DockStyle[setsCount]; + backColors = new System.Drawing.Color[setsCount]; + borderStyles = new BorderStyle[setsCount]; + readOnly = new bool[setsCount]; + fonts = new System.Drawing.Font[setsCount]; + } + + /// + /// Set attributes of the set selected by 'set' parameter + /// + /// Attribute set ID + /// Docking style + /// Background color + /// true for read only (aka label) + /// Border style + public static void Set(int id, DockStyle dockStyle, System.Drawing.Color backColor, BorderStyle borderStyle, bool readOnly, System.Drawing.Font font) + { + if (id < 0 || id >= setsCount) return; + + CustomStyle.dockStyles[id] = dockStyle; + CustomStyle.backColors[id] = backColor; + CustomStyle.borderStyles[id] = borderStyle; + CustomStyle.readOnly[id] = readOnly; + CustomStyle.fonts[id] = font; + } + + /// + /// Apply one of the attribute sets to a TextBox instance + /// + public static void Apply(int id, TextBox textBox) + { + if (id < 0 || id >= setsCount) return; + + textBox.Dock = dockStyles[id]; + textBox.BackColor = backColors[id]; + textBox.BorderStyle = borderStyles[id]; + textBox.ReadOnly = readOnly[id]; + textBox.Font = fonts[id]; + } + + /// + /// Apply one of the attribute sets to a AttachedTextBoxes text boxes + /// + public static void Apply(int id, AttachedTextBoxes textBoxes) + { + if (id < 0 || id >= setsCount) return; + + for (int i = 0; i < textBoxes.Count; i++) + { + textBoxes[i].Dock = dockStyles[id]; + textBoxes[i].BackColor = backColors[id]; + textBoxes[i].BorderStyle = borderStyles[id]; + textBoxes[i].ReadOnly = readOnly[id]; + textBoxes[i].Font = fonts[id]; + } + } + } +} diff --git a/TestBenchFramework/DBSettings.cs b/TestBenchFramework/DBSettings.cs new file mode 100644 index 000000000..778499528 --- /dev/null +++ b/TestBenchFramework/DBSettings.cs @@ -0,0 +1,28 @@ +using System; + +namespace TBF +{ + /// + /// Database settings required to make a connection + /// + public class DBSettings : ICloneable + { + public DBType DbType; + public string ConnectionString; + + public DBSettings() + { + } + + public DBSettings(DBType dbType, string connectionString) + { + this.DbType = dbType; + this.ConnectionString = connectionString; + } + + public object Clone() + { + return new DBSettings(DbType, ConnectionString); + } + } +} diff --git a/TestBenchFramework/DatabaseSettings.cs b/TestBenchFramework/DatabaseSettings.cs new file mode 100644 index 000000000..f58c7de0e --- /dev/null +++ b/TestBenchFramework/DatabaseSettings.cs @@ -0,0 +1,48 @@ +using System; +using System.Text; +using System.Xml.Serialization; + +namespace TBF +{ + /// + /// Test bench database settings, contains bench name and settings od several databases + /// + public class DatabaseSettings : ICloneable + { + // Public fields + public string BenchName; + public bool IsRealBench; + public DBSettings UsersDBSettings; + public DBSettings BenchDBSettings; + public DBSettings ProceduresDBSettings; + public DBSettings WMTypesDBSettings; + public DBSettings WaterMetersDBSettings; + + // Constructor + public DatabaseSettings() + { + BenchName = String.Empty; /// Empty string to avoid null + IsRealBench = false; + UsersDBSettings = new DBSettings(DBType.MySql, "SERVER=localhost; DATABASE=tbf_users; UID=root; PASSWORD=;"); + BenchDBSettings = new DBSettings(DBType.MySql, "SERVER=localhost; DATABASE=tbf_bench; UID=root; PASSWORD=;"); + ProceduresDBSettings = new DBSettings(DBType.MySql, "SERVER=localhost; DATABASE=tbf_procedures; UID=root; PASSWORD=;"); + WMTypesDBSettings = new DBSettings(DBType.MySql, "SERVER=localhost; DATABASE=tbf_wmtypes; UID=root; PASSWORD=;"); + WaterMetersDBSettings = new DBSettings(DBType.MySql, "SERVER=localhost; DATABASE=tbf_watermeters; UID=root; PASSWORD=;"); + } + + public object Clone() + { + DatabaseSettings result = new DatabaseSettings(); + + result.BenchName = BenchName; + result.IsRealBench = IsRealBench; + result.UsersDBSettings = (DBSettings)UsersDBSettings.Clone(); + result.BenchDBSettings = (DBSettings)BenchDBSettings.Clone(); + result.ProceduresDBSettings = (DBSettings)ProceduresDBSettings.Clone(); + result.WMTypesDBSettings = (DBSettings)WMTypesDBSettings.Clone(); + result.WaterMetersDBSettings = (DBSettings)WaterMetersDBSettings.Clone(); + + return result; + } + } +} diff --git a/TestBenchFramework/DatabaseSettingsDlg.Designer.cs b/TestBenchFramework/DatabaseSettingsDlg.Designer.cs new file mode 100644 index 000000000..e9ed65d9b --- /dev/null +++ b/TestBenchFramework/DatabaseSettingsDlg.Designer.cs @@ -0,0 +1,370 @@ +namespace TBF +{ + partial class DatabaseSettingsDlg + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(DatabaseSettingsDlg)); + this.okButton = new System.Windows.Forms.Button(); + this.cancelButton = new System.Windows.Forms.Button(); + this.label1 = new System.Windows.Forms.Label(); + this.benchNameTextBox = new System.Windows.Forms.TextBox(); + this.usersConnectionStringTextBox = new System.Windows.Forms.TextBox(); + this.connectionStringLabel = new System.Windows.Forms.Label(); + this.benchConnectionStringTextBox = new System.Windows.Forms.TextBox(); + this.proceduresConnectionStringTextBox = new System.Windows.Forms.TextBox(); + this.wmTypesConnectionStringTextBox = new System.Windows.Forms.TextBox(); + this.watermetersConnectionStringTextBox = new System.Windows.Forms.TextBox(); + this.label2 = new System.Windows.Forms.Label(); + this.label3 = new System.Windows.Forms.Label(); + this.label4 = new System.Windows.Forms.Label(); + this.label5 = new System.Windows.Forms.Label(); + this.label6 = new System.Windows.Forms.Label(); + this.testConnUsersBtn = new System.Windows.Forms.Button(); + this.createUsersDbBtn = new System.Windows.Forms.Button(); + this.realBenchCheckBox = new System.Windows.Forms.CheckBox(); + this.dbTypeLabel = new System.Windows.Forms.Label(); + this.usersDbTypeComboBox = new System.Windows.Forms.ComboBox(); + this.benchDbTypeComboBox = new System.Windows.Forms.ComboBox(); + this.proceduresDbTypeComboBox = new System.Windows.Forms.ComboBox(); + this.wmTypesDbTypeComboBox = new System.Windows.Forms.ComboBox(); + this.watermetersDbTypeComboBox = new System.Windows.Forms.ComboBox(); + this.testConnBenchBtn = new System.Windows.Forms.Button(); + this.testConnProceduresBtn = new System.Windows.Forms.Button(); + this.testConnWMTypesBtn = new System.Windows.Forms.Button(); + this.testConnWaterMetersBtn = new System.Windows.Forms.Button(); + this.createBenchDbBtn = new System.Windows.Forms.Button(); + this.createProceduresDbBtn = new System.Windows.Forms.Button(); + this.createWMTypesDbBtn = new System.Windows.Forms.Button(); + this.createWaterMetersDbBtn = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // okButton + // + this.okButton.DialogResult = System.Windows.Forms.DialogResult.OK; + this.okButton.ImageKey = global::TBF.Resources.Strings.String1; + resources.ApplyResources(this.okButton, "okButton"); + this.okButton.Name = "okButton"; + this.okButton.UseVisualStyleBackColor = true; + this.okButton.Click += new System.EventHandler(this.okButton_Click); + // + // cancelButton + // + this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.cancelButton.ImageKey = global::TBF.Resources.Strings.String1; + resources.ApplyResources(this.cancelButton, "cancelButton"); + this.cancelButton.Name = "cancelButton"; + this.cancelButton.UseVisualStyleBackColor = true; + this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click); + // + // label1 + // + resources.ApplyResources(this.label1, "label1"); + this.label1.ImageKey = global::TBF.Resources.Strings.String1; + this.label1.Name = "label1"; + // + // benchNameTextBox + // + resources.ApplyResources(this.benchNameTextBox, "benchNameTextBox"); + this.benchNameTextBox.Name = "benchNameTextBox"; + // + // usersConnectionStringTextBox + // + resources.ApplyResources(this.usersConnectionStringTextBox, "usersConnectionStringTextBox"); + this.usersConnectionStringTextBox.Name = "usersConnectionStringTextBox"; + // + // connectionStringLabel + // + resources.ApplyResources(this.connectionStringLabel, "connectionStringLabel"); + this.connectionStringLabel.ImageKey = global::TBF.Resources.Strings.String1; + this.connectionStringLabel.Name = "connectionStringLabel"; + // + // benchConnectionStringTextBox + // + resources.ApplyResources(this.benchConnectionStringTextBox, "benchConnectionStringTextBox"); + this.benchConnectionStringTextBox.Name = "benchConnectionStringTextBox"; + // + // proceduresConnectionStringTextBox + // + resources.ApplyResources(this.proceduresConnectionStringTextBox, "proceduresConnectionStringTextBox"); + this.proceduresConnectionStringTextBox.Name = "proceduresConnectionStringTextBox"; + // + // wmTypesConnectionStringTextBox + // + resources.ApplyResources(this.wmTypesConnectionStringTextBox, "wmTypesConnectionStringTextBox"); + this.wmTypesConnectionStringTextBox.Name = "wmTypesConnectionStringTextBox"; + // + // watermetersConnectionStringTextBox + // + resources.ApplyResources(this.watermetersConnectionStringTextBox, "watermetersConnectionStringTextBox"); + this.watermetersConnectionStringTextBox.Name = "watermetersConnectionStringTextBox"; + // + // label2 + // + resources.ApplyResources(this.label2, "label2"); + this.label2.ImageKey = global::TBF.Resources.Strings.String1; + this.label2.Name = "label2"; + // + // label3 + // + resources.ApplyResources(this.label3, "label3"); + this.label3.ImageKey = global::TBF.Resources.Strings.String1; + this.label3.Name = "label3"; + // + // label4 + // + resources.ApplyResources(this.label4, "label4"); + this.label4.ImageKey = global::TBF.Resources.Strings.String1; + this.label4.Name = "label4"; + // + // label5 + // + resources.ApplyResources(this.label5, "label5"); + this.label5.ImageKey = global::TBF.Resources.Strings.String1; + this.label5.Name = "label5"; + // + // label6 + // + resources.ApplyResources(this.label6, "label6"); + this.label6.ImageKey = global::TBF.Resources.Strings.String1; + this.label6.Name = "label6"; + // + // testConnUsersBtn + // + this.testConnUsersBtn.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.testConnUsersBtn.ImageKey = global::TBF.Resources.Strings.String1; + resources.ApplyResources(this.testConnUsersBtn, "testConnUsersBtn"); + this.testConnUsersBtn.Name = "testConnUsersBtn"; + this.testConnUsersBtn.UseVisualStyleBackColor = true; + this.testConnUsersBtn.Click += new System.EventHandler(this.testConnUsersBtn_Click); + // + // createUsersDbBtn + // + this.createUsersDbBtn.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.createUsersDbBtn.ImageKey = global::TBF.Resources.Strings.String1; + resources.ApplyResources(this.createUsersDbBtn, "createUsersDbBtn"); + this.createUsersDbBtn.Name = "createUsersDbBtn"; + this.createUsersDbBtn.UseVisualStyleBackColor = true; + this.createUsersDbBtn.Click += new System.EventHandler(this.createDatabasesButton_Click); + // + // realBenchCheckBox + // + resources.ApplyResources(this.realBenchCheckBox, "realBenchCheckBox"); + this.realBenchCheckBox.ImageKey = global::TBF.Resources.Strings.String1; + this.realBenchCheckBox.Name = "realBenchCheckBox"; + this.realBenchCheckBox.UseVisualStyleBackColor = true; + // + // dbTypeLabel + // + resources.ApplyResources(this.dbTypeLabel, "dbTypeLabel"); + this.dbTypeLabel.ImageKey = global::TBF.Resources.Strings.String1; + this.dbTypeLabel.Name = "dbTypeLabel"; + // + // usersDbTypeComboBox + // + this.usersDbTypeComboBox.FormattingEnabled = true; + resources.ApplyResources(this.usersDbTypeComboBox, "usersDbTypeComboBox"); + this.usersDbTypeComboBox.Name = "usersDbTypeComboBox"; + // + // benchDbTypeComboBox + // + this.benchDbTypeComboBox.FormattingEnabled = true; + resources.ApplyResources(this.benchDbTypeComboBox, "benchDbTypeComboBox"); + this.benchDbTypeComboBox.Name = "benchDbTypeComboBox"; + // + // proceduresDbTypeComboBox + // + this.proceduresDbTypeComboBox.FormattingEnabled = true; + resources.ApplyResources(this.proceduresDbTypeComboBox, "proceduresDbTypeComboBox"); + this.proceduresDbTypeComboBox.Name = "proceduresDbTypeComboBox"; + // + // wmTypesDbTypeComboBox + // + this.wmTypesDbTypeComboBox.FormattingEnabled = true; + resources.ApplyResources(this.wmTypesDbTypeComboBox, "wmTypesDbTypeComboBox"); + this.wmTypesDbTypeComboBox.Name = "wmTypesDbTypeComboBox"; + // + // watermetersDbTypeComboBox + // + this.watermetersDbTypeComboBox.FormattingEnabled = true; + resources.ApplyResources(this.watermetersDbTypeComboBox, "watermetersDbTypeComboBox"); + this.watermetersDbTypeComboBox.Name = "watermetersDbTypeComboBox"; + // + // testConnBenchBtn + // + this.testConnBenchBtn.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.testConnBenchBtn.ImageKey = global::TBF.Resources.Strings.String1; + resources.ApplyResources(this.testConnBenchBtn, "testConnBenchBtn"); + this.testConnBenchBtn.Name = "testConnBenchBtn"; + this.testConnBenchBtn.UseVisualStyleBackColor = true; + this.testConnBenchBtn.Click += new System.EventHandler(this.testConnBenchBtn_Click); + // + // testConnProceduresBtn + // + this.testConnProceduresBtn.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.testConnProceduresBtn.ImageKey = global::TBF.Resources.Strings.String1; + resources.ApplyResources(this.testConnProceduresBtn, "testConnProceduresBtn"); + this.testConnProceduresBtn.Name = "testConnProceduresBtn"; + this.testConnProceduresBtn.UseVisualStyleBackColor = true; + this.testConnProceduresBtn.Click += new System.EventHandler(this.testConnProceduresBtn_Click); + // + // testConnWMTypesBtn + // + this.testConnWMTypesBtn.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.testConnWMTypesBtn.ImageKey = global::TBF.Resources.Strings.String1; + resources.ApplyResources(this.testConnWMTypesBtn, "testConnWMTypesBtn"); + this.testConnWMTypesBtn.Name = "testConnWMTypesBtn"; + this.testConnWMTypesBtn.UseVisualStyleBackColor = true; + this.testConnWMTypesBtn.Click += new System.EventHandler(this.testConnWMTypesBtn_Click); + // + // testConnWaterMetersBtn + // + this.testConnWaterMetersBtn.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.testConnWaterMetersBtn.ImageKey = global::TBF.Resources.Strings.String1; + resources.ApplyResources(this.testConnWaterMetersBtn, "testConnWaterMetersBtn"); + this.testConnWaterMetersBtn.Name = "testConnWaterMetersBtn"; + this.testConnWaterMetersBtn.UseVisualStyleBackColor = true; + this.testConnWaterMetersBtn.Click += new System.EventHandler(this.testConnWaterMetersBtn_Click); + // + // createBenchDbBtn + // + this.createBenchDbBtn.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.createBenchDbBtn.ImageKey = global::TBF.Resources.Strings.String1; + resources.ApplyResources(this.createBenchDbBtn, "createBenchDbBtn"); + this.createBenchDbBtn.Name = "createBenchDbBtn"; + this.createBenchDbBtn.UseVisualStyleBackColor = true; + this.createBenchDbBtn.Click += new System.EventHandler(this.createbenchDbBtn_Click); + // + // createProceduresDbBtn + // + this.createProceduresDbBtn.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.createProceduresDbBtn.ImageKey = global::TBF.Resources.Strings.String1; + resources.ApplyResources(this.createProceduresDbBtn, "createProceduresDbBtn"); + this.createProceduresDbBtn.Name = "createProceduresDbBtn"; + this.createProceduresDbBtn.UseVisualStyleBackColor = true; + this.createProceduresDbBtn.Click += new System.EventHandler(this.createProecduresDbBtn_Click); + // + // createWMTypesDbBtn + // + this.createWMTypesDbBtn.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.createWMTypesDbBtn.ImageKey = global::TBF.Resources.Strings.String1; + resources.ApplyResources(this.createWMTypesDbBtn, "createWMTypesDbBtn"); + this.createWMTypesDbBtn.Name = "createWMTypesDbBtn"; + this.createWMTypesDbBtn.UseVisualStyleBackColor = true; + this.createWMTypesDbBtn.Click += new System.EventHandler(this.createWMTypesDbBtn_Click); + // + // createWaterMetersDbBtn + // + this.createWaterMetersDbBtn.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.createWaterMetersDbBtn.ImageKey = global::TBF.Resources.Strings.String1; + resources.ApplyResources(this.createWaterMetersDbBtn, "createWaterMetersDbBtn"); + this.createWaterMetersDbBtn.Name = "createWaterMetersDbBtn"; + this.createWaterMetersDbBtn.UseVisualStyleBackColor = true; + this.createWaterMetersDbBtn.Click += new System.EventHandler(this.createWaterMetersDbBtn_Click); + // + // DatabaseSettingsDlg + // + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.createWaterMetersDbBtn); + this.Controls.Add(this.createWMTypesDbBtn); + this.Controls.Add(this.createProceduresDbBtn); + this.Controls.Add(this.createBenchDbBtn); + this.Controls.Add(this.testConnWaterMetersBtn); + this.Controls.Add(this.testConnWMTypesBtn); + this.Controls.Add(this.testConnProceduresBtn); + this.Controls.Add(this.testConnBenchBtn); + this.Controls.Add(this.watermetersDbTypeComboBox); + this.Controls.Add(this.wmTypesDbTypeComboBox); + this.Controls.Add(this.proceduresDbTypeComboBox); + this.Controls.Add(this.benchDbTypeComboBox); + this.Controls.Add(this.usersDbTypeComboBox); + this.Controls.Add(this.dbTypeLabel); + this.Controls.Add(this.realBenchCheckBox); + this.Controls.Add(this.createUsersDbBtn); + this.Controls.Add(this.testConnUsersBtn); + this.Controls.Add(this.label6); + this.Controls.Add(this.label5); + this.Controls.Add(this.label4); + this.Controls.Add(this.label3); + this.Controls.Add(this.label2); + this.Controls.Add(this.watermetersConnectionStringTextBox); + this.Controls.Add(this.wmTypesConnectionStringTextBox); + this.Controls.Add(this.proceduresConnectionStringTextBox); + this.Controls.Add(this.benchConnectionStringTextBox); + this.Controls.Add(this.connectionStringLabel); + this.Controls.Add(this.usersConnectionStringTextBox); + this.Controls.Add(this.benchNameTextBox); + this.Controls.Add(this.label1); + this.Controls.Add(this.okButton); + this.Controls.Add(this.cancelButton); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MinimizeBox = false; + this.Name = "DatabaseSettingsDlg"; + this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide; + this.Load += new System.EventHandler(this.BenchSettingsDlg_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Button okButton; + private System.Windows.Forms.Button cancelButton; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox benchNameTextBox; + private System.Windows.Forms.TextBox usersConnectionStringTextBox; + private System.Windows.Forms.Label connectionStringLabel; + private System.Windows.Forms.TextBox benchConnectionStringTextBox; + private System.Windows.Forms.TextBox proceduresConnectionStringTextBox; + private System.Windows.Forms.TextBox wmTypesConnectionStringTextBox; + private System.Windows.Forms.TextBox watermetersConnectionStringTextBox; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.Button testConnUsersBtn; + private System.Windows.Forms.Button createUsersDbBtn; + private System.Windows.Forms.CheckBox realBenchCheckBox; + private System.Windows.Forms.Label dbTypeLabel; + private System.Windows.Forms.ComboBox usersDbTypeComboBox; + private System.Windows.Forms.ComboBox benchDbTypeComboBox; + private System.Windows.Forms.ComboBox proceduresDbTypeComboBox; + private System.Windows.Forms.ComboBox wmTypesDbTypeComboBox; + private System.Windows.Forms.ComboBox watermetersDbTypeComboBox; + private System.Windows.Forms.Button testConnBenchBtn; + private System.Windows.Forms.Button testConnProceduresBtn; + private System.Windows.Forms.Button testConnWMTypesBtn; + private System.Windows.Forms.Button testConnWaterMetersBtn; + private System.Windows.Forms.Button createBenchDbBtn; + private System.Windows.Forms.Button createProceduresDbBtn; + private System.Windows.Forms.Button createWMTypesDbBtn; + private System.Windows.Forms.Button createWaterMetersDbBtn; + } +} \ No newline at end of file diff --git a/TestBenchFramework/DatabaseSettingsDlg.cs b/TestBenchFramework/DatabaseSettingsDlg.cs new file mode 100644 index 000000000..6459de002 --- /dev/null +++ b/TestBenchFramework/DatabaseSettingsDlg.cs @@ -0,0 +1,261 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Windows.Forms; +using TBF.Resources; + +namespace TBF +{ + /// + /// Dialog to process test bench name and database settings (BenchSettings) + /// + public partial class DatabaseSettingsDlg : Form + { + // Reference to bench DB settins (not a local copy) + DatabaseSettings bench; + + /// + /// Constructor + /// + /// Test bench database settings + public DatabaseSettingsDlg(DatabaseSettings bench) + { + this.bench = bench; + + InitializeComponent(); + } + + void Localize() + { + Text = Strings.Test_Bench_Databases_Specification; + label1.Text = Strings.Test_bench_name; + realBenchCheckBox.Text = Strings.Test_bench_is_controlled_by_this_computer; + dbTypeLabel.Text = Strings.Database_type; + connectionStringLabel.Text = Strings.Connection_string; + label2.Text = Strings.Users_and_groups; + label3.Text = Strings.Bench_parameters; + label4.Text = Strings.Procedures; + label5.Text = Strings.Water_meter_types; + label6.Text = Strings.Water_meter_data; + okButton.Text = Strings.OkBtnText; + cancelButton.Text = Strings.CancelBtnText; + + testConnBenchBtn.Text = Strings.Test_connection; + testConnProceduresBtn.Text = Strings.Test_connection; + testConnUsersBtn.Text = Strings.Test_connection; + testConnWaterMetersBtn.Text = Strings.Test_connection; + testConnWMTypesBtn.Text = Strings.Test_connection; + + createBenchDbBtn.Text = Strings.Create_DB; + createProceduresDbBtn.Text = Strings.Create_DB; + createUsersDbBtn.Text = Strings.Create_DB; + createWaterMetersDbBtn.Text = Strings.Create_DB; + createWMTypesDbBtn.Text = Strings.Create_DB; + } + + private void BenchSettingsDlg_Load(object sender, EventArgs e) + { + Localize(); + + benchNameTextBox.Text = bench.BenchName; + realBenchCheckBox.Checked = bench.IsRealBench; + + /// Initialize 'Database type' combo-boxes + for (int i = 0; i < (int)DBType.DbTypesCount; i++) + { + DBType dbType = (DBType)i; + usersDbTypeComboBox.Items.Add(dbType); + benchDbTypeComboBox.Items.Add(dbType); + proceduresDbTypeComboBox.Items.Add(dbType); + wmTypesDbTypeComboBox.Items.Add(dbType); + watermetersDbTypeComboBox.Items.Add(dbType); + } + usersDbTypeComboBox.SelectedIndex = (int)bench.UsersDBSettings.DbType; + benchDbTypeComboBox.SelectedIndex = (int)bench.BenchDBSettings.DbType; + proceduresDbTypeComboBox.SelectedIndex = (int)bench.ProceduresDBSettings.DbType; + wmTypesDbTypeComboBox.SelectedIndex = (int)bench.WMTypesDBSettings.DbType; + watermetersDbTypeComboBox.SelectedIndex = (int)bench.WaterMetersDBSettings.DbType; + + /// Initialize connection strings + usersConnectionStringTextBox.Text = bench.UsersDBSettings.ConnectionString; + benchConnectionStringTextBox.Text = bench.BenchDBSettings.ConnectionString; + proceduresConnectionStringTextBox.Text = bench.ProceduresDBSettings.ConnectionString; + wmTypesConnectionStringTextBox.Text = bench.WMTypesDBSettings.ConnectionString; + watermetersConnectionStringTextBox.Text = bench.WaterMetersDBSettings.ConnectionString; + } + + bool UpdateBenchFromUIControls() + { + for (int i = 0; i < Program.LocalSettings.BenchesCount; i++) + { + if (bench != Program.LocalSettings.TestBenches[i] && + benchNameTextBox.Text == Program.LocalSettings.TestBenches[i].BenchName) + { + MessageBox.Show(Strings.Bench_name_conflict_Use_another_name_pls, Strings.Error, MessageBoxButtons.OK); + return false; + } + } + + bench.BenchName = benchNameTextBox.Text; + bench.IsRealBench = realBenchCheckBox.Checked; + + bench.UsersDBSettings.ConnectionString = usersConnectionStringTextBox.Text; + bench.BenchDBSettings.ConnectionString = benchConnectionStringTextBox.Text; + bench.ProceduresDBSettings.ConnectionString = proceduresConnectionStringTextBox.Text; + bench.WMTypesDBSettings.ConnectionString = wmTypesConnectionStringTextBox.Text; + bench.WaterMetersDBSettings.ConnectionString = watermetersConnectionStringTextBox.Text; + + bench.UsersDBSettings.DbType = (DBType)usersDbTypeComboBox.SelectedIndex; + bench.BenchDBSettings.DbType = (DBType)benchDbTypeComboBox.SelectedIndex; + bench.ProceduresDBSettings.DbType = (DBType)proceduresDbTypeComboBox.SelectedIndex; + bench.WMTypesDBSettings.DbType = (DBType)wmTypesDbTypeComboBox.SelectedIndex; + bench.WaterMetersDBSettings.DbType = (DBType)watermetersDbTypeComboBox.SelectedIndex; + + return true; + } + + /// + /// Update bench DB setting, return 'OK' + /// + /// Not used + /// Not used + private void okButton_Click(object sender, EventArgs e) + { + if (UpdateBenchFromUIControls()) + { + DialogResult = DialogResult.OK; + Close(); + return; + } + + DialogResult = DialogResult.None; + } + + /// + /// Throw away changes, return 'Cancel' + /// + /// Not used + /// Not used + private void cancelButton_Click(object sender, EventArgs e) + { + DialogResult = DialogResult.Cancel; + Close(); + } + + private void createDatabasesButton_Click(object sender, EventArgs e) + { + if (!UpdateBenchFromUIControls()) return; + + if (DialogResult.OK == MessageBox.Show(Strings.DB_will_be_overwritten + Environment.NewLine + + Strings.Do_you_want_to_proceed, Strings.Warning, + MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation)) + try + { + Cursor.Current = Cursors.WaitCursor; + FluentCommon.CreateEmptyUsersDB(bench.UsersDBSettings); + MessageBox.Show(Strings.DB_was_successfully_created, Strings.Notification); + Cursor.Current = Cursors.Default; + DialogResult = DialogResult.None; + } + catch (Exception exception) + { + Cursor.Current = Cursors.Default; + MessageBox.Show(Strings.Error_while_creating_DB_Reason + exception.Message, Strings.Error); + } + } + + private void createbenchDbBtn_Click(object sender, EventArgs e) + { + if (!UpdateBenchFromUIControls()) return; + + if (DialogResult.OK == MessageBox.Show(Strings.DB_will_be_overwritten + Environment.NewLine + + Strings.Do_you_want_to_proceed, Strings.Warning, + MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation)) + try + { + Cursor.Current = Cursors.WaitCursor; + FluentCommon.CreateEmptyBenchDB(bench.BenchDBSettings); + MessageBox.Show(Strings.DB_was_successfully_created, Strings.Notification); + Cursor.Current = Cursors.Default; + DialogResult = DialogResult.None; + } + catch (Exception exception) + { + Cursor.Current = Cursors.Default; + MessageBox.Show(Strings.Error_while_creating_DB_Reason + exception.Message, Strings.Error); + } + } + + private void createProecduresDbBtn_Click(object sender, EventArgs e) + { + if (!UpdateBenchFromUIControls()) return; + + if (DialogResult.OK == MessageBox.Show(Strings.DB_will_be_overwritten + Environment.NewLine + + Strings.Do_you_want_to_proceed, Strings.Warning, + MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation)) + try + { + Cursor.Current = Cursors.WaitCursor; + FluentCommon.CreateEmptyProceduresDB(bench.ProceduresDBSettings); + MessageBox.Show(Strings.DB_was_successfully_created, Strings.Notification); + Cursor.Current = Cursors.Default; + DialogResult = DialogResult.None; + } + catch (Exception exception) + { + Cursor.Current = Cursors.Default; + MessageBox.Show(Strings.Error_while_creating_DB_Reason + exception.Message, Strings.Error); + } + } + + private void createWMTypesDbBtn_Click(object sender, EventArgs e) + { + + } + + private void createWaterMetersDbBtn_Click(object sender, EventArgs e) + { + if (!UpdateBenchFromUIControls()) return; + + if (DialogResult.OK == MessageBox.Show(Strings.DB_will_be_overwritten + Environment.NewLine + + Strings.Do_you_want_to_proceed, Strings.Warning, + MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation)) + try + { + Cursor.Current = Cursors.WaitCursor; + FluentCommon.CreateEmptyWaterMetersDB(bench.WaterMetersDBSettings); + MessageBox.Show(Strings.DB_was_successfully_created, Strings.Notification); + Cursor.Current = Cursors.Default; + DialogResult = DialogResult.None; + } + catch (Exception exception) + { + Cursor.Current = Cursors.Default; + MessageBox.Show(Strings.Error_while_creating_DB_Reason + exception.Message, Strings.Error); + } + } + + private void testConnUsersBtn_Click(object sender, EventArgs e) + { + } + + private void testConnBenchBtn_Click(object sender, EventArgs e) + { + } + + private void testConnProceduresBtn_Click(object sender, EventArgs e) + { + } + + private void testConnWMTypesBtn_Click(object sender, EventArgs e) + { + } + + private void testConnWaterMetersBtn_Click(object sender, EventArgs e) + { + } + } +} \ No newline at end of file diff --git a/TestBenchFramework/DatabaseSettingsDlg.resx b/TestBenchFramework/DatabaseSettingsDlg.resx new file mode 100644 index 000000000..9e8ff90fa --- /dev/null +++ b/TestBenchFramework/DatabaseSettingsDlg.resx @@ -0,0 +1,930 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 614, 15 + + + 217, 28 + + + + 14 + + + OK + + + okButton + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 30 + + + 614, 49 + + + 217, 28 + + + 13 + + + Cancel + + + cancelButton + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 31 + + + True + + + 12, 18 + + + 93, 13 + + + 15 + + + Test Bench Name + + + label1 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 29 + + + 116, 15 + + + 315, 20 + + + 16 + + + benchNameTextBox + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 28 + + + 202, 101 + + + 406, 20 + + + 17 + + + usersConnectionStringTextBox + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 27 + + + True + + + 199, 82 + + + 89, 13 + + + 18 + + + Connection string + + + connectionStringLabel + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 26 + + + 202, 127 + + + 406, 20 + + + 19 + + + benchConnectionStringTextBox + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 25 + + + 202, 153 + + + 406, 20 + + + 20 + + + proceduresConnectionStringTextBox + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 24 + + + 202, 179 + + + 406, 20 + + + 21 + + + wmTypesConnectionStringTextBox + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 23 + + + 202, 205 + + + 406, 20 + + + 22 + + + watermetersConnectionStringTextBox + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 22 + + + True + + + 12, 104 + + + 90, 13 + + + 47 + + + Users and groups + + + label2 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 21 + + + True + + + 12, 130 + + + 93, 13 + + + 48 + + + Bench parameters + + + label3 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 20 + + + True + + + 12, 156 + + + 61, 13 + + + 49 + + + Procedures + + + label4 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 19 + + + True + + + 12, 182 + + + 90, 13 + + + 50 + + + Watermeter types + + + label5 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 18 + + + True + + + 12, 208 + + + 67, 13 + + + 51 + + + Watermeters + + + label6 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 17 + + + 614, 99 + + + 95, 23 + + + 52 + + + Test Connection + + + testConnUsersBtn + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 16 + + + 711, 99 + + + 120, 23 + + + 53 + + + Create DB + + + createUsersDbBtn + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 15 + + + True + + + 116, 47 + + + 219, 17 + + + 54 + + + Test bench is controlled by this computer + + + realBenchCheckBox + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 14 + + + True + + + 113, 82 + + + 76, 13 + + + 55 + + + Database type + + + dbTypeLabel + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 13 + + + 116, 101 + + + 80, 21 + + + 56 + + + usersDbTypeComboBox + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 12 + + + 116, 127 + + + 80, 21 + + + 57 + + + benchDbTypeComboBox + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 11 + + + 116, 153 + + + 80, 21 + + + 58 + + + proceduresDbTypeComboBox + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 10 + + + 116, 179 + + + 80, 21 + + + 59 + + + wmTypesDbTypeComboBox + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 9 + + + 116, 205 + + + 80, 21 + + + 60 + + + watermetersDbTypeComboBox + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 8 + + + + NoControl + + + 614, 125 + + + 95, 23 + + + 61 + + + Test Connection + + + testConnBenchBtn + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 7 + + + NoControl + + + 614, 151 + + + 95, 23 + + + 62 + + + Test Connection + + + testConnProceduresBtn + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 6 + + + NoControl + + + 614, 177 + + + 95, 23 + + + 63 + + + Test Connection + + + testConnWMTypesBtn + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 5 + + + NoControl + + + 614, 203 + + + 95, 23 + + + 64 + + + Test Connection + + + testConnWaterMetersBtn + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 4 + + + NoControl + + + 711, 124 + + + 120, 23 + + + 65 + + + Create DB + + + createBenchDbBtn + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 3 + + + NoControl + + + 711, 150 + + + 120, 23 + + + 66 + + + Create DB + + + createProceduresDbBtn + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 2 + + + NoControl + + + 711, 176 + + + 120, 23 + + + 67 + + + Create DB + + + createWMTypesDbBtn + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 1 + + + NoControl + + + 711, 202 + + + 120, 23 + + + 68 + + + Create DB + + + createWaterMetersDbBtn + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 0 + + + True + + + 6, 13 + + + 836, 241 + + + CenterParent + + + Test Bench Databases Specification + + + DatabaseSettingsDlg + + + System.Windows.Forms.Form, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/Entities/BenchPath.cs b/TestBenchFramework/Entities/BenchPath.cs new file mode 100644 index 000000000..5ef6f8968 --- /dev/null +++ b/TestBenchFramework/Entities/BenchPath.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; + +namespace TBF.Entities +{ + public class BenchPath : IHasItemNr, IHasValves + { + public virtual int Id { get; protected set; } + public virtual int ItemNr { get; set; } + public virtual string Name { get; set; } + public virtual float Qfrom { get; set; } /// Water flow in [m3/h] + public virtual float Qto { get; set; } /// Water flow in [m3/h] + public virtual string TempIn { get; set; } + public virtual string TempOut { get; set; } + public virtual string PressIn { get; set; } + public virtual string PressOut { get; set; } + + /// Valves + public virtual string ValvesOpen { get; set; } + public virtual string ValvesClose { get; set; } + + /// ------------- Additional stuff not mapped into the database ------------- + + public BenchPath() + { + } + + public BenchPath(string name, int itemNr) + : this() + { + Name = name; + ItemNr = itemNr; + } + + public BenchPath(BenchControl.BenchPath path) + : this(path.Name, path.ItemNr) + { + Qfrom = path.Qfrom; + Qto = path.Qto; + TempIn = (path.TempIn != null) ? path.TempIn.Cfg.Name : null; + TempOut = (path.TempOut != null) ? path.TempOut.Cfg.Name : null; + PressIn = (path.PressIn != null) ? path.PressIn.Cfg.Name : null; + PressOut = (path.PressOut != null) ? path.PressOut.Cfg.Name : null; + + string vOpen = string.Empty; + foreach (var valve in path.ValvesOpen) + { + if (vOpen != string.Empty) vOpen += ";"; + vOpen += valve.Cfg.Name; + } + ValvesOpen = vOpen; + + string vClose = string.Empty; + foreach (var valve in path.ValvesClose) + { + if (vClose != string.Empty) vClose += ";"; + vClose += valve.Cfg.Name; + } + ValvesClose = vClose; + } + + public virtual BenchPath Clone(string name, int itemNr) + { + BenchPath result = new BenchPath(name, itemNr); + + result.Qfrom = Qfrom; + result.Qto = Qto; + result.TempIn = TempIn; + result.TempOut = TempOut; + result.PressIn = PressIn; + result.PressOut = PressOut; + result.ValvesOpen = ValvesOpen; + result.ValvesClose = ValvesClose; + + return result; + } + } +} diff --git a/TestBenchFramework/Entities/Component.cs b/TestBenchFramework/Entities/Component.cs new file mode 100644 index 000000000..0e8312421 --- /dev/null +++ b/TestBenchFramework/Entities/Component.cs @@ -0,0 +1,71 @@ +using System; +using System.Collections.Generic; + +namespace TBF.Entities +{ + public class Component : IHasItemNr + { + public virtual int Id { get; protected set; } + public virtual int ItemNr { get; set; } + public virtual string Name { get; set; } + public virtual string ClassName { get; set; } + public virtual string ParentName { get; set; } + public virtual DebugMode Mode { get; set; } + public virtual LogLevel Logging { get; set; } + public virtual string Parameters { get; set; } + public virtual IList Corrections { get; set; } + + /// ------------- Additional stuff not mapped into the database ------------- + + public Component() + { + Corrections = new List(); + } + + public static Component CreateFromCfg(string name, string className, string parentName, int itemNr, + DebugMode debugLevel, LogLevel logLevel, string parameters) + { + Component result = new Component(); + result.ItemNr = itemNr; + result.Name = name; + result.ClassName = className; + result.ParentName = parentName; + result.Mode = debugLevel; + result.Logging = logLevel; + result.Parameters = parameters; + return result; + } + + // Makes a new copy of this object (not just a reference) + public virtual Component Clone() + { + Component result = new Component(); + result.ItemNr = ItemNr; + result.Name = Name; + result.ClassName = ClassName; + result.ParentName = ParentName; + result.Mode = Mode; + result.Logging = Logging; + result.Parameters = Parameters; + return result; + } + + public virtual string ToString(string indent) + { + string result = string.Empty; + + result += indent + "ItemNr = " + (ItemNr + 1).ToString() + Environment.NewLine; + result += indent + "Name = " + Name + Environment.NewLine; + result += indent + "ClassName = " + ClassName + Environment.NewLine; + if (ParentName != null) + { + result += indent + "ParentName = " + ParentName + Environment.NewLine; + } + result += indent + "DebugLevel = " + Mode.ToString() + Environment.NewLine; + result += indent + "LogLevel = " + Logging.ToString() + Environment.NewLine; + result += indent + "Parameters = " + Parameters + Environment.NewLine; + + return result; + } + } +} diff --git a/TestBenchFramework/Entities/ComponentProcedure.cs b/TestBenchFramework/Entities/ComponentProcedure.cs new file mode 100644 index 000000000..399a1c693 --- /dev/null +++ b/TestBenchFramework/Entities/ComponentProcedure.cs @@ -0,0 +1,19 @@ + +namespace TBF.Entities +{ + public class ComponentProcedure + { + public virtual int Id { get; protected set; } + public virtual string CmpntName { get; set; } /// Component name + public virtual string Parameters { get; set; } + public virtual Procedure Procedure { get; set; } + + public virtual ComponentProcedure Clone() + { + ComponentProcedure result = new ComponentProcedure(); + result.CmpntName = CmpntName; + result.Parameters = Parameters; + return result; + } + } +} diff --git a/TestBenchFramework/Entities/ComponentTest.cs b/TestBenchFramework/Entities/ComponentTest.cs new file mode 100644 index 000000000..c9d43a15e --- /dev/null +++ b/TestBenchFramework/Entities/ComponentTest.cs @@ -0,0 +1,19 @@ + +namespace TBF.Entities +{ + public class ComponentTest + { + public virtual int Id { get; protected set; } + public virtual string CmpntName { get; set; } /// Component name + public virtual string Parameters { get; set; } + public virtual Test Test { get; set; } + + public virtual ComponentTest Clone() + { + ComponentTest result = new ComponentTest(); + result.CmpntName = CmpntName; + result.Parameters = Parameters; + return result; + } + } +} diff --git a/TestBenchFramework/Entities/Enums.cs b/TestBenchFramework/Entities/Enums.cs new file mode 100644 index 000000000..5dc70d7a2 --- /dev/null +++ b/TestBenchFramework/Entities/Enums.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; + +namespace TBF.Entities +{ + /// + /// Kind of meters for the procedure / test + /// + public enum MetersKind + { + Single, + Combined, + } + + /// + /// Flow set method Std/ComposedMeter + /// + public enum QSetMethod + { + Std, + ComposedMeter, + Count, + } + + /// + /// Procedure method FSS/SSS + /// + public enum TestMethod2 + { + FSS, + SSS, + Count, + } + + public enum TestRedType + { + Fix, + /// etc. + Count, + } + + public enum FQC1 + { + FQC1, + FQP1, + Count, + } + + /// + /// Possible modes of operation of components and devices. + /// + public enum DebugMode + { + DetectedOff = -2, + DetectedOn = -1, + Normal = 0, /// Normal operation + AutoDetect, /// The component (device) will be auto-detected + Off, /// The component is off + Record, + Reply, + Simulate, /// Test bench simulation, this mode does not require any hardware + Inherit, + Count, + } + + public enum LogLevel + { + Off, + Fatal, + Error, + Warn, + Info, + Debug, + All, + Count, + } +} + diff --git a/TestBenchFramework/Entities/FeedingPath.cs b/TestBenchFramework/Entities/FeedingPath.cs new file mode 100644 index 000000000..461f77f2d --- /dev/null +++ b/TestBenchFramework/Entities/FeedingPath.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections.Generic; + +namespace TBF.Entities +{ + public class FeedingPath : IHasItemNr, IHasValves + { + public virtual int Id { get; protected set; } + public virtual int ItemNr { get; set; } + public virtual string Name { get; set; } + public virtual float Qfrom { get; set; } /// Water flow in [m3/h] + public virtual float Qto { get; set; } /// Water flow in [m3/h] + public virtual string Pump { get; set; } + + /// Valves + public virtual string ValvesOpen { get; set; } + public virtual string ValvesClose { get; set; } + + /// ------------- Additional stuff not mapped into the database ------------- + + public FeedingPath() + { + } + + public FeedingPath(string name, int itemNr) + : this() + { + Name = name; + ItemNr = itemNr; + } + + public FeedingPath(BenchControl.FeedingPath path) + : this(path.Name, path.ItemNr) + { + Qfrom = path.Qfrom; + Qto = path.Qto; + Pump = (path.Pump != null) ? path.Pump.Cfg.Name : null; + + string vOpen = string.Empty; + foreach (var valve in path.ValvesOpen) + { + if (vOpen != string.Empty) vOpen += ";"; + vOpen += valve.Cfg.Name; + } + ValvesOpen = vOpen; + + string vClose = string.Empty; + foreach (var valve in path.ValvesClose) + { + if (vClose != string.Empty) vClose += ";"; + vClose += valve.Cfg.Name; + } + ValvesClose = vClose; + } + + public virtual FeedingPath Clone(string name, int itemNr) + { + FeedingPath result = new FeedingPath(name, itemNr); + + result.Qfrom = Qfrom; + result.Qto = Qto; + result.Pump = Pump; + result.ValvesOpen = ValvesOpen; + result.ValvesClose = ValvesClose; + + return result; + } + } +} diff --git a/TestBenchFramework/Entities/Group.cs b/TestBenchFramework/Entities/Group.cs new file mode 100644 index 000000000..333a712a8 --- /dev/null +++ b/TestBenchFramework/Entities/Group.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; + +namespace TBF.Entities +{ + public class Group + { + public virtual int Id { get; protected set; } + public virtual int Gid { get; set; } + public virtual string Name { get; set; } + } +} diff --git a/TestBenchFramework/Entities/IHasItemNr.cs b/TestBenchFramework/Entities/IHasItemNr.cs new file mode 100644 index 000000000..42d37a6ad --- /dev/null +++ b/TestBenchFramework/Entities/IHasItemNr.cs @@ -0,0 +1,9 @@ + +namespace TBF.Entities +{ + interface IHasItemNr + { + int Id { get; } + int ItemNr { get; set; } + } +} diff --git a/TestBenchFramework/Entities/IHasValves.cs b/TestBenchFramework/Entities/IHasValves.cs new file mode 100644 index 000000000..7ad73f50e --- /dev/null +++ b/TestBenchFramework/Entities/IHasValves.cs @@ -0,0 +1,9 @@ + +namespace TBF.Entities +{ + public interface IHasValves + { + string ValvesOpen { get; set; } /// List of valves to be opened + string ValvesClose { get; set; } /// List of valves to be closed + } +} diff --git a/TestBenchFramework/Entities/MeasurementCorrection.cs b/TestBenchFramework/Entities/MeasurementCorrection.cs new file mode 100644 index 000000000..cc66d7c10 --- /dev/null +++ b/TestBenchFramework/Entities/MeasurementCorrection.cs @@ -0,0 +1,11 @@ +using System; + +namespace TBF.Entities +{ + public class MeasurementCorrection + { + public virtual int Id { get; protected set; } + public virtual float Measurement { get; set; } + public virtual float Correction { get; set; } + } +} diff --git a/TestBenchFramework/Entities/MeterTestResult.cs b/TestBenchFramework/Entities/MeterTestResult.cs new file mode 100644 index 000000000..4fee66c39 --- /dev/null +++ b/TestBenchFramework/Entities/MeterTestResult.cs @@ -0,0 +1,48 @@ +using System; + +namespace TBF.Entities +{ + public class MeterTestResult + { + public virtual int Id { get; protected set; } + public virtual TestResult TestResult { get; set; } /// reference to the TestResult entity + + public virtual string SerialNr { get; set; } + public virtual float VolumeStart { get; set; } /// liter + public virtual float VolumeEnd { get; set; } /// liter + public virtual float VolumeMeter { get; set; } /// liter + public virtual float VolumeRef { get; set; } /// liter + public virtual float VolumeErrorPct { get; set; } /// % + public virtual float PulsesMeter { get; set; } /// Not applicable for a combined meter + public virtual float PulsesMaster { get; set; } + public virtual float Time { get; set; } /// sec. + public virtual bool Passed { get; set; } /// true = test passed + + public MeterTestResult() + { + } + + public MeterTestResult(TestResult testResult) + : this() + { + TestResult = testResult; + } + + public virtual MeterTestResult Clone(TestResult testResult) + { + MeterTestResult result = new MeterTestResult(testResult); + + result.SerialNr = SerialNr; + result.VolumeStart = VolumeStart; + result.VolumeEnd = VolumeEnd; + result.VolumeMeter = VolumeMeter; + result.VolumeRef = VolumeRef; + result.VolumeErrorPct = VolumeErrorPct; + result.PulsesMeter = PulsesMeter; + result.PulsesMaster = PulsesMaster; + result.Time = Time; + + return result; + } + } +} diff --git a/TestBenchFramework/Entities/MetersPath.cs b/TestBenchFramework/Entities/MetersPath.cs new file mode 100644 index 000000000..e8a0c7bff --- /dev/null +++ b/TestBenchFramework/Entities/MetersPath.cs @@ -0,0 +1,157 @@ +using System; +using System.Collections.Generic; + +namespace TBF.Entities +{ + public class MetersPath : IHasItemNr + { + public virtual int Id { get; protected set; } + public virtual int ItemNr { get; set; } + public virtual string Name { get; set; } + public virtual float Qfrom { get; set; } /// Water flow in [m3/h] + public virtual float Qto { get; set; } /// Water flow in [m3/h] + + /// Sensors + public virtual string Sensor1 { get; set; } + public virtual string Sensor2 { get; set; } + public virtual string Sensor3 { get; set; } + public virtual string Sensor4 { get; set; } + public virtual string Sensor5 { get; set; } + public virtual string Sensor6 { get; set; } + public virtual string Sensor7 { get; set; } + public virtual string Sensor8 { get; set; } + public virtual string Sensor9 { get; set; } + public virtual string Sensor10 { get; set; } + public virtual string Sensor11 { get; set; } + public virtual string Sensor12 { get; set; } + public virtual string Sensor13 { get; set; } + public virtual string Sensor14 { get; set; } + public virtual string Sensor15 { get; set; } + public virtual string Sensor16 { get; set; } + public virtual string Sensor17 { get; set; } + public virtual string Sensor18 { get; set; } + public virtual string Sensor19 { get; set; } + public virtual string Sensor20 { get; set; } + + /// ------------- Additional stuff not mapped into the database ------------- + + public MetersPath() + { + } + + public MetersPath(string name, int itemNr) + : this() + { + Name = name; + ItemNr = itemNr; + } + + public MetersPath(BenchControl.MetersPath path) + : this(path.Name, path.ItemNr) + { + Qfrom = path.Qfrom; + Qto = path.Qto; + Sensor1 = (path.RegisterReaders[0] != null) ? path.RegisterReaders[0].Cfg.Name : null; +#pragma warning disable + if (Program.WMsCount >= 2) Sensor2 = (path.RegisterReaders[1] != null) ? path.RegisterReaders[1].Cfg.Name : null; + if (Program.WMsCount >= 3) Sensor3 = (path.RegisterReaders[2] != null) ? path.RegisterReaders[2].Cfg.Name : null; + if (Program.WMsCount >= 4) Sensor4 = (path.RegisterReaders[3] != null) ? path.RegisterReaders[3].Cfg.Name : null; + if (Program.WMsCount >= 5) Sensor5 = (path.RegisterReaders[4] != null) ? path.RegisterReaders[4].Cfg.Name : null; + if (Program.WMsCount >= 6) Sensor6 = (path.RegisterReaders[5] != null) ? path.RegisterReaders[5].Cfg.Name : null; + if (Program.WMsCount >= 7) Sensor7 = (path.RegisterReaders[6] != null) ? path.RegisterReaders[6].Cfg.Name : null; + if (Program.WMsCount >= 8) Sensor8 = (path.RegisterReaders[7] != null) ? path.RegisterReaders[7].Cfg.Name : null; + if (Program.WMsCount >= 9) Sensor9 = (path.RegisterReaders[8] != null) ? path.RegisterReaders[8].Cfg.Name : null; + if (Program.WMsCount >= 10) Sensor10 = (path.RegisterReaders[9] != null) ? path.RegisterReaders[9].Cfg.Name : null; + if (Program.WMsCount >= 11) Sensor11 = (path.RegisterReaders[10] != null) ? path.RegisterReaders[10].Cfg.Name : null; + if (Program.WMsCount >= 12) Sensor12 = (path.RegisterReaders[11] != null) ? path.RegisterReaders[11].Cfg.Name : null; + if (Program.WMsCount >= 13) Sensor13 = (path.RegisterReaders[12] != null) ? path.RegisterReaders[12].Cfg.Name : null; + if (Program.WMsCount >= 14) Sensor14 = (path.RegisterReaders[13] != null) ? path.RegisterReaders[13].Cfg.Name : null; + if (Program.WMsCount >= 15) Sensor15 = (path.RegisterReaders[14] != null) ? path.RegisterReaders[14].Cfg.Name : null; + if (Program.WMsCount >= 16) Sensor16 = (path.RegisterReaders[15] != null) ? path.RegisterReaders[15].Cfg.Name : null; + if (Program.WMsCount >= 17) Sensor17 = (path.RegisterReaders[16] != null) ? path.RegisterReaders[16].Cfg.Name : null; + if (Program.WMsCount >= 18) Sensor18 = (path.RegisterReaders[17] != null) ? path.RegisterReaders[17].Cfg.Name : null; + if (Program.WMsCount >= 19) Sensor19 = (path.RegisterReaders[18] != null) ? path.RegisterReaders[18].Cfg.Name : null; + if (Program.WMsCount >= 20) Sensor20 = (path.RegisterReaders[19] != null) ? path.RegisterReaders[19].Cfg.Name : null; +#pragma warning restore + } + + public virtual MetersPath Clone(string name, int itemNr) + { + MetersPath result = new MetersPath(name, itemNr); + result.Qfrom = Qfrom; + result.Qto = Qto; + result.Sensor1 = Sensor1; + result.Sensor2 = Sensor2; + result.Sensor3 = Sensor3; + result.Sensor4 = Sensor4; + result.Sensor5 = Sensor5; + result.Sensor6 = Sensor6; + result.Sensor7 = Sensor7; + result.Sensor8 = Sensor8; + result.Sensor9 = Sensor9; + result.Sensor10 = Sensor10; + result.Sensor11 = Sensor11; + result.Sensor12 = Sensor12; + result.Sensor13 = Sensor13; + result.Sensor14 = Sensor14; + result.Sensor15 = Sensor15; + result.Sensor16 = Sensor16; + result.Sensor17 = Sensor17; + result.Sensor18 = Sensor18; + result.Sensor19 = Sensor19; + result.Sensor20 = Sensor20; + return result; + } + + /// Returns the component name + public virtual string GetSensor(int i) + { + if (i == 0) return Sensor1; + else if (i == 1) return Sensor2; + else if (i == 2) return Sensor3; + else if (i == 3) return Sensor4; + else if (i == 4) return Sensor5; + else if (i == 5) return Sensor6; + else if (i == 6) return Sensor7; + else if (i == 7) return Sensor8; + else if (i == 8) return Sensor9; + else if (i == 9) return Sensor10; + else if (i == 10) return Sensor11; + else if (i == 11) return Sensor12; + else if (i == 12) return Sensor13; + else if (i == 13) return Sensor14; + else if (i == 14) return Sensor15; + else if (i == 15) return Sensor16; + else if (i == 16) return Sensor17; + else if (i == 17) return Sensor18; + else if (i == 18) return Sensor19; + else if (i == 19) return Sensor20; + else return null; + } + + /// Sets the component name + public virtual void SetSensor(int i, string cmpntName) + { + if (i == 0) Sensor1 = cmpntName; + else if (i == 1) Sensor2 = cmpntName; + else if (i == 2) Sensor3 = cmpntName; + else if (i == 3) Sensor4 = cmpntName; + else if (i == 4) Sensor5 = cmpntName; + else if (i == 5) Sensor6 = cmpntName; + else if (i == 6) Sensor7 = cmpntName; + else if (i == 7) Sensor8 = cmpntName; + else if (i == 8) Sensor9 = cmpntName; + else if (i == 9) Sensor10 = cmpntName; + else if (i == 10) Sensor11 = cmpntName; + else if (i == 11) Sensor12 = cmpntName; + else if (i == 12) Sensor13 = cmpntName; + else if (i == 13) Sensor14 = cmpntName; + else if (i == 14) Sensor15 = cmpntName; + else if (i == 15) Sensor16 = cmpntName; + else if (i == 16) Sensor17 = cmpntName; + else if (i == 17) Sensor18 = cmpntName; + else if (i == 18) Sensor19 = cmpntName; + else if (i == 19) Sensor20 = cmpntName; + } + } +} diff --git a/TestBenchFramework/Entities/OutputPath.cs b/TestBenchFramework/Entities/OutputPath.cs new file mode 100644 index 000000000..839044ade --- /dev/null +++ b/TestBenchFramework/Entities/OutputPath.cs @@ -0,0 +1,85 @@ +using System; +using System.Collections.Generic; + +namespace TBF.Entities +{ + public class OutputPath : IHasItemNr, IHasValves + { + public virtual int Id { get; protected set; } + public virtual int ItemNr { get; set; } + public virtual string Name { get; set; } + public virtual float Qfrom { get; set; } /// Water flow in [m3/h] + public virtual float Qto { get; set; } /// Water flow in [m3/h] + public virtual string RegulValve { get; set; } + public virtual string FlowMeter { get; set; } + public virtual string Diverter { get; set; } + public virtual string TempDiv { get; set; } + public virtual string Balance { get; set; } + public virtual string EmptyTankValve { get; set; } + + /// Valves + public virtual string ValvesOpen { get; set; } + public virtual string ValvesClose { get; set; } + + /// ------------- Additional stuff not mapped into the database ------------- + + public OutputPath() + { + } + + public OutputPath(string name, int itemNr) + : this() + { + Name = name; + ItemNr = itemNr; + } + + public OutputPath(BenchControl.OutputPath path) + : this(path.Name, path.ItemNr) + { + Qfrom = path.Qfrom; + Qto = path.Qto; + RegulValve = (path.RegulValve != null) ? path.RegulValve.Cfg.Name : null; + FlowMeter = (path.FlowMeter != null) ? path.FlowMeter.Cfg.Name : null; + Diverter = (path.Diverter != null) ? path.Diverter.Cfg.Name : null; + TempDiv = (path.TempDiv != null) ? path.TempDiv.Cfg.Name : null; + Balance = (path.Balance != null) ? path.Balance.Cfg.Name : null; + EmptyTankValve = (path.EmptyTankValve != null) ? path.EmptyTankValve.Cfg.Name : null; + + string vOpen = string.Empty; + foreach (var valve in path.ValvesOpen) + { + if (vOpen != string.Empty) vOpen += ";"; + vOpen += valve.Cfg.Name; + } + ValvesOpen = vOpen; + + string vClose = string.Empty; + foreach (var valve in path.ValvesClose) + { + if (vClose != string.Empty) vClose += ";"; + vClose += valve.Cfg.Name; + } + ValvesClose = vClose; + } + + public virtual OutputPath Clone(string name, int itemNr) + { + OutputPath result = new OutputPath(name, itemNr); + + result.Name = Name; + result.Qfrom = Qfrom; + result.Qto = Qto; + result.RegulValve = RegulValve; + result.FlowMeter = FlowMeter; + result.Diverter = Diverter; + result.TempDiv = TempDiv; + result.Balance = Balance; + result.EmptyTankValve = EmptyTankValve; + result.ValvesOpen = ValvesOpen; + result.ValvesClose = ValvesClose; + + return result; + } + } +} diff --git a/TestBenchFramework/Entities/Procedure.cs b/TestBenchFramework/Entities/Procedure.cs new file mode 100644 index 000000000..08fa42334 --- /dev/null +++ b/TestBenchFramework/Entities/Procedure.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; +using TBF.Resources; + +namespace TBF.Entities +{ + /// + /// Stores one test procedure, supports revisions and history log + /// + public class Procedure : IHasItemNr + { + public virtual int Id { get; protected set; } + public virtual int ItemNr { get; set; } + public virtual string Name { get; set; } + public virtual string Description { get; set; } /// Short description + public virtual string CreationUser { get; set; } /// Name of the user who has created or changed this procedure + public virtual DateTime CreationTime { get; set; } /// Date and time of the creation or change + public virtual string LastChgUser { get; set; } /// Name of the user who has created or changed this procedure + public virtual DateTime LastChgTime { get; set; } /// Date and time of the creation or change + public virtual string LongDescription { get; set; } /// Long description (notes) + public virtual string Watermeters { get; set; } /// Water meter name or Id + + public virtual string DataEntry { get; set; } /// Component to use for data entry + public virtual string ResultsPrinter { get; set; } /// Component to use for printing the results + public virtual string ResultsWriter { get; set; } /// Component to use for saving the results into the file + public virtual string TransitionStart { get; set; } + public virtual string TransitionEnd { get; set; } + + public virtual IList MoreParams { get; set; } + public virtual IList Tests { get; set; } + + ////public virtual string MetrologicalClass { get; set; } + ////public virtual IList WMTypes { get; set; } + + /// ------------- Additional stuff not mapped into the database ------------- + + public Procedure() + { + CreationUser = (User.CurrentUser != null) ? User.CurrentUser.Name : null; + CreationTime = DateTime.Now; + LastChgUser = CreationUser; + LastChgTime = CreationTime; + + MoreParams = new List(); + Tests = new List(); + + //WMTypes = new List(); + } + + public Procedure(string name, int itemNr) + : this() + { + Name = name; + ItemNr = itemNr; + } + + public virtual Procedure Clone() + { + Procedure result = new Procedure(); + + result.Name = Name; + result.Description = Description; + result.CreationUser = CreationUser; + result.CreationTime = CreationTime; + result.LastChgUser = LastChgUser; + result.LastChgTime = LastChgTime; + result.LongDescription = LongDescription; + + foreach (var prms in MoreParams) { result.MoreParams.Add(prms.Clone()); } + foreach (var test in Tests) { result.Tests.Add(test.Clone()); } + + //result.MetrologicalClass = MetrologicalClass; + //result.WMType = WMType.Clone(); + + return result; + } + } +} diff --git a/TestBenchFramework/Entities/ProcedureHistory.cs b/TestBenchFramework/Entities/ProcedureHistory.cs new file mode 100644 index 000000000..27e58148e --- /dev/null +++ b/TestBenchFramework/Entities/ProcedureHistory.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; + +namespace TBF.Entities +{ + public class ProcedureHistory + { + public virtual int Id { get; protected set; } + public virtual Procedure Current { get; set; } + public virtual IList OldProcedures { get; set; } + + /// ------------- Additional stuff not mapped into the database ------------- + + public ProcedureHistory() + { + Current = new Procedure(); + OldProcedures = new List(); + } + + public virtual ProcedureHistory Clone() + { + ProcedureHistory result = new ProcedureHistory(); + result.Current = Current.Clone(); + foreach (Procedure p in OldProcedures) result.OldProcedures.Add(p.Clone()); + return result; + } + } +} diff --git a/TestBenchFramework/Entities/Test.cs b/TestBenchFramework/Entities/Test.cs new file mode 100644 index 000000000..fdffe7c47 --- /dev/null +++ b/TestBenchFramework/Entities/Test.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; + +namespace TBF.Entities +{ + /// + /// Test, consisting of one or more repetitions of the test 'SingleTest'. + /// + public class Test : IHasItemNr + { + public virtual int Id { get; protected set; } + public virtual int ItemNr { get; set; } + public virtual string Name { get; set; } + public virtual float Qfrom { get; set; } /// Water flow low limit in [m3/h] + public virtual float Qto { get; set; } /// Water flow high limit in [m3/h] + public virtual float Volume { get; set; } /// Test volume (target) in [l] + public virtual float TstTime { get; set; } /// Test time (estimate) in [s] + public virtual int Repeats { get; set; } + public virtual bool Emptying { get; set; } + public virtual bool Zeroing { get; set; } + public virtual string Method { get; set; } + public virtual float ErrLimLo { get; set; } /// in [%] (usually < 0) + public virtual float ErrLimHi { get; set; } /// in [%] (usually > 0) + public virtual double TolerRed { get; set; } /// in [%] (always > 0) + public virtual TestRedType RedType { get; set; } + public virtual string FeedingPath { get; set; } + public virtual string BenchPath { get; set; } + public virtual string OutputPath { get; set; } + public virtual string MetersPath { get; set; } + public virtual string TransitionStart { get; set; } + public virtual string TransitionEnd { get; set; } + + public virtual IList MoreParams { get; set; } + + public virtual Procedure Procedure { get; set; } + + /// ------------- Additional stuff not mapped into the database ------------- + + public Test() + { + MoreParams = new List(); + } + + public Test(string name, int itemNr, Procedure procedure) + : this() + { + Name = name; + ItemNr = itemNr; + Procedure = procedure; + } + + // Makes a new copy of this object (not just a reference) + public virtual Test Clone() + { + Test result = new Test(Name, ItemNr, Procedure); + + result.Qfrom = Qfrom; + result.Qto = Qto; + result.Volume = Volume; + result.TstTime = TstTime; + result.Repeats = Repeats; + result.Emptying = Emptying; + result.Zeroing = Zeroing; + result.Method = Method; + result.ErrLimLo = ErrLimLo; + result.ErrLimHi = ErrLimHi; + result.TolerRed = TolerRed; + result.RedType = RedType; + result.FeedingPath = FeedingPath; + result.BenchPath = BenchPath; + result.OutputPath = OutputPath; + result.MetersPath = MetersPath; + foreach (var prms in MoreParams) { result.MoreParams.Add(prms.Clone()); } + + return result; + } + } +} diff --git a/TestBenchFramework/Entities/TestResult.cs b/TestBenchFramework/Entities/TestResult.cs new file mode 100644 index 000000000..0a1f48f61 --- /dev/null +++ b/TestBenchFramework/Entities/TestResult.cs @@ -0,0 +1,142 @@ +using System; +using System.Collections.Generic; + +namespace TBF.Entities +{ + public class TestResult + { + public virtual int Id { get; protected set; } + public virtual string Name { get; set; } + public virtual MetersKind MetersKind { get; set; } + public virtual IList Meters { get; set; } + public virtual IList CombinedMeters { get; set; } + + /// Values copied from the test (Entities.Test) + public virtual string TestName { get; set; } + public virtual bool DoNotEvaluate { get; set; } /// Not mapped to the database + public virtual bool DoNotPublish { get; set; } /// Not mapped to the database + public virtual float Qfrom { get; set; } /// Water flow low limit in [m3/h] + public virtual float Qto { get; set; } /// Water flow high limit in [m3/h] + public virtual float Volume { get; set; } /// Test volume (target) in [l] + public virtual float TstTime { get; set; } /// Test time (estimate) in [s] + public virtual int Repeats { get; set; } + public virtual bool Emptying { get; set; } + public virtual bool Zeroing { get; set; } + public virtual string Method { get; set; } + public virtual float ErrLimLo { get; set; } /// in [%] (usually < 0) + public virtual float ErrLimHi { get; set; } /// in [%] (usually > 0) + + /// To be replaced by the virtual bench component parameters + public virtual string FeedingPath { get; set; } + public virtual string BenchPath { get; set; } + public virtual string OutputPath { get; set; } + public virtual string MetersPath { get; set; } + + /// Results + public virtual DateTime TimeStart { get; set; } /// Date and time of the test start + public virtual DateTime TimeEnd { get; set; } /// Date and time of the test end + public virtual int RepetitionNr { get; set; } /// Repetition number from the set of repeated tests (1...) + public virtual float AmbientTempAve { get; set; } /// Average ambient air temperature [degC] + public virtual float AmbientPressAve { get; set; } /// Average ambient air pressure + public virtual float AmbientHumiAve { get; set; } /// Average ambient air relative humidity [%] + public virtual float PressInAvrg { get; set; } /// Input water pressure (average) [Bar] + public virtual float PressInStart { get; set; } + public virtual float PressInEnd { get; set; } + public virtual float PressOutAvrg { get; set; } + public virtual float PressOutStart { get; set; } + public virtual float PressOutEnd { get; set; } + public virtual float TempInAvrg { get; set; } + public virtual float TempInStart { get; set; } + public virtual float TempInEnd { get; set; } + public virtual float TempOutAvrg { get; set; } + public virtual float TempOutStart { get; set; } + public virtual float TempOutEnd { get; set; } + public virtual float TempDivAvrg { get; set; } + public virtual float TempDivStart { get; set; } + public virtual float TempDivEnd { get; set; } + public virtual float MassStartRaw { get; set; } + public virtual float MassStart { get; set; } + public virtual float MassEndRaw { get; set; } + public virtual float MassEnd { get; set; } + public virtual float MassDiff { get; set; } + public virtual float DensityIn { get; set; } + public virtual float DensityOut { get; set; } + public virtual float DensityDiv { get; set; } + public virtual float Buoyancy { get; set; } ///TODO -> map + public virtual float FlowMass { get; set; } /// from conventional true value + public virtual float FlowVolume { get; set; } /// from conventional true value + public virtual float VolumeCTV { get; set; } /// volume conventional true value + public virtual float VolumeMaster { get; set; } /// volume from the master flow meter + public virtual float Time { get; set; } /// measurement time in seconds + public virtual float ErrorMaster { get; set; } + public virtual float PulsesMaster { get; set; } + public virtual float ConstMaster { get; set; } /// Pulses per liter master flow meter + public virtual float TimeDivStart0 { get; set; } + public virtual float TimeDivStart1 { get; set; } + public virtual float TimeDivStart2 { get; set; } + public virtual float TimeDivStart3 { get; set; } + public virtual float TimeDivStart4 { get; set; } + public virtual float TimeDivStart5 { get; set; } + public virtual float TimeDivEnd0 { get; set; } + public virtual float TimeDivEnd1 { get; set; } + public virtual float TimeDivEnd2 { get; set; } + public virtual float TimeDivEnd3 { get; set; } + public virtual float TimeDivEnd4 { get; set; } + public virtual float TimeDivEnd5 { get; set; } + + public TestResult() + { + Meters = new List(); + CombinedMeters = new List(); + } + + public TestResult(MetersKind kind) + : this() + { + MetersKind = kind; + + if (kind == MetersKind.Single) + { + for (int i = 0; i < Program.WMsCount; i++) Meters.Add(new MeterTestResult()); + } + else if (kind == MetersKind.Combined) + { + int combinedCount = Program.WMsCount / 2; + for (int i = 0; i < 2 * combinedCount; i++) Meters.Add(new MeterTestResult()); + for (int i = 0; i < combinedCount; i++) CombinedMeters.Add(new MeterTestResult()); + } + } + + public TestResult(Test test, int repetitionNr, MetersKind kind) + : this(kind) + { + if (test.Repeats == 1) + { + Name = test.Name; + } + else + { + Name = string.Format("{0} ({1}/{2})", test.Name, repetitionNr, test.Repeats); + } + RepetitionNr = repetitionNr; + + /// Copy test parameters from Entities.Test object + TestName = test.Name; + Qfrom = test.Qfrom; + Qto = test.Qto; + Volume = test.Volume; + TstTime = test.TstTime; + Repeats = test.Repeats; + Emptying = test.Emptying; + Zeroing = test.Zeroing; + Method = test.Method; + ErrLimLo = test.ErrLimLo; + ErrLimHi = test.ErrLimHi; + + FeedingPath = test.FeedingPath; + BenchPath = test.BenchPath; + OutputPath = test.OutputPath; + MetersPath = test.MetersPath; + } + } +} diff --git a/TestBenchFramework/Entities/TransitionSequence.cs b/TestBenchFramework/Entities/TransitionSequence.cs new file mode 100644 index 000000000..480c2da21 --- /dev/null +++ b/TestBenchFramework/Entities/TransitionSequence.cs @@ -0,0 +1,37 @@ +using System.Collections.Generic; + +namespace TBF.Entities +{ + /// + /// Stores one transition sequence + /// + public class TransitionSequence : IHasItemNr + { + public virtual int Id { get; protected set; } + public virtual int ItemNr { get; set; } + public virtual string Name { get; set; } + public virtual string Description { get; set; } /// Short description + public virtual IList TransitionSteps { get; set; } + + public TransitionSequence() + { + TransitionSteps = new List(); + } + + public TransitionSequence(string name, int itemNr) + : this() + { + Name = name; + ItemNr = itemNr; + } + + public virtual TransitionSequence Clone() + { + TransitionSequence result = new TransitionSequence(); + result.Name = Name; + result.Description = Description; + foreach (var step in TransitionSteps) { result.TransitionSteps.Add(step.Clone()); } + return result; + } + } +} diff --git a/TestBenchFramework/Entities/TransitionStep.cs b/TestBenchFramework/Entities/TransitionStep.cs new file mode 100644 index 000000000..431a0e1f0 --- /dev/null +++ b/TestBenchFramework/Entities/TransitionStep.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; + +namespace TBF.Entities +{ + public class TransitionStep : IHasItemNr, IHasValves + { + public virtual int Id { get; protected set; } + public virtual int ItemNr { get; set; } /// Order of the preparation step + public virtual int Duration { get; set; } /// Duration in seconds + public virtual string ValvesOpen { get; set; } /// List of valves to be opened + public virtual string ValvesClose { get; set; } /// List of valves to be closed + public virtual string RegulValvesPct { get; set; } /// Positions of regulation valves in % separated by ';' + + public virtual TransitionSequence TransitionSequence { get; set; } + + /// ------------- Additional stuff not mapped into the database ------------- + + public TransitionStep() + { + Duration = 5; /// sec. + } + + public TransitionStep(int itemNr, TransitionSequence sequence) + : this() + { + ItemNr = itemNr; + TransitionSequence = sequence; + } + + public virtual TransitionStep Clone() + { + TransitionStep result = new TransitionStep(ItemNr, TransitionSequence); + result.Duration = Duration; + result.ValvesOpen = ValvesOpen; + result.ValvesClose = ValvesClose; + result.RegulValvesPct = RegulValvesPct; + return result; + } + + public virtual string ToString(string indent) + { + string result = ""; + result += indent + "ItemNr = " + ItemNr.ToString() + ", "; + result += indent + "Duration = " + Duration.ToString() + ", "; + result += indent + "ValvesOpen = " + ValvesOpen.ToString() + ", "; + result += indent + "ValvesClose = " + ValvesClose.ToString() + ", "; + result += indent + "RegulValvesPct = " + RegulValvesPct.ToString() + Environment.NewLine; + return result; + } + } +} diff --git a/TestBenchFramework/Entities/User.cs b/TestBenchFramework/Entities/User.cs new file mode 100644 index 000000000..fba683d46 --- /dev/null +++ b/TestBenchFramework/Entities/User.cs @@ -0,0 +1,226 @@ +using System; +using System.Collections.Generic; +using System.Security.Cryptography; +using System.Text; +using System.Diagnostics; + +namespace TBF.Entities +{ + public class User + { + public virtual int Id { get; protected set; } + public virtual string Name { get; set; } + public virtual string Password { get; set; } + public virtual string Description { get; set; } + public virtual DateTime LastPwChange { get; set; } + public virtual IList Groups { get; set; } //User can be a member of a list of groups + + public User() + { + Groups = new List(); + } + + public virtual void AddGroup(Group group) + { + Groups.Add(group); + } + + /// ------------- Additional stuff not mapped into the database ------------- + + /// + /// Authorized user (static) + /// + private static User currentUser = null; /// Updated by instance methods Authorize, Unauthorize + public static User CurrentUser + { + get { return currentUser; } + set { currentUser = value; } + } + + private static DateTime lastAuthorization = DateTime.Now; + public static DateTime LastAuthorization { get { return lastAuthorization; } } + + /// + /// Check whether user is a member of a group. + /// + /// Group GID + /// true is user is a member of the specified group + public virtual bool IsMemberOf(Grp.GID groupId) + { + if (groupId == Grp.GID.None) + { + return true; + } + else if (groupId >= 0 && (int)groupId < Grp.Count) + { + // for all group elements in User.groups + for (int i = 0; i < Groups.Count; ++i) + { + // element GID = parameter GroupId ? + if (((Group)Groups[i]).Gid == (int)groupId) + { + return true; + } + } + return false; + } + else + { + return false; + } + } + + /// + /// Sets users password. It then will be encrypted. + /// + /// Password + public virtual void SetPassword(string password) + { + this.Password = EncryptedPassword(password); + LastPwChange = DateTime.Now; + } + + + public virtual string EncryptedPassword(string password) + { + return getHash(password); + } + + /// + /// Verifies users password. Used by static bool Authorisation(...) + /// + /// Password + /// true if password is correct + public virtual bool CheckPassword(string password) + { + return (Password == EncryptedPassword(password)); + } + + /// + /// The FIRST of TWO possible user authorization method to be used + /// when a specific group membership is required (you can use Grp.GID.None). + /// If the user is not authorized, the current user remains to be a current user + /// (i.e. the access rights were not risen to a higher level). + /// If you require different behavior, use Unauthorize() before calling Authorize(). + /// + /// + /// + /// + /// true = authorized + public virtual bool Authorize(string userName, string password, TBF.Grp.GID requiredGroupMembership) + { + if (Name.ToLower() == userName.ToLower()) + { + if (IsMemberOf(requiredGroupMembership) && CheckPassword(password)) + { + currentUser = this; + lastAuthorization = DateTime.Now; + return true; + } + else + { + return false; + } + } + return false; + } + + /// + /// The SECOND of TWO possible user authorization method to be used when + /// no specific group membership is required. + /// If the user is not authorized, the current user remains to be a current user + /// (i.e. the access rights were not risen to a higher level). + /// If you require different behavior, use Unauthorize() before calling Authorize(). + /// + /// + /// + /// + /// true = authorized + public virtual bool Authorize(string userName, string password) + { + return Authorize(userName, password, Grp.GID.None); + } + + /// + /// Returns a 'User' with a given username from a database. + /// + /// User name for the query + /// reference to a 'User' (if it exists) or null + public static User AuthorizeDummyUser(string username) + { + User user = new User(); + user.Name = username; + currentUser = user; + return user; + } + + /// + /// Returns a 'User' with a given username from an ARBITRARY database. + /// + /// User name for the query + /// reference to a 'User' (if it exists) or null + public static User LoadUserByName(string username, DBSettings dbSettings) + { + IList listOfUsers = FluentCommon.CreateSessionFactory(Database.Users, dbSettings, false) + .OpenSession() + .CreateQuery("FROM User WHERE LOWER(Name) = :username") + .SetParameter("username", username.ToLower()) + .List(); + if (listOfUsers.Count > 0) return listOfUsers[0]; + return null; + } + + /// + /// Returns a 'User' with a given username from the users database. + /// + /// User name for the query + /// reference to a 'User' (if it exists) or null + public static User LoadUserByName(string username) + { + IList listOfUsers = FluentCommon.CreateSession(Database.Users) + .CreateQuery("FROM User WHERE LOWER(Name) = :username") + .SetParameter("username", username.ToLower()) + .List(); + if (listOfUsers.Count > 0) return listOfUsers[0]; + return null; + } + + /// + /// returns an IList of all Users + /// + public static IList GetAllUsers() + { + return FluentCommon.CreateSession(Database.Users) + .CreateQuery("FROM User") + .List(); + } + + + /// + /// Unauthorize, abandon current users authorization. + /// + public static void Unauthorize() + { + currentUser = null; + lastAuthorization = DateTime.Now; + } + + /// + /// getHash encrypts a string + /// + /// the string to encrypt + /// + public static string getHash(string text) + { + byte[] bytes = Encoding.Unicode.GetBytes(text); + SHA512Managed hashstring = new SHA512Managed(); + byte[] hash = hashstring.ComputeHash(bytes); + string hashString = string.Empty; + foreach (byte x in hash) + { + hashString += String.Format("{0:x2}", x); + } + return hashString; + } + } +} diff --git a/TestBenchFramework/Entities/WMType.cs b/TestBenchFramework/Entities/WMType.cs new file mode 100644 index 000000000..2a66a92ab --- /dev/null +++ b/TestBenchFramework/Entities/WMType.cs @@ -0,0 +1,75 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +/// This class holds the watermeter type specific data +/// that have all watermaters of the same type in common + +namespace TBF.Entities +{ + public class WMType + { + // mapped + public virtual int Id { get; protected set; } /// primary key + public virtual DateTime CreateTime { get; set; } /// Date and time of the creation or change + public virtual string CreateUserName { get; set; } /// Name of the user who has created or changed this procedure + public virtual string CreateDescription { get; set; } /// Description\ + + public virtual string Name { get; set; } /// type name + public virtual float PulseRate { get; set; } /// Pulses per Liter + + // not yet mapped + public virtual int IdentNr { get; protected set; } /// identification number of watermeter tzpe + public virtual int Diameter { get; set; } /// nominal diameter + public virtual int Pressure { get; set; } /// nominal pressure + public virtual int Length { get; set; } /// construction length + public virtual int Temperatur { get; set; } /// nominal temperature in C + public virtual float NominalFlow { get; set; } /// nominal flow Qn + + /// ------------- Additional stuff not mapped into the database ------------- + + public WMType() + { + } + + public static WMType DefaultWMType() + { + WMType procedure = new WMType() + { + CreateTime = DateTime.Now, + CreateUserName = User.CurrentUser.Name, + CreateDescription = "A default water meter created.", + Name = "Watermeter", + PulseRate = 1000, + }; + return procedure; + } + + public virtual WMType Clone() + { + WMType result = new WMType(); + + result.CreateTime = CreateTime; + result.CreateUserName = CreateUserName; + result.CreateDescription = CreateDescription; + result.Name = Name; + result.PulseRate = PulseRate; + + return result; + } + + public override string ToString() + { + string result = ""; + result += "WMTpe: " + Environment.NewLine; + result += " Name = " + Name + Environment.NewLine; + result += " Created by = " + CreateUserName + Environment.NewLine; + result += " Created on = " + CreateTime.ToString() + Environment.NewLine; + result += " Description = " + CreateDescription + Environment.NewLine; + result += " Pulse rate = " + PulseRate.ToString() + Environment.NewLine; + return result; + } + } +} + diff --git a/TestBenchFramework/Entities/Watermeter.cs b/TestBenchFramework/Entities/Watermeter.cs new file mode 100644 index 000000000..69d8333f6 --- /dev/null +++ b/TestBenchFramework/Entities/Watermeter.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using TBF; +using NHibernate; +using FluentNHibernate; + +namespace TBF.Entities +{ + public class Watermeter + { + public virtual int Id { get; protected set; } /// primary key + + public virtual DateTime CreateTime { get; set; } /// Date and time of the creation or change + public virtual string CreateUserName { get; set; } /// Name of the user who has created or changed this procedure + public virtual string CreateDescription { get; set; } /// Description + + /// mapped + public virtual string Serial { get; set; } /// serial number + public virtual WMType WMType { get; set; } /// type of watermeter + /// + + /// + /// Load a watermeter from the database + /// + public static Watermeter LoadBySerialnr(string SerialNr) + { + IList ListOfWatermeters = FluentCommon.CreateSession(Database.WaterMeters) + .CreateQuery("FROM Watermeter WHERE Serial = :SerialNrParameter") + .SetParameter("SerialNrParameter", SerialNr) + .List(); + if (ListOfWatermeters.Count > 0) return ListOfWatermeters.ElementAt(0); + return null; + } + } +} diff --git a/TestBenchFramework/ErrorHandler.cs b/TestBenchFramework/ErrorHandler.cs new file mode 100644 index 000000000..219723302 --- /dev/null +++ b/TestBenchFramework/ErrorHandler.cs @@ -0,0 +1,31 @@ +using System; +using System.Windows.Forms; +using TBF.Forms; +using TBF.Resources; + +namespace TBF.ErrorHandler { + + public static class ErrorHandler + { + public static DialogResult HandleError(Exception e, string Message, string Origin) + { + + //catch (FluentNHibernate.Cfg.FluentConfigurationException fe) + // { + // string message; + // if (fe.InnerException != null) + // { + // message = fe.InnerException.Message; + // } + // else + // { + // message = fe.Message; + // } + // MessageBox.Show( message, "RetVal", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); + + ErrorDlg dlg = new ErrorDlg(Strings.Unhandled_error_occured_in_ + Origin + Environment.NewLine + Message + Environment.NewLine + e.ToString() + Environment.NewLine + e.InnerException.ToString()); + dlg.ShowDialog(); + return dlg.returnvalue; + } + } +} diff --git a/TestBenchFramework/FluentCommon.cs b/TestBenchFramework/FluentCommon.cs new file mode 100644 index 000000000..e697367d5 --- /dev/null +++ b/TestBenchFramework/FluentCommon.cs @@ -0,0 +1,317 @@ +using System; +using FluentNHibernate.Cfg; +using FluentNHibernate.Cfg.Db; +using NHibernate; +using NHibernate.Cfg; +using NHibernate.Tool.hbm2ddl; +using TBF.Resources; + +namespace TBF +{ + /// + /// Identifies the content of a database + /// + public enum Database + { + Users, + Bench, + Procedures, + WaterMeters, + Count, + } + + /// + /// Identifies the type of a database + /// + public enum DBType + { + SQLite, /// SQLite + MySql, /// MySQL database + DbTypesCount, + } + + + public static class FluentCommon + { + /// + /// Session factories for regular sessions. + /// + public static ISessionFactory[] SessionFactories = new ISessionFactory[(int)Database.Count]; + + /// + /// NHibernate session factory (to create the database session 'SessionFactory') + /// + /// A database session + static ISessionFactory CreateSessionFactory(Database database) + { + DBType dbType; + string connectionString; + + switch (database) + { + default: + case Database.Users: + dbType = Program.CurrentBench.UsersDBSettings.DbType; + connectionString = Program.CurrentBench.UsersDBSettings.ConnectionString; + break; + case Database.Bench: + dbType = Program.CurrentBench.BenchDBSettings.DbType; + connectionString = Program.CurrentBench.BenchDBSettings.ConnectionString; + break; + case Database.Procedures: + dbType = Program.CurrentBench.ProceduresDBSettings.DbType; + connectionString = Program.CurrentBench.ProceduresDBSettings.ConnectionString; + break; + case Database.WaterMeters: + dbType = Program.CurrentBench.WaterMetersDBSettings.DbType; + connectionString = Program.CurrentBench.WaterMetersDBSettings.ConnectionString; + break; + } + + return CreateSessionFactory(database, new DBSettings(dbType, connectionString), false); + } + + /// + /// NHibernate session factory (to create the database session 'SessionFactory') + /// + /// A database session + public static ISessionFactory CreateSessionFactory(Database database, DBSettings dbSettings, bool createDB) + { + try + { + FluentConfiguration cfg = Fluently.Configure(); + + switch (dbSettings.DbType) + { + default: + case DBType.SQLite: + cfg = cfg.Database(SQLiteConfiguration.Standard.UsingFile(dbSettings.ConnectionString)); + break; + case DBType.MySql: + cfg = cfg.Database(MySQLConfiguration.Standard.ConnectionString(dbSettings.ConnectionString)); + break; + } + + switch (database) + { + default: + case Database.Users: + cfg = cfg.Mappings(m => m.FluentMappings.AddFromAssemblyOf()); + break; + case Database.Bench: + cfg = cfg.Mappings(m => m.FluentMappings.AddFromAssemblyOf()); + break; + case Database.Procedures: + cfg = cfg.Mappings(m => m.FluentMappings.AddFromAssemblyOf()); + break; + case Database.WaterMeters: + cfg = cfg.Mappings(m => m.FluentMappings.AddFromAssemblyOf()); + break; + } + + if (createDB) + { + return cfg.ExposeConfiguration(BuildSchemaCreate).BuildSessionFactory(); + } + else + { + return cfg.ExposeConfiguration(BuildSchema).BuildSessionFactory(); + } + } + catch (Exception e) + { + return null; + } + } + + public delegate void BuildSchemaDlgt(Configuration config); + + static void BuildSchema(Configuration config) + { + /// This NHibernate tool takes a configuration (with mapping info in) + /// and exports a database schema from it + new SchemaExport(config).SetOutputFile("db_schema"); + } + + static void BuildSchemaCreate(Configuration config) + { + /// This NHibernate tool takes a configuration (with mapping info in) + /// and exports a database schema from it + new SchemaExport(config).Create(true, true); + } + + /// Create a NHibernate session for the given database + public static ISession CreateSession(Database database) + { + int ix = (int)database; + if (ix < 0 || ix >= (int)Database.Count) return null; + + if (SessionFactories[ix] == null) SessionFactories[ix] = CreateSessionFactory(database); + + return SessionFactories[ix].OpenSession(); + } + + public static void SaveToDb(Database database, object obj) + { + ISession session = FluentCommon.CreateSession(database); + SaveToDb(session, obj); + } + + public static void SaveToDb(ISession session, object obj) + { + using (var transaction = session.BeginTransaction()) + { + session.SaveOrUpdate(obj); + try { transaction.Commit(); } + catch { } + } + } + + public static void DeleteFromDb(Database database, object obj) + { + ISession session = FluentCommon.CreateSession(database); + SaveToDb(session, obj); + } + + public static void DeleteFromDb(ISession session, object obj) + { + using (var transaction = session.BeginTransaction()) + { + session.Delete(obj); + transaction.Commit(); + } + } + + /// + /// Create an empty users database. + /// Database contains only the user 'admin' and the control board component 'CB'. + /// + /// DBType.SQLite or DBType.MySql + /// Connection string + /// true=success, false=error + public static bool CreateEmptyUsersDB(DBSettings dbSettings) + { + ISessionFactory sessionFactory = CreateSessionFactory(Database.Users, dbSettings, true); + if (sessionFactory == null) return false; + + /// Populate the database + using (var session = sessionFactory.OpenSession()) + { + using (var transaction = session.BeginTransaction()) + { + /// + /// Prepare all groups + /// + var testers = new Entities.Group { Gid = (int)TBF.Grp.GID.Testers, Name = Strings.Tester }; + var testingSpecialists = new Entities.Group { Gid = (int)TBF.Grp.GID.TestingSpecialists, Name = Strings.Testing_Specialist }; + var headOfLab = new Entities.Group { Gid = (int)TBF.Grp.GID.HeadOfLab, Name = Strings.Head_of_Lab }; + var maintenanceSpecialists = new Entities.Group { Gid = (int)TBF.Grp.GID.MaintenanceSpecialists, Name = Strings.Maintenance_Specialist }; + var metrologists = new Entities.Group { Gid = (int)TBF.Grp.GID.Metrologists, Name = Strings.Metrologist }; + var calibrationSpecialists = new Entities.Group { Gid = (int)TBF.Grp.GID.CalibrationSpecialists, Name = Strings.Calibration_Specialist }; + var administrators = new Entities.Group { Gid = (int)TBF.Grp.GID.Administrators, Name = Strings.Administrator }; + + /// Create the user 'admin' add his groups + var admin = new Entities.User + { + Name = Program.AdminUsername, + Description = "Administrator", + LastPwChange = DateTime.Now + }; + admin.SetPassword(Program.AdminPassword); + admin.AddGroup(testers); + admin.AddGroup(testingSpecialists); + admin.AddGroup(headOfLab); + admin.AddGroup(maintenanceSpecialists); + admin.AddGroup(metrologists); + admin.AddGroup(calibrationSpecialists); + admin.AddGroup(administrators); + + session.SaveOrUpdate(admin); + + /// Create the control board component + var cmpnt = (new BenchControl.Elde.ControlBoardCfg(new BenchControl.Elde.ControlBoardFactory(), "CB", 1)).CreateDbEntity(); + session.SaveOrUpdate(cmpnt); + + transaction.Commit(); + } + } + + return true; + } + + /// + /// Create an empty bench database + /// + /// DBType.SQLite or DBType.MySql + /// Connection string + /// true=success, false=error + public static bool CreateEmptyBenchDB(DBSettings dbSettings) + { + ISessionFactory sessionFactory = CreateSessionFactory(Database.Users, dbSettings, true); + if (sessionFactory == null) return false; + + /// Populate the database + //using (var session = sessionFactory.OpenSession()) + //{ + // using (var transaction = session.BeginTransaction()) + // { + // /// Create one component + // var cmpnt = (new BenchControl.Elde.ControlBoardCfg("CB", 1)).CreateDbEntity(); + // session.SaveOrUpdate(cmpnt); + // transaction.Commit(); + // } + //} + return true; + } + + /// + /// Create an empty procedures database + /// + /// DBType.SQLite or DBType.MySql + /// Connection string + /// true=success, false=error + public static bool CreateEmptyProceduresDB(DBSettings dbSettings) + { + ISessionFactory sessionFactory = CreateSessionFactory(Database.Users, dbSettings, true); + if (sessionFactory == null) return false; + + /// Populate the database + //using (var session = sessionFactory.OpenSession()) + //{ + // using (var transaction = session.BeginTransaction()) + // { + // /// Create one component + // var cmpnt = (new BenchControl.Elde.ControlBoardCfg("CB", 1)).CreateDbEntity(); + // session.SaveOrUpdate(cmpnt); + // transaction.Commit(); + // } + //} + return true; + } + + /// + /// Create an empty water meters database + /// + /// DBType.SQLite or DBType.MySql + /// Connection string + /// true=success, false=error + public static bool CreateEmptyWaterMetersDB(DBSettings dbSettings) + { + ISessionFactory sessionFactory = CreateSessionFactory(Database.Users, dbSettings, true); + if (sessionFactory == null) return false; + + /// Populate the database + //using (var session = sessionFactory.OpenSession()) + //{ + // using (var transaction = session.BeginTransaction()) + // { + // /// Create one component + // var cmpnt = (new BenchControl.Elde.ControlBoardCfg("CB", 1)).CreateDbEntity(); + // session.SaveOrUpdate(cmpnt); + // transaction.Commit(); + // } + //} + return true; + } + } +} diff --git a/TestBenchFramework/Forms/AboutDlg.Designer.cs b/TestBenchFramework/Forms/AboutDlg.Designer.cs new file mode 100644 index 000000000..06b1a1733 --- /dev/null +++ b/TestBenchFramework/Forms/AboutDlg.Designer.cs @@ -0,0 +1,100 @@ +namespace TBF.Forms +{ + partial class AboutDlg + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(AboutDlg)); + this.copyrightLabel = new System.Windows.Forms.Label(); + this.versionLabel = new System.Windows.Forms.Label(); + this.buildDateLabel = new System.Windows.Forms.Label(); + this.closeButton = new System.Windows.Forms.Button(); + this.logoPictureBox = new System.Windows.Forms.PictureBox(); + ((System.ComponentModel.ISupportInitialize)(this.logoPictureBox)).BeginInit(); + this.SuspendLayout(); + // + // copyrightLabel + // + resources.ApplyResources(this.copyrightLabel, "copyrightLabel"); + this.copyrightLabel.ImageKey = global::TBF.Resources.Strings.String1; + this.copyrightLabel.Name = "copyrightLabel"; + // + // versionLabel + // + resources.ApplyResources(this.versionLabel, "versionLabel"); + this.versionLabel.ImageKey = global::TBF.Resources.Strings.String1; + this.versionLabel.Name = "versionLabel"; + // + // buildDateLabel + // + resources.ApplyResources(this.buildDateLabel, "buildDateLabel"); + this.buildDateLabel.ImageKey = global::TBF.Resources.Strings.String1; + this.buildDateLabel.Name = "buildDateLabel"; + // + // closeButton + // + resources.ApplyResources(this.closeButton, "closeButton"); + this.closeButton.DialogResult = System.Windows.Forms.DialogResult.OK; + this.closeButton.ImageKey = global::TBF.Resources.Strings.String1; + this.closeButton.Name = "closeButton"; + this.closeButton.UseVisualStyleBackColor = true; + // + // logoPictureBox + // + resources.ApplyResources(this.logoPictureBox, "logoPictureBox"); + this.logoPictureBox.BackgroundImage = global::TBF.Properties.Resources.sensus_logo; + this.logoPictureBox.Name = "logoPictureBox"; + this.logoPictureBox.TabStop = false; + // + // AboutDlg + // + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.BackColor = System.Drawing.SystemColors.Window; + this.Controls.Add(this.logoPictureBox); + this.Controls.Add(this.closeButton); + this.Controls.Add(this.buildDateLabel); + this.Controls.Add(this.versionLabel); + this.Controls.Add(this.copyrightLabel); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.Name = "AboutDlg"; + this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide; + ((System.ComponentModel.ISupportInitialize)(this.logoPictureBox)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label copyrightLabel; + private System.Windows.Forms.Label versionLabel; + private System.Windows.Forms.Label buildDateLabel; + private System.Windows.Forms.Button closeButton; + private System.Windows.Forms.PictureBox logoPictureBox; + } +} \ No newline at end of file diff --git a/TestBenchFramework/Forms/AboutDlg.cs b/TestBenchFramework/Forms/AboutDlg.cs new file mode 100644 index 000000000..e7ad3131b --- /dev/null +++ b/TestBenchFramework/Forms/AboutDlg.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Windows.Forms; + +namespace TBF.Forms +{ + /// + /// About dialog + /// + public partial class AboutDlg : Form + { + /// + /// Contsructor + /// + /// Language neutral version string + /// Regionally formated build date string + public AboutDlg(string version, string buildDate) + { + InitializeComponent(); + versionLabel.Text = versionLabel.Text.Replace("_VERSION_", version); + buildDateLabel.Text = buildDateLabel.Text.Replace("_BUILD_DATE_", buildDate); + } + } +} \ No newline at end of file diff --git a/TestBenchFramework/Forms/AboutDlg.de.resx b/TestBenchFramework/Forms/AboutDlg.de.resx new file mode 100644 index 000000000..85a3599fe --- /dev/null +++ b/TestBenchFramework/Forms/AboutDlg.de.resx @@ -0,0 +1,136 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 117, 13 + + + © 2014 Sensus GmbH + + + erstellt am _BUILD_DATE_ + + + &Schließen + + + Über Test Bench Framework + + \ No newline at end of file diff --git a/TestBenchFramework/Forms/AboutDlg.resx b/TestBenchFramework/Forms/AboutDlg.resx new file mode 100644 index 000000000..a3a3d45f5 --- /dev/null +++ b/TestBenchFramework/Forms/AboutDlg.resx @@ -0,0 +1,279 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + About Test Bench Framework + + + $this + + + + 6, 13 + + + versionLabel + + + copyrightLabel + + + logoPictureBox + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Windows.Forms.Form, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + AboutDlg + + + $this + + + + True + + + True + + + 103, 30 + + + 3 + + + 105, 13 + + + + Stretch + + + 458, 99 + + + 0 + + + 145, 41 + + + CenterParent + + + 341, 36 + + + 145, 64 + + + Version _VERSION_ + + + System.Windows.Forms.PictureBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 136, 13 + + + closeButton + + + 11 + + + 4 + + + 12 + + + 105, 28 + + + 6 + + + Copyright © 2013 + + + 4 + + + &Close + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + True + + + 12, 34 + + + 2 + + + $this + + + 1 + + + $this + + + buildDateLabel + + + 90, 13 + + + + + + 145, 19 + + + 5 + + + Build date _BUILD_DATE_ + + + True + + + de + + \ No newline at end of file diff --git a/TestBenchFramework/Forms/ClosingProgram.Designer.cs b/TestBenchFramework/Forms/ClosingProgram.Designer.cs new file mode 100644 index 000000000..8acdbce86 --- /dev/null +++ b/TestBenchFramework/Forms/ClosingProgram.Designer.cs @@ -0,0 +1,66 @@ +namespace TBF.Forms +{ + partial class ClosingProgram + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.label1 = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Font = new System.Drawing.Font("Microsoft Sans Serif", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label1.Location = new System.Drawing.Point(37, 68); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(306, 24); + this.label1.TabIndex = 0; + this.label1.Text = "Closing the Test Bench Framework"; + // + // ClosingProgram + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.BackColor = System.Drawing.Color.PeachPuff; + this.ClientSize = new System.Drawing.Size(373, 161); + this.Controls.Add(this.label1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "ClosingProgram"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "Closing the Test Bench Framework"; + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label label1; + } +} \ No newline at end of file diff --git a/TestBenchFramework/Forms/ClosingProgram.cs b/TestBenchFramework/Forms/ClosingProgram.cs new file mode 100644 index 000000000..ac5cd3315 --- /dev/null +++ b/TestBenchFramework/Forms/ClosingProgram.cs @@ -0,0 +1,31 @@ +using System; +using System.Windows.Forms; + +namespace TBF.Forms +{ + public partial class ClosingProgram : Form + { + Timer timer; + + public ClosingProgram() + { + InitializeComponent(); + + timer = new Timer(); + timer.Interval = 1000; + timer.Tick += new EventHandler(timer_Tick); + timer.Start(); + } + + void timer_Tick(object sender, EventArgs args) + { + if (!TBF.BenchControl.StateMachine.Running) + { + timer.Stop(); + timer.Dispose(); + DialogResult = DialogResult.OK; + Close(); + } + } + } +} diff --git a/TestBenchFramework/Forms/ClosingProgram.resx b/TestBenchFramework/Forms/ClosingProgram.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/TestBenchFramework/Forms/ClosingProgram.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/Forms/EditSelectedUser.Designer.cs b/TestBenchFramework/Forms/EditSelectedUser.Designer.cs new file mode 100644 index 000000000..a4897dada --- /dev/null +++ b/TestBenchFramework/Forms/EditSelectedUser.Designer.cs @@ -0,0 +1,145 @@ +namespace TBF.Forms +{ + partial class EditSelectedUser + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(EditSelectedUser)); + this.txtName = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.btnOk = new System.Windows.Forms.Button(); + this.btnCancel = new System.Windows.Forms.Button(); + this.txtPassword = new System.Windows.Forms.TextBox(); + this.label3 = new System.Windows.Forms.Label(); + this.txtDescription = new System.Windows.Forms.TextBox(); + this.label4 = new System.Windows.Forms.Label(); + this.checkedListBoxGroups = new System.Windows.Forms.CheckedListBox(); + this.label5 = new System.Windows.Forms.Label(); + this.toolTip1 = new System.Windows.Forms.ToolTip(this.components); + this.SuspendLayout(); + // + // txtName + // + resources.ApplyResources(this.txtName, "txtName"); + this.txtName.Name = "txtName"; + this.txtName.TextChanged += new System.EventHandler(this.txtName_TextChanged); + this.txtName.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.txtName_KeyPress); + this.txtName.Validated += new System.EventHandler(this.txtName_Validated); + // + // label1 + // + resources.ApplyResources(this.label1, "label1"); + this.label1.Name = "label1"; + // + // btnOk + // + resources.ApplyResources(this.btnOk, "btnOk"); + this.btnOk.Name = "btnOk"; + this.btnOk.UseVisualStyleBackColor = true; + this.btnOk.Click += new System.EventHandler(this.btnOk_Click); + // + // btnCancel + // + resources.ApplyResources(this.btnCancel, "btnCancel"); + this.btnCancel.Name = "btnCancel"; + this.btnCancel.UseVisualStyleBackColor = true; + this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click); + // + // txtPassword + // + resources.ApplyResources(this.txtPassword, "txtPassword"); + this.txtPassword.Name = "txtPassword"; + this.txtPassword.TextChanged += new System.EventHandler(this.txtPassword_TextChanged); + // + // label3 + // + resources.ApplyResources(this.label3, "label3"); + this.label3.Name = "label3"; + // + // txtDescription + // + resources.ApplyResources(this.txtDescription, "txtDescription"); + this.txtDescription.Name = "txtDescription"; + this.txtDescription.TextChanged += new System.EventHandler(this.txtDescription_TextChanged); + this.txtDescription.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.txtDescription_KeyPress); + // + // label4 + // + resources.ApplyResources(this.label4, "label4"); + this.label4.Name = "label4"; + // + // checkedListBoxGroups + // + this.checkedListBoxGroups.CheckOnClick = true; + this.checkedListBoxGroups.FormattingEnabled = true; + resources.ApplyResources(this.checkedListBoxGroups, "checkedListBoxGroups"); + this.checkedListBoxGroups.Name = "checkedListBoxGroups"; + this.checkedListBoxGroups.Click += new System.EventHandler(this.checkedListBoxGroups_Click); + // + // label5 + // + resources.ApplyResources(this.label5, "label5"); + this.label5.Name = "label5"; + // + // EditSelectedUser + // + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.label5); + this.Controls.Add(this.checkedListBoxGroups); + this.Controls.Add(this.btnCancel); + this.Controls.Add(this.btnOk); + this.Controls.Add(this.label4); + this.Controls.Add(this.label3); + this.Controls.Add(this.label1); + this.Controls.Add(this.txtDescription); + this.Controls.Add(this.txtPassword); + this.Controls.Add(this.txtName); + this.Name = "EditSelectedUser"; + this.Load += new System.EventHandler(this.EditSelectedUser_Load); + this.Shown += new System.EventHandler(this.EditSelectedUser_Shown); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TextBox txtName; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Button btnOk; + private System.Windows.Forms.Button btnCancel; + private System.Windows.Forms.TextBox txtPassword; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.TextBox txtDescription; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.CheckedListBox checkedListBoxGroups; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.ToolTip toolTip1; + } +} \ No newline at end of file diff --git a/TestBenchFramework/Forms/EditSelectedUser.cs b/TestBenchFramework/Forms/EditSelectedUser.cs new file mode 100644 index 000000000..89db52e02 --- /dev/null +++ b/TestBenchFramework/Forms/EditSelectedUser.cs @@ -0,0 +1,175 @@ +using System; +using System.Collections.Generic; +using System.Windows.Forms; +using NHibernate; +using TBF.Entities; +using TBF.Resources; + +namespace TBF.Forms +{ + public partial class EditSelectedUser : Form + { + public User CurrentEditUser; + public NHibernate.ISession Session; + + public EditSelectedUser() + { + InitializeComponent(); + this.toolTip1.SetToolTip(this.txtName, Strings.MaxChars.Replace("_X_", Convert.ToString(20))); + + btnOk.Enabled = false; + } + + private void EditSelectedUser_Load(object sender, EventArgs e) + { + txtName.Text = CurrentEditUser.Name; + txtDescription.Text = CurrentEditUser.Description; + txtPassword.Text = ""; + ShowGroups(); + } + + + public void ShowGroups() + { + checkedListBoxGroups.Items.Clear(); + for (int i= 0; (int)i < Grp.Count; i++) + { + Group group = Grp.FromId((Grp.GID)i); + + bool boolIsMember = CurrentEditUser.IsMemberOf((Grp.GID)group.Gid); + if (boolIsMember == true) + { + checkedListBoxGroups.Items.Add(group.Name); + checkedListBoxGroups.SetItemCheckState(i, CheckState.Checked); + } + else + { + checkedListBoxGroups.Items.Add(group.Name); + checkedListBoxGroups.SetItemCheckState(i, CheckState.Unchecked); + + } + } + } + + + public bool Save() { + + // todo: check if this name is given to another user + if (IsUserNameAllreadyTaken(txtName.Text)) + { + MessageBox.Show(Strings.Username_taken); + return false; + } + + + CurrentEditUser.Name = txtName.Text; + + if (txtPassword.Text != "") + { + CurrentEditUser.SetPassword(txtPassword.Text); + } + CurrentEditUser.Description = txtDescription.Text; + + // Groups + CurrentEditUser.Groups.Clear(); + for (int i = 0; (int)i < checkedListBoxGroups.Items.Count ; i++) + { + if (checkedListBoxGroups.GetItemChecked(i)) { + Group newGroup = Grp.FromId((Grp.GID)i); + CurrentEditUser.Groups.Add(newGroup ); + } + } + + Cursor.Current = Cursors.WaitCursor; + FluentCommon.SaveToDb(Session, CurrentEditUser); + Cursor.Current = Cursors.Default; + + return true; + } + + /// + /// returns true if the username allready exists for another user + /// + private bool IsUserNameAllreadyTaken(string Username) + { + // have a look into all other users + IList ListOfUsers = User.GetAllUsers(); + foreach (var person in ListOfUsers) + { + if (person.Id != CurrentEditUser.Id) { + // other user + if (person.Name.ToLower() == Username.ToLower()) + { + // Name is equal, so allready taken + return true; + } + } + } + return false; + } + + + private void btnOk_Click(object sender, EventArgs e) + { + if (Save()) + { + this.Close(); + } + } + + private void btnCancel_Click(object sender, EventArgs e) + { + this.Close(); + } + + + + private void CheckIfFormCanBeSubmitted() + { + btnOk.Enabled = false; + if (txtName.Text == "") return; + btnOk.Enabled = true; + } + + private void EditSelectedUser_Shown(object sender, EventArgs e) + { + txtName.Focus(); + } + + private void txtName_Validated(object sender, EventArgs e) + { + CheckIfFormCanBeSubmitted(); + } + + private void txtName_KeyPress(object sender, KeyPressEventArgs e) + { + CheckIfFormCanBeSubmitted(); + + } + + private void txtName_TextChanged(object sender, EventArgs e) + { + CheckIfFormCanBeSubmitted(); + } + + private void txtPassword_TextChanged(object sender, EventArgs e) + { + CheckIfFormCanBeSubmitted(); + } + + private void txtDescription_TextChanged(object sender, EventArgs e) + { + CheckIfFormCanBeSubmitted(); + } + + private void txtDescription_KeyPress(object sender, KeyPressEventArgs e) + { + CheckIfFormCanBeSubmitted(); + } + + private void checkedListBoxGroups_Click(object sender, EventArgs e) + { + CheckIfFormCanBeSubmitted(); + } + } +} diff --git a/TestBenchFramework/Forms/EditSelectedUser.de.resx b/TestBenchFramework/Forms/EditSelectedUser.de.resx new file mode 100644 index 000000000..95145c290 --- /dev/null +++ b/TestBenchFramework/Forms/EditSelectedUser.de.resx @@ -0,0 +1,181 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 106, 9 + + + 9, 16 + + + 75, 13 + + + Benutzername + + + 106, 252 + + + 232, 252 + + + 74, 23 + + + Abbrechen + + + 106, 40 + + + 9, 43 + + + 50, 13 + + + Passwort + + + 106, 70 + + + 72, 13 + + + Beschreibung + + + 106, 135 + + + 9, 135 + + + 48, 13 + + + Gruppen + + + Benutzer einrichten + + \ No newline at end of file diff --git a/TestBenchFramework/Forms/EditSelectedUser.resx b/TestBenchFramework/Forms/EditSelectedUser.resx new file mode 100644 index 000000000..c37f77d1b --- /dev/null +++ b/TestBenchFramework/Forms/EditSelectedUser.resx @@ -0,0 +1,398 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 75, 9 + + + 200, 20 + + + + 0 + + + txtName + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 9 + + + True + + + 12, 9 + + + 35, 13 + + + 1 + + + Name + + + label1 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 6 + + + 75, 252 + + + 75, 23 + + + 3 + + + OK + + + btnOk + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 3 + + + 200, 252 + + + 75, 23 + + + 3 + + + Cancel + + + btnCancel + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 2 + + + 75, 40 + + + * + + + 200, 20 + + + 0 + + + txtPassword + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 8 + + + True + + + 9, 40 + + + 53, 13 + + + 1 + + + Password + + + label3 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 5 + + + 75, 70 + + + True + + + 200, 59 + + + 0 + + + txtDescription + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 7 + + + True + + + 9, 70 + + + 60, 13 + + + 1 + + + Description + + + label4 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 4 + + + 75, 135 + + + 200, 94 + + + 4 + + + checkedListBoxGroups + + + System.Windows.Forms.CheckedListBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 1 + + + True + + + 12, 135 + + + 41, 13 + + + 5 + + + Groups + + + label5 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 0 + + + 17, 17 + + + de + + + True + + + 6, 13 + + + 318, 287 + + + Edit User + + + toolTip1 + + + System.Windows.Forms.ToolTip, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + EditSelectedUser + + + System.Windows.Forms.Form, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/Forms/EditUsers.Designer.cs b/TestBenchFramework/Forms/EditUsers.Designer.cs new file mode 100644 index 000000000..f78329859 --- /dev/null +++ b/TestBenchFramework/Forms/EditUsers.Designer.cs @@ -0,0 +1,125 @@ +namespace TBF.Forms +{ + partial class EditUsers + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(EditUsers)); + this.listViewUsers = new System.Windows.Forms.ListView(); + this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.btnAdd = new System.Windows.Forms.Button(); + this.btnEdit = new System.Windows.Forms.Button(); + this.btnDelete = new System.Windows.Forms.Button(); + this.btnOk = new System.Windows.Forms.Button(); + this.statusStrip1 = new System.Windows.Forms.StatusStrip(); + this.SuspendLayout(); + // + // listViewUsers + // + this.listViewUsers.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeader1, + this.columnHeader2}); + this.listViewUsers.FullRowSelect = true; + resources.ApplyResources(this.listViewUsers, "listViewUsers"); + this.listViewUsers.MultiSelect = false; + this.listViewUsers.Name = "listViewUsers"; + this.listViewUsers.UseCompatibleStateImageBehavior = false; + this.listViewUsers.View = System.Windows.Forms.View.Details; + this.listViewUsers.SelectedIndexChanged += new System.EventHandler(this.listViewUsers_SelectedIndexChanged); + this.listViewUsers.DoubleClick += new System.EventHandler(this.listViewUsers_DoubleClick); + // + // columnHeader1 + // + resources.ApplyResources(this.columnHeader1, "columnHeader1"); + // + // columnHeader2 + // + resources.ApplyResources(this.columnHeader2, "columnHeader2"); + // + // btnAdd + // + resources.ApplyResources(this.btnAdd, "btnAdd"); + this.btnAdd.Name = "btnAdd"; + this.btnAdd.UseVisualStyleBackColor = true; + this.btnAdd.Click += new System.EventHandler(this.btnAdd_Click); + // + // btnEdit + // + resources.ApplyResources(this.btnEdit, "btnEdit"); + this.btnEdit.Name = "btnEdit"; + this.btnEdit.UseVisualStyleBackColor = true; + this.btnEdit.Click += new System.EventHandler(this.btnEdit_Click); + // + // btnDelete + // + resources.ApplyResources(this.btnDelete, "btnDelete"); + this.btnDelete.Name = "btnDelete"; + this.btnDelete.UseVisualStyleBackColor = true; + this.btnDelete.Click += new System.EventHandler(this.btnDelete_Click); + // + // btnOk + // + resources.ApplyResources(this.btnOk, "btnOk"); + this.btnOk.Name = "btnOk"; + this.btnOk.UseVisualStyleBackColor = true; + this.btnOk.Click += new System.EventHandler(this.btnOk_Click); + // + // statusStrip1 + // + resources.ApplyResources(this.statusStrip1, "statusStrip1"); + this.statusStrip1.Name = "statusStrip1"; + // + // EditUsers + // + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.statusStrip1); + this.Controls.Add(this.btnOk); + this.Controls.Add(this.btnDelete); + this.Controls.Add(this.btnEdit); + this.Controls.Add(this.btnAdd); + this.Controls.Add(this.listViewUsers); + this.Name = "EditUsers"; + this.Activated += new System.EventHandler(this.EditUsers_Activated); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.ListView listViewUsers; + private System.Windows.Forms.Button btnAdd; + private System.Windows.Forms.Button btnEdit; + private System.Windows.Forms.Button btnDelete; + private System.Windows.Forms.Button btnOk; + private System.Windows.Forms.StatusStrip statusStrip1; + private System.Windows.Forms.ColumnHeader columnHeader1; + private System.Windows.Forms.ColumnHeader columnHeader2; + } +} \ No newline at end of file diff --git a/TestBenchFramework/Forms/EditUsers.cs b/TestBenchFramework/Forms/EditUsers.cs new file mode 100644 index 000000000..6cb574e7c --- /dev/null +++ b/TestBenchFramework/Forms/EditUsers.cs @@ -0,0 +1,120 @@ +using System; +using System.Collections.Generic; +using System.Windows.Forms; + +using NHibernate; +using TBF.Entities; + + +namespace TBF.Forms +{ + public partial class EditUsers: Form + { + NHibernate.ISession session; + IList ListOfUsers; + int LastSelectedIndex; + + public EditUsers() + { + InitializeComponent(); + } + + private void EditUsers_Activated(object sender, EventArgs e) + { + Cursor.Current = Cursors.WaitCursor; + session = FluentCommon.CreateSession(Database.Users); + ListUsers(); + RefreshButtonStates(); + } + + public void ListUsers() + { + Cursor.Current = Cursors.WaitCursor; + + if (User.CurrentUser.IsMemberOf(Grp.GID.Administrators) || User.CurrentUser.IsMemberOf(Grp.GID.HeadOfLab)) + { + /// Admin and HeadOfLab can edit all users + ListOfUsers = session.CreateQuery("FROM User") + .List(); + } + else + { + /// user can only edit their own data + ListOfUsers = session.CreateQuery("FROM User WHERE id= :CurrentUserId") + .SetParameter("CurrentUserId", User.CurrentUser.Id) + .List(); + } + + listViewUsers.Items.Clear(); + foreach (var person in ListOfUsers) + { + ListViewItem item = new ListViewItem(person.Name); + item.SubItems.Add(person.Id.ToString()); + item.Tag = person; + this.listViewUsers.Items.Add(item); + } + this.listViewUsers.Refresh(); + + Cursor.Current = Cursors.Default; + } + + private void btnOk_Click(object sender, EventArgs e) + { + this.Close(); + } + + + private void RefreshButtonStates() + { + btnEdit.Enabled = (listViewUsers.SelectedItems.Count > 0); + btnDelete.Enabled = (listViewUsers.SelectedItems.Count > 0); + } + + private void listViewUsers_SelectedIndexChanged(object sender, EventArgs e) + { + RefreshButtonStates(); + if (listViewUsers.SelectedItems.Count > 0) + { + LastSelectedIndex = listViewUsers.SelectedItems[0].Index; + } + else + { + LastSelectedIndex = -1; + } + } + + private void btnEdit_Click(object sender, EventArgs e) + { + Forms.EditSelectedUser dlg = new Forms.EditSelectedUser(); + dlg.CurrentEditUser = (User)listViewUsers.SelectedItems[0].Tag; + dlg.Session = session; + dlg.ShowDialog(); + ListUsers(); + } + + private void listViewUsers_DoubleClick(object sender, EventArgs e) + { + btnEdit_Click (sender, e); + } + + private void btnAdd_Click(object sender, EventArgs e) + { + Forms.EditSelectedUser dlg; + dlg = new Forms.EditSelectedUser(); + dlg.Session = session; + dlg.CurrentEditUser = new Entities.User(); + dlg.ShowDialog(); + ListUsers(); + } + + private void btnDelete_Click(object sender, EventArgs e) + { + Object Selecteduser = listViewUsers.SelectedItems[0].Tag; + FluentCommon.DeleteFromDb(session, Selecteduser); + ListUsers(); + } + } + +} + + diff --git a/TestBenchFramework/Forms/EditUsers.de.resx b/TestBenchFramework/Forms/EditUsers.de.resx new file mode 100644 index 000000000..c75bf86b5 --- /dev/null +++ b/TestBenchFramework/Forms/EditUsers.de.resx @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + &Neu... + + + &Bearbeiten + + + &Löschen + + + Benutzerverwaltung + + \ No newline at end of file diff --git a/TestBenchFramework/Forms/EditUsers.resx b/TestBenchFramework/Forms/EditUsers.resx new file mode 100644 index 000000000..2da933732 --- /dev/null +++ b/TestBenchFramework/Forms/EditUsers.resx @@ -0,0 +1,308 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Name + + + + 162 + + + ID + + + + 12, 12 + + + 357, 399 + + + 0 + + + listViewUsers + + + System.Windows.Forms.ListView, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 5 + + + 388, 42 + + + 75, 23 + + + 1 + + + Add + + + btnAdd + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 4 + + + 388, 71 + + + 75, 23 + + + 1 + + + Edit + + + btnEdit + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 3 + + + 388, 100 + + + 75, 23 + + + 1 + + + Delete + + + btnDelete + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 2 + + + 388, 388 + + + 75, 23 + + + 1 + + + OK + + + btnOk + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 1 + + + 17, 17 + + + 0, 442 + + + 475, 22 + + + 2 + + + statusStrip1 + + + statusStrip1 + + + System.Windows.Forms.StatusStrip, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 0 + + + de + + + True + + + 6, 13 + + + 475, 464 + + + user management + + + columnHeader1 + + + System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + columnHeader2 + + + System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + EditUsers + + + System.Windows.Forms.Form, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/Forms/EmergencyStopForm.cs b/TestBenchFramework/Forms/EmergencyStopForm.cs new file mode 100644 index 000000000..83c996286 --- /dev/null +++ b/TestBenchFramework/Forms/EmergencyStopForm.cs @@ -0,0 +1,56 @@ +using System; +using System.Drawing; +using System.Windows.Forms; +using TBF.Resources; + +namespace TBF.Forms +{ + public partial class EmergencyStopForm : Form + { + public static bool ClosingForm = false; + + /// + /// Parameterless constructor (does the localization) + /// + public EmergencyStopForm() + { + Visible = false; + InitializeComponent(); + emergencyStopMsgLabel.Text = Strings.Emergency_STOP; + emergencyStopMsgLabel.Enabled = false; + emergencyStopMsgLabel.Visible = false; + + UiBridge.Bridge.EmergencyStopChangedHandler += delegate(object sender, UiBridge.EmergencyStopEventArgs args) + { + if (ClosingForm) return; + + if (InvokeRequired) + { + Invoke(new EventHandler(OnEmergencyStopStateChanged), sender, args); + } + else OnEmergencyStopStateChanged(sender, args); + }; + } + + void OnEmergencyStopStateChanged(Object sender, UiBridge.EmergencyStopEventArgs args) + { + if (args.EmergencyStopState == UiBridge.EmergencyStopEventArgs.State.Active) + { + Visible = true; + emergencyStopMsgLabel.Enabled = true; + emergencyStopMsgLabel.Visible = true; + } + else if (args.EmergencyStopState == UiBridge.EmergencyStopEventArgs.State.Inactive) + { + Visible = false; + emergencyStopMsgLabel.Enabled = false; + emergencyStopMsgLabel.Visible = false; + } + else if (args.EmergencyStopState == UiBridge.EmergencyStopEventArgs.State.CloseForm) + { + ClosingForm = true; + Close(); + } + } + } +} diff --git a/TestBenchFramework/Forms/EmergencyStopForm.designer.cs b/TestBenchFramework/Forms/EmergencyStopForm.designer.cs new file mode 100644 index 000000000..d8d406f57 --- /dev/null +++ b/TestBenchFramework/Forms/EmergencyStopForm.designer.cs @@ -0,0 +1,73 @@ +namespace TBF.Forms +{ + partial class EmergencyStopForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.emergencyStopMsgLabel = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // emergencyStopMsgLabel + // + this.emergencyStopMsgLabel.AutoSize = true; + this.emergencyStopMsgLabel.Enabled = false; + this.emergencyStopMsgLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 24F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(238))); + this.emergencyStopMsgLabel.ForeColor = System.Drawing.Color.Yellow; + this.emergencyStopMsgLabel.Location = new System.Drawing.Point(67, 86); + this.emergencyStopMsgLabel.Name = "emergencyStopMsgLabel"; + this.emergencyStopMsgLabel.Size = new System.Drawing.Size(287, 37); + this.emergencyStopMsgLabel.TabIndex = 1; + this.emergencyStopMsgLabel.Text = "Emergency STOP"; + this.emergencyStopMsgLabel.Visible = false; + // + // EmergencyStopForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.AutoSize = true; + this.BackColor = System.Drawing.Color.Red; + this.ClientSize = new System.Drawing.Size(412, 212); + this.Controls.Add(this.emergencyStopMsgLabel); + this.Enabled = false; + this.ForeColor = System.Drawing.Color.Yellow; + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "EmergencyStopForm"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "Emergency STOP"; + this.TopMost = true; + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label emergencyStopMsgLabel; + } +} \ No newline at end of file diff --git a/TestBenchFramework/Forms/EmergencyStopForm.resx b/TestBenchFramework/Forms/EmergencyStopForm.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/TestBenchFramework/Forms/EmergencyStopForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/Forms/EnterPasswordDlg.Designer.cs b/TestBenchFramework/Forms/EnterPasswordDlg.Designer.cs new file mode 100644 index 000000000..18eeacada --- /dev/null +++ b/TestBenchFramework/Forms/EnterPasswordDlg.Designer.cs @@ -0,0 +1,106 @@ +namespace TBF.Forms +{ + partial class EnterPasswordDlg + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.cancelButton = new System.Windows.Forms.Button(); + this.passwordTextBox = new System.Windows.Forms.TextBox(); + this.passwordLabel = new System.Windows.Forms.Label(); + this.okButton = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // cancelButton + // + this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.cancelButton.ImeMode = System.Windows.Forms.ImeMode.NoControl; + this.cancelButton.Location = new System.Drawing.Point(275, 43); + this.cancelButton.Name = "cancelButton"; + this.cancelButton.Size = new System.Drawing.Size(105, 28); + this.cancelButton.TabIndex = 8; + this.cancelButton.Text = "Cancel"; + this.cancelButton.UseVisualStyleBackColor = true; + this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click); + // + // passwordTextBox + // + this.passwordTextBox.Location = new System.Drawing.Point(85, 26); + this.passwordTextBox.Name = "passwordTextBox"; + this.passwordTextBox.Size = new System.Drawing.Size(168, 20); + this.passwordTextBox.TabIndex = 7; + this.passwordTextBox.UseSystemPasswordChar = true; + // + // passwordLabel + // + this.passwordLabel.AutoSize = true; + this.passwordLabel.ImeMode = System.Windows.Forms.ImeMode.NoControl; + this.passwordLabel.Location = new System.Drawing.Point(12, 29); + this.passwordLabel.Name = "passwordLabel"; + this.passwordLabel.Size = new System.Drawing.Size(53, 13); + this.passwordLabel.TabIndex = 6; + this.passwordLabel.Text = "Password"; + // + // okButton + // + this.okButton.DialogResult = System.Windows.Forms.DialogResult.OK; + this.okButton.ImeMode = System.Windows.Forms.ImeMode.NoControl; + this.okButton.Location = new System.Drawing.Point(275, 10); + this.okButton.Name = "okButton"; + this.okButton.Size = new System.Drawing.Size(105, 28); + this.okButton.TabIndex = 9; + this.okButton.Text = "OK"; + this.okButton.UseVisualStyleBackColor = true; + this.okButton.Click += new System.EventHandler(this.okButton_Click); + // + // EnterPasswordDlg + // + this.AcceptButton = okButton; + this.CancelButton = cancelButton; + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(392, 79); + this.Controls.Add(this.okButton); + this.Controls.Add(this.cancelButton); + this.Controls.Add(this.passwordTextBox); + this.Controls.Add(this.passwordLabel); + this.Name = "EnterPasswordDlg"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "Enter password"; + this.Load += new System.EventHandler(this.PasswordDlg_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Button cancelButton; + private System.Windows.Forms.TextBox passwordTextBox; + private System.Windows.Forms.Label passwordLabel; + private System.Windows.Forms.Button okButton; + } +} \ No newline at end of file diff --git a/TestBenchFramework/Forms/EnterPasswordDlg.cs b/TestBenchFramework/Forms/EnterPasswordDlg.cs new file mode 100644 index 000000000..229db2ccb --- /dev/null +++ b/TestBenchFramework/Forms/EnterPasswordDlg.cs @@ -0,0 +1,48 @@ +using System; +using System.Windows.Forms; +using TBF.Resources; + +namespace TBF.Forms +{ + public partial class EnterPasswordDlg : Form + { + /// + /// If set, this is the password that should be entered by the user to pass, + /// otherwise user has to enter the current user password (Entities.User.CurrentUser). + /// + public string Password; + + public EnterPasswordDlg() + { + InitializeComponent(); + } + + private void PasswordDlg_Load(object sender, EventArgs e) + { + Text = Strings.Enter_password; + passwordLabel.Text = Strings.Password; + okButton.Text = Strings.OkBtnText; + cancelButton.Text = Strings.CancelBtnText; + } + + private void okButton_Click(object sender, EventArgs e) + { + if ((Password != null && Password.Equals(passwordTextBox.Text)) || + (Password == null && Entities.User.CurrentUser.CheckPassword(passwordTextBox.Text))) + { + DialogResult = DialogResult.OK; + Close(); + return; + } + + MessageBox.Show(Strings.Invalid_password, Strings.Error, MessageBoxButtons.OK, MessageBoxIcon.Error); + DialogResult = DialogResult.None; + } + + private void cancelButton_Click(object sender, EventArgs e) + { + DialogResult = DialogResult.Cancel; + Close(); + } + } +} diff --git a/TestBenchFramework/Forms/EnterPasswordDlg.resx b/TestBenchFramework/Forms/EnterPasswordDlg.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/TestBenchFramework/Forms/EnterPasswordDlg.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/Forms/ErrorDlg.Designer.cs b/TestBenchFramework/Forms/ErrorDlg.Designer.cs new file mode 100644 index 000000000..135c3a45e --- /dev/null +++ b/TestBenchFramework/Forms/ErrorDlg.Designer.cs @@ -0,0 +1,106 @@ +namespace TBF.Forms +{ + + partial class ErrorDlg + { + private string m_message; + + public string Message + { + get + { + return m_message; + } + + set + { + m_message = value; + textBoxMessage.Text = m_message; + } + } + + + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ErrorDlg)); + this.btnCancel = new System.Windows.Forms.Button(); + this.btnIgnore = new System.Windows.Forms.Button(); + this.btnRetry = new System.Windows.Forms.Button(); + this.textBoxMessage = new System.Windows.Forms.TextBox(); + this.SuspendLayout(); + // + // btnCancel + // + resources.ApplyResources(this.btnCancel, "btnCancel"); + this.btnCancel.ImageKey = global::TBF.Resources.Strings.String1; + this.btnCancel.Name = "btnCancel"; + this.btnCancel.UseVisualStyleBackColor = true; + this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click); + // + // btnIgnore + // + resources.ApplyResources(this.btnIgnore, "btnIgnore"); + this.btnIgnore.ImageKey = global::TBF.Resources.Strings.String1; + this.btnIgnore.Name = "btnIgnore"; + this.btnIgnore.UseVisualStyleBackColor = true; + this.btnIgnore.Click += new System.EventHandler(this.btnIgnore_Click); + // + // btnRetry + // + resources.ApplyResources(this.btnRetry, "btnRetry"); + this.btnRetry.ImageKey = global::TBF.Resources.Strings.String1; + this.btnRetry.Name = "btnRetry"; + this.btnRetry.UseVisualStyleBackColor = true; + this.btnRetry.Click += new System.EventHandler(this.btnRetry_Click); + // + // textBoxMessage + // + resources.ApplyResources(this.textBoxMessage, "textBoxMessage"); + this.textBoxMessage.Name = "textBoxMessage"; + // + // ErrorDlg + // + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.textBoxMessage); + this.Controls.Add(this.btnRetry); + this.Controls.Add(this.btnIgnore); + this.Controls.Add(this.btnCancel); + this.Name = "ErrorDlg"; + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Button btnCancel; + private System.Windows.Forms.Button btnIgnore; + private System.Windows.Forms.Button btnRetry; + private System.Windows.Forms.TextBox textBoxMessage; + } +} \ No newline at end of file diff --git a/TestBenchFramework/Forms/ErrorDlg.cs b/TestBenchFramework/Forms/ErrorDlg.cs new file mode 100644 index 000000000..9896e1066 --- /dev/null +++ b/TestBenchFramework/Forms/ErrorDlg.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Windows.Forms; +using TBF; +using TBF.ErrorHandler; + +namespace TBF.Forms +{ + public partial class ErrorDlg : Form + { + public ErrorDlg() + { + InitializeComponent(); + } + + public DialogResult returnvalue; + + public ErrorDlg(string ErrorDescription) + { + InitializeComponent(); + textBoxMessage.Text = ErrorDescription; + } + + private void btnOk_Click(object sender, EventArgs e) + { + returnvalue = DialogResult.OK; + this.Close(); + } + + private void btnIgnore_Click(object sender, EventArgs e) + { + returnvalue = DialogResult.Ignore; + this.Close(); + } + + private void btnCancel_Click(object sender, EventArgs e) + { + returnvalue = DialogResult.Cancel; + this.Close(); + } + + private void btnRetry_Click(object sender, EventArgs e) + { + returnvalue = DialogResult.Retry; + this.Close(); + } + } +} diff --git a/TestBenchFramework/Forms/ErrorDlg.de.resx b/TestBenchFramework/Forms/ErrorDlg.de.resx new file mode 100644 index 000000000..5983d6919 --- /dev/null +++ b/TestBenchFramework/Forms/ErrorDlg.de.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + &Abbrechen + + + Ein unbehandelter Fehler ist aufgetreten! + + \ No newline at end of file diff --git a/TestBenchFramework/Forms/ErrorDlg.resx b/TestBenchFramework/Forms/ErrorDlg.resx new file mode 100644 index 000000000..b267ccbac --- /dev/null +++ b/TestBenchFramework/Forms/ErrorDlg.resx @@ -0,0 +1,243 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + Vertical + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 6, 13 + + + 1 + + + Ignore + + + System.Windows.Forms.Form, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 1 + + + ErrorDlg + + + 508, 280 + + + 399, 340 + + + btnIgnore + + + 2 + + + $this + + + 1 + + + 0 + + + 530, 375 + + + 187, 340 + + + 100, 23 + + + 12, 43 + + + 1 + + + textBoxMessage + + + $this + + + 3 + + + btnCancel + + + btnRetry + + + $this + + + 100, 23 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Cancel + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 293, 340 + + + 2 + + + True + + + 100, 23 + + + $this + + + An unhandled Error occured + + + Retry + + + True + + + de + + \ No newline at end of file diff --git a/TestBenchFramework/Forms/NoBenchOrDatabaseDlg.Designer.cs b/TestBenchFramework/Forms/NoBenchOrDatabaseDlg.Designer.cs new file mode 100644 index 000000000..6dd239be9 --- /dev/null +++ b/TestBenchFramework/Forms/NoBenchOrDatabaseDlg.Designer.cs @@ -0,0 +1,120 @@ +namespace TBF.Forms +{ + partial class NoBenchOrDatabaseDlg + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(NoBenchOrDatabaseDlg)); + this.exitButton = new System.Windows.Forms.Button(); + this.retryButton = new System.Windows.Forms.Button(); + this.configureButton = new System.Windows.Forms.Button(); + this.pictureBox1 = new System.Windows.Forms.PictureBox(); + this.errorMessageLabel = new System.Windows.Forms.Label(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit(); + this.SuspendLayout(); + // + // exitButton + // + this.exitButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.exitButton.Location = new System.Drawing.Point(42, 68); + this.exitButton.Name = "exitButton"; + this.exitButton.Size = new System.Drawing.Size(246, 33); + this.exitButton.TabIndex = 0; + this.exitButton.Text = "Exit"; + this.exitButton.UseVisualStyleBackColor = true; + this.exitButton.Click += new System.EventHandler(this.exitButton_Click); + // + // retryButton + // + this.retryButton.Location = new System.Drawing.Point(42, 146); + this.retryButton.Name = "retryButton"; + this.retryButton.Size = new System.Drawing.Size(246, 33); + this.retryButton.TabIndex = 1; + this.retryButton.Text = "Retry database connection"; + this.retryButton.UseVisualStyleBackColor = true; + this.retryButton.Click += new System.EventHandler(this.retryButton_Click); + // + // configureButton + // + this.configureButton.Location = new System.Drawing.Point(42, 107); + this.configureButton.Name = "configureButton"; + this.configureButton.Size = new System.Drawing.Size(246, 33); + this.configureButton.TabIndex = 2; + this.configureButton.Text = "Configure test benches (password required)"; + this.configureButton.UseVisualStyleBackColor = true; + this.configureButton.Click += new System.EventHandler(this.configureButton_Click); + // + // pictureBox1 + // + this.pictureBox1.ErrorImage = ((System.Drawing.Image)(resources.GetObject("pictureBox1.ErrorImage"))); + this.pictureBox1.Image = ((System.Drawing.Image)(resources.GetObject("pictureBox1.Image"))); + this.pictureBox1.InitialImage = null; + this.pictureBox1.Location = new System.Drawing.Point(42, 21); + this.pictureBox1.Name = "pictureBox1"; + this.pictureBox1.Size = new System.Drawing.Size(32, 32); + this.pictureBox1.TabIndex = 3; + this.pictureBox1.TabStop = false; + // + // errorMessageLabel + // + this.errorMessageLabel.AutoSize = true; + this.errorMessageLabel.Location = new System.Drawing.Point(80, 31); + this.errorMessageLabel.Name = "errorMessageLabel"; + this.errorMessageLabel.Size = new System.Drawing.Size(160, 13); + this.errorMessageLabel.TabIndex = 4; + this.errorMessageLabel.Text = "Cannot connect to the database"; + // + // NoBenchOrDatabaseDlg + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.exitButton; + this.ClientSize = new System.Drawing.Size(328, 194); + this.Controls.Add(this.errorMessageLabel); + this.Controls.Add(this.pictureBox1); + this.Controls.Add(this.configureButton); + this.Controls.Add(this.retryButton); + this.Controls.Add(this.exitButton); + this.Name = "NoBenchOrDatabaseDlg"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "Error"; + this.Load += new System.EventHandler(this.NoDatabaseMsgDlg_Load); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Button exitButton; + private System.Windows.Forms.Button retryButton; + private System.Windows.Forms.Button configureButton; + private System.Windows.Forms.PictureBox pictureBox1; + private System.Windows.Forms.Label errorMessageLabel; + } +} \ No newline at end of file diff --git a/TestBenchFramework/Forms/NoBenchOrDatabaseDlg.cs b/TestBenchFramework/Forms/NoBenchOrDatabaseDlg.cs new file mode 100644 index 000000000..780207983 --- /dev/null +++ b/TestBenchFramework/Forms/NoBenchOrDatabaseDlg.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Windows.Forms; +using TBF.Resources; + +namespace TBF.Forms +{ + public partial class NoBenchOrDatabaseDlg : Form + { + public string Message; + public bool ShowRetry; + + public NoBenchOrDatabaseDlg() + { + InitializeComponent(); + } + + private void NoDatabaseMsgDlg_Load(object sender, EventArgs e) + { + Text = Strings.Error; + errorMessageLabel.Text = (Message != null) ? Message : Strings.Error; + exitButton.Text = Strings.ExitBtnText; + retryButton.Text = Strings.RetryDatabaseText; + configureButton.Text = Strings.ConfigureDatabaseText; + if (!ShowRetry) retryButton.Enabled = false; + } + + private void exitButton_Click(object sender, EventArgs e) + { + DialogResult = DialogResult.Abort; + } + + private void retryButton_Click(object sender, EventArgs e) + { + DialogResult = DialogResult.Retry; + } + + private void configureButton_Click(object sender, EventArgs e) + { + DialogResult = DialogResult.OK; + } + } +} diff --git a/TestBenchFramework/Forms/NoBenchOrDatabaseDlg.resx b/TestBenchFramework/Forms/NoBenchOrDatabaseDlg.resx new file mode 100644 index 000000000..e42c6fc53 --- /dev/null +++ b/TestBenchFramework/Forms/NoBenchOrDatabaseDlg.resx @@ -0,0 +1,272 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + 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 + QBqFBwCQRuEBAKRReAAAaRQeAEAahQcAkEbhAQCkUXgAAGkUHgBAGoUHAJBG4QEApFF4AABpFB4AQBqF + BwCQRuEBAKRReAAAaRQeAEAahQcAkEbhAQCkUXgAAGkUHgBAGoUHAJBG4QEApFF4AABpFB4AQBqFBwCQ + RuEBAKRReAAAaRQeAEAahQcAkEbhAQCkUXgAAGkUHgBAGoUHAJBG4QEApFF4AABpFB4AQBqFBwCQRuEB + AKRReAAAaRQeAEAahQcAkEbhAQCkUXgAAGkUHgBAGoUHAJBG4QEApFF4AABpFB4AQBqFBwCQRuEBAKRR + eAAAaRQeAEAahQcAkEbhAQCkUXgAAGkUHgBAGoUHAJBG4QEApFF4AABpFB4AQBqFBwCQRuEBAKRReAAA + aRQeAEAahQcAkEbhAQCkUXgAAGkUHgBAGoUHAJBG4QEApFF4AABpFB4AQBqFBwCQRuEBAKRReAAAaRQe + AEAahQcAkEbhAQCkUXgAAGkUHgBAGoUHAJBG4QEApFF4AABpFB4AQBqFBwCQRuEBAKRReAAAaRQeAEAa + hQcAkEbhAQCkUXgAAGkUHgBAGoUHAJBG4QEApFF4AABpFB4AQBqFBwCQRuEBAKRReAAAaRQeAEAahQcA + kEbhAQCkUXgAAGkUHgBAGoUHAJBG4QEApFF4AABpFB4AQBqFBwCQRuEBAKRReAAAaRQeAEAahQcAkEbh + AQCkUXgAAGkUHgBAGoUHAJBG4QEApFF4AABpFB4AQBqFBwCQRuEBAKRReAAAaRQeAEAahQcAkEbhAQCk + UXgAAGkUHgBAGoUHAJBG4QEApFF4AABpFB4AQBqFBwCQRuEBAKRReAAAaRQeAEAahQcAkEbhAQCkUXgA + AGkUHgBAGoUHAJBG4QEApFF4AABpFB4AQBqFBwCQRuEBAKRReAAAaRQeAEAahQcAkEbhAQCkUXgAAGkU + HgBAGoUHAJBG4QEApFF4AABpFB4AQBqFBwCQRuEBAKRReAAAaRQeAEAahQcAkEbhAQCkUXgAAGkUHgBA + GoUHAJBG4QEApFF4AABpFB4AQBqFBwCQRuEBAKRReAAAaRQeAEAahQcAkEbhAQCkUXgAAGkUHgBAGoUH + AJBG4QEApFF4AABpFB4AQBqFBwCQRuEBAKRReAAAaRQeAEAahQcAkEbhAQCkUXgAAGkUHgBAGoUHAJBG + 4QEApFF4AABpFB4AQBqFBwCQRuEBAKRReAAAaRQeAEAahQcAkEbhAQCkUXgAAGkUHgBAGoUHAJBG4QEA + pFF4AABpFB4AQBqFBwCQRuEBAKRReAAAaRQeAEAahQcAkEbhAQCkUXgAAGkUHgBAGoUHAJBG4QEApFF4 + AABpFB4AQBqFBwCQRuEBAKRReAAAaRQeAEAahQcAkEbhAQCkUXgAAGkUHgBAGoUHAJBG4QEApFF4AABp + FB4AQBqFBwCQRuEBAKRReAAAaRQeAEAahQcAkEbhAQCkUXgAAGkUHgBAGoUHAJBG4QEApFF4AABpFB4A + QBqFBwCQRuEBAKRReAAAaRQeAEAahQcAkEbhAQCkUXgAAGkUHgBAGoUHAJBG4QEApFF4AABpFB4AQBqF + BwCQRuEBAKRReAAAaRQeAEAahQcAkEbhAQCkUXgAAGkUHgBAGoUHAJBG4QEApFF4AABpFB4AQBqFBwCQ + RuEBAKRReAAAaRQeAEAahQcAkEbhAQCkUXgAAGkUHgBAGoUHAJBG4QEApFF4AABpFB4AQBqFBwCQRuEB + AKRReAAAaRQeAEAahQcAkEbhAQCkUXgAAGkUHgBAGoUHAJBG4QEApFF4AABpFB4AQBqFBwCQRuEBAKRR + eAAAaRQeAEAahQcAkEbhAQCkUXgAAGkUHgBAGoUHAJBG4QEApFF4AABpFB4AQBqFBwCQRuEBAKRReAAA + aRQeAEAahQcAkEbhAQCkUXgAAGkUHgBAGoUHAJBG4QEApFF4AABpFB4AQBqFBwCQRuEBAKRReAAAaRQe + AEAahQcAkEbhAQCkUXgAAGkUHgBAGoUHAJBG4QEApFF4AABpFB4AQBqFBwCQRuEBAKRReAAAaRQeAEAa + hQcAkEbhAQCkUXgAAGkUHgBAGoUHAJBG4QEApFF4AABpFB4AQBqFBwCQRuEBAKRReAAAaRQeAEAahQcA + kEbhAQCkUXgAAGkUHgBAGoUHAJBG4QEApFF4AABpFB4AQBqFBwCQRuEBAKRReAAAaRQeAEAahQcAkEbh + AQCkUXgAAGkUHgBAGoUHAJBG4QEApFF4AABpFB4AQBqFBwCQRuEBAKRReAAAaRQeAEAahQcAkEbhAQCk + UXgAAGkUHgBAGoUHAJBG4QEApFF4AABpFB4AQBqFBwCQRuEBAKRReAAAaRQeAEAahQcAkEbhAQCkUXgA + AGkUHgBAGoUHAJBG4QEApFF4AABpFB4AQBqFBwCQRuEBAKRReAAAaRQeAEAahQcAkEbhAQCkUXgAAGkU + HgBAGoUHAJBG4QEApFF4AABpFB4AQBqFBwCQRuEBAKRReAAAaRQeAEAahQcAkEbhAQCkUXgAAGkUHgBA + GoUHAJBG4QEApFF4AABpFB4AQBqFBwCQRuEBAKRReAAAaRQeAEAahQcAkEbhAQCkUXgAAGkUHgBAGoUH + AJBG4QEApFF4AABpFB4AQBqFBwCQRuEBAKRReAAAaRQeAEAahQcAkEbhAQCkUXgAAGkUHgBAGoUHAJBG + 4QEApFF4AABpFB4AQBqFBwCQRuEBAKRReAAAaRQeAEAahQcAkEbhAQCkUXgAAGkUHgBAGoUHAJBG4QEA + pFF4AABpFB4AQBqFBwCQRuEBAKRReAAAaRQeAEAahQcAkEbhAQCkUXgAAGkUHgBAGoUHAJBG4QEApFF4 + AABpFB4AQBqFBwCQRuEBAKRReAAAaRQeAEAahQcAkEbhAQCkUXgAAGkUHgBAGoUHAJBG4QEApFF4AABp + FB4AQBqFBwCQRuEBAKRReAAAaRQeAEAahQcAkEbhAQCkUXgAAGkUHgBAGoUHAJBG4QEApFF4AABpFB4A + QBqFBwCQRuEBAKRReAAAaRQeAEAahQcAkEbhAQCkUXgAAGkUHgBAGoUHAJBG4QEApFF4AABpFB4AQBqF + BwCQRuEBAKRReAAAaRQeAEAahQcAkEbhAQCkUXgAAGkUHgBAGoUHAJBG4QEApFF4AABpFB4AQBqFBwCQ + RuEBAKRReAAAaRQeAEAahQcAkEbhAQCkUXgAAGkUHgBAGoUHAJBG4QEApFF4AABpFB4AQBqFBwCQRuEB + AKRReAAAaRQeAEAahQcAkEbhAQCkUXgAAGkUHgBAGoUHAJBG4QEApFF4AABpFB4AQBqFBwCQRuEBAKRR + eAAAaRQeAEAahQcAkEbhAQCkUXgAAGkUHgBAGoUHAJBG4QEApFF4AABpFB4AQBqFBwCQRuEBAKRReAAA + Wc6d+2/gNp2ukwoN8QAAAABJRU5ErkJggg== + + + + + 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 + YUP1lbK+/k8KJ49ubHudCAAAAABJRU5ErkJggg== + + + \ No newline at end of file diff --git a/TestBenchFramework/Forms/ResultsConfig.Designer.cs b/TestBenchFramework/Forms/ResultsConfig.Designer.cs new file mode 100644 index 000000000..f83b14b28 --- /dev/null +++ b/TestBenchFramework/Forms/ResultsConfig.Designer.cs @@ -0,0 +1,254 @@ +namespace TBF.Forms +{ + partial class ResultsConfig + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.testsRowsRadioButton = new System.Windows.Forms.RadioButton(); + this.testsColumnsRadioButton = new System.Windows.Forms.RadioButton(); + this.testsArangementGroupBox = new System.Windows.Forms.GroupBox(); + this.metersArangementGroupBox = new System.Windows.Forms.GroupBox(); + this.verticallyRadioButton = new System.Windows.Forms.RadioButton(); + this.horizontallyRadioButton = new System.Windows.Forms.RadioButton(); + this.okButton = new System.Windows.Forms.Button(); + this.cancelButton = new System.Windows.Forms.Button(); + this.availableResultsListBox = new System.Windows.Forms.ListBox(); + this.selectedResultsListBox = new System.Windows.Forms.ListBox(); + this.availableResultsLabel = new System.Windows.Forms.Label(); + this.selectedResultsLabel = new System.Windows.Forms.Label(); + this.removeAllButton = new System.Windows.Forms.Button(); + this.removeButton = new System.Windows.Forms.Button(); + this.addButton = new System.Windows.Forms.Button(); + this.testsArangementGroupBox.SuspendLayout(); + this.metersArangementGroupBox.SuspendLayout(); + this.SuspendLayout(); + // + // testsRowsRadioButton + // + this.testsRowsRadioButton.AutoSize = true; + this.testsRowsRadioButton.Location = new System.Drawing.Point(21, 24); + this.testsRowsRadioButton.Name = "testsRowsRadioButton"; + this.testsRowsRadioButton.Size = new System.Drawing.Size(120, 17); + this.testsRowsRadioButton.TabIndex = 0; + this.testsRowsRadioButton.TabStop = true; + this.testsRowsRadioButton.Text = "Tests are table rows"; + this.testsRowsRadioButton.UseVisualStyleBackColor = true; + // + // testsColumnsRadioButton + // + this.testsColumnsRadioButton.AutoSize = true; + this.testsColumnsRadioButton.Location = new System.Drawing.Point(21, 46); + this.testsColumnsRadioButton.Name = "testsColumnsRadioButton"; + this.testsColumnsRadioButton.Size = new System.Drawing.Size(137, 17); + this.testsColumnsRadioButton.TabIndex = 1; + this.testsColumnsRadioButton.TabStop = true; + this.testsColumnsRadioButton.Text = "Tests are table columns"; + this.testsColumnsRadioButton.UseVisualStyleBackColor = true; + // + // testsArangementGroupBox + // + this.testsArangementGroupBox.Controls.Add(this.testsColumnsRadioButton); + this.testsArangementGroupBox.Controls.Add(this.testsRowsRadioButton); + this.testsArangementGroupBox.Location = new System.Drawing.Point(12, 12); + this.testsArangementGroupBox.Name = "testsArangementGroupBox"; + this.testsArangementGroupBox.Size = new System.Drawing.Size(254, 74); + this.testsArangementGroupBox.TabIndex = 2; + this.testsArangementGroupBox.TabStop = false; + this.testsArangementGroupBox.Text = "Arangement of tests"; + // + // metersArangementGroupBox + // + this.metersArangementGroupBox.Controls.Add(this.verticallyRadioButton); + this.metersArangementGroupBox.Controls.Add(this.horizontallyRadioButton); + this.metersArangementGroupBox.Location = new System.Drawing.Point(12, 92); + this.metersArangementGroupBox.Name = "metersArangementGroupBox"; + this.metersArangementGroupBox.Size = new System.Drawing.Size(254, 75); + this.metersArangementGroupBox.TabIndex = 3; + this.metersArangementGroupBox.TabStop = false; + this.metersArangementGroupBox.Text = "Arangement of tested meters"; + // + // verticallyRadioButton + // + this.verticallyRadioButton.AutoSize = true; + this.verticallyRadioButton.Location = new System.Drawing.Point(21, 24); + this.verticallyRadioButton.Name = "verticallyRadioButton"; + this.verticallyRadioButton.Size = new System.Drawing.Size(67, 17); + this.verticallyRadioButton.TabIndex = 3; + this.verticallyRadioButton.TabStop = true; + this.verticallyRadioButton.Text = "Vertically"; + this.verticallyRadioButton.UseVisualStyleBackColor = true; + // + // horizontallyRadioButton + // + this.horizontallyRadioButton.AutoSize = true; + this.horizontallyRadioButton.Location = new System.Drawing.Point(21, 46); + this.horizontallyRadioButton.Name = "horizontallyRadioButton"; + this.horizontallyRadioButton.Size = new System.Drawing.Size(79, 17); + this.horizontallyRadioButton.TabIndex = 2; + this.horizontallyRadioButton.TabStop = true; + this.horizontallyRadioButton.Text = "Horizontally"; + this.horizontallyRadioButton.UseVisualStyleBackColor = true; + // + // okButton + // + this.okButton.Location = new System.Drawing.Point(283, 18); + this.okButton.Name = "okButton"; + this.okButton.Size = new System.Drawing.Size(104, 30); + this.okButton.TabIndex = 4; + this.okButton.Text = "OK"; + this.okButton.UseVisualStyleBackColor = true; + this.okButton.Click += new System.EventHandler(this.okButton_Click); + // + // cancelButton + // + this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.cancelButton.Location = new System.Drawing.Point(283, 55); + this.cancelButton.Name = "cancelButton"; + this.cancelButton.Size = new System.Drawing.Size(104, 30); + this.cancelButton.TabIndex = 5; + this.cancelButton.Text = "Cancel"; + this.cancelButton.UseVisualStyleBackColor = true; + // + // availableResultsListBox + // + this.availableResultsListBox.FormattingEnabled = true; + this.availableResultsListBox.Location = new System.Drawing.Point(12, 205); + this.availableResultsListBox.Name = "availableResultsListBox"; + this.availableResultsListBox.Size = new System.Drawing.Size(135, 160); + this.availableResultsListBox.TabIndex = 6; + this.availableResultsListBox.DoubleClick += new System.EventHandler(this.availableResultsListBox_DoubleClick); + // + // selectedResultsListBox + // + this.selectedResultsListBox.FormattingEnabled = true; + this.selectedResultsListBox.Location = new System.Drawing.Point(252, 205); + this.selectedResultsListBox.Name = "selectedResultsListBox"; + this.selectedResultsListBox.Size = new System.Drawing.Size(135, 160); + this.selectedResultsListBox.TabIndex = 7; + this.selectedResultsListBox.DoubleClick += new System.EventHandler(this.selectedResultsListBox_DoubleClick); + // + // availableResultsLabel + // + this.availableResultsLabel.AutoSize = true; + this.availableResultsLabel.Location = new System.Drawing.Point(12, 183); + this.availableResultsLabel.Name = "availableResultsLabel"; + this.availableResultsLabel.Size = new System.Drawing.Size(86, 13); + this.availableResultsLabel.TabIndex = 8; + this.availableResultsLabel.Text = "Available results:"; + // + // selectedResultsLabel + // + this.selectedResultsLabel.AutoSize = true; + this.selectedResultsLabel.Location = new System.Drawing.Point(249, 183); + this.selectedResultsLabel.Name = "selectedResultsLabel"; + this.selectedResultsLabel.Size = new System.Drawing.Size(85, 13); + this.selectedResultsLabel.TabIndex = 9; + this.selectedResultsLabel.Text = "Selected results:"; + // + // removeAllButton + // + this.removeAllButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.removeAllButton.Location = new System.Drawing.Point(153, 306); + this.removeAllButton.Name = "removeAllButton"; + this.removeAllButton.Size = new System.Drawing.Size(94, 30); + this.removeAllButton.TabIndex = 46; + this.removeAllButton.Text = "<< R&emove all"; + this.removeAllButton.UseVisualStyleBackColor = true; + this.removeAllButton.Click += new System.EventHandler(this.removeAllButton_Click); + // + // removeButton + // + this.removeButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.removeButton.Location = new System.Drawing.Point(153, 271); + this.removeButton.Name = "removeButton"; + this.removeButton.Size = new System.Drawing.Size(93, 30); + this.removeButton.TabIndex = 45; + this.removeButton.Text = "< &Remove"; + this.removeButton.UseVisualStyleBackColor = true; + this.removeButton.Click += new System.EventHandler(this.removeButton_Click); + // + // addButton + // + this.addButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.addButton.Location = new System.Drawing.Point(153, 236); + this.addButton.Name = "addButton"; + this.addButton.Size = new System.Drawing.Size(93, 30); + this.addButton.TabIndex = 44; + this.addButton.Text = "&Add >"; + this.addButton.UseVisualStyleBackColor = true; + this.addButton.Click += new System.EventHandler(this.addButton_Click); + // + // ResultsConfig + // + this.AcceptButton = this.okButton; + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.cancelButton; + this.ClientSize = new System.Drawing.Size(399, 379); + this.Controls.Add(this.removeAllButton); + this.Controls.Add(this.removeButton); + this.Controls.Add(this.addButton); + this.Controls.Add(this.selectedResultsLabel); + this.Controls.Add(this.availableResultsLabel); + this.Controls.Add(this.selectedResultsListBox); + this.Controls.Add(this.availableResultsListBox); + this.Controls.Add(this.cancelButton); + this.Controls.Add(this.okButton); + this.Controls.Add(this.metersArangementGroupBox); + this.Controls.Add(this.testsArangementGroupBox); + this.Name = "ResultsConfig"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "ResultsConfig"; + this.Load += new System.EventHandler(this.ResultsConfig_Load); + this.testsArangementGroupBox.ResumeLayout(false); + this.testsArangementGroupBox.PerformLayout(); + this.metersArangementGroupBox.ResumeLayout(false); + this.metersArangementGroupBox.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.RadioButton testsRowsRadioButton; + private System.Windows.Forms.RadioButton testsColumnsRadioButton; + private System.Windows.Forms.GroupBox testsArangementGroupBox; + private System.Windows.Forms.GroupBox metersArangementGroupBox; + private System.Windows.Forms.RadioButton verticallyRadioButton; + private System.Windows.Forms.RadioButton horizontallyRadioButton; + private System.Windows.Forms.Button okButton; + private System.Windows.Forms.Button cancelButton; + private System.Windows.Forms.ListBox availableResultsListBox; + private System.Windows.Forms.ListBox selectedResultsListBox; + private System.Windows.Forms.Label availableResultsLabel; + private System.Windows.Forms.Label selectedResultsLabel; + private System.Windows.Forms.Button removeAllButton; + private System.Windows.Forms.Button removeButton; + private System.Windows.Forms.Button addButton; + } +} \ No newline at end of file diff --git a/TestBenchFramework/Forms/ResultsConfig.cs b/TestBenchFramework/Forms/ResultsConfig.cs new file mode 100644 index 000000000..03b540c95 --- /dev/null +++ b/TestBenchFramework/Forms/ResultsConfig.cs @@ -0,0 +1,195 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Windows.Forms; +using TBF.Resources; + +namespace TBF.Forms +{ + public partial class ResultsConfig : Form + { + /// Arrangement of tests + public enum TestsAre + { + Rows, + Columns, + } + public TestsAre TestsArrangement; + + /// Arrangement of meters + public enum Meters + { + Vertically, + Horizontally, + } + public Meters MetersArrangement; + + /// Results items to be selected in the configuration + public enum ResultsItem + { + Hovno, + Makove, + Count + } + // + public IList AvailableItems; + public IList SelectedItems; + + + public ResultsConfig() + { + InitializeComponent(); + + SelectedItems = new List(); + AvailableItems = GetListOfAvailableItems(); + } + + void Localize() + { + Text = Strings.Configuration; + testsArangementGroupBox.Text = Strings.Arrangement_of_tests; + metersArangementGroupBox.Text = Strings.Arrangement_of_meters; + testsRowsRadioButton.Text = Strings.Tests_are_rows; + testsColumnsRadioButton.Text = Strings.Tests_are_columns; + horizontallyRadioButton.Text = Strings.Horizontally; + verticallyRadioButton.Text = Strings.Vertically; + availableResultsLabel.Text = Strings.Available_results; + selectedResultsLabel.Text = Strings.Selected_results; + addButton.Text = Strings.Add; + removeButton.Text = Strings.Remove; + removeAllButton.Text = Strings.Remove_all; + okButton.Text = Strings.OkBtnText; + cancelButton.Text = Strings.CancelBtnText; + } + + void ResultsConfig_Load(object sender, EventArgs e) + { + Localize(); + + testsRowsRadioButton.Checked = (TestsArrangement == TestsAre.Rows); + testsColumnsRadioButton.Checked = (TestsArrangement == TestsAre.Columns); + + horizontallyRadioButton.Checked = (MetersArrangement == Meters.Horizontally); + verticallyRadioButton.Checked = (MetersArrangement == Meters.Vertically); + + RedrawAvailable(); + RedrawSelected(); + } + + /// + /// Create a list of available items from the complete list from 'auxBrdUpgInfo' + /// and the list of selected items. In this way the order of items in the created list + /// is always the same as in the original list in 'auxBrdUpgInfo'. + /// + /// A list of available items which does not contain the selected items + IList GetListOfAvailableItems() + { + IList availableItems = new List(); + for (ResultsItem item = 0; item < ResultsItem.Count; item++) + { + if (!SelectedItems.Contains(item)) availableItems.Add(item); + } + return availableItems; + } + + /// + /// Redraw selected items (right hand side) + /// + void RedrawAvailable() + { + availableResultsListBox.Items.Clear(); + foreach (var item in AvailableItems) availableResultsListBox.Items.Add(item.ToString()); + } + + /// + /// Redraw selected items (right hand side) + /// + void RedrawSelected() + { + selectedResultsListBox.Items.Clear(); + foreach (var item in SelectedItems) selectedResultsListBox.Items.Add(item.ToString()); + } + + void okButton_Click(object sender, EventArgs e) + { + if (testsColumnsRadioButton.Checked) TestsArrangement = TestsAre.Columns; + else TestsArrangement = TestsAre.Rows; + + if (horizontallyRadioButton.Checked) MetersArrangement = Meters.Horizontally; + else MetersArrangement = Meters.Vertically; + + DialogResult = DialogResult.OK; + Close(); + } + + private void availableResultsListBox_DoubleClick(object sender, EventArgs e) + { + /// Double click works when just one item is selected + IList itemsToRemove = new List(); + if (availableResultsListBox.SelectedIndices.Count == 1) + { + var item = AvailableItems[availableResultsListBox.SelectedIndices[0]]; + SelectedItems.Add(item); + AvailableItems.Remove(item); + RedrawAvailable(); + RedrawSelected(); + } + } + + void addButton_Click(object sender, EventArgs e) + { + /// Append at the end, this code supports multiple selected items, + /// although ListBox control settings may limit the max.number of selected items to one. + + for (int i = availableResultsListBox.SelectedIndices.Count - 1; i >= 0; i--) + { + var item = AvailableItems[availableResultsListBox.SelectedIndices[i]]; + SelectedItems.Add(item); + AvailableItems.Remove(item); + } + RedrawAvailable(); + RedrawSelected(); + } + + private void selectedResultsListBox_DoubleClick(object sender, EventArgs e) + { + /// Double click works when just one item is selected + + if (selectedResultsListBox.SelectedIndices.Count == 1) + { + SelectedItems.RemoveAt(selectedResultsListBox.SelectedIndices[0]); + AvailableItems = GetListOfAvailableItems(); + RedrawAvailable(); + RedrawSelected(); + } + } + + void removeButton_Click(object sender, EventArgs e) + { + /// Remove from the list (the last selected item first so that the indexes are not affected) + + for (int i = selectedResultsListBox.SelectedIndices.Count - 1; i >= 0; i--) + { + ResultsItem item = SelectedItems[selectedResultsListBox.SelectedIndices[i]]; + SelectedItems.Remove(item); + } + AvailableItems = GetListOfAvailableItems(); + RedrawAvailable(); + RedrawSelected(); + } + + void removeAllButton_Click(object sender, EventArgs e) + { + /// Remove all items from 'Selected' list + + SelectedItems.Clear(); + AvailableItems = GetListOfAvailableItems(); + RedrawAvailable(); + RedrawSelected(); + } + } +} diff --git a/TestBenchFramework/Forms/ResultsConfig.resx b/TestBenchFramework/Forms/ResultsConfig.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/TestBenchFramework/Forms/ResultsConfig.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/Forms/TabNameDlg.Designer.cs b/TestBenchFramework/Forms/TabNameDlg.Designer.cs new file mode 100644 index 000000000..24302293f --- /dev/null +++ b/TestBenchFramework/Forms/TabNameDlg.Designer.cs @@ -0,0 +1,73 @@ +namespace TBF.Forms +{ + partial class TabNameDlg + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.tabNameTextBox = new System.Windows.Forms.TextBox(); + this.okButton = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // tabNameTextBox + // + this.tabNameTextBox.Location = new System.Drawing.Point(33, 25); + this.tabNameTextBox.Name = "tabNameTextBox"; + this.tabNameTextBox.Size = new System.Drawing.Size(145, 20); + this.tabNameTextBox.TabIndex = 1; + // + // okButton + // + this.okButton.Location = new System.Drawing.Point(209, 18); + this.okButton.Name = "okButton"; + this.okButton.Size = new System.Drawing.Size(85, 33); + this.okButton.TabIndex = 2; + this.okButton.Text = "OK"; + this.okButton.UseVisualStyleBackColor = true; + this.okButton.Click += new System.EventHandler(this.okButton_Click); + // + // TabNameDlg + // + this.AcceptButton = this.okButton; + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(316, 69); + this.Controls.Add(this.okButton); + this.Controls.Add(this.tabNameTextBox); + this.Name = "TabNameDlg"; + this.Text = "TabName"; + this.Load += new System.EventHandler(this.TabNameDlg_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TextBox tabNameTextBox; + private System.Windows.Forms.Button okButton; + } +} \ No newline at end of file diff --git a/TestBenchFramework/Forms/TabNameDlg.cs b/TestBenchFramework/Forms/TabNameDlg.cs new file mode 100644 index 000000000..a66332127 --- /dev/null +++ b/TestBenchFramework/Forms/TabNameDlg.cs @@ -0,0 +1,31 @@ +using System; +using System.Windows.Forms; +using TBF.Resources; + +namespace TBF.Forms +{ + public partial class TabNameDlg : Form + { + public string TabNameLabel; + public string TabName; + + public TabNameDlg() + { + InitializeComponent(); + } + + private void TabNameDlg_Load(object sender, EventArgs e) + { + Text = TabNameLabel; + tabNameTextBox.Text = TabName; + okButton.Text = Strings.OkBtnText; + } + + private void okButton_Click(object sender, EventArgs e) + { + TabName = tabNameTextBox.Text; + DialogResult = DialogResult.OK; + Close(); + } + } +} diff --git a/TestBenchFramework/Forms/TabNameDlg.resx b/TestBenchFramework/Forms/TabNameDlg.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/TestBenchFramework/Forms/TabNameDlg.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/Grp.cs b/TestBenchFramework/Grp.cs new file mode 100644 index 000000000..3e0ee3a29 --- /dev/null +++ b/TestBenchFramework/Grp.cs @@ -0,0 +1,98 @@ +using System; +using System.Collections.Generic; +using System.Text; + +using TBF.Entities; +using NHibernate; +using FluentNHibernate; + +namespace TBF +{ + /// + /// Enum Grp.GID specifies GID-s of user groups. + /// An instance of this class represenst a group, which contains a list of its members (users). + /// Static private array 'groups' of this class, accesible through indexer, contains all groups. + /// + public class Grp + { + /// + /// GID-s of user groups, each user is member of one or more groups. + /// + public enum GID + { + // The first NrOfGroups items are GroupID-s (0..NrOfGroups-1) + Testers = 0, + TestingSpecialists, + HeadOfLab, + MaintenanceSpecialists, + Metrologists, + CalibrationSpecialists, + Administrators, // application / network / database administrator + Custom1, + Custom2, + Custom3, + NrOfGroups, // Number of groups (this is not a GroupID) + None, // Not a GroupID, can be used to indicate no group membership is required + Invalid = -1, // Not a GroupID, indicates a variable has not been properly set so far + } + + /// + /// Number of groups. + /// + public const int Count = (int)GID.NrOfGroups; + + // Static array of all groups. + static Grp[] groups; + + /// + /// Static constructor, creates all groups with no members. + /// + static Grp() + { + groups = new Grp[Count]; + for (int i = 0; i < Count; i++) + { + groups[i] = new Grp((GID)i); + } + } + + /// + /// Returns a Group from Id. + /// + /// Group Gid + /// Entities.Group object reference + public static Entities.Group FromId(GID gid) + { + int i = (int)gid; + + if (i >= 0 && i < Count) + { + return groups[i].group; + } + else + { + return null; + } + } + + ///////////////////// ^ static ^ ///////////////////// v instance v ///////////////////// + + /// Public properties + public GID Gid { get { return (GID)group.Gid; } } + public string Name { get { return group.Name; } set { group.Name = value; } } + + /// Private fields + Entities.Group group; + + /// + /// Instance constructor. + /// + /// + public Grp(GID gid) + { + group = new Entities.Group(); + this.group.Gid = (int)gid; + this.group.Name = gid.ToString(); + } + } +} diff --git a/TestBenchFramework/LocalSettings.cs b/TestBenchFramework/LocalSettings.cs new file mode 100644 index 000000000..8cbe2fe2c --- /dev/null +++ b/TestBenchFramework/LocalSettings.cs @@ -0,0 +1,135 @@ +using System; +using System.IO; +using System.Text; +using System.Xml.Serialization; + +namespace TBF +{ + /// + /// Class to be serialized to an XML file... + /// Public members are local settings. + /// These settings are modified by dialogs invoked by menu items + /// Edit->Preferences ... PreferencesDlg ... S1.1(language, etc. local settings), and + /// Edit->Advanced settings ... AdvancedSettingsDlg ... S1.2(spec. where bench settings are stored) + /// + [XmlRootAttribute("TestBenchFramework")] + public class LocalSettings + { + /// + /// Available languages. + /// Method ToString should give a supported culture info string: + /// ("en","de","fr","es","it","cn", etc.). + /// + public enum Languages + { + en, + de, + sk, + Count, + } + + /// + /// User interface language ("en","de","fr","es","it","cn", etc.). + /// + public string Language = "en"; + + /// + /// Names and database settings of test benches. + /// + [XmlArrayAttribute("TestBenches")] + public DatabaseSettings[] testBenches; + + [XmlIgnore] + public DatabaseSettings[] TestBenches { get { return testBenches; } } + + [XmlIgnore] + public int BenchesCount { get { return testBenches != null ? testBenches.GetLength(0) : 0; } } + + /// + /// Currently selected bench name (local or remote) or null (= no selection done). + /// + [XmlElementAttribute("LastBench")] + public string LastBenchName; + + /// + /// Currently selected procedure name or null (= no selection done yet). + /// + [XmlElementAttribute("LastProcedure")] + public string LastProcedureName; + + public int RightPaneHorizSplitterDistance; + + public Forms.ResultsConfig.Meters ResultsConfigMeters; + public Forms.ResultsConfig.TestsAre ResultsConfigTests; + + /// + /// Copy public fields from a LocalSettings object to this object. + /// + /// Origin + public void Assign(LocalSettings ls) + { + if (ls != null) + { + Language = ls.Language; + testBenches = new DatabaseSettings[ls.testBenches.Length]; + for (int i = 0; i < testBenches.Length; i++) testBenches[i] = ls.testBenches[i]; + LastBenchName = ls.LastBenchName; + LastProcedureName = ls.LastProcedureName; + RightPaneHorizSplitterDistance = ls.RightPaneHorizSplitterDistance; + ResultsConfigMeters = ls.ResultsConfigMeters; + ResultsConfigTests = ls.ResultsConfigTests; + } + } + + [XmlIgnore] + public readonly bool AlwaysAskPasswdWhenUnlocking; + + [XmlIgnore] + public readonly bool RestoreUserWhenLeavingDialog; + + + public LocalSettings() + { + AlwaysAskPasswdWhenUnlocking = false; + RestoreUserWhenLeavingDialog = true; + } + + /// + /// Load public fields of this class from the XML file. + /// + public void Load() + { + try + { + using (TextReader reader = new StreamReader(Program.LocalSettingsFileName)) + { + LocalSettings ls = (new XmlSerializer(typeof(LocalSettings))).Deserialize(reader) as LocalSettings; + // Copy the settings just in case De-serialize() completes OK + this.Assign(ls); + } + } + catch (Exception e) + { + string msg = e.Message; + } + } + + /// + /// Save public fields of this class to the XML file. + /// + public void Save() + { + try + { + using (TextWriter writer = new StreamWriter(Program.LocalSettingsFileName)) + { + (new XmlSerializer(typeof(LocalSettings))).Serialize(writer, this); + } + } + catch (Exception e) + { + string msg = e.Message; + } + } + } +} diff --git a/TestBenchFramework/LoginDlg.Designer.cs b/TestBenchFramework/LoginDlg.Designer.cs new file mode 100644 index 000000000..716264e0e --- /dev/null +++ b/TestBenchFramework/LoginDlg.Designer.cs @@ -0,0 +1,107 @@ +namespace TBF +{ + partial class LoginDlg + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(LoginDlg)); + this.label1 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.passwordTextBox = new System.Windows.Forms.TextBox(); + this.cancelButton = new System.Windows.Forms.Button(); + this.okButton = new System.Windows.Forms.Button(); + this.userNameTextBox = new System.Windows.Forms.TextBox(); + this.SuspendLayout(); + // + // label1 + // + resources.ApplyResources(this.label1, "label1"); + this.label1.Name = "label1"; + // + // label2 + // + resources.ApplyResources(this.label2, "label2"); + this.label2.Name = "label2"; + // + // passwordTextBox + // + resources.ApplyResources(this.passwordTextBox, "passwordTextBox"); + this.passwordTextBox.Name = "passwordTextBox"; + this.passwordTextBox.UseSystemPasswordChar = true; + // + // cancelButton + // + this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; + resources.ApplyResources(this.cancelButton, "cancelButton"); + this.cancelButton.Name = "cancelButton"; + this.cancelButton.UseVisualStyleBackColor = true; + this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click); + // + // okButton + // + this.okButton.DialogResult = System.Windows.Forms.DialogResult.OK; + resources.ApplyResources(this.okButton, "okButton"); + this.okButton.Name = "okButton"; + this.okButton.UseVisualStyleBackColor = true; + this.okButton.Click += new System.EventHandler(this.okButton_Click); + // + // userNameTextBox + // + resources.ApplyResources(this.userNameTextBox, "userNameTextBox"); + this.userNameTextBox.Name = "userNameTextBox"; + // + // LoginDlg + // + this.AcceptButton = this.okButton; + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.cancelButton; + this.Controls.Add(this.userNameTextBox); + this.Controls.Add(this.okButton); + this.Controls.Add(this.cancelButton); + this.Controls.Add(this.passwordTextBox); + this.Controls.Add(this.label2); + this.Controls.Add(this.label1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.Name = "LoginDlg"; + this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide; + this.Load += new System.EventHandler(this.LoginDlg_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.TextBox userNameTextBox; + private System.Windows.Forms.TextBox passwordTextBox; + private System.Windows.Forms.Button cancelButton; + private System.Windows.Forms.Button okButton; + } +} \ No newline at end of file diff --git a/TestBenchFramework/LoginDlg.cs b/TestBenchFramework/LoginDlg.cs new file mode 100644 index 000000000..63ad41f21 --- /dev/null +++ b/TestBenchFramework/LoginDlg.cs @@ -0,0 +1,124 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Windows.Forms; +using TBF.Resources; + +namespace TBF +{ + /// + /// Provides login dialog as well as user authorization using TBF.User.Authorize(...) + /// (i.e. when DialogResult is OK, user was authorized). + /// + public partial class LoginDlg : Form + { + // Private fields + string user; + string password; + Grp.GID requiredGroupMembership = Grp.GID.Invalid; + + /// + /// Constructor. + /// + public LoginDlg() + { + InitializeComponent(); + } + + /// + /// Constructor with a predefined user. + /// + public LoginDlg(string predefinedUser) + : this() + { + user = predefinedUser; + userNameTextBox.Text = predefinedUser; + } + + /// + /// Constructor when a specific group membership is required. + /// + public LoginDlg(Grp.GID requiredGroupMembership) + : this() + { + this.requiredGroupMembership = requiredGroupMembership; + } + + /// + /// Constructor with a predefined user when a specific group membership is required. + /// + public LoginDlg(string predefinedUser, Grp.GID requiredGroupMembership) + : this() + { + user = predefinedUser; + userNameTextBox.Text = predefinedUser; + this.requiredGroupMembership = requiredGroupMembership; + } + + private void LoginDlg_Load(object sender, EventArgs e) + { + Text = Strings.User_Login; + label1.Text = Strings.Username; + label2.Text = Strings.Password; + okButton.Text = Strings.OkBtnText; + cancelButton.Text = Strings.CancelBtnText; + + if (user == null) userNameTextBox.Select(); + else passwordTextBox.Select(); + } + + /// + /// Try to authorize the user when OK clicked. + /// + private void okButton_Click(object sender, EventArgs e) + { + user = userNameTextBox.Text; + password = passwordTextBox.Text; + + Entities.User loadedUser = Entities.User.LoadUserByName(user); + if (loadedUser != null) + { + bool authorized; + + if (requiredGroupMembership == Grp.GID.Invalid) + { + authorized = loadedUser.Authorize(user, password); + } + else + { + authorized = loadedUser.Authorize(user, password, requiredGroupMembership); + } + + if (authorized) + { + DialogResult = DialogResult.OK; + Close(); + Program.MainWnd.UpdateUser(); + return; + } + } + + MessageBox.Show(Strings.Invalid_username_or_password, Strings.Error, MessageBoxButtons.OK); + DialogResult = DialogResult.None; + return; + } + + /// + /// Cancel clicked, do not try to authorize. + /// + private void cancelButton_Click(object sender, EventArgs e) + { + if (requiredGroupMembership == Grp.GID.Invalid) + { + Entities.User.Unauthorize(); + } + + DialogResult = DialogResult.Cancel; + Close(); + return; + } + } +} diff --git a/TestBenchFramework/LoginDlg.de.resx b/TestBenchFramework/LoginDlg.de.resx new file mode 100644 index 000000000..e161a92e1 --- /dev/null +++ b/TestBenchFramework/LoginDlg.de.resx @@ -0,0 +1,142 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 75, 13 + + + Benutzername + + + 50, 13 + + + Passwort + + + &Abbrechen + + + &OK + + + Anmelden + + \ No newline at end of file diff --git a/TestBenchFramework/LoginDlg.resx b/TestBenchFramework/LoginDlg.resx new file mode 100644 index 000000000..96457b1db --- /dev/null +++ b/TestBenchFramework/LoginDlg.resx @@ -0,0 +1,291 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + True + + + + 8, 24 + + + 58, 13 + + + 0 + + + User name + + + label1 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 5 + + + True + + + 8, 51 + + + 53, 13 + + + 1 + + + Password + + + label2 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 4 + + + 96, 48 + + + 168, 20 + + + 3 + + + passwordTextBox + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 3 + + + 285, 48 + + + 105, 28 + + + 5 + + + Cancel + + + cancelButton + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 2 + + + 285, 14 + + + 105, 28 + + + 4 + + + OK + + + okButton + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 1 + + + 96, 22 + + + 168, 20 + + + 2 + + + userNameTextBox + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 0 + + + de + + + True + + + 6, 13 + + + 402, 88 + + + + CenterScreen + + + User login + + + LoginDlg + + + System.Windows.Forms.Form, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/LoginDlgWithBenchSelection.cs b/TestBenchFramework/LoginDlgWithBenchSelection.cs new file mode 100644 index 000000000..7b9e7d4b4 --- /dev/null +++ b/TestBenchFramework/LoginDlgWithBenchSelection.cs @@ -0,0 +1,111 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Windows.Forms; +using TBF.Resources; + + +namespace TBF +{ + /// + /// Provides login dialog that includes test bench selection. + /// It is used only once on program startup. Does not do authorisation + /// as User.users have not been loadded from the DB yet. + /// + public partial class LoginDlgWithBenchSelection : Form + { + // Private fields + string user; + string password; + string benchName = null; + + // Readonly public properties to do the authorization. + public string User { get { return user; } } + public string Password { get { return password; } } + public string BenchName { get { return benchName; } } + + /// + /// Constructor. + /// + public LoginDlgWithBenchSelection() + { + InitializeComponent(); + } + + /// + /// Constructor with a predefined bench. + /// + public LoginDlgWithBenchSelection(string predefinedBench) + : this() + { + benchName = predefinedBench; + } + + private void LoginDlgWithBenchSelection_Load(object sender, EventArgs e) + { +#if DEBUG + userNameTextBox.Text = Program.AdminUsername; + passwordTextBox.Text = Program.AdminPassword; +#endif + int nrOfBenches = Program.LocalSettings.testBenches == null ? 0 : Program.LocalSettings.testBenches.GetLength(0); + for (int i = 0; i < nrOfBenches; i++) + { + testBenchComboBox.Items.Add(Program.LocalSettings.testBenches[i].BenchName); + if (benchName != null && benchName == Program.LocalSettings.testBenches[i].BenchName) + { + testBenchComboBox.Text = benchName; + } + } + } + + /// + /// OK clicked (authorization is done outside this dialog). + /// + private void okButton_Click(object sender, EventArgs e) + { + if (testBenchComboBox.SelectedItem != null) + { + user = userNameTextBox.Text; + password = passwordTextBox.Text; + benchName = testBenchComboBox.SelectedItem.ToString(); + + DialogResult = DialogResult.OK; + Close(); + return; + } + else + { + MessageBox.Show(Strings.PLs_select_testbench, Strings.Warning, MessageBoxButtons.OK); + } + } + + /// + /// Cancel clicked. + /// + private void cancelButton_Click(object sender, EventArgs e) + { + DialogResult = DialogResult.Cancel; + Close(); + return; + } + + private void passwordTextBox_TextChanged(object sender, EventArgs e) + { + if (passwordTextBox.Text != "") + { + this.AcceptButton = okButton; + } + } + + private void userNameTextBox_KeyPress(object sender, KeyPressEventArgs e) + { + if (Convert.ToInt32(e.KeyChar) == 13) + { + passwordTextBox.Focus(); + } + } + } +} diff --git a/TestBenchFramework/LoginDlgWithBenchSelection.de.resx b/TestBenchFramework/LoginDlgWithBenchSelection.de.resx new file mode 100644 index 000000000..030cbca00 --- /dev/null +++ b/TestBenchFramework/LoginDlgWithBenchSelection.de.resx @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 75, 13 + + + Benutzername + + + 50, 13 + + + Passwort + + + 52, 13 + + + Prüfstand + + + Abbrechen + + + Anmelden am Prüfstand + + \ No newline at end of file diff --git a/TestBenchFramework/LoginDlgWithBenchSelection.designer.cs b/TestBenchFramework/LoginDlgWithBenchSelection.designer.cs new file mode 100644 index 000000000..38d169add --- /dev/null +++ b/TestBenchFramework/LoginDlgWithBenchSelection.designer.cs @@ -0,0 +1,130 @@ +namespace TBF +{ + partial class LoginDlgWithBenchSelection + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(LoginDlgWithBenchSelection)); + this.label1 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.label3 = new System.Windows.Forms.Label(); + this.testBenchComboBox = new System.Windows.Forms.ComboBox(); + this.passwordTextBox = new System.Windows.Forms.TextBox(); + this.cancelButton = new System.Windows.Forms.Button(); + this.okButton = new System.Windows.Forms.Button(); + this.userNameTextBox = new System.Windows.Forms.TextBox(); + this.SuspendLayout(); + // + // label1 + // + resources.ApplyResources(this.label1, "label1"); + this.label1.ImageKey = global::TBF.Resources.Strings.String1; + this.label1.Name = "label1"; + // + // label2 + // + resources.ApplyResources(this.label2, "label2"); + this.label2.ImageKey = global::TBF.Resources.Strings.String1; + this.label2.Name = "label2"; + // + // label3 + // + resources.ApplyResources(this.label3, "label3"); + this.label3.ImageKey = global::TBF.Resources.Strings.String1; + this.label3.Name = "label3"; + // + // testBenchComboBox + // + resources.ApplyResources(this.testBenchComboBox, "testBenchComboBox"); + this.testBenchComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.testBenchComboBox.FormattingEnabled = true; + this.testBenchComboBox.Name = "testBenchComboBox"; + // + // passwordTextBox + // + resources.ApplyResources(this.passwordTextBox, "passwordTextBox"); + this.passwordTextBox.Name = "passwordTextBox"; + this.passwordTextBox.UseSystemPasswordChar = true; + this.passwordTextBox.TextChanged += new System.EventHandler(this.passwordTextBox_TextChanged); + // + // cancelButton + // + resources.ApplyResources(this.cancelButton, "cancelButton"); + this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.cancelButton.ImageKey = global::TBF.Resources.Strings.String1; + this.cancelButton.Name = "cancelButton"; + this.cancelButton.UseVisualStyleBackColor = true; + this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click); + // + // okButton + // + resources.ApplyResources(this.okButton, "okButton"); + this.okButton.DialogResult = System.Windows.Forms.DialogResult.OK; + this.okButton.ImageKey = global::TBF.Resources.Strings.String1; + this.okButton.Name = "okButton"; + this.okButton.UseVisualStyleBackColor = true; + this.okButton.Click += new System.EventHandler(this.okButton_Click); + // + // userNameTextBox + // + resources.ApplyResources(this.userNameTextBox, "userNameTextBox"); + this.userNameTextBox.Name = "userNameTextBox"; + this.userNameTextBox.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.userNameTextBox_KeyPress); + // + // LoginDlgWithBenchSelection + // + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.userNameTextBox); + this.Controls.Add(this.okButton); + this.Controls.Add(this.cancelButton); + this.Controls.Add(this.passwordTextBox); + this.Controls.Add(this.testBenchComboBox); + this.Controls.Add(this.label3); + this.Controls.Add(this.label2); + this.Controls.Add(this.label1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.Name = "LoginDlgWithBenchSelection"; + this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide; + this.Load += new System.EventHandler(this.LoginDlgWithBenchSelection_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.TextBox userNameTextBox; + private System.Windows.Forms.TextBox passwordTextBox; + private System.Windows.Forms.ComboBox testBenchComboBox; + private System.Windows.Forms.Button cancelButton; + private System.Windows.Forms.Button okButton; + } +} \ No newline at end of file diff --git a/TestBenchFramework/LoginDlgWithBenchSelection.resx b/TestBenchFramework/LoginDlgWithBenchSelection.resx new file mode 100644 index 000000000..f44b0b6fe --- /dev/null +++ b/TestBenchFramework/LoginDlgWithBenchSelection.resx @@ -0,0 +1,339 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + User name + + + + 402, 102 + + + 105, 28 + + + 285, 48 + + + Cancel + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + LoginDlgWithBenchSelection + + + label1 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 5 + + + $this + + + 96, 15 + + + 61, 13 + + + $this + + + 96, 67 + + + label3 + + + True + + + + CenterScreen + + + $this + + + 8, 70 + + + 7 + + + 96, 41 + + + userNameTextBox + + + 1 + + + 58, 13 + + + 4 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 3 + + + 6, 13 + + + 6 + + + 53, 13 + + + testBenchComboBox + + + 168, 20 + + + 105, 28 + + + $this + + + 168, 21 + + + 0 + + + 168, 20 + + + 2 + + + 285, 14 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Test bench + + + okButton + + + $this + + + 1 + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + True + + + 3 + + + True + + + label2 + + + $this + + + 4 + + + cancelButton + + + 8, 17 + + + User login + + + passwordTextBox + + + Password + + + 2 + + + 8, 44 + + + 7 + + + OK + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + System.Windows.Forms.Form, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 5 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 6 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 0 + + + True + + + de + + \ No newline at end of file diff --git a/TestBenchFramework/LoginDlgWithBenchSelection.sk.resx b/TestBenchFramework/LoginDlgWithBenchSelection.sk.resx new file mode 100644 index 000000000..07b0af6b5 --- /dev/null +++ b/TestBenchFramework/LoginDlgWithBenchSelection.sk.resx @@ -0,0 +1,157 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 95, 13 + + + Meno používateľa + + + 34, 13 + + + Heslo + + + 97, 13 + + + Testovacia stanica + + + 109, 67 + + + 109, 41 + + + Zrušíť + + + Prihlásiť sa + + + 109, 15 + + + Prihlásenie + + \ No newline at end of file diff --git a/TestBenchFramework/MainWnd.Designer.cs b/TestBenchFramework/MainWnd.Designer.cs new file mode 100644 index 000000000..36c42af1b --- /dev/null +++ b/TestBenchFramework/MainWnd.Designer.cs @@ -0,0 +1,578 @@ +namespace TBF +{ + partial class MainWnd + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + try + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + catch(System.Exception) + { + } + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainWnd)); + this.verticalSplitContainer = new System.Windows.Forms.SplitContainer(); + this.horizontalSplitContainer = new System.Windows.Forms.SplitContainer(); + this.progressGroupBox = new System.Windows.Forms.GroupBox(); + this.mainProgressBar = new System.Windows.Forms.ProgressBar(); + this.activityGroupBox = new System.Windows.Forms.GroupBox(); + this.activityLabel = new System.Windows.Forms.Label(); + this.procedureGroupBox = new System.Windows.Forms.GroupBox(); + this.procedureComboBox = new System.Windows.Forms.ComboBox(); + this.mainTabControl = new System.Windows.Forms.TabControl(); + this.homeTabPage = new System.Windows.Forms.TabPage(); + this.ctrlBrdComponent = new ControlCom2VB.ControlCom2panel(); + this.processTabPage = new System.Windows.Forms.TabPage(); + this.processTabPageCtrl = new TBF.Screens.ProcessTabPageCtrl(); + this.measurementTabPage = new System.Windows.Forms.TabPage(); + this.MeasurementTabPageCtrl = new TBF.Screens.MeasurementTabPageCtrl(); + this.insertTabPage = new System.Windows.Forms.TabPage(); + this.picturesTabPage = new System.Windows.Forms.TabPage(); + this.picturesTabPageCtrl1 = new TBF.Screens.PicturesTabPageCtrl(); + this.resultsTabPage = new System.Windows.Forms.TabPage(); + this.resultsTabPageCtrl = new TBF.Screens.ResultsTabPageCtrl(); + this.logsTabPage = new System.Windows.Forms.TabPage(); + this.logsTabPageCtrl = new TBF.Screens.LogsTabPageCtrl(); + this.rightHorizSplitContainer = new System.Windows.Forms.SplitContainer(); + this.progressFlowLayoutPanel = new System.Windows.Forms.FlowLayoutPanel(); + this.statusStrip1 = new System.Windows.Forms.StatusStrip(); + this.userInfoStatusLabel = new System.Windows.Forms.ToolStripStatusLabel(); + this.activityStatusLabel = new System.Windows.Forms.ToolStripStatusLabel(); + this.benchTSMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.benchComponentsTSMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.benchPathsTSMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.benchTransitionsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.benchMetrologyTSMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); + this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.homeTSMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.measurementTSMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.resultsTSMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.logsTSMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.editTSMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.usersTSMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.localSettingsTSMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.databaseSettingsTSMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.passwortToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.helpTSMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.aboutTSMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.mainMenuStrip = new System.Windows.Forms.MenuStrip(); + this.proceduresToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.processToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.picturesTSMItem = new System.Windows.Forms.ToolStripMenuItem(); + this.resultsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + ((System.ComponentModel.ISupportInitialize)(this.verticalSplitContainer)).BeginInit(); + this.verticalSplitContainer.Panel1.SuspendLayout(); + this.verticalSplitContainer.Panel2.SuspendLayout(); + this.verticalSplitContainer.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.horizontalSplitContainer)).BeginInit(); + this.horizontalSplitContainer.Panel1.SuspendLayout(); + this.horizontalSplitContainer.Panel2.SuspendLayout(); + this.horizontalSplitContainer.SuspendLayout(); + this.progressGroupBox.SuspendLayout(); + this.activityGroupBox.SuspendLayout(); + this.procedureGroupBox.SuspendLayout(); + this.mainTabControl.SuspendLayout(); + this.homeTabPage.SuspendLayout(); + this.processTabPage.SuspendLayout(); + this.measurementTabPage.SuspendLayout(); + this.picturesTabPage.SuspendLayout(); + this.resultsTabPage.SuspendLayout(); + this.logsTabPage.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.rightHorizSplitContainer)).BeginInit(); + this.rightHorizSplitContainer.Panel1.SuspendLayout(); + this.rightHorizSplitContainer.SuspendLayout(); + this.statusStrip1.SuspendLayout(); + this.mainMenuStrip.SuspendLayout(); + this.SuspendLayout(); + // + // verticalSplitContainer + // + resources.ApplyResources(this.verticalSplitContainer, "verticalSplitContainer"); + this.verticalSplitContainer.FixedPanel = System.Windows.Forms.FixedPanel.Panel2; + this.verticalSplitContainer.Name = "verticalSplitContainer"; + // + // verticalSplitContainer.Panel1 + // + this.verticalSplitContainer.Panel1.Controls.Add(this.horizontalSplitContainer); + // + // verticalSplitContainer.Panel2 + // + this.verticalSplitContainer.Panel2.Controls.Add(this.rightHorizSplitContainer); + // + // horizontalSplitContainer + // + resources.ApplyResources(this.horizontalSplitContainer, "horizontalSplitContainer"); + this.horizontalSplitContainer.FixedPanel = System.Windows.Forms.FixedPanel.Panel1; + this.horizontalSplitContainer.Name = "horizontalSplitContainer"; + // + // horizontalSplitContainer.Panel1 + // + this.horizontalSplitContainer.Panel1.BackColor = System.Drawing.SystemColors.Control; + this.horizontalSplitContainer.Panel1.Controls.Add(this.progressGroupBox); + this.horizontalSplitContainer.Panel1.Controls.Add(this.procedureGroupBox); + this.horizontalSplitContainer.Panel1.Controls.Add(this.activityGroupBox); + // + // horizontalSplitContainer.Panel2 + // + this.horizontalSplitContainer.Panel2.Controls.Add(this.mainTabControl); + // + // progressGroupBox + // + this.progressGroupBox.Controls.Add(this.mainProgressBar); + resources.ApplyResources(this.progressGroupBox, "progressGroupBox"); + this.progressGroupBox.Name = "progressGroupBox"; + this.progressGroupBox.TabStop = false; + // + // mainProgressBar + // + resources.ApplyResources(this.mainProgressBar, "mainProgressBar"); + this.mainProgressBar.Name = "mainProgressBar"; + // + // activityGroupBox + // + this.activityGroupBox.Controls.Add(this.activityLabel); + resources.ApplyResources(this.activityGroupBox, "activityGroupBox"); + this.activityGroupBox.Name = "activityGroupBox"; + this.activityGroupBox.TabStop = false; + // + // activityLabel + // + resources.ApplyResources(this.activityLabel, "activityLabel"); + this.activityLabel.Name = "activityLabel"; + // + // procedureGroupBox + // + this.procedureGroupBox.Controls.Add(this.procedureComboBox); + resources.ApplyResources(this.procedureGroupBox, "procedureGroupBox"); + this.procedureGroupBox.Name = "procedureGroupBox"; + this.procedureGroupBox.TabStop = false; + // + // procedureComboBox + // + resources.ApplyResources(this.procedureComboBox, "procedureComboBox"); + this.procedureComboBox.FormattingEnabled = true; + this.procedureComboBox.Name = "procedureComboBox"; + this.procedureComboBox.SelectedIndexChanged += new System.EventHandler(this.procedureComboBox_SelectedIndexChanged); + // + // mainTabControl + // + this.mainTabControl.Controls.Add(this.homeTabPage); + this.mainTabControl.Controls.Add(this.processTabPage); + this.mainTabControl.Controls.Add(this.measurementTabPage); + this.mainTabControl.Controls.Add(this.insertTabPage); + this.mainTabControl.Controls.Add(this.picturesTabPage); + this.mainTabControl.Controls.Add(this.resultsTabPage); + this.mainTabControl.Controls.Add(this.logsTabPage); + resources.ApplyResources(this.mainTabControl, "mainTabControl"); + this.mainTabControl.Name = "mainTabControl"; + this.mainTabControl.SelectedIndex = 0; + this.mainTabControl.SizeMode = System.Windows.Forms.TabSizeMode.Fixed; + // + // homeTabPage + // + this.homeTabPage.BackColor = System.Drawing.SystemColors.Control; + this.homeTabPage.Controls.Add(this.ctrlBrdComponent); + resources.ApplyResources(this.homeTabPage, "homeTabPage"); + this.homeTabPage.Name = "homeTabPage"; + // + // ctrlBrdComponent + // + this.ctrlBrdComponent.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224))))); + resources.ApplyResources(this.ctrlBrdComponent, "ctrlBrdComponent"); + this.ctrlBrdComponent.Name = "ctrlBrdComponent"; + // + // processTabPage + // + this.processTabPage.Controls.Add(this.processTabPageCtrl); + resources.ApplyResources(this.processTabPage, "processTabPage"); + this.processTabPage.Name = "processTabPage"; + this.processTabPage.UseVisualStyleBackColor = true; + // + // processTabPageCtrl + // + this.processTabPageCtrl.BackColor = System.Drawing.SystemColors.Control; + resources.ApplyResources(this.processTabPageCtrl, "processTabPageCtrl"); + this.processTabPageCtrl.Name = "processTabPageCtrl"; + // + // measurementTabPage + // + this.measurementTabPage.Controls.Add(this.MeasurementTabPageCtrl); + resources.ApplyResources(this.measurementTabPage, "measurementTabPage"); + this.measurementTabPage.Name = "measurementTabPage"; + this.measurementTabPage.UseVisualStyleBackColor = true; + // + // MeasurementTabPageCtrl + // + this.MeasurementTabPageCtrl.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(150)))), ((int)(((byte)(180)))), ((int)(((byte)(200))))); + resources.ApplyResources(this.MeasurementTabPageCtrl, "MeasurementTabPageCtrl"); + this.MeasurementTabPageCtrl.Name = "MeasurementTabPageCtrl"; + // + // insertTabPage + // + this.insertTabPage.BackColor = System.Drawing.Color.Silver; + resources.ApplyResources(this.insertTabPage, "insertTabPage"); + this.insertTabPage.Name = "insertTabPage"; + // + // picturesTabPage + // + this.picturesTabPage.Controls.Add(this.picturesTabPageCtrl1); + resources.ApplyResources(this.picturesTabPage, "picturesTabPage"); + this.picturesTabPage.Name = "picturesTabPage"; + this.picturesTabPage.UseVisualStyleBackColor = true; + // + // picturesTabPageCtrl1 + // + this.picturesTabPageCtrl1.BackColor = System.Drawing.Color.Silver; + resources.ApplyResources(this.picturesTabPageCtrl1, "picturesTabPageCtrl1"); + this.picturesTabPageCtrl1.Name = "picturesTabPageCtrl1"; + // + // resultsTabPage + // + this.resultsTabPage.Controls.Add(this.resultsTabPageCtrl); + resources.ApplyResources(this.resultsTabPage, "resultsTabPage"); + this.resultsTabPage.Name = "resultsTabPage"; + this.resultsTabPage.UseVisualStyleBackColor = true; + // + // resultsTabPageCtrl + // + this.resultsTabPageCtrl.BackColor = System.Drawing.SystemColors.Control; + resources.ApplyResources(this.resultsTabPageCtrl, "resultsTabPageCtrl"); + this.resultsTabPageCtrl.Name = "resultsTabPageCtrl"; + // + // logsTabPage + // + this.logsTabPage.Controls.Add(this.logsTabPageCtrl); + resources.ApplyResources(this.logsTabPage, "logsTabPage"); + this.logsTabPage.Name = "logsTabPage"; + this.logsTabPage.UseVisualStyleBackColor = true; + // + // logsTabPageCtrl + // + this.logsTabPageCtrl.BackColor = System.Drawing.SystemColors.Control; + resources.ApplyResources(this.logsTabPageCtrl, "logsTabPageCtrl"); + this.logsTabPageCtrl.Name = "logsTabPageCtrl"; + // + // rightHorizSplitContainer + // + resources.ApplyResources(this.rightHorizSplitContainer, "rightHorizSplitContainer"); + this.rightHorizSplitContainer.FixedPanel = System.Windows.Forms.FixedPanel.Panel1; + this.rightHorizSplitContainer.Name = "rightHorizSplitContainer"; + // + // rightHorizSplitContainer.Panel1 + // + this.rightHorizSplitContainer.Panel1.Controls.Add(this.progressFlowLayoutPanel); + this.rightHorizSplitContainer.SplitterMoved += new System.Windows.Forms.SplitterEventHandler(this.rightHorizSplitContainer_SplitterMoved); + // + // progressFlowLayoutPanel + // + resources.ApplyResources(this.progressFlowLayoutPanel, "progressFlowLayoutPanel"); + this.progressFlowLayoutPanel.BackColor = System.Drawing.SystemColors.Control; + this.progressFlowLayoutPanel.Name = "progressFlowLayoutPanel"; + // + // statusStrip1 + // + this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.userInfoStatusLabel, + this.activityStatusLabel}); + resources.ApplyResources(this.statusStrip1, "statusStrip1"); + this.statusStrip1.Name = "statusStrip1"; + // + // userInfoStatusLabel + // + this.userInfoStatusLabel.Name = "userInfoStatusLabel"; + resources.ApplyResources(this.userInfoStatusLabel, "userInfoStatusLabel"); + // + // activityStatusLabel + // + this.activityStatusLabel.Name = "activityStatusLabel"; + resources.ApplyResources(this.activityStatusLabel, "activityStatusLabel"); + // + // benchTSMenuItem + // + this.benchTSMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.benchComponentsTSMenuItem, + this.benchPathsTSMenuItem, + this.benchTransitionsToolStripMenuItem, + this.benchMetrologyTSMenuItem, + this.toolStripSeparator1, + this.exitToolStripMenuItem}); + this.benchTSMenuItem.Name = "benchTSMenuItem"; + resources.ApplyResources(this.benchTSMenuItem, "benchTSMenuItem"); + // + // benchComponentsTSMenuItem + // + this.benchComponentsTSMenuItem.Name = "benchComponentsTSMenuItem"; + resources.ApplyResources(this.benchComponentsTSMenuItem, "benchComponentsTSMenuItem"); + this.benchComponentsTSMenuItem.Click += new System.EventHandler(this.benchComponentsTSMItem_Click); + // + // benchPathsTSMenuItem + // + this.benchPathsTSMenuItem.Name = "benchPathsTSMenuItem"; + resources.ApplyResources(this.benchPathsTSMenuItem, "benchPathsTSMenuItem"); + this.benchPathsTSMenuItem.Click += new System.EventHandler(this.benchPathsTSMItem_Click); + // + // benchTransitionsToolStripMenuItem + // + this.benchTransitionsToolStripMenuItem.Name = "benchTransitionsToolStripMenuItem"; + resources.ApplyResources(this.benchTransitionsToolStripMenuItem, "benchTransitionsToolStripMenuItem"); + this.benchTransitionsToolStripMenuItem.Click += new System.EventHandler(this.benchTransitionsTSMItem_Click); + // + // benchMetrologyTSMenuItem + // + this.benchMetrologyTSMenuItem.Name = "benchMetrologyTSMenuItem"; + resources.ApplyResources(this.benchMetrologyTSMenuItem, "benchMetrologyTSMenuItem"); + this.benchMetrologyTSMenuItem.Click += new System.EventHandler(this.benchMetrologyTSMItem_Click); + // + // toolStripSeparator1 + // + this.toolStripSeparator1.Name = "toolStripSeparator1"; + resources.ApplyResources(this.toolStripSeparator1, "toolStripSeparator1"); + // + // exitToolStripMenuItem + // + this.exitToolStripMenuItem.Name = "exitToolStripMenuItem"; + resources.ApplyResources(this.exitToolStripMenuItem, "exitToolStripMenuItem"); + this.exitToolStripMenuItem.Click += new System.EventHandler(this.exitToolStripMenuItem_Click); + // + // homeTSMenuItem + // + this.homeTSMenuItem.Name = "homeTSMenuItem"; + resources.ApplyResources(this.homeTSMenuItem, "homeTSMenuItem"); + this.homeTSMenuItem.Click += new System.EventHandler(this.homeTSMenuItem_Click); + // + // measurementTSMenuItem + // + this.measurementTSMenuItem.Name = "measurementTSMenuItem"; + resources.ApplyResources(this.measurementTSMenuItem, "measurementTSMenuItem"); + this.measurementTSMenuItem.Click += new System.EventHandler(this.measurementTSMenuItem_Click); + // + // resultsTSMenuItem + // + this.resultsTSMenuItem.Name = "resultsTSMenuItem"; + resources.ApplyResources(this.resultsTSMenuItem, "resultsTSMenuItem"); + // + // logsTSMenuItem + // + this.logsTSMenuItem.Name = "logsTSMenuItem"; + resources.ApplyResources(this.logsTSMenuItem, "logsTSMenuItem"); + this.logsTSMenuItem.Click += new System.EventHandler(this.logsTSMenuItem_Click); + // + // editTSMenuItem + // + this.editTSMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.usersTSMenuItem, + this.localSettingsTSMenuItem, + this.databaseSettingsTSMenuItem, + this.passwortToolStripMenuItem}); + this.editTSMenuItem.Name = "editTSMenuItem"; + resources.ApplyResources(this.editTSMenuItem, "editTSMenuItem"); + // + // usersTSMenuItem + // + this.usersTSMenuItem.Name = "usersTSMenuItem"; + resources.ApplyResources(this.usersTSMenuItem, "usersTSMenuItem"); + this.usersTSMenuItem.Click += new System.EventHandler(this.usersTSMItem_Click); + // + // localSettingsTSMenuItem + // + this.localSettingsTSMenuItem.Name = "localSettingsTSMenuItem"; + resources.ApplyResources(this.localSettingsTSMenuItem, "localSettingsTSMenuItem"); + this.localSettingsTSMenuItem.Click += new System.EventHandler(this.localSettingsTSMItem_Click); + // + // databaseSettingsTSMenuItem + // + this.databaseSettingsTSMenuItem.Name = "databaseSettingsTSMenuItem"; + resources.ApplyResources(this.databaseSettingsTSMenuItem, "databaseSettingsTSMenuItem"); + this.databaseSettingsTSMenuItem.Click += new System.EventHandler(this.databaseSettingsTSMItem_Click); + // + // passwortToolStripMenuItem + // + this.passwortToolStripMenuItem.Name = "passwortToolStripMenuItem"; + resources.ApplyResources(this.passwortToolStripMenuItem, "passwortToolStripMenuItem"); + // + // helpTSMenuItem + // + this.helpTSMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.aboutTSMenuItem}); + this.helpTSMenuItem.Name = "helpTSMenuItem"; + resources.ApplyResources(this.helpTSMenuItem, "helpTSMenuItem"); + // + // aboutTSMenuItem + // + this.aboutTSMenuItem.Name = "aboutTSMenuItem"; + resources.ApplyResources(this.aboutTSMenuItem, "aboutTSMenuItem"); + this.aboutTSMenuItem.Click += new System.EventHandler(this.aboutTSMItem_Click); + // + // mainMenuStrip + // + this.mainMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.benchTSMenuItem, + this.proceduresToolStripMenuItem, + this.homeTSMenuItem, + this.processToolStripMenuItem, + this.measurementTSMenuItem, + this.picturesTSMItem, + this.resultsToolStripMenuItem, + this.logsTSMenuItem, + this.editTSMenuItem, + this.helpTSMenuItem}); + resources.ApplyResources(this.mainMenuStrip, "mainMenuStrip"); + this.mainMenuStrip.Name = "mainMenuStrip"; + // + // proceduresToolStripMenuItem + // + this.proceduresToolStripMenuItem.Name = "proceduresToolStripMenuItem"; + resources.ApplyResources(this.proceduresToolStripMenuItem, "proceduresToolStripMenuItem"); + this.proceduresToolStripMenuItem.Click += new System.EventHandler(this.proceduresTSMItem_Click); + // + // processToolStripMenuItem + // + this.processToolStripMenuItem.Name = "processToolStripMenuItem"; + resources.ApplyResources(this.processToolStripMenuItem, "processToolStripMenuItem"); + this.processToolStripMenuItem.Click += new System.EventHandler(this.processTSMenuItem_Click); + // + // picturesTSMItem + // + this.picturesTSMItem.Name = "picturesTSMItem"; + resources.ApplyResources(this.picturesTSMItem, "picturesTSMItem"); + this.picturesTSMItem.Click += new System.EventHandler(this.picturesTSMItem_Click); + // + // resultsToolStripMenuItem + // + this.resultsToolStripMenuItem.Name = "resultsToolStripMenuItem"; + resources.ApplyResources(this.resultsToolStripMenuItem, "resultsToolStripMenuItem"); + this.resultsToolStripMenuItem.Click += new System.EventHandler(this.resultsTSMenuItem_Click); + // + // MainWnd + // + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.verticalSplitContainer); + this.Controls.Add(this.statusStrip1); + this.Controls.Add(this.mainMenuStrip); + this.KeyPreview = true; + this.MainMenuStrip = this.mainMenuStrip; + this.Name = "MainWnd"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainWnd_FormClosing); + this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.MainWnd_FormClosed); + this.Load += new System.EventHandler(this.MainWnd_Load); + this.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.MainWnd_KeyPress); + this.verticalSplitContainer.Panel1.ResumeLayout(false); + this.verticalSplitContainer.Panel2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.verticalSplitContainer)).EndInit(); + this.verticalSplitContainer.ResumeLayout(false); + this.horizontalSplitContainer.Panel1.ResumeLayout(false); + this.horizontalSplitContainer.Panel2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.horizontalSplitContainer)).EndInit(); + this.horizontalSplitContainer.ResumeLayout(false); + this.progressGroupBox.ResumeLayout(false); + this.activityGroupBox.ResumeLayout(false); + this.activityGroupBox.PerformLayout(); + this.procedureGroupBox.ResumeLayout(false); + this.mainTabControl.ResumeLayout(false); + this.homeTabPage.ResumeLayout(false); + this.processTabPage.ResumeLayout(false); + this.measurementTabPage.ResumeLayout(false); + this.picturesTabPage.ResumeLayout(false); + this.resultsTabPage.ResumeLayout(false); + this.logsTabPage.ResumeLayout(false); + this.rightHorizSplitContainer.Panel1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.rightHorizSplitContainer)).EndInit(); + this.rightHorizSplitContainer.ResumeLayout(false); + this.statusStrip1.ResumeLayout(false); + this.statusStrip1.PerformLayout(); + this.mainMenuStrip.ResumeLayout(false); + this.mainMenuStrip.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TabControl mainTabControl; + private System.Windows.Forms.TabPage homeTabPage; + private System.Windows.Forms.TabPage measurementTabPage; + private System.Windows.Forms.TabPage insertTabPage; + private System.Windows.Forms.TabPage resultsTabPage; + private System.Windows.Forms.TabPage logsTabPage; + private System.Windows.Forms.StatusStrip statusStrip1; + private System.Windows.Forms.ToolStripStatusLabel userInfoStatusLabel; + private System.Windows.Forms.ToolStripStatusLabel activityStatusLabel; + public Screens.MeasurementTabPageCtrl MeasurementTabPageCtrl; + private Screens.ResultsTabPageCtrl resultsTabPageCtrl; + private Screens.LogsTabPageCtrl logsTabPageCtrl; + +#if DN100 + private ControlCom2VB.ControlCom2panel ctrlBrdComponent; +#elif MUNICH + private ControlComponent3Munich.UserControl1 ctrlBrdComponent; +#elif FUZHOU150 + private ControlComponent3Munich.UserControl1 ctrlBrdComponent; +#endif + + private System.Windows.Forms.ToolStripMenuItem benchTSMenuItem; + private System.Windows.Forms.ToolStripMenuItem homeTSMenuItem; + private System.Windows.Forms.ToolStripMenuItem measurementTSMenuItem; + private System.Windows.Forms.ToolStripMenuItem resultsTSMenuItem; + private System.Windows.Forms.ToolStripMenuItem logsTSMenuItem; + private System.Windows.Forms.ToolStripMenuItem editTSMenuItem; + private System.Windows.Forms.ToolStripMenuItem usersTSMenuItem; + private System.Windows.Forms.ToolStripMenuItem localSettingsTSMenuItem; + private System.Windows.Forms.ToolStripMenuItem databaseSettingsTSMenuItem; + private System.Windows.Forms.ToolStripMenuItem passwortToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem helpTSMenuItem; + private System.Windows.Forms.ToolStripMenuItem aboutTSMenuItem; + private System.Windows.Forms.MenuStrip mainMenuStrip; + private System.Windows.Forms.ToolStripMenuItem benchComponentsTSMenuItem; + private System.Windows.Forms.ToolStripMenuItem benchPathsTSMenuItem; + private System.Windows.Forms.ToolStripMenuItem benchMetrologyTSMenuItem; + private System.Windows.Forms.ToolStripMenuItem proceduresToolStripMenuItem; + private System.Windows.Forms.SplitContainer verticalSplitContainer; + private System.Windows.Forms.SplitContainer horizontalSplitContainer; + private System.Windows.Forms.ToolStripMenuItem processToolStripMenuItem; + private System.Windows.Forms.TabPage processTabPage; + private Screens.ProcessTabPageCtrl processTabPageCtrl; + private System.Windows.Forms.ToolStripMenuItem resultsToolStripMenuItem; + private System.Windows.Forms.SplitContainer rightHorizSplitContainer; + private System.Windows.Forms.FlowLayoutPanel progressFlowLayoutPanel; + private System.Windows.Forms.GroupBox progressGroupBox; + private System.Windows.Forms.ProgressBar mainProgressBar; + private System.Windows.Forms.GroupBox activityGroupBox; + private System.Windows.Forms.Label activityLabel; + private System.Windows.Forms.GroupBox procedureGroupBox; + private System.Windows.Forms.ComboBox procedureComboBox; + private System.Windows.Forms.ToolStripMenuItem benchTransitionsToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem picturesTSMItem; + private System.Windows.Forms.TabPage picturesTabPage; + private Screens.PicturesTabPageCtrl picturesTabPageCtrl1; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator1; + private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem; + } +} + diff --git a/TestBenchFramework/MainWnd.cs b/TestBenchFramework/MainWnd.cs new file mode 100644 index 000000000..6748f2329 --- /dev/null +++ b/TestBenchFramework/MainWnd.cs @@ -0,0 +1,408 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Windows.Forms; +using log4net; +using TBF.Entities; +using TBF.UiBridge; +using TBF.Resources; + +namespace TBF +{ + public partial class MainWnd : Form + { + static readonly ILog log = LogManager.GetLogger(typeof(MainWnd)); + + public UiControls.BenchControlPanel BenchControlPanel; + public string ProcedureName; + public Entities.Procedure CurrentProcedure; + + /// + /// This dialog is shown when emergency stop is activated + /// + TBF.Forms.EmergencyStopForm emergencyStopModelessDlg; + + bool benchInitializationFailed; + TestProgressControls testProgressControls; + + /// + /// Set when procedures are updated while the ProceduresComboBox is disabled (i.e. during a test). + /// Reset when the ProceduresComboBox list of items is successfully reloaded in ReloadProcedures(). + /// This flag is tested when ProcedureComboBox is being enabled in OnButtonsEtc(), + /// optionaly ReloadProcedures() is called. + /// + public bool ProceduresUpdated = false; + + /// + /// MainTabPage ID-s + /// The order of TabPages in this enum must be the same as the order + /// of their additions into the mainTabControl in MainWnd.Designer.cs + /// TODO: Find a better way + /// + public enum MainTabPageId + { + Invalid = -1, + Hydraulics = 0, + Process, + Measurement, + Insert, + Pictures, + Results, + Logs, + TabPagesCount + } + + /// + /// Event handlers switching between tab pages + /// + private void homeTSMenuItem_Click(object sender, EventArgs e) { mainTabControl.SelectTab((int)MainTabPageId.Hydraulics); } + private void processTSMenuItem_Click(object sender, EventArgs e) { mainTabControl.SelectTab((int)MainTabPageId.Process); } + private void measurementTSMenuItem_Click(object sender, EventArgs e) { mainTabControl.SelectTab((int)MainTabPageId.Measurement); } + private void picturesTSMItem_Click(object sender, EventArgs e) { mainTabControl.SelectTab((int)MainTabPageId.Pictures); } + private void resultsTSMenuItem_Click(object sender, EventArgs e) { mainTabControl.SelectTab((int)MainTabPageId.Results); } + private void logsTSMenuItem_Click(object sender, EventArgs e) { mainTabControl.SelectTab((int)MainTabPageId.Logs); } + + /// + /// Constructor + /// + public MainWnd() + { + InitializeComponent(); + + Text = "Test Bench Framework - " + Program.CurrentBench.BenchName + + (Program.CurrentBench.IsRealBench ? "" : Strings._offline); + + usersTSMenuItem.Visible = User.CurrentUser.IsMemberOf(Grp.GID.Administrators) || + User.CurrentUser.IsMemberOf(Grp.GID.HeadOfLab); + + benchInitializationFailed = false; + /// + if (Program.CurrentBench.IsRealBench) + { + try + { + BenchControl.StateMachine.InitializeBoardEtc(ctrlBrdComponent); + testProgressControls = new TestProgressControls(progressFlowLayoutPanel); + } + catch (Exception exc) + { + benchInitializationFailed = true; + log.Fatal("Failed to initialize a test bench component", exc); + MessageBox.Show(exc.Message, Strings.Error, System.Windows.Forms.MessageBoxButtons.OK, + System.Windows.Forms.MessageBoxIcon.Exclamation); + } + } + } + + void Localize() + { + procedureGroupBox.Text = Strings.Procedure; + activityGroupBox.Text = Strings.Activity; + progressGroupBox.Text = Strings.Progress; + } + + /// + /// Initializes this window and its controls + /// + private void MainWnd_Load(object sender, EventArgs e) + { + Localize(); + + if (Program.CurrentBench.IsRealBench && !benchInitializationFailed) + { + try + { + BenchControl.StateMachine.InitializeDevices(); + + //emergencyStopModelessDlg = new TBF.Forms.EmergencyStopForm(); + //emergencyStopModelessDlg.Show(); + + Bridge.ButtonsEtcHandler += delegate(object sndr, ButtonsEtcEventArgs args) + { + if (InvokeRequired) + { + Invoke(new EventHandler(OnButtonsEtc), sndr, args); + } + else OnButtonsEtc(sndr, args); + }; + + Bridge.ActivityHandler += delegate(object sndr, UiBridge.ActivityEventArgs args) + { + if (InvokeRequired) + { + Invoke(new EventHandler(OnActivity), sndr, args); + } + else OnActivity(sndr, args); + }; + + Bridge.StateChangedHandler += delegate(object sndr, UiBridge.StateChangedEventArgs args) + { + if (InvokeRequired) + { + Invoke(new EventHandler(OnStateChanged), sndr, args); + } + else OnStateChanged(sndr, args); + }; + + Bridge.TestProgressHandler += delegate(object sndr, UiBridge.TestProgressEventArgs args) + { + if (InvokeRequired) + { + Invoke(new EventHandler(OnTestProgress), sndr, args); + } + else OnTestProgress(sndr, args); + }; + + Bridge.ProcedureSelectedHandler += delegate(object sndr, UiBridge.ProcedureSelectedEventArgs args) + { + if (InvokeRequired) + { + Invoke(new EventHandler(OnProcedureSelected), sndr, args); + } + else OnProcedureSelected(sndr, args); + }; + } + catch (Exception exc) + { + benchInitializationFailed = true; + log.Fatal("Failed to initialize a test bench component", exc); + MessageBox.Show(exc.Message, Strings.Error, System.Windows.Forms.MessageBoxButtons.OK, + System.Windows.Forms.MessageBoxIcon.Exclamation); + } + } + + procedureComboBox.Text = Program.LocalSettings.LastProcedureName; + ProcedureName = Program.LocalSettings.LastProcedureName; + rightHorizSplitContainer.SplitterDistance = Program.LocalSettings.RightPaneHorizSplitterDistance; + + /// Text boxes for data input, with border and white background + CustomStyle.Set(0, DockStyle.Fill, Color.White, BorderStyle.FixedSingle, false, + new System.Drawing.Font("Verdana", 10.5F, FontStyle.Regular, GraphicsUnit.Point, (byte)(238))); + + // Read only text boxes (labels), its background matches the window background + + /// Measurement + CustomStyle.Set(1, DockStyle.Fill, Color.FromArgb(150, 180, 200), BorderStyle.None, true, + new System.Drawing.Font("Verdana", 10.5F, FontStyle.Regular, GraphicsUnit.Point, (byte)(238))); + + /// Not used + CustomStyle.Set(2, DockStyle.Fill, Color.OliveDrab, BorderStyle.None, true, + new System.Drawing.Font("Verdana", 10.5F, FontStyle.Regular, GraphicsUnit.Point, (byte)(238))); + + /// Procedure + CustomStyle.Set(3, DockStyle.Fill, Color.FromArgb(200, 200, 150), BorderStyle.None, true, + new System.Drawing.Font("Verdana", 10.5F, FontStyle.Regular, GraphicsUnit.Point, (byte)(238))); + + /// Initialize bench control user interface(s) + /// Initialize bench control user interface(s) + BenchControlPanel = new TBF.UiControls.BenchControlPanel(); + BenchControlPanel.BackColor = System.Drawing.Color.LightGray; + new System.ComponentModel.ComponentResourceManager(typeof(MainWnd)).ApplyResources(BenchControlPanel, "benchControlPanel"); + BenchControlPanel.Name = "benchControlPanel"; + rightHorizSplitContainer.Panel2.Controls.Add(BenchControlPanel); + ReloadProcedures(); + + /// Select the initial tab page + mainTabControl.SelectTab((int)MainTabPageId.Hydraulics); + UpdateUser(); + + if (Program.CurrentBench.IsRealBench) + { + if (!benchInitializationFailed) + { + BenchControl.StateMachine.Start(); + log.Info("Test bench started"); + } + else + { + BenchControlPanel.OnButtonsEtc(null, new ButtonsEtcEventArgs(TBF.UiBridge.ButtonsEtc.None)); + MessageBox.Show(Strings.Bench_is_not_running, + Strings.Warning, + System.Windows.Forms.MessageBoxButtons.OK, + System.Windows.Forms.MessageBoxIcon.Exclamation); + } + } + } + + /// + /// Pass any pressed keys to the Bench control panel. + /// Note that MainWnd.KeyPreview must be set to true. + /// + private void MainWnd_KeyPress(object sender, KeyPressEventArgs e) + { + if (BenchControlPanel != null && BenchControlPanel.ProcessKey(e.KeyChar)) + { + e.Handled = true; + } + } + + /// + /// Invoked from the UiBridge to update the activity label. + /// + void OnActivity(object sender, UiBridge.ActivityEventArgs args) + { + activityLabel.Text = args.Activity; + } + + /// + /// Invoked from the UiBridge to update the current state status bar item. + /// + void OnStateChanged(object sender, StateChangedEventArgs args) + { + activityStatusLabel.Text = args.StateChangedMsg; + } + + void OnTestProgress(object sender, UiBridge.TestProgressEventArgs args) + { + mainProgressBar.Value = (int)(100.499f * args.OveralProgress); + } + + void OnProcedureSelected(object sender, UiBridge.ProcedureSelectedEventArgs args) + { + mainProgressBar.Value = 0; + } + + void OnButtonsEtc(object sender, UiBridge.ButtonsEtcEventArgs args) + { + if (((args.Flags & ButtonsEtc.ShowBenchEmpty) != 0) || + ((args.Flags & ButtonsEtc.ShowBenchFilled) != 0)) + { + return; + } + + procedureComboBox.Enabled = ((args.Flags & UiBridge.ButtonsEtc.ProcedureCmbBoxEn) != 0); + + if (procedureComboBox.Enabled && ProceduresUpdated) + { + ReloadProcedures(); + } + } + + public void UpdateUser() + { + userInfoStatusLabel.Text = Strings.User_ + Entities.User.CurrentUser.Name + " , "; + } + + /// + /// Stop the bench when program closes + /// + /// + /// + private void MainWnd_FormClosed(object sender, FormClosedEventArgs e) + { + //BenchControl.StateMachine.Stop(); + } + + private void benchComponentsTSMItem_Click(object s, EventArgs e) { new ComponentsManagerDlg().ShowDialog(); } + private void benchPathsTSMItem_Click(object s, EventArgs e) { new PathsDlg().ShowDialog(); } + private void benchTransitionsTSMItem_Click(object s, EventArgs e) { new TransitionsDlg().ShowDialog(); } + private void benchMetrologyTSMItem_Click(object s, EventArgs e) { new MetrologyDlg().ShowDialog(); } + private void proceduresTSMItem_Click(object s, EventArgs e) { new ProceduresDlg().ShowDialog(); } + private void localSettingsTSMItem_Click(object s, EventArgs e) { new PreferencesDlg().ShowDialog(); } + private void databaseSettingsTSMItem_Click(object s, EventArgs e) { new BenchesDlg().ShowDialog(); } + private void usersTSMItem_Click(object s, EventArgs e) { new Forms.EditUsers().ShowDialog(); } + private void aboutTSMItem_Click(object s, EventArgs e) { new Forms.AboutDlg("1.0", "07.01.2014").ShowDialog(); } + + /// + /// Read the database and re-initialize procedureComboBox items. + /// Try to preserve the original selection. + /// + public void ReloadProcedures() + { + if (procedureComboBox.Enabled) + { + string oriProcName = procedureComboBox.Text; + + IList procedures = FluentCommon.CreateSession(Database.Procedures) + .CreateQuery("FROM Procedure ORDER BY ItemNr") + .List(); + + procedureComboBox.Items.Clear(); + foreach (var proc in procedures) procedureComboBox.Items.Add(proc.Name); + + if (procedureComboBox.Items.Contains(oriProcName)) + { + procedureComboBox.Text = oriProcName; + ProcedureName = oriProcName; + } + else if (procedures.Count > 0) + { + procedureComboBox.Text = procedures[0].Name; + ProcedureName = procedures[0].Name; + } + else + { + procedureComboBox.Text = string.Empty; + ProcedureName = null; + } + + ProceduresUpdated = false; + + BenchControlPanel.ReloadTests(); + } + else + { + ProceduresUpdated = true; + } + } + + private void procedureComboBox_SelectedIndexChanged(object sender, EventArgs e) + { + ProcedureName = procedureComboBox.Text; + BenchControlPanel.ReloadTests(); + if (CurrentProcedure != null && testProgressControls != null) + { + testProgressControls.ProcedureSelectedInUI(this, new UiBridge.ProcedureSelectedEventArgs(CurrentProcedure)); + } + if (!string.IsNullOrEmpty(ProcedureName)) + { + Program.LocalSettings.LastProcedureName = ProcedureName; + Program.LocalSettings.Save(); + } + } + + private void rightHorizSplitContainer_SplitterMoved(object sender, SplitterEventArgs e) + { + Program.LocalSettings.RightPaneHorizSplitterDistance = rightHorizSplitContainer.SplitterDistance; + Program.LocalSettings.Save(); + } + + private void MainWnd_FormClosing(object sender, FormClosingEventArgs e) + { + if (DialogResult == DialogResult.None) + { + exitToolStripMenuItem_Click(sender, e); + } + } + + private void exitToolStripMenuItem_Click(object sender, EventArgs e) + { + bool oriEmgStopState = false; + if (emergencyStopModelessDlg != null) + { + oriEmgStopState = emergencyStopModelessDlg.Visible; + emergencyStopModelessDlg.Visible = false; + } + + if (DialogResult.Yes == MessageBox.Show("Do you want to exit the Test Bench Framework?", "Closing the program", + MessageBoxButtons.YesNo, MessageBoxIcon.Question)) + { + BenchControl.StateMachine.Stop(); + UiBridge.Bridge.OnEmergencyStopChanged(this, UiBridge.EmergencyStopEventArgs.State.CloseForm); + new Forms.ClosingProgram().ShowDialog(); + DialogResult = DialogResult.OK; + Close(); + return; + } + else if (e is FormClosingEventArgs) + { + (e as FormClosingEventArgs).Cancel = true; + } + + if (emergencyStopModelessDlg != null) emergencyStopModelessDlg.Visible = oriEmgStopState; + } + } +} \ No newline at end of file diff --git a/TestBenchFramework/MainWnd.de.resx b/TestBenchFramework/MainWnd.de.resx new file mode 100644 index 000000000..bc36c1826 --- /dev/null +++ b/TestBenchFramework/MainWnd.de.resx @@ -0,0 +1,314 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 1020, 562 + + + 1020, 666 + + + 230, 666 + + + 1254, 666 + + + 1012, 553 + + + 1012, 553 + + + 1012, 553 + + + 1012, 553 + + + 1012, 553 + + + 1012, 553 + + + 1012, 553 + + + 1012, 553 + + + 1012, 553 + + + 1012, 553 + + + 1012, 553 + + + 1012, 553 + + + 1012, 553 + + + 0, 690 + + + 73, 17 + + + User : admin + + + + No + + + 132, 17 + + + Please start a procedure + + + 70, 20 + + + Prüfstand + + + 152, 22 + + + Komponenten + + + 152, 22 + + + Pfade + + + 152, 22 + + + Übergänge + + + 152, 22 + + + Metrologie + + + 149, 6 + + + 152, 22 + + + Beenden + + + 122, 20 + + + Schema-Diagramm + + + 67, 20 + + + Messung + + + 75, 20 + + + Ergebnisse + + + 73, 20 + + + Protokolle + + + 79, 20 + + + Verwaltung + + + 131, 22 + + + Benutzer + + + 131, 22 + + + Sprache + + + 131, 22 + + + Datenbank + + + 131, 22 + + + Passwort + + + Hilfe + + + 99, 22 + + + Über + + + 75, 20 + + + Prüfungen + + + 49, 20 + + + Bilder + + + 70, 20 + + + Ergebnise + + + 1254, 712 + + \ No newline at end of file diff --git a/TestBenchFramework/MainWnd.resx b/TestBenchFramework/MainWnd.resx new file mode 100644 index 000000000..8dc8dfac2 --- /dev/null +++ b/TestBenchFramework/MainWnd.resx @@ -0,0 +1,1203 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + Fill + + + + True + + + + 0, 24 + + + Fill + + + True + + + 0, 0 + + + Horizontal + + + NoControl + + + 6, 25 + + + 237, 33 + + + 0 + + + mainProgressBar + + + System.Windows.Forms.ProgressBar, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + progressGroupBox + + + 0 + + + Verdana, 12pt + + + 767, 15 + + + 249, 68 + + + 19 + + + Progress + + + progressGroupBox + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + horizontalSplitContainer.Panel1 + + + 0 + + + False + + + Verdana, 15.75pt + + + 8, 25 + + + 244, 33 + + + 6 + + + procedureComboBox + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + procedureGroupBox + + + 0 + + + Verdana, 12pt + + + 503, 15 + + + 258, 68 + + + 17 + + + Procedure + + + procedureGroupBox + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + horizontalSplitContainer.Panel1 + + + 1 + + + True + + + Verdana, 15.75pt + + + NoControl + + + 6, 28 + + + 0, 25 + + + 0 + + + activityLabel + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + activityGroupBox + + + 0 + + + Verdana, 12pt + + + 12, 15 + + + 485, 68 + + + 18 + + + Activity + + + activityGroupBox + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + horizontalSplitContainer.Panel1 + + + 2 + + + horizontalSplitContainer.Panel1 + + + System.Windows.Forms.SplitterPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + horizontalSplitContainer + + + 0 + + + Fill + + + 0, 0 + + + 1012, 543 + + + 1 + + + ctrlBrdComponent + + + ControlCom2VB.ControlCom2panel, ControlCom2VB, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + + homeTabPage + + + 0 + + + 4, 5 + + + 1012, 543 + + + 29 + + + Hydraulics + + + homeTabPage + + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + mainTabControl + + + 0 + + + Fill + + + Microsoft Sans Serif, 8.25pt + + + 0, 0 + + + 4, 4, 4, 4 + + + 1012, 543 + + + 1 + + + processTabPageCtrl + + + TBF.Screens.ProcessTabPageCtrl, TBF, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + + processTabPage + + + 0 + + + 4, 5 + + + 1012, 543 + + + 30 + + + Process + + + processTabPage + + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + mainTabControl + + + 1 + + + Fill + + + Verdana, 11.25pt + + + 0, 0 + + + 4, 4, 4, 4 + + + 1012, 543 + + + 0 + + + MeasurementTabPageCtrl + + + TBF.Screens.MeasurementTabPageCtrl, TBF, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + + measurementTabPage + + + 0 + + + 4, 5 + + + 1012, 543 + + + 25 + + + Measurement + + + measurementTabPage + + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + mainTabControl + + + 2 + + + 4, 5 + + + 1012, 543 + + + 22 + + + Insert + + + insertTabPage + + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + mainTabControl + + + 3 + + + Fill + + + Microsoft Sans Serif, 8.25pt + + + 0, 0 + + + 1012, 543 + + + 0 + + + picturesTabPageCtrl1 + + + TBF.Screens.PicturesTabPageCtrl, TBF, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + + picturesTabPage + + + 0 + + + 4, 5 + + + 1012, 543 + + + 31 + + + Pictures + + + picturesTabPage + + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + mainTabControl + + + 4 + + + Fill + + + Microsoft Sans Serif, 8.25pt + + + 0, 0 + + + 4, 4, 4, 4 + + + 1012, 543 + + + 0 + + + resultsTabPageCtrl + + + TBF.Screens.ResultsTabPageCtrl, TBF, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + + resultsTabPage + + + 0 + + + 4, 5 + + + 1012, 543 + + + 15 + + + Results + + + resultsTabPage + + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + mainTabControl + + + 5 + + + Fill + + + Microsoft Sans Serif, 8.25pt + + + 0, 0 + + + 4, 4, 4, 4 + + + 1012, 543 + + + 0 + + + logsTabPageCtrl + + + TBF.Screens.LogsTabPageCtrl, TBF, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + + logsTabPage + + + 0 + + + 4, 5 + + + 1012, 543 + + + 21 + + + Logs + + + logsTabPage + + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + mainTabControl + + + 6 + + + Fill + + + 0, 1 + + + 0, 0 + + + 1020, 552 + + + 1 + + + mainTabControl + + + System.Windows.Forms.TabControl, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + horizontalSplitContainer.Panel2 + + + 0 + + + horizontalSplitContainer.Panel2 + + + System.Windows.Forms.SplitterPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + horizontalSplitContainer + + + 1 + + + 1020, 656 + + + 100 + + + 2 + + + horizontalSplitContainer + + + System.Windows.Forms.SplitContainer, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + verticalSplitContainer.Panel1 + + + 0 + + + verticalSplitContainer.Panel1 + + + System.Windows.Forms.SplitterPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + verticalSplitContainer + + + 0 + + + Fill + + + 0, 0 + + + Horizontal + + + True + + + Fill + + + TopDown + + + 0, 0 + + + 230, 240 + + + 1 + + + False + + + progressFlowLayoutPanel + + + System.Windows.Forms.FlowLayoutPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + rightHorizSplitContainer.Panel1 + + + 0 + + + rightHorizSplitContainer.Panel1 + + + System.Windows.Forms.SplitterPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + rightHorizSplitContainer + + + 0 + + + rightHorizSplitContainer.Panel2 + + + System.Windows.Forms.SplitterPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + rightHorizSplitContainer + + + 1 + + + 230, 656 + + + 240 + + + 0 + + + rightHorizSplitContainer + + + System.Windows.Forms.SplitContainer, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + verticalSplitContainer.Panel2 + + + 0 + + + verticalSplitContainer.Panel2 + + + System.Windows.Forms.SplitterPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + verticalSplitContainer + + + 1 + + + 1254, 656 + + + 1020 + + + 3 + + + verticalSplitContainer + + + System.Windows.Forms.SplitContainer, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 0 + + + 152, 17 + + + 0, 17 + + + 0, 17 + + + 0, 680 + + + 1254, 22 + + + 2 + + + statusStrip1 + + + statusStrip1 + + + System.Windows.Forms.StatusStrip, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 1 + + + 143, 22 + + + Components + + + 143, 22 + + + Paths + + + 143, 22 + + + Transitions + + + 143, 22 + + + Metrology + + + 140, 6 + + + 143, 22 + + + Exit + + + 52, 20 + + + Bench + + + 52, 20 + + + Home + + + 92, 20 + + + Measurement + + + 56, 20 + + + Results + + + 44, 20 + + + Logs + + + 126, 22 + + + Users + + + 126, 22 + + + Language + + + 126, 22 + + + Database + + + 126, 22 + + + Password + + + 61, 20 + + + Settings + + + 107, 22 + + + About + + + 44, 20 + + + Help + + + 17, 17 + + + 78, 20 + + + Procedures + + + 59, 20 + + + Process + + + 61, 20 + + + Pictures + + + 56, 20 + + + Results + + + 0, 0 + + + 1254, 24 + + + 0 + + + mainMenuStrip + + + mainMenuStrip + + + System.Windows.Forms.MenuStrip, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 2 + + + True + + + 25 + + + 6, 13 + + + 1254, 702 + + + Test Bench Framework + + + userInfoStatusLabel + + + System.Windows.Forms.ToolStripStatusLabel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + activityStatusLabel + + + System.Windows.Forms.ToolStripStatusLabel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + benchTSMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + benchComponentsTSMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + benchPathsTSMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + benchTransitionsToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + benchMetrologyTSMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + toolStripSeparator1 + + + System.Windows.Forms.ToolStripSeparator, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + exitToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + homeTSMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + measurementTSMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + resultsTSMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + logsTSMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + editTSMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + usersTSMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + localSettingsTSMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + databaseSettingsTSMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + passwortToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + helpTSMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + aboutTSMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + proceduresToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + processToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + picturesTSMItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + resultsToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + MainWnd + + + System.Windows.Forms.Form, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/Mappings/BenchPathMap.cs b/TestBenchFramework/Mappings/BenchPathMap.cs new file mode 100644 index 000000000..e5a6eb473 --- /dev/null +++ b/TestBenchFramework/Mappings/BenchPathMap.cs @@ -0,0 +1,27 @@ +using FluentNHibernate.Mapping; +using TBF.Entities; + +namespace TBF.Mappings +{ + class BenchPathMap : ClassMap + { + public BenchPathMap() + { + Id(x => x.Id); + Map(x => x.ItemNr); + Map(x => x.Name); + Map(x => x.Qfrom); + Map(x => x.Qto); + Map(x => x.TempIn); + Map(x => x.TempOut); + Map(x => x.PressIn); + Map(x => x.PressOut); + Map(x => x.ValvesOpen) + .CustomType("StringClob") + .CustomSqlType("varchar(8000)"); + Map(x => x.ValvesClose) + .CustomType("StringClob") + .CustomSqlType("varchar(8000)"); + } + } +} diff --git a/TestBenchFramework/Mappings/ComponentMap.cs b/TestBenchFramework/Mappings/ComponentMap.cs new file mode 100644 index 000000000..90082dfbf --- /dev/null +++ b/TestBenchFramework/Mappings/ComponentMap.cs @@ -0,0 +1,25 @@ +using FluentNHibernate.Mapping; +using TBF.Entities; + +namespace TBF.Mappings +{ + class ComponentMap : ClassMap + { + public ComponentMap() + { + Id(x => x.Id); + Map(x => x.Name); + Map(x => x.ClassName); + Map(x => x.ParentName); + Map(x => x.ItemNr); + Map(x => x.Mode); + Map(x => x.Logging); + Map(x => x.Parameters) + .CustomType("StringClob") + .CustomSqlType("varchar(8000)"); + HasMany(x => x.Corrections) + .OrderBy("Measurement") + .Cascade.All(); + } + } +} diff --git a/TestBenchFramework/Mappings/ComponentProcedureMap.cs b/TestBenchFramework/Mappings/ComponentProcedureMap.cs new file mode 100644 index 000000000..12409f4b4 --- /dev/null +++ b/TestBenchFramework/Mappings/ComponentProcedureMap.cs @@ -0,0 +1,19 @@ +using FluentNHibernate.Mapping; +using TBF.Entities; + +namespace TBF.Mappings +{ + class ComponentProcedureMap : ClassMap + { + public ComponentProcedureMap() + { + Id(x => x.Id); + Map(x => x.CmpntName); + Map(x => x.Parameters) + .CustomType("StringClob") + .CustomSqlType("varchar(8000)"); + + References(x => x.Procedure); + } + } +} diff --git a/TestBenchFramework/Mappings/ComponentTestMap.cs b/TestBenchFramework/Mappings/ComponentTestMap.cs new file mode 100644 index 000000000..2b50393d9 --- /dev/null +++ b/TestBenchFramework/Mappings/ComponentTestMap.cs @@ -0,0 +1,19 @@ +using FluentNHibernate.Mapping; +using TBF.Entities; + +namespace TBF.Mappings +{ + class ComponentTestMap : ClassMap + { + public ComponentTestMap() + { + Id(x => x.Id); + Map(x => x.CmpntName); + Map(x => x.Parameters) + .CustomType("StringClob") + .CustomSqlType("varchar(8000)"); + + References(x => x.Test); + } + } +} diff --git a/TestBenchFramework/Mappings/FeedingPathMap.cs b/TestBenchFramework/Mappings/FeedingPathMap.cs new file mode 100644 index 000000000..c58a5ad7a --- /dev/null +++ b/TestBenchFramework/Mappings/FeedingPathMap.cs @@ -0,0 +1,24 @@ +using FluentNHibernate.Mapping; +using TBF.Entities; + +namespace TBF.Mappings +{ + class FeedingPathMap : ClassMap + { + public FeedingPathMap() + { + Id(x => x.Id); + Map(x => x.ItemNr); + Map(x => x.Name); + Map(x => x.Qfrom); + Map(x => x.Qto); + Map(x => x.Pump); + Map(x => x.ValvesOpen) + .CustomType("StringClob") + .CustomSqlType("varchar(8000)"); + Map(x => x.ValvesClose) + .CustomType("StringClob") + .CustomSqlType("varchar(8000)"); + } + } +} diff --git a/TestBenchFramework/Mappings/GroupMap.cs b/TestBenchFramework/Mappings/GroupMap.cs new file mode 100644 index 000000000..17436f8b3 --- /dev/null +++ b/TestBenchFramework/Mappings/GroupMap.cs @@ -0,0 +1,14 @@ +using FluentNHibernate.Mapping; + +namespace TBF.Mappings +{ + class GroupMap : ClassMap + { + public GroupMap() + { + Id(x => x.Id); + Map(x => x.Gid); + Map(x => x.Name); + } + } +} diff --git a/TestBenchFramework/Mappings/MeasurementCorrectionMap.cs b/TestBenchFramework/Mappings/MeasurementCorrectionMap.cs new file mode 100644 index 000000000..42529581e --- /dev/null +++ b/TestBenchFramework/Mappings/MeasurementCorrectionMap.cs @@ -0,0 +1,15 @@ +using FluentNHibernate.Mapping; +using TBF.Entities; + +namespace TBF.Mappings +{ + class MeasurementCorrectionMap : ClassMap + { + public MeasurementCorrectionMap() + { + Id(x => x.Id); + Map(x => x.Measurement); + Map(x => x.Correction); + } + } +} diff --git a/TestBenchFramework/Mappings/MeterTestResultMap.cs b/TestBenchFramework/Mappings/MeterTestResultMap.cs new file mode 100644 index 000000000..a4ddd0417 --- /dev/null +++ b/TestBenchFramework/Mappings/MeterTestResultMap.cs @@ -0,0 +1,23 @@ +using FluentNHibernate.Mapping; +using TBF.Entities; + +namespace TBF.Mappings +{ + class MeterTestResultMap : ClassMap + { + public MeterTestResultMap() + { + Id(x => x.Id); + References(x => x.TestResult); + Map(x => x.SerialNr); + Map(x => x.VolumeStart); + Map(x => x.VolumeEnd); + Map(x => x.VolumeMeter); + Map(x => x.VolumeRef); + Map(x => x.VolumeErrorPct); + Map(x => x.PulsesMeter); + Map(x => x.PulsesMaster); + Map(x => x.Time); + } + } +} diff --git a/TestBenchFramework/Mappings/MetersPathMap.cs b/TestBenchFramework/Mappings/MetersPathMap.cs new file mode 100644 index 000000000..b6672eb9d --- /dev/null +++ b/TestBenchFramework/Mappings/MetersPathMap.cs @@ -0,0 +1,39 @@ +using FluentNHibernate.Mapping; +using TBF.Entities; + +namespace TBF.Mappings +{ + class MetersPathMap : ClassMap + { + public MetersPathMap() + { + Id(x => x.Id); + Map(x => x.ItemNr); + Map(x => x.Name); + Map(x => x.Qfrom); + Map(x => x.Qto); + Map(x => x.Sensor1); +#pragma warning disable + if (Program.WMsCount >= 2) Map(x => x.Sensor2); + if (Program.WMsCount >= 3) Map(x => x.Sensor3); + if (Program.WMsCount >= 4) Map(x => x.Sensor4); + if (Program.WMsCount >= 5) Map(x => x.Sensor5); + if (Program.WMsCount >= 6) Map(x => x.Sensor6); + if (Program.WMsCount >= 7) Map(x => x.Sensor7); + if (Program.WMsCount >= 8) Map(x => x.Sensor8); + if (Program.WMsCount >= 9) Map(x => x.Sensor9); + if (Program.WMsCount >= 10) Map(x => x.Sensor10); + if (Program.WMsCount >= 11) Map(x => x.Sensor11); + if (Program.WMsCount >= 12) Map(x => x.Sensor12); + if (Program.WMsCount >= 13) Map(x => x.Sensor13); + if (Program.WMsCount >= 14) Map(x => x.Sensor14); + if (Program.WMsCount >= 15) Map(x => x.Sensor15); + if (Program.WMsCount >= 16) Map(x => x.Sensor16); + if (Program.WMsCount >= 17) Map(x => x.Sensor17); + if (Program.WMsCount >= 18) Map(x => x.Sensor18); + if (Program.WMsCount >= 19) Map(x => x.Sensor19); + if (Program.WMsCount >= 20) Map(x => x.Sensor20); +#pragma warning restore + } + } +} diff --git a/TestBenchFramework/Mappings/OutputPathMap.cs b/TestBenchFramework/Mappings/OutputPathMap.cs new file mode 100644 index 000000000..5930b5eae --- /dev/null +++ b/TestBenchFramework/Mappings/OutputPathMap.cs @@ -0,0 +1,29 @@ +using FluentNHibernate.Mapping; +using TBF.Entities; + +namespace TBF.Mappings +{ + class OutputPathMap : ClassMap + { + public OutputPathMap() + { + Id(x => x.Id); + Map(x => x.ItemNr); + Map(x => x.Name); + Map(x => x.Qfrom); + Map(x => x.Qto); + Map(x => x.RegulValve); + Map(x => x.FlowMeter); + Map(x => x.Diverter); + Map(x => x.TempDiv); + Map(x => x.Balance); + Map(x => x.EmptyTankValve); + Map(x => x.ValvesOpen) + .CustomType("StringClob") + .CustomSqlType("varchar(8000)"); + Map(x => x.ValvesClose) + .CustomType("StringClob") + .CustomSqlType("varchar(8000)"); + } + } +} diff --git a/TestBenchFramework/Mappings/ProcedureMap.cs b/TestBenchFramework/Mappings/ProcedureMap.cs new file mode 100644 index 000000000..b2e2c7bb8 --- /dev/null +++ b/TestBenchFramework/Mappings/ProcedureMap.cs @@ -0,0 +1,34 @@ +using FluentNHibernate.Mapping; +using TBF.Entities; + +namespace TBF.Mappings +{ + class ProcedureMap : ClassMap + { + public ProcedureMap() + { + Id(x => x.Id); + Map(x => x.ItemNr); + Map(x => x.Name); + Map(x => x.Description); + Map(x => x.CreationUser); + Map(x => x.CreationTime); + Map(x => x.LastChgUser); + Map(x => x.LastChgTime); + Map(x => x.LongDescription); + Map(x => x.Watermeters); + Map(x => x.DataEntry); + Map(x => x.ResultsPrinter); + Map(x => x.ResultsWriter); + Map(x => x.TransitionStart); + Map(x => x.TransitionEnd); + ////Map(x => x.MetrologicalClass); + ////HasOne(x => x.WMType); + HasMany(x => x.MoreParams) + .Cascade.All(); + HasMany(x => x.Tests) + .OrderBy("ItemNr") + .Cascade.All(); + } + } +} diff --git a/TestBenchFramework/Mappings/TestMap.cs b/TestBenchFramework/Mappings/TestMap.cs new file mode 100644 index 000000000..199eac46b --- /dev/null +++ b/TestBenchFramework/Mappings/TestMap.cs @@ -0,0 +1,36 @@ +using FluentNHibernate.Mapping; +using TBF.Entities; + +namespace TBF.Mappings +{ + class TestMap : ClassMap + { + public TestMap() + { + Id(x => x.Id); + Map(x => x.ItemNr); + Map(x => x.Name); + Map(x => x.Qfrom); + Map(x => x.Qto); + Map(x => x.Volume); + Map(x => x.TstTime); + Map(x => x.Repeats); + Map(x => x.Emptying); + Map(x => x.Zeroing); + Map(x => x.Method); + Map(x => x.ErrLimLo); + Map(x => x.ErrLimHi); + Map(x => x.TolerRed); /// ??? + Map(x => x.RedType); /// ??? + Map(x => x.FeedingPath); + Map(x => x.BenchPath); + Map(x => x.OutputPath); + Map(x => x.MetersPath); + Map(x => x.TransitionStart); + Map(x => x.TransitionEnd); + HasMany(x => x.MoreParams) + .Cascade.All(); + References(x => x.Procedure); + } + } +} diff --git a/TestBenchFramework/Mappings/TestResultMap.cs b/TestBenchFramework/Mappings/TestResultMap.cs new file mode 100644 index 000000000..9a90142c8 --- /dev/null +++ b/TestBenchFramework/Mappings/TestResultMap.cs @@ -0,0 +1,93 @@ +using FluentNHibernate.Mapping; +using TBF.Entities; + +namespace TBF.Mappings +{ + class TestResultMap : ClassMap + { + public TestResultMap() + { + Id(x => x.Id); + Map(x => x.Name); + HasMany(x => x.Meters) + .Cascade.All(); + HasMany(x => x.CombinedMeters) + .Cascade.All(); + + Map(x => x.TestName); + Map(x => x.Qfrom); + Map(x => x.Qto); + Map(x => x.Volume); + Map(x => x.TstTime); + Map(x => x.Repeats); + Map(x => x.Emptying); + Map(x => x.Zeroing); + Map(x => x.Method); + Map(x => x.ErrLimLo); + Map(x => x.ErrLimHi); + + Map(x => x.FeedingPath) + .CustomType("StringClob") + .CustomSqlType("varchar(4000)"); + Map(x => x.BenchPath) + .CustomType("StringClob") + .CustomSqlType("varchar(4000)"); + Map(x => x.OutputPath) + .CustomType("StringClob") + .CustomSqlType("varchar(4000)"); + Map(x => x.MetersPath) + .CustomType("StringClob") + .CustomSqlType("varchar(4000)"); + + Map(x => x.TimeStart); + Map(x => x.TimeEnd); + Map(x => x.RepetitionNr); + Map(x => x.AmbientTempAve); + Map(x => x.AmbientPressAve); + Map(x => x.AmbientHumiAve); + Map(x => x.PressInAvrg); + Map(x => x.PressInStart); + Map(x => x.PressInEnd); + Map(x => x.PressOutAvrg); + Map(x => x.PressOutStart); + Map(x => x.PressOutEnd); + Map(x => x.TempInAvrg); + Map(x => x.TempInStart); + Map(x => x.TempInEnd); + Map(x => x.TempOutAvrg); + Map(x => x.TempOutStart); + Map(x => x.TempOutEnd); + Map(x => x.TempDivAvrg); + Map(x => x.TempDivStart); + Map(x => x.TempDivEnd); + Map(x => x.MassStartRaw); + Map(x => x.MassStart); + Map(x => x.MassEndRaw); + Map(x => x.MassEnd); + Map(x => x.MassDiff); + Map(x => x.DensityIn); + Map(x => x.DensityOut); + Map(x => x.DensityDiv); + Map(x => x.FlowMass); /// from conventional true value + Map(x => x.FlowVolume); /// from conventional true value + Map(x => x.VolumeCTV); /// volume conventional true value + Map(x => x.VolumeMaster); /// volume from the master flow meter + Map(x => x.Time); /// measurement time in seconds + Map(x => x.ErrorMaster); + Map(x => x.PulsesMaster); + Map(x => x.ConstMaster); /// Pulses per liter master flow meter + Map(x => x.TimeDivStart0); + Map(x => x.TimeDivStart1); + Map(x => x.TimeDivStart2); + Map(x => x.TimeDivStart3); + Map(x => x.TimeDivStart4); + Map(x => x.TimeDivStart5); + Map(x => x.TimeDivEnd0); + Map(x => x.TimeDivEnd1); + Map(x => x.TimeDivEnd2); + Map(x => x.TimeDivEnd3); + Map(x => x.TimeDivEnd4); + Map(x => x.TimeDivEnd5); + } + } +} diff --git a/TestBenchFramework/Mappings/TransitionSequenceMap.cs b/TestBenchFramework/Mappings/TransitionSequenceMap.cs new file mode 100644 index 000000000..22b5f3f34 --- /dev/null +++ b/TestBenchFramework/Mappings/TransitionSequenceMap.cs @@ -0,0 +1,19 @@ +using FluentNHibernate.Mapping; +using TBF.Entities; + +namespace TBF.Mappings +{ + class TransitionSequenceMap : ClassMap + { + public TransitionSequenceMap() + { + Id(x => x.Id); + Map(x => x.ItemNr); + Map(x => x.Name); + Map(x => x.Description); + HasMany(x => x.TransitionSteps) + .OrderBy("ItemNr") + .Cascade.All(); + } + } +} diff --git a/TestBenchFramework/Mappings/TransitionStepMap.cs b/TestBenchFramework/Mappings/TransitionStepMap.cs new file mode 100644 index 000000000..f729c5422 --- /dev/null +++ b/TestBenchFramework/Mappings/TransitionStepMap.cs @@ -0,0 +1,24 @@ +using FluentNHibernate.Mapping; +using TBF.Entities; + +namespace TBF.Mappings +{ + class TransitionStepMap : ClassMap + { + public TransitionStepMap() + { + Id(x => x.Id); + Map(x => x.ItemNr); + Map(x => x.Duration); + Map(x => x.ValvesOpen) + .CustomType("StringClob") + .CustomSqlType("varchar(8000)"); + Map(x => x.ValvesClose) + .CustomType("StringClob") + .CustomSqlType("varchar(8000)"); + Map(x => x.RegulValvesPct); + + References(x => x.TransitionSequence); + } + } +} diff --git a/TestBenchFramework/Mappings/UserMap.cs b/TestBenchFramework/Mappings/UserMap.cs new file mode 100644 index 000000000..84c0721ad --- /dev/null +++ b/TestBenchFramework/Mappings/UserMap.cs @@ -0,0 +1,18 @@ +using FluentNHibernate.Mapping; + +namespace TBF.Mappings +{ + class UserMap : ClassMap + { + public UserMap() + { + Id(x => x.Id); + Map(x => x.Name); + Map(x => x.Password); + Map(x => x.Description); + Map(x => x.LastPwChange); + HasMany(x => x.Groups) + .Cascade.All(); + } + } +} diff --git a/TestBenchFramework/Mappings/WMTypeMap.cs b/TestBenchFramework/Mappings/WMTypeMap.cs new file mode 100644 index 000000000..8f567a9f2 --- /dev/null +++ b/TestBenchFramework/Mappings/WMTypeMap.cs @@ -0,0 +1,17 @@ +using FluentNHibernate.Mapping; + +namespace TBF.Mappings +{ + class WMTypeMap : ClassMap + { + public WMTypeMap() + { + Id(x => x.Id); + Map(x => x.CreateTime); + Map(x => x.CreateUserName); + Map(x => x.CreateDescription); + Map(x => x.Name); + Map(x => x.PulseRate); + } + } +} diff --git a/TestBenchFramework/Mappings/WatermeterMap.cs b/TestBenchFramework/Mappings/WatermeterMap.cs new file mode 100644 index 000000000..73255819a --- /dev/null +++ b/TestBenchFramework/Mappings/WatermeterMap.cs @@ -0,0 +1,16 @@ +using FluentNHibernate.Mapping; + +namespace TBF.Mappings +{ + class WatermeterMap : ClassMap + { + public WatermeterMap() + { + Id(x => x.Id); + Map(x => x.Serial); + // HasOne(x => x.WMType) + // .Cascade.All(); + References(x => x.WMType); + } + } +} diff --git a/TestBenchFramework/MetrologyDlg.Designer.cs b/TestBenchFramework/MetrologyDlg.Designer.cs new file mode 100644 index 000000000..4d9d70406 --- /dev/null +++ b/TestBenchFramework/MetrologyDlg.Designer.cs @@ -0,0 +1,100 @@ +namespace TBF +{ + partial class MetrologyDlg + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.splitContainer = new System.Windows.Forms.SplitContainer(); + this.metrologyTabControl = new System.Windows.Forms.TabControl(); + this.sharedButtons = new TBF.UiControls.SharedButtons(); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).BeginInit(); + this.splitContainer.Panel1.SuspendLayout(); + this.splitContainer.Panel2.SuspendLayout(); + this.splitContainer.SuspendLayout(); + this.SuspendLayout(); + // + // splitContainer + // + this.splitContainer.Dock = System.Windows.Forms.DockStyle.Fill; + this.splitContainer.FixedPanel = System.Windows.Forms.FixedPanel.Panel2; + this.splitContainer.Location = new System.Drawing.Point(0, 0); + this.splitContainer.Name = "splitContainer"; + // + // splitContainer.Panel1 + // + this.splitContainer.Panel1.Controls.Add(this.metrologyTabControl); + // + // splitContainer.Panel2 + // + this.splitContainer.Panel2.Controls.Add(this.sharedButtons); + this.splitContainer.Size = new System.Drawing.Size(965, 344); + this.splitContainer.SplitterDistance = 863; + this.splitContainer.TabIndex = 0; + // + // metrologyTabControl + // + this.metrologyTabControl.Dock = System.Windows.Forms.DockStyle.Fill; + this.metrologyTabControl.ItemSize = new System.Drawing.Size(60, 30); + this.metrologyTabControl.Location = new System.Drawing.Point(0, 0); + this.metrologyTabControl.Name = "metrologyTabControl"; + this.metrologyTabControl.SelectedIndex = 0; + this.metrologyTabControl.Size = new System.Drawing.Size(863, 344); + this.metrologyTabControl.TabIndex = 0; + this.metrologyTabControl.SelectedIndexChanged += new System.EventHandler(this.metrologyTabControl_SelectedIndexChanged); + // + // sharedButtons + // + this.sharedButtons.Location = new System.Drawing.Point(-2, 0); + this.sharedButtons.Name = "sharedButtons"; + this.sharedButtons.Size = new System.Drawing.Size(100, 400); + this.sharedButtons.TabIndex = 0; + // + // MetrologyDlg + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(965, 344); + this.Controls.Add(this.splitContainer); + this.Name = "MetrologyDlg"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "Metrology"; + this.Load += new System.EventHandler(this.MetrologyDlg_Load); + this.splitContainer.Panel1.ResumeLayout(false); + this.splitContainer.Panel2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).EndInit(); + this.splitContainer.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.SplitContainer splitContainer; + private System.Windows.Forms.TabControl metrologyTabControl; + private UiControls.SharedButtons sharedButtons; + } +} \ No newline at end of file diff --git a/TestBenchFramework/MetrologyDlg.cs b/TestBenchFramework/MetrologyDlg.cs new file mode 100644 index 000000000..6bdaeee6d --- /dev/null +++ b/TestBenchFramework/MetrologyDlg.cs @@ -0,0 +1,145 @@ +using System; +using System.Collections.Generic; +using System.Windows.Forms; +using NHibernate; +using log4net; +using TBF.UiControls; +using TBF.BenchControl; +using TBF.Resources; + +namespace TBF +{ + public partial class MetrologyDlg : Form, IParentOfListViewEx + { + static readonly ILog log = LogManager.GetLogger(typeof(MetrologyDlg)); + + public IList cmpntEntities; + + ISession session; + + public MetrologyDlg() + { + InitializeComponent(); + + /// SharedDlgButtons configuration + sharedButtons.RequiredGroupMembership = Grp.GID.Metrologists; + sharedButtons.OptionalButtons = SharedButtons.Buttons.Add | SharedButtons.Buttons.Remove; + sharedButtons.Unlocked += unlockButton_Click; + sharedButtons.OKClicked += okButton_Click; + sharedButtons.CancelClicked += cancelButton_Click; + sharedButtons.AddClicked += addButton_Click; + sharedButtons.RemoveClicked += removeButton_Click; + } + + private void MetrologyDlg_Load(object sender, EventArgs e) + { + Text = Strings.Metrology; + + int balancesCount = 0; + int flowMetersCount = 0; + int pressMetersCount = 0; + + session = FluentCommon.CreateSession(Database.Bench); + cmpntEntities = session.CreateQuery("FROM Component ORDER BY ItemNr") + .List(); + + foreach (var cmpnt in cmpntEntities) + { + BenchControl.Generic.IComponentFactory factory = TbfComponents.CmpntFactoryFromClassName(cmpnt.ClassName); + + if (factory is BenchControl.MettlerToledo.BalanceFactory || + factory is BenchControl.MettlerToledo.BalanceNewFactory) + { + balancesCount++; + TabPage tabPage = new TabPage(" " + Strings.Balance + " " + balancesCount.ToString() + " "); + MetrologyDlgBalanceTab uiControl = new MetrologyDlgBalanceTab(); + uiControl.MeterEntity = cmpnt; + uiControl.Dock = DockStyle.Fill; + tabPage.Tag = uiControl; + tabPage.Controls.Add(uiControl); + metrologyTabControl.TabPages.Add(tabPage); + } + if (factory is BenchControl.Elde.FlowMeter.FlowMeterFactory) + { + flowMetersCount++; + TabPage tabPage = new TabPage(" " + Strings.Reference + " " + flowMetersCount.ToString() + " "); + MetrologyDlgFlowMeterTab uiControl = new MetrologyDlgFlowMeterTab(); + uiControl.MeterEntity = cmpnt; + uiControl.Dock = DockStyle.Fill; + tabPage.Tag = uiControl; + tabPage.Controls.Add(uiControl); + metrologyTabControl.TabPages.Add(tabPage); + } + if (factory is BenchControl.Elde.PressureMeter.PressureMeterFactory) + { + pressMetersCount++; + TabPage tabPage = new TabPage(" " + Strings.Pressure_meter + pressMetersCount.ToString() + " "); + MetrologyDlgPressMeterTab uiControl = new MetrologyDlgPressMeterTab(); + uiControl.MeterEntity = cmpnt; + uiControl.Dock = DockStyle.Fill; + tabPage.Tag = uiControl; + tabPage.Controls.Add(uiControl); + metrologyTabControl.TabPages.Add(tabPage); + } + } + } + + private void unlockButton_Click(object sender, EventArgs e) + { + foreach (TabPage tabPage in metrologyTabControl.TabPages) + { + (tabPage.Tag as IMetrologyDlgTab).Unlock(); + } + } + + private void okButton_Click(object sender, EventArgs e) + { + foreach (TabPage tabPage in metrologyTabControl.TabPages) + { + IMetrologyDlgTab tab = tabPage.Tag as IMetrologyDlgTab; + tab.OkBtnClicked(); + FluentCommon.SaveToDb(session, tab.MeterEntity); + foreach (var entity in tab.ToBeRemoved) FluentCommon.DeleteFromDb(session, entity); + } + DialogResult = DialogResult.OK; + Close(); + } + + private void cancelButton_Click(object sender, EventArgs e) + { + foreach (TabPage tabPage in metrologyTabControl.TabPages) + { + (tabPage.Tag as IMetrologyDlgTab).CancelBtnClicked(); + } + DialogResult = DialogResult.Cancel; + Close(); + } + + private void addButton_Click(object sender, EventArgs e) + { + (metrologyTabControl.SelectedTab.Tag as IMetrologyDlgTab).AddOne(); + } + + private void removeButton_Click(object sender, EventArgs e) + { + (metrologyTabControl.SelectedTab.Tag as IMetrologyDlgTab).RemoveSelected(); + } + + public void UpdateButtonStates(SharedButtons.SelectedItemPos selectedItemPos) + { + if (selectedItemPos == SharedButtons.SelectedItemPos.None) + { + sharedButtons.DisableButtons(SharedButtons.Buttons.Remove); + } + else + { + sharedButtons.EnableButtons(SharedButtons.Buttons.Remove); + } + } + + private void metrologyTabControl_SelectedIndexChanged(object sender, EventArgs e) + { + sharedButtons.DisableButtons(SharedButtons.Buttons.Remove); + } + } +} diff --git a/TestBenchFramework/MetrologyDlg.resx b/TestBenchFramework/MetrologyDlg.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/TestBenchFramework/MetrologyDlg.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/PathsDlg.Designer.cs b/TestBenchFramework/PathsDlg.Designer.cs new file mode 100644 index 000000000..612523edd --- /dev/null +++ b/TestBenchFramework/PathsDlg.Designer.cs @@ -0,0 +1,190 @@ +namespace TBF +{ + partial class PathsDlg + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(PathsDlg)); + this.splitContainer = new System.Windows.Forms.SplitContainer(); + this.pathsTabControl = new System.Windows.Forms.TabControl(); + this.feedingTabPage = new System.Windows.Forms.TabPage(); + this.pathsFeedingCtrl = new TBF.UiControls.PathsFeedingCtrl(); + this.benchTabPage = new System.Windows.Forms.TabPage(); + this.pathsBenchCtrl = new TBF.UiControls.PathsBenchCtrl(); + this.outputTabPage = new System.Windows.Forms.TabPage(); + this.pathsOutputCtrl = new TBF.UiControls.PathsOutputCtrl(); + this.metersTabPage = new System.Windows.Forms.TabPage(); + this.pathsMetersCtrl = new TBF.UiControls.PathsMetersCtrl(); + this.sharedButtons = new TBF.UiControls.SharedButtons(); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).BeginInit(); + this.splitContainer.Panel1.SuspendLayout(); + this.splitContainer.Panel2.SuspendLayout(); + this.splitContainer.SuspendLayout(); + this.pathsTabControl.SuspendLayout(); + this.feedingTabPage.SuspendLayout(); + this.benchTabPage.SuspendLayout(); + this.outputTabPage.SuspendLayout(); + this.metersTabPage.SuspendLayout(); + this.SuspendLayout(); + // + // splitContainer + // + resources.ApplyResources(this.splitContainer, "splitContainer"); + this.splitContainer.FixedPanel = System.Windows.Forms.FixedPanel.Panel2; + this.splitContainer.Name = "splitContainer"; + // + // splitContainer.Panel1 + // + this.splitContainer.Panel1.Controls.Add(this.pathsTabControl); + // + // splitContainer.Panel2 + // + this.splitContainer.Panel2.Controls.Add(this.sharedButtons); + // + // pathsTabControl + // + this.pathsTabControl.Controls.Add(this.feedingTabPage); + this.pathsTabControl.Controls.Add(this.benchTabPage); + this.pathsTabControl.Controls.Add(this.outputTabPage); + this.pathsTabControl.Controls.Add(this.metersTabPage); + resources.ApplyResources(this.pathsTabControl, "pathsTabControl"); + this.pathsTabControl.Name = "pathsTabControl"; + this.pathsTabControl.SelectedIndex = 0; + this.pathsTabControl.SelectedIndexChanged += new System.EventHandler(this.pathsTabControl_SelectedIndexChanged); + // + // feedingTabPage + // + this.feedingTabPage.Controls.Add(this.pathsFeedingCtrl); + resources.ApplyResources(this.feedingTabPage, "feedingTabPage"); + this.feedingTabPage.Name = "feedingTabPage"; + this.feedingTabPage.UseVisualStyleBackColor = true; + // + // pathsFeedingCtrl + // + resources.ApplyResources(this.pathsFeedingCtrl, "pathsFeedingCtrl"); + this.pathsFeedingCtrl.DoubleClickActivation = false; + this.pathsFeedingCtrl.FullRowSelect = true; + this.pathsFeedingCtrl.GridLines = true; + this.pathsFeedingCtrl.Name = "pathsFeedingCtrl"; + this.pathsFeedingCtrl.UseCompatibleStateImageBehavior = false; + this.pathsFeedingCtrl.View = System.Windows.Forms.View.Details; + this.pathsFeedingCtrl.SelectedIndexChanged += new System.EventHandler(this.SelectedIndexChanged); + // + // benchTabPage + // + this.benchTabPage.Controls.Add(this.pathsBenchCtrl); + resources.ApplyResources(this.benchTabPage, "benchTabPage"); + this.benchTabPage.Name = "benchTabPage"; + this.benchTabPage.UseVisualStyleBackColor = true; + // + // pathsBenchCtrl + // + resources.ApplyResources(this.pathsBenchCtrl, "pathsBenchCtrl"); + this.pathsBenchCtrl.DoubleClickActivation = false; + this.pathsBenchCtrl.FullRowSelect = true; + this.pathsBenchCtrl.GridLines = true; + this.pathsBenchCtrl.Name = "pathsBenchCtrl"; + this.pathsBenchCtrl.UseCompatibleStateImageBehavior = false; + this.pathsBenchCtrl.View = System.Windows.Forms.View.Details; + this.pathsBenchCtrl.SelectedIndexChanged += new System.EventHandler(this.SelectedIndexChanged); + // + // outputTabPage + // + this.outputTabPage.Controls.Add(this.pathsOutputCtrl); + resources.ApplyResources(this.outputTabPage, "outputTabPage"); + this.outputTabPage.Name = "outputTabPage"; + this.outputTabPage.UseVisualStyleBackColor = true; + // + // pathsOutputCtrl + // + resources.ApplyResources(this.pathsOutputCtrl, "pathsOutputCtrl"); + this.pathsOutputCtrl.DoubleClickActivation = false; + this.pathsOutputCtrl.FullRowSelect = true; + this.pathsOutputCtrl.GridLines = true; + this.pathsOutputCtrl.Name = "pathsOutputCtrl"; + this.pathsOutputCtrl.UseCompatibleStateImageBehavior = false; + this.pathsOutputCtrl.View = System.Windows.Forms.View.Details; + this.pathsOutputCtrl.SelectedIndexChanged += new System.EventHandler(this.SelectedIndexChanged); + // + // metersTabPage + // + this.metersTabPage.Controls.Add(this.pathsMetersCtrl); + resources.ApplyResources(this.metersTabPage, "metersTabPage"); + this.metersTabPage.Name = "metersTabPage"; + this.metersTabPage.UseVisualStyleBackColor = true; + // + // pathsMetersCtrl + // + resources.ApplyResources(this.pathsMetersCtrl, "pathsMetersCtrl"); + this.pathsMetersCtrl.DoubleClickActivation = false; + this.pathsMetersCtrl.FullRowSelect = true; + this.pathsMetersCtrl.GridLines = true; + this.pathsMetersCtrl.Name = "pathsMetersCtrl"; + this.pathsMetersCtrl.UseCompatibleStateImageBehavior = false; + this.pathsMetersCtrl.View = System.Windows.Forms.View.Details; + this.pathsMetersCtrl.SelectedIndexChanged += new System.EventHandler(this.SelectedIndexChanged); + // + // sharedButtons + // + resources.ApplyResources(this.sharedButtons, "sharedButtons"); + this.sharedButtons.Name = "sharedButtons"; + // + // PathsDlg + // + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.splitContainer); + this.Name = "PathsDlg"; + this.Load += new System.EventHandler(this.PathsDlg_Load); + this.splitContainer.Panel1.ResumeLayout(false); + this.splitContainer.Panel2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).EndInit(); + this.splitContainer.ResumeLayout(false); + this.pathsTabControl.ResumeLayout(false); + this.feedingTabPage.ResumeLayout(false); + this.benchTabPage.ResumeLayout(false); + this.outputTabPage.ResumeLayout(false); + this.metersTabPage.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.SplitContainer splitContainer; + private System.Windows.Forms.TabControl pathsTabControl; + private System.Windows.Forms.TabPage feedingTabPage; + private System.Windows.Forms.TabPage benchTabPage; + private System.Windows.Forms.TabPage outputTabPage; + private System.Windows.Forms.TabPage metersTabPage; + private UiControls.SharedButtons sharedButtons; + private UiControls.PathsFeedingCtrl pathsFeedingCtrl; + private UiControls.PathsBenchCtrl pathsBenchCtrl; + private UiControls.PathsOutputCtrl pathsOutputCtrl; + private UiControls.PathsMetersCtrl pathsMetersCtrl; + } +} \ No newline at end of file diff --git a/TestBenchFramework/PathsDlg.cs b/TestBenchFramework/PathsDlg.cs new file mode 100644 index 000000000..233d97212 --- /dev/null +++ b/TestBenchFramework/PathsDlg.cs @@ -0,0 +1,178 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Windows.Forms; +using NHibernate; +using log4net; +using TBF.UiControls; +using TBF.BenchControl.GenericDevices; +using TBF.Resources; + +namespace TBF +{ + public partial class PathsDlg : Form, IParentOfListViewEx + { + static readonly ILog log = LogManager.GetLogger(typeof(PathsDlg)); + + enum PathsDlgTabs + { + Feeding, + Bench, + Output, + Meters, + } + + /// Used when re-scaling the dialog: 100% = 96dpi, 125% = 120dpi, 150% = 144dpi + public readonly int Dpi; + public const int Dpi100pct = 96; + + public IList TbfComponents; + public IList Valves; + public ISession Session; /// One common DB session passed also to the controls inside tab pages + + public PathsDlg() + { + /// Detect display setting: 100% = 96dpi, 125% = 120dpi, 150% = 144dpi. + Dpi = (int)this.CreateGraphics().DpiX; + + InitializeComponent(); + + /// SharedDlgButtons configuration + sharedButtons.RequiredGroupMembership = Grp.GID.Metrologists; + sharedButtons.OptionalButtons = SharedButtons.Buttons.Add | SharedButtons.Buttons.Remove | + SharedButtons.Buttons.Up | SharedButtons.Buttons.Down; + sharedButtons.Unlocked += Unlocked; + sharedButtons.OKClicked += okButton_Click; + sharedButtons.CancelClicked += cancelButton_Click; + sharedButtons.AddClicked += addButton_Click; + sharedButtons.RemoveClicked += removeButton_Click; + sharedButtons.UpClicked += upButton_Click; + sharedButtons.DownClicked += downButton_Click; + + /// Load the list of components from the database + TbfComponents = BenchControl.TbfComponents.LoadComponentsFromDB(FluentCommon.CreateSession(Database.Bench)); + + /// Find all master valves + Valves = BenchControl.GenericDevices.ValveBase.MasterValves(TbfComponents); + + /// Create the database session for paths + Session = FluentCommon.CreateSession(Database.Procedures); + + pathsTabControl.TabPages[(int)PathsDlgTabs.Feeding].Tag = pathsFeedingCtrl; + pathsTabControl.TabPages[(int)PathsDlgTabs.Bench].Tag = pathsBenchCtrl; + pathsTabControl.TabPages[(int)PathsDlgTabs.Output].Tag = pathsOutputCtrl; + pathsTabControl.TabPages[(int)PathsDlgTabs.Meters].Tag = pathsMetersCtrl; + + // Requires 'Session' to be created + pathsFeedingCtrl.Initialize(this, pathsTabControl.TabPages[(int)PathsDlgTabs.Feeding]); + pathsBenchCtrl.Initialize(this, pathsTabControl.TabPages[(int)PathsDlgTabs.Bench]); + pathsOutputCtrl.Initialize(this, pathsTabControl.TabPages[(int)PathsDlgTabs.Output]); + pathsMetersCtrl.Initialize(this, pathsTabControl.TabPages[(int)PathsDlgTabs.Meters]); + } + + private void PathsDlg_Load(object sender, EventArgs e) + { + } + + private void Unlocked(object sender, EventArgs e) + { + foreach (TabPage tab in pathsTabControl.TabPages) + { + (tab.Tag as ITabWithListViewEx).Unlock(); + } + } + + private void okButton_Click(object sender, EventArgs e) + { + foreach (TabPage tab in pathsTabControl.TabPages) + { + (tab.Tag as ITabWithListViewEx).OkBtnClicked(); + } + DialogResult = DialogResult.OK; + Close(); + } + + private void cancelButton_Click(object sender, EventArgs e) + { + foreach (TabPage tab in pathsTabControl.TabPages) + { + (tab.Tag as ITabWithListViewEx).CancelBtnClicked(); + } + DialogResult = DialogResult.Cancel; + Close(); + } + + private void addButton_Click(object sender, EventArgs e) + { + (pathsTabControl.SelectedTab.Tag as ITabWithListViewEx).AddOne(); + } + + private void removeButton_Click(object sender, EventArgs e) + { + (pathsTabControl.SelectedTab.Tag as ITabWithListViewEx).RemoveSelected(); + } + + private void upButton_Click(object sender, EventArgs e) + { + (pathsTabControl.SelectedTab.Tag as ITabWithListViewEx).MoveUpSelected(); + } + + private void downButton_Click(object sender, EventArgs e) + { + (pathsTabControl.SelectedTab.Tag as ITabWithListViewEx).MoveDownSelected(); + } + + /// + /// Common part for three xxxListViewEx_SelectedIndexChanged event handlers + /// + /// + void SelectedIndexChanged(object sender, EventArgs e) + { + ListViewEx listViewEx = sender as ListViewEx; + if (listViewEx.SelectedItems.Count != 1) + { + /// No item selected + sharedButtons.DisableButtons(SharedButtons.Buttons.Remove | SharedButtons.Buttons.Up | SharedButtons.Buttons.Down); + } + else if (listViewEx.Items.Count == 1) + { + /// One (the first and the last) item selected + sharedButtons.EnableButtons(SharedButtons.Buttons.Remove); + sharedButtons.DisableButtons(SharedButtons.Buttons.Up | SharedButtons.Buttons.Down); + } + else if (listViewEx.SelectedIndices[0] == 0) + { + /// The first of many items selected + sharedButtons.EnableButtons(SharedButtons.Buttons.Remove | SharedButtons.Buttons.Down); + sharedButtons.DisableButtons(SharedButtons.Buttons.Up); + } + else if (listViewEx.SelectedIndices[0] == (listViewEx.Items.Count - 1)) + { + /// The last of many items selected + sharedButtons.EnableButtons(SharedButtons.Buttons.Remove | SharedButtons.Buttons.Up); + sharedButtons.DisableButtons(SharedButtons.Buttons.Down); + } + else + { + /// One of middle items selected + sharedButtons.EnableButtons(SharedButtons.Buttons.Remove | SharedButtons.Buttons.Up | SharedButtons.Buttons.Down); + } + } + + /// + /// Tab page changed - item is unselected + /// + private void pathsTabControl_SelectedIndexChanged(object sender, EventArgs e) + { + UpdateButtonStates(SharedButtons.SelectedItemPos.None); + } + + public void UpdateButtonStates(SharedButtons.SelectedItemPos selectedItemPos) + { + if (selectedItemPos == SharedButtons.SelectedItemPos.None) + { + sharedButtons.DisableButtons(SharedButtons.Buttons.Remove | SharedButtons.Buttons.Up | SharedButtons.Buttons.Down); + } + } + } +} diff --git a/TestBenchFramework/PathsDlg.de.resx b/TestBenchFramework/PathsDlg.de.resx new file mode 100644 index 000000000..71b5d6fe8 --- /dev/null +++ b/TestBenchFramework/PathsDlg.de.resx @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Speisung + + + Bank + + + Ausgabe + + + Messsensoren + + + Pfade + + \ No newline at end of file diff --git a/TestBenchFramework/PathsDlg.resx b/TestBenchFramework/PathsDlg.resx new file mode 100644 index 000000000..71161813e --- /dev/null +++ b/TestBenchFramework/PathsDlg.resx @@ -0,0 +1,450 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + Fill + + + + True + + + + 0, 0 + + + Fill + + + 3, 3 + + + 825, 271 + + + 0 + + + pathsFeedingCtrl + + + TBF.UiControls.PathsFeedingCtrl, TBF, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + + feedingTabPage + + + 0 + + + 4, 34 + + + 3, 3, 3, 3 + + + 831, 277 + + + 0 + + + Feeding + + + feedingTabPage + + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pathsTabControl + + + 0 + + + Fill + + + 3, 3 + + + 825, 271 + + + 0 + + + pathsBenchCtrl + + + TBF.UiControls.PathsBenchCtrl, TBF, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + + benchTabPage + + + 0 + + + 4, 34 + + + 3, 3, 3, 3 + + + 831, 277 + + + 1 + + + Bench + + + benchTabPage + + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pathsTabControl + + + 1 + + + Fill + + + 3, 3 + + + 825, 271 + + + 0 + + + pathsOutputCtrl + + + TBF.UiControls.PathsOutputCtrl, TBF, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + + outputTabPage + + + 0 + + + 4, 34 + + + 3, 3, 3, 3 + + + 831, 277 + + + 2 + + + Output + + + outputTabPage + + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pathsTabControl + + + 2 + + + Fill + + + 0, 0 + + + 831, 277 + + + 0 + + + pathsMetersCtrl + + + TBF.UiControls.PathsMetersCtrl, TBF, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + + metersTabPage + + + 0 + + + 4, 34 + + + 831, 277 + + + 3 + + + Sensors + + + metersTabPage + + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pathsTabControl + + + 3 + + + Fill + + + 42, 30 + + + 0, 0 + + + 839, 315 + + + 0 + + + pathsTabControl + + + System.Windows.Forms.TabControl, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + splitContainer.Panel1 + + + 0 + + + splitContainer.Panel1 + + + System.Windows.Forms.SplitterPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + splitContainer + + + 0 + + + -2, 0 + + + 100, 521 + + + 0 + + + sharedButtons + + + TBF.UiControls.SharedButtons, TBF, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + + splitContainer.Panel2 + + + 0 + + + splitContainer.Panel2 + + + System.Windows.Forms.SplitterPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + splitContainer + + + 1 + + + 941, 315 + + + 839 + + + 0 + + + splitContainer + + + System.Windows.Forms.SplitContainer, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 0 + + + de + + + True + + + 6, 13 + + + 941, 315 + + + CenterParent + + + Bench - Paths + + + PathsDlg + + + System.Windows.Forms.Form, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/PreferencesDlg.Designer.cs b/TestBenchFramework/PreferencesDlg.Designer.cs new file mode 100644 index 000000000..23065b940 --- /dev/null +++ b/TestBenchFramework/PreferencesDlg.Designer.cs @@ -0,0 +1,90 @@ +namespace TBF +{ + partial class PreferencesDlg + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(PreferencesDlg)); + this.languageLabel = new System.Windows.Forms.Label(); + this.okButton = new System.Windows.Forms.Button(); + this.cancelButton = new System.Windows.Forms.Button(); + this.languageListBox = new System.Windows.Forms.ListBox(); + this.SuspendLayout(); + // + // languageLabel + // + resources.ApplyResources(this.languageLabel, "languageLabel"); + this.languageLabel.Name = "languageLabel"; + // + // okButton + // + this.okButton.DialogResult = System.Windows.Forms.DialogResult.OK; + resources.ApplyResources(this.okButton, "okButton"); + this.okButton.Name = "okButton"; + this.okButton.UseVisualStyleBackColor = true; + this.okButton.Click += new System.EventHandler(this.okButton_Click); + // + // cancelButton + // + this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; + resources.ApplyResources(this.cancelButton, "cancelButton"); + this.cancelButton.Name = "cancelButton"; + this.cancelButton.UseVisualStyleBackColor = true; + this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click); + // + // languageListBox + // + this.languageListBox.FormattingEnabled = true; + resources.ApplyResources(this.languageListBox, "languageListBox"); + this.languageListBox.Name = "languageListBox"; + this.languageListBox.SelectedIndexChanged += new System.EventHandler(this.languageListBox_SelectedIndexChanged); + // + // PreferencesDlg + // + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.languageListBox); + this.Controls.Add(this.okButton); + this.Controls.Add(this.cancelButton); + this.Controls.Add(this.languageLabel); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.Name = "PreferencesDlg"; + this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide; + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label languageLabel; + private System.Windows.Forms.Button okButton; + private System.Windows.Forms.Button cancelButton; + private System.Windows.Forms.ListBox languageListBox; + } +} \ No newline at end of file diff --git a/TestBenchFramework/PreferencesDlg.cs b/TestBenchFramework/PreferencesDlg.cs new file mode 100644 index 000000000..8628f20a2 --- /dev/null +++ b/TestBenchFramework/PreferencesDlg.cs @@ -0,0 +1,71 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Windows.Forms; +using System.Globalization; +using TBF.Resources; + +namespace TBF +{ + /// + /// Dialog to edit local settings that specify UI preferences, language, etc. (S1.1) + /// + public partial class PreferencesDlg : Form + { + // Local copy of 'local settings' initialized to Program.localSettings. + // Dialog modifies this copy and updates Program.localSettings just + // when 'OK' is pressed. + LocalSettings localSettings; + + public PreferencesDlg() + { + localSettings = new LocalSettings(); + localSettings.Assign(Program.LocalSettings); + + InitializeComponent(); + + // Initialize the list box with langauges + for (int i = 0; i < (int)LocalSettings.Languages.Count; i++) + { + languageListBox.Items.Add(((LocalSettings.Languages)i).ToString()); + } + languageListBox.Text = localSettings.Language; + } + + private void languageListBox_SelectedIndexChanged(object sender, EventArgs e) + { + localSettings.Language = ((LocalSettings.Languages)languageListBox.SelectedIndex).ToString(); + } + + /// + /// Update setting, return DialogResult.OK + /// + /// Not used + /// Not used + private void okButton_Click(object sender, EventArgs e) + { + Program.LocalSettings.Assign(localSettings); // Update 'global' local settings + DialogResult = DialogResult.OK; + Close(); + + System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(localSettings.Language); + DialogResult response = MessageBox.Show(Strings.Restart_To_Apply_Changes); + return; + } + + /// + /// Throw away changes, return DialogResult.Cancel + /// + /// Not used + /// Not used + private void cancelButton_Click(object sender, EventArgs e) + { + DialogResult = DialogResult.Cancel; + Close(); + return; + } + } +} \ No newline at end of file diff --git a/TestBenchFramework/PreferencesDlg.de.resx b/TestBenchFramework/PreferencesDlg.de.resx new file mode 100644 index 000000000..b1a0304b9 --- /dev/null +++ b/TestBenchFramework/PreferencesDlg.de.resx @@ -0,0 +1,148 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 12, 13 + + + 47, 13 + + + Sprache + + + 271, 13 + + + &OK + + + 271, 52 + + + &Abbrechen + + + 89, 13 + + + Sprache wählen + + \ No newline at end of file diff --git a/TestBenchFramework/PreferencesDlg.resx b/TestBenchFramework/PreferencesDlg.resx new file mode 100644 index 000000000..adb65a187 --- /dev/null +++ b/TestBenchFramework/PreferencesDlg.resx @@ -0,0 +1,243 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + True + + + + 25, 13 + + + 55, 13 + + + 0 + + + Language + + + languageLabel + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 3 + + + 271, 11 + + + 105, 28 + + + 10 + + + OK + + + okButton + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 1 + + + 271, 45 + + + 105, 28 + + + 9 + + + Cancel + + + cancelButton + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 2 + + + 102, 12 + + + 143, 69 + + + 11 + + + languageListBox + + + System.Windows.Forms.ListBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 0 + + + de + + + True + + + 6, 13 + + + 388, 92 + + + + CenterParent + + + Language + + + PreferencesDlg + + + System.Windows.Forms.Form, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/ProcedureDlg.Designer.cs b/TestBenchFramework/ProcedureDlg.Designer.cs new file mode 100644 index 000000000..505f2ccc6 --- /dev/null +++ b/TestBenchFramework/ProcedureDlg.Designer.cs @@ -0,0 +1,464 @@ +namespace TBF +{ + partial class ProcedureDlg + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ProcedureDlg)); + this.mainSplitContainer = new System.Windows.Forms.SplitContainer(); + this.tabControl = new System.Windows.Forms.TabControl(); + this.generalTabPage = new System.Windows.Forms.TabPage(); + this.transitionEndComboBox = new System.Windows.Forms.ComboBox(); + this.transitionEndLabel = new System.Windows.Forms.Label(); + this.transitionStartComboBox = new System.Windows.Forms.ComboBox(); + this.transitionStartLabel = new System.Windows.Forms.Label(); + this.resultsWriterComboBox = new System.Windows.Forms.ComboBox(); + this.resultsPrinterComboBox = new System.Windows.Forms.ComboBox(); + this.dataEntryComboBox = new System.Windows.Forms.ComboBox(); + this.resultsWriterLabel = new System.Windows.Forms.Label(); + this.resultsPrinterLabel = new System.Windows.Forms.Label(); + this.dataEntryLabel = new System.Windows.Forms.Label(); + this.notesTextBox = new System.Windows.Forms.TextBox(); + this.label18 = new System.Windows.Forms.Label(); + this.watermetersTextBox = new System.Windows.Forms.TextBox(); + this.watermetersLabel = new System.Windows.Forms.Label(); + this.lastChangedOnTextBox = new System.Windows.Forms.TextBox(); + this.label15 = new System.Windows.Forms.Label(); + this.lastChangedByTextBox = new System.Windows.Forms.TextBox(); + this.label16 = new System.Windows.Forms.Label(); + this.createdOnTextBox = new System.Windows.Forms.TextBox(); + this.label14 = new System.Windows.Forms.Label(); + this.createdByTextBox = new System.Windows.Forms.TextBox(); + this.label13 = new System.Windows.Forms.Label(); + this.descriptionTextBox = new System.Windows.Forms.TextBox(); + this.label12 = new System.Windows.Forms.Label(); + this.procNameTextBox = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.historyTabPage = new System.Windows.Forms.TabPage(); + this.historyListViewEx = new TBF.UiControls.ListViewEx(); + this.changedByClmnHdr = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.dateClmnHdr = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.descriptionClmnHdr = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.metrology1TabPage = new System.Windows.Forms.TabPage(); + this.metrology1ListViewEx = new TBF.UiControls.ListViewEx(); + this.metrology2TabPage = new System.Windows.Forms.TabPage(); + this.metrology2ListViewEx = new TBF.UiControls.ListViewEx(); + this.processTabPage = new System.Windows.Forms.TabPage(); + this.processListViewEx = new TBF.UiControls.ListViewEx(); + this.sharedButtons = new TBF.UiControls.SharedButtons(); + ((System.ComponentModel.ISupportInitialize)(this.mainSplitContainer)).BeginInit(); + this.mainSplitContainer.Panel1.SuspendLayout(); + this.mainSplitContainer.Panel2.SuspendLayout(); + this.mainSplitContainer.SuspendLayout(); + this.tabControl.SuspendLayout(); + this.generalTabPage.SuspendLayout(); + this.historyTabPage.SuspendLayout(); + this.metrology1TabPage.SuspendLayout(); + this.metrology2TabPage.SuspendLayout(); + this.processTabPage.SuspendLayout(); + this.SuspendLayout(); + // + // mainSplitContainer + // + resources.ApplyResources(this.mainSplitContainer, "mainSplitContainer"); + this.mainSplitContainer.FixedPanel = System.Windows.Forms.FixedPanel.Panel2; + this.mainSplitContainer.Name = "mainSplitContainer"; + // + // mainSplitContainer.Panel1 + // + this.mainSplitContainer.Panel1.Controls.Add(this.tabControl); + // + // mainSplitContainer.Panel2 + // + this.mainSplitContainer.Panel2.Controls.Add(this.sharedButtons); + // + // tabControl + // + this.tabControl.Controls.Add(this.generalTabPage); + this.tabControl.Controls.Add(this.historyTabPage); + this.tabControl.Controls.Add(this.metrology1TabPage); + this.tabControl.Controls.Add(this.metrology2TabPage); + this.tabControl.Controls.Add(this.processTabPage); + resources.ApplyResources(this.tabControl, "tabControl"); + this.tabControl.Name = "tabControl"; + this.tabControl.SelectedIndex = 0; + this.tabControl.SelectedIndexChanged += new System.EventHandler(this.tabControl_SelectedIndexChanged); + // + // generalTabPage + // + this.generalTabPage.Controls.Add(this.transitionEndComboBox); + this.generalTabPage.Controls.Add(this.transitionEndLabel); + this.generalTabPage.Controls.Add(this.transitionStartComboBox); + this.generalTabPage.Controls.Add(this.transitionStartLabel); + this.generalTabPage.Controls.Add(this.resultsWriterComboBox); + this.generalTabPage.Controls.Add(this.resultsPrinterComboBox); + this.generalTabPage.Controls.Add(this.dataEntryComboBox); + this.generalTabPage.Controls.Add(this.resultsWriterLabel); + this.generalTabPage.Controls.Add(this.resultsPrinterLabel); + this.generalTabPage.Controls.Add(this.dataEntryLabel); + this.generalTabPage.Controls.Add(this.notesTextBox); + this.generalTabPage.Controls.Add(this.label18); + this.generalTabPage.Controls.Add(this.watermetersTextBox); + this.generalTabPage.Controls.Add(this.watermetersLabel); + this.generalTabPage.Controls.Add(this.lastChangedOnTextBox); + this.generalTabPage.Controls.Add(this.label15); + this.generalTabPage.Controls.Add(this.lastChangedByTextBox); + this.generalTabPage.Controls.Add(this.label16); + this.generalTabPage.Controls.Add(this.createdOnTextBox); + this.generalTabPage.Controls.Add(this.label14); + this.generalTabPage.Controls.Add(this.createdByTextBox); + this.generalTabPage.Controls.Add(this.label13); + this.generalTabPage.Controls.Add(this.descriptionTextBox); + this.generalTabPage.Controls.Add(this.label12); + this.generalTabPage.Controls.Add(this.procNameTextBox); + this.generalTabPage.Controls.Add(this.label1); + this.generalTabPage.ImageKey = global::TBF.Resources.Strings.String1; + resources.ApplyResources(this.generalTabPage, "generalTabPage"); + this.generalTabPage.Name = "generalTabPage"; + this.generalTabPage.ToolTipText = global::TBF.Resources.Strings.String1; + this.generalTabPage.UseVisualStyleBackColor = true; + // + // transitionEndComboBox + // + this.transitionEndComboBox.FormattingEnabled = true; + resources.ApplyResources(this.transitionEndComboBox, "transitionEndComboBox"); + this.transitionEndComboBox.Name = "transitionEndComboBox"; + // + // transitionEndLabel + // + resources.ApplyResources(this.transitionEndLabel, "transitionEndLabel"); + this.transitionEndLabel.ImageKey = global::TBF.Resources.Strings.String1; + this.transitionEndLabel.Name = "transitionEndLabel"; + // + // transitionStartComboBox + // + this.transitionStartComboBox.FormattingEnabled = true; + resources.ApplyResources(this.transitionStartComboBox, "transitionStartComboBox"); + this.transitionStartComboBox.Name = "transitionStartComboBox"; + // + // transitionStartLabel + // + resources.ApplyResources(this.transitionStartLabel, "transitionStartLabel"); + this.transitionStartLabel.ImageKey = global::TBF.Resources.Strings.String1; + this.transitionStartLabel.Name = "transitionStartLabel"; + // + // resultsWriterComboBox + // + this.resultsWriterComboBox.FormattingEnabled = true; + resources.ApplyResources(this.resultsWriterComboBox, "resultsWriterComboBox"); + this.resultsWriterComboBox.Name = "resultsWriterComboBox"; + // + // resultsPrinterComboBox + // + this.resultsPrinterComboBox.FormattingEnabled = true; + resources.ApplyResources(this.resultsPrinterComboBox, "resultsPrinterComboBox"); + this.resultsPrinterComboBox.Name = "resultsPrinterComboBox"; + // + // dataEntryComboBox + // + this.dataEntryComboBox.FormattingEnabled = true; + resources.ApplyResources(this.dataEntryComboBox, "dataEntryComboBox"); + this.dataEntryComboBox.Name = "dataEntryComboBox"; + // + // resultsWriterLabel + // + resources.ApplyResources(this.resultsWriterLabel, "resultsWriterLabel"); + this.resultsWriterLabel.ImageKey = global::TBF.Resources.Strings.String1; + this.resultsWriterLabel.Name = "resultsWriterLabel"; + // + // resultsPrinterLabel + // + resources.ApplyResources(this.resultsPrinterLabel, "resultsPrinterLabel"); + this.resultsPrinterLabel.ImageKey = global::TBF.Resources.Strings.String1; + this.resultsPrinterLabel.Name = "resultsPrinterLabel"; + // + // dataEntryLabel + // + resources.ApplyResources(this.dataEntryLabel, "dataEntryLabel"); + this.dataEntryLabel.ImageKey = global::TBF.Resources.Strings.String1; + this.dataEntryLabel.Name = "dataEntryLabel"; + // + // notesTextBox + // + resources.ApplyResources(this.notesTextBox, "notesTextBox"); + this.notesTextBox.Name = "notesTextBox"; + // + // label18 + // + resources.ApplyResources(this.label18, "label18"); + this.label18.ImageKey = global::TBF.Resources.Strings.String1; + this.label18.Name = "label18"; + // + // watermetersTextBox + // + resources.ApplyResources(this.watermetersTextBox, "watermetersTextBox"); + this.watermetersTextBox.Name = "watermetersTextBox"; + // + // watermetersLabel + // + resources.ApplyResources(this.watermetersLabel, "watermetersLabel"); + this.watermetersLabel.ImageKey = global::TBF.Resources.Strings.String1; + this.watermetersLabel.Name = "watermetersLabel"; + // + // lastChangedOnTextBox + // + resources.ApplyResources(this.lastChangedOnTextBox, "lastChangedOnTextBox"); + this.lastChangedOnTextBox.Name = "lastChangedOnTextBox"; + // + // label15 + // + resources.ApplyResources(this.label15, "label15"); + this.label15.ImageKey = global::TBF.Resources.Strings.String1; + this.label15.Name = "label15"; + // + // lastChangedByTextBox + // + resources.ApplyResources(this.lastChangedByTextBox, "lastChangedByTextBox"); + this.lastChangedByTextBox.Name = "lastChangedByTextBox"; + // + // label16 + // + resources.ApplyResources(this.label16, "label16"); + this.label16.ImageKey = global::TBF.Resources.Strings.String1; + this.label16.Name = "label16"; + // + // createdOnTextBox + // + resources.ApplyResources(this.createdOnTextBox, "createdOnTextBox"); + this.createdOnTextBox.Name = "createdOnTextBox"; + // + // label14 + // + resources.ApplyResources(this.label14, "label14"); + this.label14.ImageKey = global::TBF.Resources.Strings.String1; + this.label14.Name = "label14"; + // + // createdByTextBox + // + resources.ApplyResources(this.createdByTextBox, "createdByTextBox"); + this.createdByTextBox.Name = "createdByTextBox"; + // + // label13 + // + resources.ApplyResources(this.label13, "label13"); + this.label13.ImageKey = global::TBF.Resources.Strings.String1; + this.label13.Name = "label13"; + // + // descriptionTextBox + // + resources.ApplyResources(this.descriptionTextBox, "descriptionTextBox"); + this.descriptionTextBox.Name = "descriptionTextBox"; + // + // label12 + // + resources.ApplyResources(this.label12, "label12"); + this.label12.ImageKey = global::TBF.Resources.Strings.String1; + this.label12.Name = "label12"; + // + // procNameTextBox + // + resources.ApplyResources(this.procNameTextBox, "procNameTextBox"); + this.procNameTextBox.Name = "procNameTextBox"; + // + // label1 + // + resources.ApplyResources(this.label1, "label1"); + this.label1.ImageKey = global::TBF.Resources.Strings.String1; + this.label1.Name = "label1"; + // + // historyTabPage + // + this.historyTabPage.Controls.Add(this.historyListViewEx); + this.historyTabPage.ImageKey = global::TBF.Resources.Strings.String1; + resources.ApplyResources(this.historyTabPage, "historyTabPage"); + this.historyTabPage.Name = "historyTabPage"; + this.historyTabPage.ToolTipText = global::TBF.Resources.Strings.String1; + this.historyTabPage.UseVisualStyleBackColor = true; + // + // historyListViewEx + // + this.historyListViewEx.AllowColumnReorder = true; + this.historyListViewEx.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.changedByClmnHdr, + this.dateClmnHdr, + this.descriptionClmnHdr}); + resources.ApplyResources(this.historyListViewEx, "historyListViewEx"); + this.historyListViewEx.DoubleClickActivation = false; + this.historyListViewEx.FullRowSelect = true; + this.historyListViewEx.GridLines = true; + this.historyListViewEx.Name = "historyListViewEx"; + this.historyListViewEx.UseCompatibleStateImageBehavior = false; + this.historyListViewEx.View = System.Windows.Forms.View.Details; + // + // changedByClmnHdr + // + resources.ApplyResources(this.changedByClmnHdr, "changedByClmnHdr"); + // + // dateClmnHdr + // + resources.ApplyResources(this.dateClmnHdr, "dateClmnHdr"); + // + // descriptionClmnHdr + // + resources.ApplyResources(this.descriptionClmnHdr, "descriptionClmnHdr"); + // + // metrology1TabPage + // + this.metrology1TabPage.Controls.Add(this.metrology1ListViewEx); + this.metrology1TabPage.ImageKey = global::TBF.Resources.Strings.String1; + resources.ApplyResources(this.metrology1TabPage, "metrology1TabPage"); + this.metrology1TabPage.Name = "metrology1TabPage"; + this.metrology1TabPage.ToolTipText = global::TBF.Resources.Strings.String1; + this.metrology1TabPage.UseVisualStyleBackColor = true; + // + // metrology1ListViewEx + // + this.metrology1ListViewEx.AllowColumnReorder = true; + resources.ApplyResources(this.metrology1ListViewEx, "metrology1ListViewEx"); + this.metrology1ListViewEx.DoubleClickActivation = false; + this.metrology1ListViewEx.FullRowSelect = true; + this.metrology1ListViewEx.GridLines = true; + this.metrology1ListViewEx.Name = "metrology1ListViewEx"; + this.metrology1ListViewEx.UseCompatibleStateImageBehavior = false; + this.metrology1ListViewEx.View = System.Windows.Forms.View.Details; + this.metrology1ListViewEx.SelectedIndexChanged += new System.EventHandler(this.metrology1ListViewEx_SelectedIndexChanged); + // + // metrology2TabPage + // + this.metrology2TabPage.Controls.Add(this.metrology2ListViewEx); + this.metrology2TabPage.ImageKey = global::TBF.Resources.Strings.String1; + resources.ApplyResources(this.metrology2TabPage, "metrology2TabPage"); + this.metrology2TabPage.Name = "metrology2TabPage"; + this.metrology2TabPage.ToolTipText = global::TBF.Resources.Strings.String1; + this.metrology2TabPage.UseVisualStyleBackColor = true; + // + // metrology2ListViewEx + // + this.metrology2ListViewEx.AllowColumnReorder = true; + resources.ApplyResources(this.metrology2ListViewEx, "metrology2ListViewEx"); + this.metrology2ListViewEx.DoubleClickActivation = false; + this.metrology2ListViewEx.FullRowSelect = true; + this.metrology2ListViewEx.GridLines = true; + this.metrology2ListViewEx.Name = "metrology2ListViewEx"; + this.metrology2ListViewEx.UseCompatibleStateImageBehavior = false; + this.metrology2ListViewEx.View = System.Windows.Forms.View.Details; + this.metrology2ListViewEx.SelectedIndexChanged += new System.EventHandler(this.metrology2ListViewEx_SelectedIndexChanged); + // + // processTabPage + // + this.processTabPage.Controls.Add(this.processListViewEx); + this.processTabPage.ImageKey = global::TBF.Resources.Strings.String1; + resources.ApplyResources(this.processTabPage, "processTabPage"); + this.processTabPage.Name = "processTabPage"; + this.processTabPage.ToolTipText = global::TBF.Resources.Strings.String1; + this.processTabPage.UseVisualStyleBackColor = true; + // + // processListViewEx + // + this.processListViewEx.AllowColumnReorder = true; + resources.ApplyResources(this.processListViewEx, "processListViewEx"); + this.processListViewEx.DoubleClickActivation = false; + this.processListViewEx.FullRowSelect = true; + this.processListViewEx.GridLines = true; + this.processListViewEx.Name = "processListViewEx"; + this.processListViewEx.UseCompatibleStateImageBehavior = false; + this.processListViewEx.View = System.Windows.Forms.View.Details; + this.processListViewEx.SelectedIndexChanged += new System.EventHandler(this.processListViewEx_SelectedIndexChanged); + // + // sharedButtons + // + resources.ApplyResources(this.sharedButtons, "sharedButtons"); + this.sharedButtons.Name = "sharedButtons"; + // + // ProcedureDlg + // + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.mainSplitContainer); + this.Name = "ProcedureDlg"; + this.Load += new System.EventHandler(this.ProcedureDlg_Load); + this.mainSplitContainer.Panel1.ResumeLayout(false); + this.mainSplitContainer.Panel2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.mainSplitContainer)).EndInit(); + this.mainSplitContainer.ResumeLayout(false); + this.tabControl.ResumeLayout(false); + this.generalTabPage.ResumeLayout(false); + this.generalTabPage.PerformLayout(); + this.historyTabPage.ResumeLayout(false); + this.metrology1TabPage.ResumeLayout(false); + this.metrology2TabPage.ResumeLayout(false); + this.processTabPage.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.SplitContainer mainSplitContainer; + private System.Windows.Forms.TabControl tabControl; + private System.Windows.Forms.TabPage historyTabPage; + private UiControls.ListViewEx historyListViewEx; + private System.Windows.Forms.ColumnHeader changedByClmnHdr; + private System.Windows.Forms.ColumnHeader dateClmnHdr; + private System.Windows.Forms.ColumnHeader descriptionClmnHdr; + private System.Windows.Forms.TabPage metrology1TabPage; + private UiControls.ListViewEx metrology1ListViewEx; + private System.Windows.Forms.TabPage metrology2TabPage; + private UiControls.ListViewEx metrology2ListViewEx; + private System.Windows.Forms.TabPage processTabPage; + private UiControls.ListViewEx processListViewEx; + private UiControls.SharedButtons sharedButtons; + private System.Windows.Forms.TabPage generalTabPage; + private System.Windows.Forms.ComboBox resultsWriterComboBox; + private System.Windows.Forms.ComboBox resultsPrinterComboBox; + private System.Windows.Forms.ComboBox dataEntryComboBox; + private System.Windows.Forms.Label resultsWriterLabel; + private System.Windows.Forms.Label resultsPrinterLabel; + private System.Windows.Forms.Label dataEntryLabel; + private System.Windows.Forms.TextBox notesTextBox; + private System.Windows.Forms.Label label18; + private System.Windows.Forms.TextBox watermetersTextBox; + private System.Windows.Forms.Label watermetersLabel; + private System.Windows.Forms.TextBox lastChangedOnTextBox; + private System.Windows.Forms.Label label15; + private System.Windows.Forms.TextBox lastChangedByTextBox; + private System.Windows.Forms.Label label16; + private System.Windows.Forms.TextBox createdOnTextBox; + private System.Windows.Forms.Label label14; + private System.Windows.Forms.TextBox createdByTextBox; + private System.Windows.Forms.Label label13; + private System.Windows.Forms.TextBox descriptionTextBox; + private System.Windows.Forms.Label label12; + private System.Windows.Forms.TextBox procNameTextBox; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.ComboBox transitionEndComboBox; + private System.Windows.Forms.Label transitionEndLabel; + private System.Windows.Forms.ComboBox transitionStartComboBox; + private System.Windows.Forms.Label transitionStartLabel; + + } +} \ No newline at end of file diff --git a/TestBenchFramework/ProcedureDlg.cs b/TestBenchFramework/ProcedureDlg.cs new file mode 100644 index 000000000..b3a8df3f3 --- /dev/null +++ b/TestBenchFramework/ProcedureDlg.cs @@ -0,0 +1,1084 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows.Forms; +using log4net; + +using TBF.BenchControl.Generic; +using TBF.BenchControl.GenericDevices; +using TBF.Entities; +using TBF.Resources; +using TBF.UiControls; + +namespace TBF +{ + public partial class ProcedureDlg : Form, IParentOfListViewEx + { + static readonly ILog log = LogManager.GetLogger(typeof(ProcedureDlg)); + + /// Used when re-scaling the dialog: 100% = 96dpi, 125% = 120dpi, 150% = 144dpi + public readonly int Dpi; + public const int Dpi100pct = 96; + + /// + /// Procedure to be updated by this dialog. + /// Set by the constructor or updated by the parent after creation and before loading. + /// + public Entities.Procedure LoadedProcedure; + + /// Auxiliary public lists used also by user controls in tab pages + public IList TbfComponents; + public IList Valves; + public IList RegulValves; + public IList TestMethods; + public IList UsedTestMethods; + ComboBox methodCBox; + + /// Auxiliary private lists + IList feedingPaths; + IList benchPaths; + IList outputPaths; + IList metersPaths; + IList transitionSequences; + + IList testParamsCtrls; + IList procedureParamsCtrls; + + bool unlocked; + + public ProcedureDlg() + { + /// Detect display setting: 100% = 96dpi, 125% = 120dpi, 150% = 144dpi. + Dpi = (int)this.CreateGraphics().DpiX; + + InitializeComponent(); + + /// SharedDlgButtons configuration + sharedButtons.RequiredGroupMembership = Grp.GID.Metrologists; + sharedButtons.OptionalButtons = SharedButtons.Buttons.Add | SharedButtons.Buttons.Remove | + SharedButtons.Buttons.Up | SharedButtons.Buttons.Down; + sharedButtons.Unlocked += Unlocked; + sharedButtons.OKClicked += okButton_Click; + sharedButtons.CancelClicked += cancelButton_Click; + sharedButtons.AddClicked += addButton_Click; + sharedButtons.RemoveClicked += removeButton_Click; + sharedButtons.UpClicked += upButton_Click; + sharedButtons.DownClicked += downButton_Click; + + /// ListViewEx-es configuration + metrology1ListViewEx.SubItemClicked += new SubItemEventHandler(metrology1ListViewEx_SubItemClicked); + metrology1ListViewEx.SubItemEndEditing += new SubItemEndEditingEventHandler(metrology1ListViewEx_SubItemEndEditing); + + metrology2ListViewEx.SubItemClicked += new SubItemEventHandler(metrology2ListViewEx_SubItemClicked); + metrology2ListViewEx.SubItemEndEditing += new SubItemEndEditingEventHandler(metrology2ListViewEx_SubItemEndEditing); + + processListViewEx.SubItemClicked += new SubItemEventHandler(processListViewEx_SubItemClicked); + processListViewEx.SubItemEndEditing += new SubItemEndEditingEventHandler(processListViewEx_SubItemEndEditing); + } + + public ProcedureDlg(Entities.Procedure procedure) + : this() + { + if (procedure == null) throw new ArgumentNullException("procedure"); + + LoadedProcedure = procedure; + + /// Prepare a list of components and a list of all valves in the test bench + using (NHibernate.ISession session = FluentCommon.CreateSession(Database.Bench)) + { + TbfComponents = BenchControl.TbfComponents.LoadComponentsFromDB(session); + Valves = BenchControl.GenericDevices.ValveBase.MasterValves(TbfComponents); + RegulValves = new List(); + TestMethods = new List(); + foreach (var cmpnt in TbfComponents) + { + if (cmpnt is IRegulValve) RegulValves.Add(cmpnt as IRegulValve); + if (cmpnt is ITestMethod) TestMethods.Add(cmpnt as ITestMethod); + if (cmpnt is IDataEntry) dataEntryComboBox.Items.Add(cmpnt.Cfg.Name); + if (cmpnt is IResultsPrinter) resultsPrinterComboBox.Items.Add(cmpnt.Cfg.Name); + if (cmpnt is IResultsWriter) resultsWriterComboBox.Items.Add(cmpnt.Cfg.Name); + } + } + + /// Loads paths, this must be done before PrepareMetrology12AndProcessTabs() call + using (NHibernate.ISession session = FluentCommon.CreateSession(Database.Procedures)) + { + feedingPaths = session.CreateQuery("FROM FeedingPath").List(); + benchPaths = session.CreateQuery("FROM BenchPath").List(); + outputPaths = session.CreateQuery("FROM OutputPath").List(); + metersPaths = session.CreateQuery("FROM MetersPath").List(); + transitionSequences = session.CreateQuery("FROM TransitionSequence").List(); + } + + transitionStartComboBox.Items.Add("---"); + transitionEndComboBox.Items.Add("---"); + foreach (var trans in transitionSequences) + { + transitionStartComboBox.Items.Add(trans.Name); + transitionEndComboBox.Items.Add(trans.Name); + } + + /// Find all test methods used in this procedure + UsedTestMethods = new List(); + foreach (var test in LoadedProcedure.Tests) + { + ITestMethod method = BenchControl.TbfComponents.FindComponent(test.Method, TbfComponents) as ITestMethod; + if (method != null && !UsedTestMethods.Contains(method)) UsedTestMethods.Add(method); + } + + /// Create a tab with a TestParamsCtrl control for each used test method + testParamsCtrls = new List(); + foreach (var method in UsedTestMethods) + { + if (method.Cfg.Factory.HasTestParams) + { + TabPage nwTab = new TabPage(method.Cfg.Name); + TestParamsCtrl testParamsCtrl = new TestParamsCtrl(this, method, true); + testParamsCtrls.Add(testParamsCtrl); + nwTab.Controls.Add(testParamsCtrl); + this.tabControl.TabPages.Add(nwTab); + } + } + + /// Prepare a list of all meters paths used in this procedure (in any test) + IList usedMPaths = new List(); + foreach (var test in LoadedProcedure.Tests) + { + if (test.MetersPath != null && !usedMPaths.Contains(test.MetersPath)) usedMPaths.Add(test.MetersPath); + } + + /// Create an empty list of ProcedureParamsCtrl controls. + procedureParamsCtrls = new List(); + + /// Create a control for the water meters and add it to the list. + IList waterMeters = new List(); + foreach (var cmpnt in TbfComponents) + { + if (cmpnt is IWaterMeter) waterMeters.Add(cmpnt); + } + TabPage newTab = new TabPage(Strings.Water_meters); + ProcedureParamsCtrl procedureParamsCtrl = new ProcedureParamsCtrl(this, waterMeters, false); + procedureParamsCtrls.Add(procedureParamsCtrl); + newTab.Controls.Add(procedureParamsCtrl); + this.tabControl.TabPages.Add(newTab); + + /// Create controls for each sensors path used in this procedure. + /// Initialize it with its components (sensors or cameras) and add it to the list. + foreach (var usedPathName in usedMPaths) + { + Entities.MetersPath usedPath = null; + try { usedPath = metersPaths.First(x => (x.Name == usedPathName)); } + catch { } + if (usedPath != null) + { + IList cmpntsInMPath = new List(); + for (int i = 0; i < Program.WMsCount; i++) + { + IComponent sensor = TbfComponents.FirstOrDefault(x => (x.Cfg.Name.Equals(usedPath.GetSensor(i)))); + cmpntsInMPath.Add(sensor); + } + + TabPage nwTab = new TabPage(usedPathName); + ProcedureParamsCtrl procParamsCtrl = new ProcedureParamsCtrl(this, cmpntsInMPath, true); + procedureParamsCtrls.Add(procParamsCtrl); + nwTab.Controls.Add(procParamsCtrl); + this.tabControl.TabPages.Add(nwTab); + } + } + + /// Create a control for the printed protocol. + IComponent printer = BenchControl.TbfComponents.FindComponent(LoadedProcedure.ResultsPrinter, TbfComponents); + if (printer != null) + { + IList printers = new List(); + printers.Add(printer); + newTab = new TabPage(Strings.Printer); + procedureParamsCtrl = new ProcedureParamsCtrl(this, printers, false); + procedureParamsCtrls.Add(procedureParamsCtrl); + newTab.Controls.Add(procedureParamsCtrl); + this.tabControl.TabPages.Add(newTab); + } + + /// Create a control for another component with Test parameters which was not handled yet + foreach (var cmpnt in TbfComponents) + { + if (cmpnt.Cfg.Factory.HasTestParams && !(cmpnt is ITestMethod)) + { + newTab = new TabPage(cmpnt.Cfg.Name); + TestParamsCtrl testParamsCtrl = new TestParamsCtrl(this, cmpnt, true); + testParamsCtrls.Add(testParamsCtrl); + newTab.Controls.Add(testParamsCtrl); + this.tabControl.TabPages.Add(newTab); + } + } + } + + private void ProcedureDlg_Load(object sender, EventArgs e) + { + if (LoadedProcedure == null) return; /// return in case the dialog is open in the designer + + /// Create LisViewEx columns and edit controls for 'Metrology1', 'Metrology2' and 'Process' tabs + PrepareMetrology12AndProcessTabs(); + + /// Disable controls in General tab + procNameTextBox.Enabled = false; + descriptionTextBox.Enabled = false; + watermetersTextBox.Enabled = false; + dataEntryComboBox.Enabled = false; + resultsPrinterComboBox.Enabled = false; + resultsWriterComboBox.Enabled = false; + transitionStartComboBox.Enabled = false; + transitionEndComboBox.Enabled = false; + notesTextBox.Enabled = false; + + /// Make some controls readonly + createdByTextBox.ReadOnly = true; + createdOnTextBox.ReadOnly = true; + lastChangedByTextBox.ReadOnly = true; + lastChangedOnTextBox.ReadOnly = true; + + /// Now refresh the content of the dialog + foreach (var ctrl in testParamsCtrls) + { + ctrl.Initialize(); + } + foreach (var ctrl in procedureParamsCtrls) + { + ctrl.Initialize(); + } + RefreshAllTabs(); + } + + void RefreshAllTabs() + { + RefreshGeneralTab(); + RefreshMetrology12AndProcessTabs(); + } + + + #region General + + void RefreshGeneralTab() + { + procNameTextBox.Text = LoadedProcedure.Name; + Text = string.Format("{0} '{1}'", Strings.Procedure, LoadedProcedure.Name); + + descriptionTextBox.Text = LoadedProcedure.Description; + createdByTextBox.Text = LoadedProcedure.CreationUser; + createdOnTextBox.Text = LoadedProcedure.CreationTime.ToShortDateString(); + lastChangedByTextBox.Text = LoadedProcedure.LastChgUser; + if (LoadedProcedure.LastChgTime > LoadedProcedure.CreationTime) + { + lastChangedOnTextBox.Text = LoadedProcedure.LastChgTime.ToShortDateString(); + } + notesTextBox.Text = LoadedProcedure.LongDescription; + dataEntryComboBox.Text = LoadedProcedure.DataEntry; + resultsPrinterComboBox.Text = LoadedProcedure.ResultsPrinter; + resultsWriterComboBox.Text = LoadedProcedure.ResultsWriter; + transitionStartComboBox.Text = string.IsNullOrEmpty(LoadedProcedure.TransitionStart) ? "---" : LoadedProcedure.TransitionStart; + transitionEndComboBox.Text = string.IsNullOrEmpty(LoadedProcedure.TransitionEnd) ? "---" : LoadedProcedure.TransitionEnd; + } + + void UpdateFromGeneralTab() + { + LoadedProcedure.Name = procNameTextBox.Text; + Text = string.Format("{0} '{1}'", Strings.Procedure, LoadedProcedure.Name); + + LoadedProcedure.Description = descriptionTextBox.Text; + LoadedProcedure.LastChgUser = User.CurrentUser.Name; + LoadedProcedure.LastChgTime = DateTime.Now; + LoadedProcedure.LongDescription = notesTextBox.Text; + LoadedProcedure.Watermeters = watermetersTextBox.Text; + float ppl; + if (dataEntryComboBox.Items.Contains(dataEntryComboBox.Text)) { LoadedProcedure.DataEntry = dataEntryComboBox.Text; } + if (resultsPrinterComboBox.Items.Contains(resultsPrinterComboBox.Text)) { LoadedProcedure.ResultsPrinter = resultsPrinterComboBox.Text; } + if (resultsWriterComboBox.Items.Contains(resultsWriterComboBox.Text)) { LoadedProcedure.ResultsWriter = resultsWriterComboBox.Text; } + if (transitionStartComboBox.Items.Contains(transitionStartComboBox.Text)) + { + LoadedProcedure.TransitionStart = transitionStartComboBox.Text.Equals("---") ? string.Empty : transitionStartComboBox.Text; + } + if (transitionEndComboBox.Items.Contains(transitionEndComboBox.Text)) + { + LoadedProcedure.TransitionEnd = transitionEndComboBox.Text.Equals("---") ? string.Empty : transitionEndComboBox.Text; + } + } + + #endregion + + #region Metrology12 and Process + + Control[] metrology1Editors; + Control[] metrology2Editors; + Control[] processEditors; + + void PrepareMetrology12AndProcessTabs() + { + metrology1ListViewEx.Columns.Add(new ColumnHeader { Text = Strings.Test_chdr, Width = 70 }); + metrology1ListViewEx.Columns.Add(new ColumnHeader { Text = Strings.Q_from_m3h, Width = 80 }); + metrology1ListViewEx.Columns.Add(new ColumnHeader { Text = Strings.Q_to_m3h, Width = 80 }); + metrology1ListViewEx.Columns.Add(new ColumnHeader { Text = Strings.Volume_ltr_chdr, Width = 70 }); + metrology1ListViewEx.Columns.Add(new ColumnHeader { Text = Strings.Test_time_s_chdr, Width = 70 }); + metrology1ListViewEx.Columns.Add(new ColumnHeader { Text = Strings.Repeats_nr_chdr, Width = 80 }); + metrology1ListViewEx.Columns.Add(new ColumnHeader { Text = Strings.Emptying_chdr, Width = 60 }); + metrology1ListViewEx.Columns.Add(new ColumnHeader { Text = Strings.Zeroing_chdr, Width = 50 }); + metrology1ListViewEx.Columns.Add(new ColumnHeader { Text = Strings.Method_chdr, Width = 150 }); + //metrology1ListViewEx.Columns.Add(new ColumnHeader { Text = Strings.Q_set_method_chdr, Width = 100 }); + //metrology1ListViewEx.Columns.Add(new ColumnHeader { Text = Strings.Method1_chdr, Width = 100 }); + //metrology1ListViewEx.Columns.Add(new ColumnHeader { Text = Strings.Method2_chdr, Width = 110 }); + + metrology2ListViewEx.Columns.Add(new ColumnHeader { Text = Strings.Test_chdr, Width = 70 }); + metrology2ListViewEx.Columns.Add(new ColumnHeader { Text = Strings.Q_from_m3h, Width = 80 }); + metrology2ListViewEx.Columns.Add(new ColumnHeader { Text = Strings.Q_to_m3h, Width = 80 }); + metrology2ListViewEx.Columns.Add(new ColumnHeader { Text = Strings.Err_limit_neg_pct_chdr, Width = 100 }); + metrology2ListViewEx.Columns.Add(new ColumnHeader { Text = Strings.Err_limit_pos_pct_chdr, Width = 100 }); + metrology2ListViewEx.Columns.Add(new ColumnHeader { Text = Strings.Tol_red_pct_chdr, Width = 80 }); + metrology2ListViewEx.Columns.Add(new ColumnHeader { Text = Strings.Red_type_chdr, Width = 80 }); + metrology2ListViewEx.Columns.Add(new ColumnHeader { Text = Strings.Err_cor_neg_pct_chdr, Width = 90 }); + metrology2ListViewEx.Columns.Add(new ColumnHeader { Text = Strings.Err_cor_pos_pct_chdr, Width = 90 }); + + processListViewEx.Columns.Add(new ColumnHeader { Text = Strings.Test_chdr, Width = 70 }); + processListViewEx.Columns.Add(new ColumnHeader { Text = Strings.Q_from_m3h, Width = 80 }); + processListViewEx.Columns.Add(new ColumnHeader { Text = Strings.Q_to_m3h, Width = 80 }); + processListViewEx.Columns.Add(new ColumnHeader { Text = Strings.Feeding_chdr, Width = 90 }); + processListViewEx.Columns.Add(new ColumnHeader { Text = Strings.Bench_chdr, Width = 90 }); + processListViewEx.Columns.Add(new ColumnHeader { Text = Strings.Output_chdr, Width = 90 }); + processListViewEx.Columns.Add(new ColumnHeader { Text = Strings.Sensors_chdr, Width = 90 }); + processListViewEx.Columns.Add(new ColumnHeader { Text = Strings.TransitionStart_chdr, Width = 100 }); + processListViewEx.Columns.Add(new ColumnHeader { Text = Strings.TransitionEnd_chdr, Width = 100 }); + + ComboBox yesNo1CBox = new ComboBox(); + yesNo1CBox.Items.Add(Strings.yes); + yesNo1CBox.Items.Add(Strings.no); + + ComboBox yesNo2CBox = new ComboBox(); + yesNo2CBox.Items.Add(Strings.yes); + yesNo2CBox.Items.Add(Strings.no); + + methodCBox = new ComboBox(); + foreach (var m in TestMethods) methodCBox.Items.Add(m.Cfg.Name); + + //ComboBox qmethod = new ComboBox(); + //for (Entities.QSetMethod method = 0; method < Entities.QSetMethod.Count; method++) qmethod.Items.Add(method.ToString()); + //ComboBox method1 = new ComboBox(); + //for (Entities.TestMethod method = 0; method < Entities.TestMethod.Count; method++) method1.Items.Add(method.ToString()); + //ComboBox method2 = new ComboBox(); + //for (Entities.TestMethod2 method = 0; method < Entities.TestMethod2.Count; method++) method2.Items.Add(method.ToString()); + + metrology1Editors = new Control[] + { + new TextBox(), /// 0 test name + new TextBox(), /// 1 Qfrom + new TextBox(), /// 2 Qto + new TextBox(), /// 3 Volume + new TextBox(), /// 4 Test time + new TextBox(), /// 5 Repeats # + yesNo1CBox, /// 6 Emptying + yesNo2CBox, /// 7 Zeroing + methodCBox, + }; + + metrology2Editors = new Control[] + { + new TextBox(), /// 0 test name + new TextBox(), /// 1 Qfrom + new TextBox(), /// 2 Qto + new TextBox(), /// 3 Err.Lim. - + new TextBox(), /// 4 Err.Lim. + + new TextBox(), /// 5 Tol.Red. + new ComboBox(), /// 6 Red.Type + }; + + processEditors = new Control[] + { + new TextBox(), /// 0 test name + new TextBox(), /// 1 Qfrom + new TextBox(), /// 2 Qto + new ComboBox(), /// 3 Feeding + new ComboBox(), /// 4 Table + new ComboBox(), /// 5 Output + new ComboBox(), /// 6 Meters + new ComboBox(), /// 7 TransitionStart + new ComboBox(), /// 8 TransitionEnd + }; + + foreach (var ctrl in metrology1Editors) metrology1TabPage.Controls.Add(ctrl); + foreach (var ctrl in metrology2Editors) metrology2TabPage.Controls.Add(ctrl); + foreach (var ctrl in processEditors) processTabPage.Controls.Add(ctrl); + + foreach (var path in feedingPaths) ((ComboBox)processEditors[3]).Items.Add(path.Name); + foreach (var path in benchPaths) ((ComboBox)processEditors[4]).Items.Add(path.Name); + foreach (var path in outputPaths) ((ComboBox)processEditors[5]).Items.Add(path.Name); + foreach (var path in metersPaths) ((ComboBox)processEditors[6]).Items.Add(path.Name); + + ((ComboBox)processEditors[7]).Items.Add("---"); + ((ComboBox)processEditors[8]).Items.Add("---"); + foreach (var trans in transitionSequences) + { + ((ComboBox)processEditors[7]).Items.Add(trans.Name); + ((ComboBox)processEditors[8]).Items.Add(trans.Name); + } + } + + void RefreshMetrology12AndProcessTabs() + { + metrology1ListViewEx.Items.Clear(); + metrology2ListViewEx.Items.Clear(); + processListViewEx.Items.Clear(); + foreach (var test in LoadedProcedure.Tests) AddToMetrology12AndProcessTab(test); + foreach (var ctrl in testParamsCtrls) ctrl.RedrawAll(); + foreach (var ctrl in procedureParamsCtrls) ctrl.RedrawAll(); + } + + void AddToMetrology12AndProcessTab(Test test) + { + ListViewItem lviMetrlg1 = new ListViewItem(test.Name); /// + ListViewItem lviMetrlg2 = new ListViewItem(test.Name); /// SubItem 0 + ListViewItem lviProcess = new ListViewItem(test.Name); /// + lviMetrlg1.Tag = test; + lviMetrlg2.Tag = test; + lviProcess.Tag = test; + + lviMetrlg1.SubItems.Add(test.Qfrom.ToString()); /// + lviMetrlg2.SubItems.Add(test.Qfrom.ToString()); /// SubItem 1 + lviProcess.SubItems.Add(test.Qfrom.ToString()); /// + + lviMetrlg1.SubItems.Add(test.Qto.ToString()); /// + lviMetrlg2.SubItems.Add(test.Qto.ToString()); /// SubItem 2 + lviProcess.SubItems.Add(test.Qto.ToString()); /// + + lviMetrlg1.SubItems.Add(test.Volume.ToString()); /// SubItem 3 + lviMetrlg1.SubItems.Add(test.TstTime.ToString()); /// SubItem 4 + lviMetrlg1.SubItems.Add(test.Repeats.ToString()); /// SubItem 5 + lviMetrlg1.SubItems.Add(test.Emptying ? Strings.yes : Strings.no); /// SubItem 6 + lviMetrlg1.SubItems.Add(test.Zeroing ? Strings.yes : Strings.no); /// SubItem 7 + lviMetrlg1.SubItems.Add((test.Method != null) ? test.Method.ToString() : string.Empty); /// SubItem 8 + + lviMetrlg2.SubItems.Add(test.ErrLimLo.ToString()); /// SubItem 3 + lviMetrlg2.SubItems.Add(test.ErrLimHi.ToString()); /// SubItem 4 + lviMetrlg2.SubItems.Add(test.TolerRed.ToString()); /// SubItem 5 + lviMetrlg2.SubItems.Add(test.RedType.ToString()); /// SubItem 6 + + lviProcess.SubItems.Add(test.FeedingPath); /// SubItem 3 + lviProcess.SubItems.Add(test.BenchPath); /// SubItem 4 + lviProcess.SubItems.Add(test.OutputPath); /// SubItem 5 + lviProcess.SubItems.Add(test.MetersPath); /// SubItem 6 + lviProcess.SubItems.Add(string.IsNullOrEmpty(test.TransitionStart) ? "---" : test.TransitionStart); /// SubItem 7 + lviProcess.SubItems.Add(string.IsNullOrEmpty(test.TransitionEnd) ? "---" : test.TransitionEnd); /// SubItem 8 + + metrology1ListViewEx.Items.Add(lviMetrlg1); + metrology2ListViewEx.Items.Add(lviMetrlg2); + processListViewEx.Items.Add(lviProcess); + } + + void UpdateFromMetrology1Tab() + { + for (int i = 0; i < metrology1ListViewEx.Items.Count; i++) + { + ListViewItem lvi = metrology1ListViewEx.Items[i]; + Entities.Test entity = (Entities.Test)lvi.Tag; + entity.Name = lvi.Text; + + float Qfrom; + bool allOk = Utils.TryParseUFloat(lvi.SubItems[1].Text, out Qfrom); + entity.Qfrom = Qfrom; + + float Qto; + allOk &= Utils.TryParseUFloat(lvi.SubItems[2].Text, out Qto); + entity.Qto = Qto; + + float volume; + allOk &= Utils.TryParseUFloat(lvi.SubItems[3].Text, out volume); + entity.Volume = volume; + + float testTime; + allOk &= Utils.TryParseUFloat(lvi.SubItems[4].Text, out testTime); + entity.TstTime = testTime; + + int repeats; + allOk &= int.TryParse(lvi.SubItems[5].Text, out repeats); + entity.Repeats = repeats; + + if (lvi.SubItems[6].Text.Equals(Strings.yes)) entity.Emptying = true; + else if (lvi.SubItems[6].Text.Equals(Strings.no)) entity.Emptying = false; + + if (lvi.SubItems[7].Text.Equals(Strings.yes)) entity.Zeroing = true; + else if (lvi.SubItems[7].Text.Equals(Strings.no)) entity.Zeroing = false; + + if (methodCBox.Items.Contains(lvi.SubItems[8].Text)) + { + entity.Method = lvi.SubItems[8].Text; + } + } + } + + void UpdateFromMetrology2Tab() + { + for (int i = 0; i < metrology2ListViewEx.Items.Count; i++) + { + ListViewItem lvi = metrology2ListViewEx.Items[i]; + Entities.Test entity = (Entities.Test)lvi.Tag; + entity.Name = lvi.Text; + + float Qfrom; + bool allOk = Utils.TryParseUFloat(lvi.SubItems[1].Text, out Qfrom); + entity.Qfrom = Qfrom; + + float Qto; + allOk &= Utils.TryParseUFloat(lvi.SubItems[2].Text, out Qto); + entity.Qto = Qto; + + float errLimLo; + allOk &= Utils.TryParseSFloat(lvi.SubItems[3].Text, out errLimLo); + entity.ErrLimLo = errLimLo; + + float errLimHi; + allOk &= Utils.TryParseSFloat(lvi.SubItems[4].Text, out errLimHi); + entity.ErrLimHi = errLimHi; + } + } + + void UpdateFromProcessTab() + { + for (int i = 0; i < processListViewEx.Items.Count; i++) + { + ListViewItem lvi = processListViewEx.Items[i]; + Entities.Test entity = (Entities.Test)lvi.Tag; + entity.Name = lvi.Text; + + float Qfrom; + bool allOk = Utils.TryParseUFloat(lvi.SubItems[1].Text, out Qfrom); + entity.Qfrom = Qfrom; + + float Qto; + allOk &= Utils.TryParseUFloat(lvi.SubItems[2].Text, out Qto); + entity.Qto = Qto; + + if ((processEditors[3] as ComboBox).Items.Contains(lvi.SubItems[3].Text)) entity.FeedingPath= lvi.SubItems[3].Text; + if ((processEditors[4] as ComboBox).Items.Contains(lvi.SubItems[4].Text)) entity.BenchPath = lvi.SubItems[4].Text; + if ((processEditors[5] as ComboBox).Items.Contains(lvi.SubItems[5].Text)) entity.OutputPath = lvi.SubItems[5].Text; + if ((processEditors[6] as ComboBox).Items.Contains(lvi.SubItems[6].Text)) entity.MetersPath = lvi.SubItems[6].Text; + if ((processEditors[7] as ComboBox).Items.Contains(lvi.SubItems[7].Text)) + { + entity.TransitionStart = lvi.SubItems[7].Text.Equals("---") ? string.Empty : lvi.SubItems[7].Text; + } + if ((processEditors[8] as ComboBox).Items.Contains(lvi.SubItems[8].Text)) + { + entity.TransitionEnd = lvi.SubItems[8].Text.Equals("---") ? string.Empty : lvi.SubItems[8].Text; + } + } + } + + private void metrology1ListViewEx_SubItemClicked(object sender, SubItemEventArgs e) + { + if (!unlocked || e.SubItem >= metrology1Editors.Length) return; + metrology1ListViewEx.StartEditing(metrology1Editors[e.SubItem], e.Item, e.SubItem); + } + + private void metrology1ListViewEx_SubItemEndEditing(object sender, SubItemEndEditingEventArgs e) + { + if (e.SubItem != 1 && e.SubItem != 2 && e.SubItem != 3 && e.SubItem != 4) return; + + float Qfrom = 1.0f; + float Qto = 1.0f; + float volume = 0.0f; + float testTime = 0.0f; + + bool calculateVolume = false; + bool calculateTime = false; + bool allOk = true; + + if (e.SubItem == 1 && Utils.TryParseUFloat(e.DisplayText, out Qfrom)) + { + allOk &= Utils.TryParseUFloat(e.Item.SubItems[2].Text, out Qto); + allOk &= Utils.TryParseUFloat(e.Item.SubItems[3].Text, out volume); + if (allOk) calculateTime = true; + } + else if (e.SubItem == 2 && Utils.TryParseUFloat(e.DisplayText, out Qto)) + { + allOk &= Utils.TryParseUFloat(e.Item.SubItems[1].Text, out Qfrom); + allOk &= Utils.TryParseUFloat(e.Item.SubItems[3].Text, out volume); + if (allOk) calculateTime = true; + } + else if (e.SubItem == 3 && Utils.TryParseUFloat(e.DisplayText, out volume)) + { + allOk &= Utils.TryParseUFloat(e.Item.SubItems[1].Text, out Qfrom); + allOk &= Utils.TryParseUFloat(e.Item.SubItems[2].Text, out Qto); + if (allOk) calculateTime = true; + } + else if (e.SubItem == 4 && Utils.TryParseUFloat(e.DisplayText, out testTime)) + { + allOk &= Utils.TryParseUFloat(e.Item.SubItems[1].Text, out Qfrom); + allOk &= Utils.TryParseUFloat(e.Item.SubItems[2].Text, out Qto); + if (allOk) calculateVolume = true; + } + + float Qave_lps = (Qfrom + Qto) / 7.2f; + if (calculateTime) + { + testTime = volume / Qave_lps; + e.Item.SubItems[4].Text = testTime.ToString(); + } + else if (calculateVolume) + { + volume = testTime * Qave_lps; + e.Item.SubItems[3].Text = volume.ToString(); + } + else + { + e.DisplayText = e.Item.SubItems[e.SubItem].Text; + e.Cancel = true; + } + } + + private void metrology2ListViewEx_SubItemClicked(object sender, SubItemEventArgs e) + { + if (!unlocked || e.SubItem >= metrology2Editors.Length) return; + metrology2ListViewEx.StartEditing(metrology2Editors[e.SubItem], e.Item, e.SubItem); + } + + private void metrology2ListViewEx_SubItemEndEditing(object sender, SubItemEndEditingEventArgs e) + { + } + + private void processListViewEx_SubItemClicked(object sender, SubItemEventArgs e) + { + if (!unlocked || e.SubItem >= processEditors.Length) return; + processListViewEx.StartEditing(processEditors[e.SubItem], e.Item, e.SubItem); + } + + private void processListViewEx_SubItemEndEditing(object sender, SubItemEndEditingEventArgs e) + { + if ((e.SubItem == 3 && !(processEditors[3] as ComboBox).Items.Contains(e.DisplayText)) || + (e.SubItem == 4 && !(processEditors[4] as ComboBox).Items.Contains(e.DisplayText)) || + (e.SubItem == 5 && !(processEditors[5] as ComboBox).Items.Contains(e.DisplayText)) || + (e.SubItem == 6 && !(processEditors[6] as ComboBox).Items.Contains(e.DisplayText)) || + (e.SubItem == 7 && !(processEditors[7] as ComboBox).Items.Contains(e.DisplayText)) || + (e.SubItem == 8 && !(processEditors[8] as ComboBox).Items.Contains(e.DisplayText))) + { + e.DisplayText = e.Item.SubItems[e.SubItem].Text; + e.Cancel = true; + } + } + + #endregion + + + private void Unlocked(object sender, EventArgs e) + { + unlocked = true; + if (testParamsCtrls != null) foreach (var ctrl in testParamsCtrls) ctrl.Unlock(); + if (procedureParamsCtrls != null) foreach (var ctrl in procedureParamsCtrls) ctrl.Unlock(); + + procNameTextBox.Enabled = true; + descriptionTextBox.Enabled = true; + watermetersTextBox.Enabled = true; + dataEntryComboBox.Enabled = true; + resultsPrinterComboBox.Enabled = true; + resultsWriterComboBox.Enabled = true; + transitionStartComboBox.Enabled = true; + transitionEndComboBox.Enabled = true; + notesTextBox.Enabled = true; + + ListViewEx listViewEx; + + switch (selectedTab) + { + case ProcedureTabs.Metrology1: + listViewEx = metrology1ListViewEx; + break; + case ProcedureTabs.Metrology2: + listViewEx = metrology2ListViewEx; + break; + case ProcedureTabs.Process: + listViewEx = processListViewEx; + break; + default: + return; + } + + if (listViewEx.SelectedItems.Count == 1) + { + int ix = listViewEx.SelectedIndices[0]; + listViewEx.Focus(); + listViewEx.Items[ix].Selected = true; + listViewEx.Items[ix].EnsureVisible(); + } + } + + private void okButton_Click(object sender, EventArgs e) + { + switch (selectedTab) + { + case ProcedureTabs.General: UpdateFromGeneralTab(); break; + case ProcedureTabs.Metrology1: UpdateFromMetrology1Tab(); break; + case ProcedureTabs.Metrology2: UpdateFromMetrology2Tab(); break; + case ProcedureTabs.Process: UpdateFromProcessTab(); break; + } + + foreach (var ctrl in testParamsCtrls) ctrl.UpdateAll(); + foreach (var ctrl in procedureParamsCtrls) ctrl.UpdateAll(); + + DialogResult = DialogResult.OK; + Close(); + return; + } + + private void cancelButton_Click(object sender, EventArgs e) + { + DialogResult = DialogResult.Cancel; + Close(); + return; + } + + #region Tab switching + + enum ProcedureTabs + { + General, + History, + Metrology1, + Metrology2, + Process, + PurgeStart, + PurgeEnd + } + + ProcedureTabs selectedTab = ProcedureTabs.General; + + private void tabControl_SelectedIndexChanged(object sender, EventArgs e) + { + switch (selectedTab) + { + case ProcedureTabs.General: UpdateFromGeneralTab(); break; + case ProcedureTabs.Metrology1: UpdateFromMetrology1Tab(); break; + case ProcedureTabs.Metrology2: UpdateFromMetrology2Tab(); break; + case ProcedureTabs.Process: UpdateFromProcessTab(); break; + } + + selectedTab = (ProcedureTabs)tabControl.SelectedIndex; + + sharedButtons.SetEnabled(SharedButtons.Buttons.Add, + selectedTab == ProcedureTabs.Metrology1 || + selectedTab == ProcedureTabs.Metrology2 || + selectedTab == ProcedureTabs.Process || + selectedTab == ProcedureTabs.PurgeStart || + selectedTab == ProcedureTabs.PurgeEnd); + + //bool removeBtnEnabled = (selectedTab != ProcedureTabs.General && + // selectedTab != ProcedureTabs.History && + // selectedTab != ProcedureTabs.Calibration); + + sharedButtons.DisableButtons(SharedButtons.Buttons.Remove); + + RefreshAllTabs(); + } + + #endregion + + #region 'Add', 'Remove', 'Up' and 'Down' + + private void addButton_Click(object sender, EventArgs e) + { + ListViewEx listViewEx; + + switch (selectedTab) + { + case ProcedureTabs.Metrology1: listViewEx = metrology1ListViewEx; break; + case ProcedureTabs.Metrology2: listViewEx = metrology2ListViewEx; break; + case ProcedureTabs.Process: listViewEx = processListViewEx; break; + + default: return; + } + + /// Find an unused test name + string newName; + for (int nameId = 1; true; nameId++) + { + newName = Strings.New_test_name + nameId.ToString(); + bool notUsed = true; + foreach (var t in LoadedProcedure.Tests) if (t.Name.Equals(newName)) notUsed = false; + if (notUsed) break; + } + + /// Add a test + Test test = new Test(newName, listViewEx.Items.Count, LoadedProcedure); + + /// Run a create new test wizard + TestWizard.FlowSelection flowDlg = new TestWizard.FlowSelection(test); + TestWizard.MethodSelection methodDlg = new TestWizard.MethodSelection(test, TestMethods, metersPaths); + TestWizard.VolumeAndErrorSelection volumeDlg = new TestWizard.VolumeAndErrorSelection(test); + //TestWizard.SensorsSelection sensorsDlg = new TestWizard.SensorsSelection(test); + + flowLabel: + switch (flowDlg.ShowDialog()) + { + case DialogResult.Cancel: return; + } + + methodLabel: + switch (methodDlg.ShowDialog()) + { + case DialogResult.Cancel: return; + case DialogResult.Retry: goto flowLabel; + } + + switch (volumeDlg.ShowDialog()) + { + case DialogResult.Cancel: return; + case DialogResult.Retry: goto methodLabel; + } + + /// Set few other parameters + test.Repeats = 1; + test.TolerRed = 0.2f; + + /// Depending on the chosen Q select the paths + float Qaver = (test.Qfrom + test.Qto) / 2.0f; + foreach (var path in feedingPaths) + { + if ((path.Qfrom <= Qaver) && (Qaver <= path.Qto)) + { + test.FeedingPath = path.Name; + break; + } + } + foreach (var path in benchPaths) + { + if ((path.Qfrom <= Qaver) && (Qaver <= path.Qto)) + { + test.BenchPath = path.Name; + break; + } + } + foreach (var path in outputPaths) + { + if ((path.Qfrom <= Qaver) && (Qaver <= path.Qto)) + { + test.OutputPath = path.Name; + break; + } + } + + LoadedProcedure.Tests.Add(test); + AddToMetrology12AndProcessTab(test); + foreach (var ctrl in testParamsCtrls) + { + ctrl.AddOne(test); + } + + listViewEx.Focus(); + listViewEx.SelectedItems.Clear(); + listViewEx.Items[listViewEx.Items.Count - 1].Selected = true; + listViewEx.Items[listViewEx.Items.Count - 1].EnsureVisible(); + } + + private void removeButton_Click(object sender, EventArgs e) + { + ListViewEx listViewEx; + + switch (selectedTab) + { + case ProcedureTabs.Metrology1: + UpdateFromMetrology1Tab(); + listViewEx = metrology1ListViewEx; + break; + + case ProcedureTabs.Metrology2: + UpdateFromMetrology2Tab(); + listViewEx = metrology2ListViewEx; + break; + + case ProcedureTabs.Process: + UpdateFromProcessTab(); + listViewEx = processListViewEx; + break; + + default: return; + } + + /// Check the selected index validity + if (listViewEx.SelectedItems.Count != 1) return; + int removeItemNr = listViewEx.SelectedIndices[0]; + + /// Remove the selected test + Entities.Test toBeDeleted = LoadedProcedure.Tests[removeItemNr]; + LoadedProcedure.Tests.Remove(toBeDeleted); + for (int i = removeItemNr; i < LoadedProcedure.Tests.Count; i++) LoadedProcedure.Tests[i].ItemNr--; + + RefreshMetrology12AndProcessTabs(); + foreach (var ctrl in testParamsCtrls) ctrl.RedrawAll(); + + if (removeItemNr < listViewEx.Items.Count) + { + listViewEx.Focus(); + listViewEx.Items[removeItemNr].Selected = true; + listViewEx.Items[removeItemNr].EnsureVisible(); + } + else + { + UpdateButtonStates(SharedButtons.SelectedItemPos.None); + } + } + + private void upButton_Click(object sender, EventArgs e) + { + ListViewEx listViewEx; + + switch (selectedTab) + { + case ProcedureTabs.Metrology1: + UpdateFromMetrology1Tab(); + listViewEx = metrology1ListViewEx; + break; + + case ProcedureTabs.Metrology2: + UpdateFromMetrology2Tab(); + listViewEx = metrology2ListViewEx; + break; + + case ProcedureTabs.Process: + UpdateFromProcessTab(); + listViewEx = processListViewEx; + break; + + default: return; + } + + /// Check the selected index validity + if (listViewEx.SelectedItems.Count != 1) return; + int ix = listViewEx.SelectedIndices[0]; + if (ix <= 0 || ix >= listViewEx.Items.Count) return; + + /// Swap two items (move the selected item up) + Entities.Test test1 = LoadedProcedure.Tests[ix - 1]; + Entities.Test test2 = LoadedProcedure.Tests[ix]; + test1.ItemNr++; + test2.ItemNr--; + LoadedProcedure.Tests.RemoveAt(ix); + LoadedProcedure.Tests.Insert(ix - 1, test2); + + RefreshMetrology12AndProcessTabs(); + + listViewEx.Focus(); + listViewEx.Items[ix - 1].Selected = true; + listViewEx.Items[ix - 1].EnsureVisible(); + } + + private void downButton_Click(object sender, EventArgs e) + { + ListViewEx listViewEx; + + switch (selectedTab) + { + case ProcedureTabs.Metrology1: + UpdateFromMetrology1Tab(); + listViewEx = metrology1ListViewEx; + break; + + case ProcedureTabs.Metrology2: + UpdateFromMetrology2Tab(); + listViewEx = metrology2ListViewEx; + break; + + case ProcedureTabs.Process: + UpdateFromProcessTab(); + listViewEx = processListViewEx; + break; + + default: return; + } + + /// Check the selected index validity + if (listViewEx.SelectedItems.Count != 1) return; + int ix = listViewEx.SelectedIndices[0]; + if (ix < 0 || ix >= listViewEx.Items.Count - 1) return; + + /// Swap two items (move the selected item down) + Entities.Test test1 = LoadedProcedure.Tests[ix]; + Entities.Test test2 = LoadedProcedure.Tests[ix + 1]; + test1.ItemNr++; + test2.ItemNr--; + LoadedProcedure.Tests.RemoveAt(ix + 1); + LoadedProcedure.Tests.Insert(ix, test2); + + RefreshMetrology12AndProcessTabs(); + + listViewEx.Focus(); + listViewEx.Items[ix + 1].Selected = true; + listViewEx.Items[ix + 1].EnsureVisible(); + } + + #endregion + + public void UpdateButtonStates(SharedButtons.SelectedItemPos selectedItemPos) + { + if (selectedItemPos == SharedButtons.SelectedItemPos.None) + { + sharedButtons.DisableButtons(SharedButtons.Buttons.Remove | SharedButtons.Buttons.Up | SharedButtons.Buttons.Down); + } + else if (selectedItemPos == SharedButtons.SelectedItemPos.First) + { + sharedButtons.EnableButtons(SharedButtons.Buttons.Remove | SharedButtons.Buttons.Down); + sharedButtons.DisableButtons(SharedButtons.Buttons.Up); + } + else if (selectedItemPos == SharedButtons.SelectedItemPos.Last) + { + sharedButtons.EnableButtons(SharedButtons.Buttons.Remove | SharedButtons.Buttons.Up); + sharedButtons.DisableButtons(SharedButtons.Buttons.Down); + } + else if (selectedItemPos == SharedButtons.SelectedItemPos.FirstAndLast) + { + sharedButtons.EnableButtons(SharedButtons.Buttons.Remove); + sharedButtons.DisableButtons(SharedButtons.Buttons.Up | SharedButtons.Buttons.Down); + } + else + { + sharedButtons.EnableButtons(SharedButtons.Buttons.Remove | SharedButtons.Buttons.Up | SharedButtons.Buttons.Down); + } + } + + private void metrology1ListViewEx_SelectedIndexChanged(object sender, EventArgs e) + { + SelectedIndexChanged(sender, e); + } + + private void metrology2ListViewEx_SelectedIndexChanged(object sender, EventArgs e) + { + SelectedIndexChanged(sender, e); + } + + private void processListViewEx_SelectedIndexChanged(object sender, EventArgs e) + { + SelectedIndexChanged(sender, e); + } + + /// + /// Common part for three xxxListViewEx_SelectedIndexChanged event handlers + /// + /// + void SelectedIndexChanged(object sender, EventArgs e) + { + ListViewEx listViewEx = sender as ListViewEx; + if (listViewEx.SelectedItems.Count != 1) + { + UpdateButtonStates(SharedButtons.SelectedItemPos.None); + } + else if (listViewEx.Items.Count == 1) + { + UpdateButtonStates(SharedButtons.SelectedItemPos.FirstAndLast); + } + else if (listViewEx.SelectedIndices[0] == 0) + { + UpdateButtonStates(SharedButtons.SelectedItemPos.First); + } + else if (listViewEx.SelectedIndices[0] == (listViewEx.Items.Count - 1)) + { + UpdateButtonStates(SharedButtons.SelectedItemPos.Last); + } + else + { + UpdateButtonStates(SharedButtons.SelectedItemPos.Middle); + } + } + } +} diff --git a/TestBenchFramework/ProcedureDlg.de.resx b/TestBenchFramework/ProcedureDlg.de.resx new file mode 100644 index 000000000..e5fdb4910 --- /dev/null +++ b/TestBenchFramework/ProcedureDlg.de.resx @@ -0,0 +1,311 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 931, 409 + + + 1034, 409 + + + 923, 371 + + + Allgemein + + + 139, 325 + + + 24, 330 + + + 139, 295 + + + 24, 300 + + + 139, 264 + + + 139, 233 + + + 139, 203 + + + 24, 267 + + + 24, 236 + + + 24, 206 + + + 348, 205 + + + 317, 141 + + + 281, 208 + + + 61, 13 + + + Bemerkung + + + 139, 162 + + + 526, 20 + + + 24, 165 + + + 348, 120 + + + 38, 13 + + + Datum + + + 140, 121 + + + 102, 13 + + + letzte Änderung von + + + 348, 87 + + + 38, 13 + + + Datum + + + 62, 13 + + + Errstellt von + + + 526, 20 + + + 92, 13 + + + Kurzbeschreibung + + + 75, 13 + + + Prüfungsname + + + 923, 406 + + + Änderungen + + + 917, 400 + + + Benutzername + + + Datum + + + Kurzbeschreibung + + + 923, 406 + + + Metrologie I. + + + 917, 400 + + + 923, 406 + + + Metrologie II. + + + 917, 400 + + + 923, 406 + + + Prozess + + + 917, 400 + + + + 3, 3, 3, 3 + + + 923, 406 + + + Spülung - Start + + + 3, 3 + + + 917, 400 + + + 923, 406 + + + Spülung - Ende + + + 923, 406 + + + 1034, 409 + + + Prüfung + + \ No newline at end of file diff --git a/TestBenchFramework/ProcedureDlg.resx b/TestBenchFramework/ProcedureDlg.resx new file mode 100644 index 000000000..c52523c49 --- /dev/null +++ b/TestBenchFramework/ProcedureDlg.resx @@ -0,0 +1,1176 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + Fill + + + + True + + + + 0, 0 + + + 139, 313 + + + 121, 21 + + + 29 + + + transitionEndComboBox + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + generalTabPage + + + 0 + + + True + + + NoControl + + + 24, 318 + + + 63, 13 + + + 28 + + + Purge - End + + + transitionEndLabel + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + generalTabPage + + + 1 + + + 139, 283 + + + 121, 21 + + + 27 + + + transitionStartComboBox + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + generalTabPage + + + 2 + + + True + + + NoControl + + + 24, 288 + + + 71, 13 + + + 26 + + + Purge - Begin + + + transitionStartLabel + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + generalTabPage + + + 3 + + + 139, 253 + + + 121, 21 + + + 25 + + + resultsWriterComboBox + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + generalTabPage + + + 4 + + + 139, 222 + + + 121, 21 + + + 24 + + + resultsPrinterComboBox + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + generalTabPage + + + 5 + + + 139, 191 + + + 121, 21 + + + 23 + + + dataEntryComboBox + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + generalTabPage + + + 6 + + + True + + + NoControl + + + 24, 258 + + + 70, 13 + + + 22 + + + Results writer + + + resultsWriterLabel + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + generalTabPage + + + 7 + + + True + + + NoControl + + + 24, 227 + + + 74, 13 + + + 21 + + + Results printer + + + resultsPrinterLabel + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + generalTabPage + + + 8 + + + True + + + NoControl + + + 25, 194 + + + 57, 13 + + + 20 + + + Data Entry + + + dataEntryLabel + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + generalTabPage + + + 9 + + + 344, 191 + + + True + + + 317, 143 + + + 17 + + + notesTextBox + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + generalTabPage + + + 10 + + + True + + + NoControl + + + 291, 194 + + + 35, 13 + + + 16 + + + Notes + + + label18 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + generalTabPage + + + 11 + + + 139, 156 + + + 522, 20 + + + 15 + + + watermetersTextBox + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + generalTabPage + + + 12 + + + True + + + NoControl + + + 24, 159 + + + 94, 13 + + + 14 + + + Meter types tested + + + watermetersLabel + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + generalTabPage + + + 13 + + + 344, 120 + + + 97, 20 + + + 13 + + + lastChangedOnTextBox + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + generalTabPage + + + 14 + + + True + + + NoControl + + + 291, 123 + + + 30, 13 + + + 12 + + + Date + + + label15 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + generalTabPage + + + 15 + + + 139, 120 + + + 121, 20 + + + 11 + + + lastChangedByTextBox + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + generalTabPage + + + 16 + + + True + + + NoControl + + + 24, 123 + + + 86, 13 + + + 10 + + + Last changed by + + + label16 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + generalTabPage + + + 17 + + + 344, 87 + + + 97, 20 + + + 9 + + + createdOnTextBox + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + generalTabPage + + + 18 + + + True + + + NoControl + + + 291, 90 + + + 30, 13 + + + 8 + + + Date + + + label14 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + generalTabPage + + + 19 + + + 139, 87 + + + 121, 20 + + + 7 + + + createdByTextBox + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + generalTabPage + + + 20 + + + True + + + NoControl + + + 24, 90 + + + 58, 13 + + + 6 + + + Created by + + + label13 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + generalTabPage + + + 21 + + + 139, 53 + + + 522, 20 + + + 5 + + + descriptionTextBox + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + generalTabPage + + + 22 + + + True + + + NoControl + + + 24, 56 + + + 86, 13 + + + 4 + + + Short description + + + label12 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + generalTabPage + + + 23 + + + 139, 21 + + + 217, 20 + + + 3 + + + procNameTextBox + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + generalTabPage + + + 24 + + + True + + + NoControl + + + 24, 24 + + + 85, 13 + + + 2 + + + Procedure name + + + label1 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + generalTabPage + + + 25 + + + 4, 34 + + + 3, 3, 3, 3 + + + 923, 352 + + + 0 + + + General + + + generalTabPage + + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabControl + + + 0 + + + Changed by + + + 80 + + + Date + + + Description + + + 400 + + + Fill + + + 3, 3 + + + 917, 346 + + + 0 + + + historyListViewEx + + + TBF.UiControls.ListViewEx, TBF, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + + historyTabPage + + + 0 + + + 4, 34 + + + 3, 3, 3, 3 + + + 923, 352 + + + 1 + + + History of Changes + + + historyTabPage + + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabControl + + + 1 + + + Fill + + + 3, 3 + + + 917, 346 + + + 0 + + + metrology1ListViewEx + + + TBF.UiControls.ListViewEx, TBF, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + + metrology1TabPage + + + 0 + + + 4, 34 + + + 3, 3, 3, 3 + + + 923, 352 + + + 2 + + + Metrology I. + + + metrology1TabPage + + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabControl + + + 2 + + + Fill + + + 3, 3 + + + 917, 346 + + + 0 + + + metrology2ListViewEx + + + TBF.UiControls.ListViewEx, TBF, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + + metrology2TabPage + + + 0 + + + 4, 34 + + + 3, 3, 3, 3 + + + 923, 352 + + + 3 + + + Metrology II. + + + metrology2TabPage + + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabControl + + + 3 + + + Fill + + + 3, 3 + + + 917, 346 + + + 0 + + + processListViewEx + + + TBF.UiControls.ListViewEx, TBF, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + + processTabPage + + + 0 + + + 4, 34 + + + 3, 3, 3, 3 + + + 923, 352 + + + 4 + + + Process + + + processTabPage + + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabControl + + + 4 + + + Fill + + + 58, 30 + + + 0, 0 + + + 931, 390 + + + 1 + + + tabControl + + + System.Windows.Forms.TabControl, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + mainSplitContainer.Panel1 + + + 0 + + + mainSplitContainer.Panel1 + + + System.Windows.Forms.SplitterPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + mainSplitContainer + + + 0 + + + -1, 0 + + + 100, 400 + + + 0 + + + sharedButtons + + + TBF.UiControls.SharedButtons, TBF, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + + mainSplitContainer.Panel2 + + + 0 + + + mainSplitContainer.Panel2 + + + System.Windows.Forms.SplitterPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + mainSplitContainer + + + 1 + + + 1034, 390 + + + 931 + + + 1 + + + mainSplitContainer + + + System.Windows.Forms.SplitContainer, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 0 + + + True + + + 6, 13 + + + 1034, 390 + + + CenterParent + + + Procedure + + + changedByClmnHdr + + + System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + dateClmnHdr + + + System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + descriptionClmnHdr + + + System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + ProcedureDlg + + + System.Windows.Forms.Form, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/ProceduresDlg.Designer.cs b/TestBenchFramework/ProceduresDlg.Designer.cs new file mode 100644 index 000000000..cb3ed815f --- /dev/null +++ b/TestBenchFramework/ProceduresDlg.Designer.cs @@ -0,0 +1,103 @@ +namespace TBF +{ + partial class ProceduresDlg + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.splitContainer = new System.Windows.Forms.SplitContainer(); + this.proceduresCtrl = new TBF.UiControls.ProceduresCtrl(); + this.sharedButtons = new TBF.UiControls.SharedButtons(); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).BeginInit(); + this.splitContainer.Panel1.SuspendLayout(); + this.splitContainer.Panel2.SuspendLayout(); + this.splitContainer.SuspendLayout(); + this.SuspendLayout(); + // + // splitContainer + // + this.splitContainer.Dock = System.Windows.Forms.DockStyle.Fill; + this.splitContainer.FixedPanel = System.Windows.Forms.FixedPanel.Panel2; + this.splitContainer.Location = new System.Drawing.Point(0, 0); + this.splitContainer.Name = "splitContainer"; + // + // splitContainer.Panel1 + // + this.splitContainer.Panel1.Controls.Add(this.proceduresCtrl); + // + // splitContainer.Panel2 + // + this.splitContainer.Panel2.Controls.Add(this.sharedButtons); + this.splitContainer.Size = new System.Drawing.Size(517, 402); + this.splitContainer.SplitterDistance = 412; + this.splitContainer.TabIndex = 0; + // + // proceduresCtrl + // + this.proceduresCtrl.Dock = System.Windows.Forms.DockStyle.Fill; + this.proceduresCtrl.DoubleClickActivation = false; + this.proceduresCtrl.FullRowSelect = true; + this.proceduresCtrl.GridLines = true; + this.proceduresCtrl.Location = new System.Drawing.Point(0, 0); + this.proceduresCtrl.Name = "proceduresCtrl"; + this.proceduresCtrl.Size = new System.Drawing.Size(412, 402); + this.proceduresCtrl.TabIndex = 0; + this.proceduresCtrl.UseCompatibleStateImageBehavior = false; + this.proceduresCtrl.View = System.Windows.Forms.View.Details; + this.proceduresCtrl.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.proceduresCtrl_MouseDoubleClick); + // + // sharedButtons + // + this.sharedButtons.Location = new System.Drawing.Point(1, 0); + this.sharedButtons.Name = "sharedButtons"; + this.sharedButtons.Size = new System.Drawing.Size(100, 521); + this.sharedButtons.TabIndex = 0; + // + // ProceduresDlg + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(517, 402); + this.Controls.Add(this.splitContainer); + this.Name = "ProceduresDlg"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "ProceduresDlg"; + this.Load += new System.EventHandler(this.ProceduresDlg_Load); + this.splitContainer.Panel1.ResumeLayout(false); + this.splitContainer.Panel2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).EndInit(); + this.splitContainer.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.SplitContainer splitContainer; + private UiControls.SharedButtons sharedButtons; + private UiControls.ProceduresCtrl proceduresCtrl; + } +} \ No newline at end of file diff --git a/TestBenchFramework/ProceduresDlg.cs b/TestBenchFramework/ProceduresDlg.cs new file mode 100644 index 000000000..6bb2f5f64 --- /dev/null +++ b/TestBenchFramework/ProceduresDlg.cs @@ -0,0 +1,153 @@ +using System; +using System.Windows.Forms; +using log4net; +using TBF.Resources; +using TBF.UiControls; + +namespace TBF +{ + public partial class ProceduresDlg : Form + { + static readonly ILog log = LogManager.GetLogger(typeof(ProceduresDlg)); + + /// Used when re-scaling the dialog: 100% = 96dpi, 125% = 120dpi, 150% = 144dpi + public readonly int Dpi; + public const int Dpi100pct = 96; + + bool unlocked; + + public ProceduresDlg() + { + /// Detect display setting: 100% = 96dpi, 125% = 120dpi, 150% = 144dpi. + Dpi = (int)this.CreateGraphics().DpiX; + + InitializeComponent(); + + /// SharedDlgButtons configuration + sharedButtons.RequiredGroupMembership = Grp.GID.Metrologists; + sharedButtons.OptionalButtons = SharedButtons.Buttons.Add | SharedButtons.Buttons.Remove | + SharedButtons.Buttons.Up | SharedButtons.Buttons.Down | + SharedButtons.Buttons.Edit | SharedButtons.Buttons.Copy; + + sharedButtons.Unlocked += Unlocked; + sharedButtons.OKClicked += okButton_Click; + sharedButtons.CancelClicked += cancelButton_Click; + sharedButtons.AddClicked += addButton_Click; + sharedButtons.RemoveClicked += removeButton_Click; + sharedButtons.UpClicked += upButton_Click; + sharedButtons.DownClicked += downButton_Click; + sharedButtons.EditClicked += proceduresCtrl.editButton_Click; + sharedButtons.CopyClicked += proceduresCtrl.copyButton_Click; + } + + private void ProceduresDlg_Load(object sender, EventArgs e) + { + Text = Strings.Procedures; + proceduresCtrl.Initialize(this, splitContainer.Panel1); + } + + /// + /// Called from ProceduresCtrl when item editing is completed with OK. + /// Authorisation occurs in the editted ProcedureDlg dialog. + /// + public void Unlock() + { + sharedButtons.UnlockButtons(); + unlocked = true; + proceduresCtrl.Unlock(); + } + + /// + /// Called from sharedButtons when user clicks 'Unlock' button an is authorised. + /// + private void Unlocked(object sender, EventArgs e) + { + unlocked = true; + proceduresCtrl.Unlock(); + } + + private void okButton_Click(object sender, EventArgs e) + { + proceduresCtrl.OkBtnClicked(); + DialogResult = DialogResult.OK; + Close(); + } + + private void cancelButton_Click(object sender, EventArgs e) + { + proceduresCtrl.CancelBtnClicked(); + DialogResult = DialogResult.Cancel; + Close(); + } + + private void addButton_Click(object sender, EventArgs e) + { + proceduresCtrl.AddOne(); + } + + private void removeButton_Click(object sender, EventArgs e) + { + proceduresCtrl.RemoveSelected(); + } + + private void upButton_Click(object sender, EventArgs e) + { + proceduresCtrl.MoveUpSelected(); + } + + private void downButton_Click(object sender, EventArgs e) + { + proceduresCtrl.MoveDownSelected(); + } + + private void proceduresCtrl_MouseDoubleClick(object sender, MouseEventArgs e) + { + proceduresCtrl.editButton_Click(sender, e); + } + + /// + /// Common part for three xxxListViewEx_SelectedIndexChanged event handlers + /// + /// + void SelectedIndexChanged(object sender, EventArgs e) + { + ListViewEx listViewEx = sender as ListViewEx; + if (listViewEx.SelectedItems.Count != 1) + { + /// No item selected + sharedButtons.DisableButtons(SharedButtons.Buttons.Remove | SharedButtons.Buttons.Up | SharedButtons.Buttons.Down); + } + else if (listViewEx.Items.Count == 1) + { + /// One (the first and the last) item selected + sharedButtons.EnableButtons(SharedButtons.Buttons.Remove); + sharedButtons.DisableButtons(SharedButtons.Buttons.Up | SharedButtons.Buttons.Down); + } + else if (listViewEx.SelectedIndices[0] == 0) + { + /// The first of many items selected + sharedButtons.EnableButtons(SharedButtons.Buttons.Remove | SharedButtons.Buttons.Down); + sharedButtons.DisableButtons(SharedButtons.Buttons.Up); + } + else if (listViewEx.SelectedIndices[0] == (listViewEx.Items.Count - 1)) + { + /// The last of many items selected + sharedButtons.EnableButtons(SharedButtons.Buttons.Remove | SharedButtons.Buttons.Up); + sharedButtons.DisableButtons(SharedButtons.Buttons.Down); + } + else + { + /// One of middle items selected + sharedButtons.EnableButtons(SharedButtons.Buttons.Remove | SharedButtons.Buttons.Up | SharedButtons.Buttons.Down); + } + } + + public void UpdateButtonStates(SharedButtons.SelectedItemPos selectedItemPos) + { + if (selectedItemPos == SharedButtons.SelectedItemPos.None) + { + sharedButtons.DisableButtons(SharedButtons.Buttons.Remove | SharedButtons.Buttons.Up | SharedButtons.Buttons.Down); + } + } + } +} diff --git a/TestBenchFramework/ProceduresDlg.resx b/TestBenchFramework/ProceduresDlg.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/TestBenchFramework/ProceduresDlg.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/Program.cs b/TestBenchFramework/Program.cs new file mode 100644 index 000000000..1fa6ff890 --- /dev/null +++ b/TestBenchFramework/Program.cs @@ -0,0 +1,247 @@ +using System; +using System.IO; +using System.Collections.Generic; +using System.Windows.Forms; +using log4net; +using TBF.Resources; +using TBF.Forms; +using TBF.ErrorHandler; + +using NHibernate; + +namespace TBF +{ + public class Program + { + public const string AdminUsername = "admin"; + public const string AdminPassword = "staratura"; + + public const string HomeDir = "C:\\Tbf\\"; /// Contains subdirectories Results, Logs, Images, ... + + /// log4net + static readonly ILog log = LogManager.GetLogger(typeof(Program)); + const string log4netConfigFName = "log4netConfig.xml"; + + /// Local settings + public static LocalSettings LocalSettings = new LocalSettings(); + public const string LocalSettingsFileName = "config.xml"; + + /// Database related: This object reference is set after a successful user login + public static DatabaseSettings CurrentBench; + const string SQLiteDbFName = "SQLite.db"; + +#if (DN100 || MUNICH) + public const int WMsCount = 3; +#else + public const int WMsCount = 6; +#endif + + /// + /// Selected procedure data + /// - before the main program window is open, objects referenced by this variable + /// are loaded from the database. + /// - user interface displays data stored in objects referenced by this variable. + /// When user modifies procedure settings and confirms changes (choses to save them), + /// data referenced by this variable are updated and written to the database. + /// - when users starts a test procedure, state machine creates its own copy + /// of procedure data and uses them for the test. Changes of 'SelectedProcedure' + /// done during the test do not have any influence on the currently running test. + /// + public static Entities.Procedure SelectedProcedure = null; + + /// + /// Main window object. + /// + public static MainWnd MainWnd; + + + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() + { + /// Local program configuration directory including the trailing backslash + string locAppDataDir = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + + Path.DirectorySeparatorChar + "TestBenchFramework" + Path.DirectorySeparatorChar; + + /// Check whether local application data directory exists. + /// If not, create it and copy the initial configuration to this directory. + /// This is done only once after a clean program installation on the first program start-up + try + { + if (!Directory.Exists(locAppDataDir)) + { + Directory.CreateDirectory(locAppDataDir); + Environment.CurrentDirectory = locAppDataDir; + + string sampleConfig = Application.StartupPath + Path.DirectorySeparatorChar + "SampleConfig" + Path.DirectorySeparatorChar; + if (File.Exists(sampleConfig + LocalSettingsFileName)) { File.Copy(sampleConfig + LocalSettingsFileName, LocalSettingsFileName); } + if (File.Exists(sampleConfig + log4netConfigFName)) { File.Copy(sampleConfig + log4netConfigFName, log4netConfigFName); } + if (File.Exists(sampleConfig + SQLiteDbFName)) { File.Copy(sampleConfig + SQLiteDbFName, SQLiteDbFName); } + + File.SetAttributes(LocalSettingsFileName, FileAttributes.Normal); + File.SetAttributes(log4netConfigFName, FileAttributes.Normal); + File.SetAttributes(SQLiteDbFName, FileAttributes.Normal); + } + else + { + Environment.CurrentDirectory = locAppDataDir; + } + } + catch (Exception e) + { + log.Error("A problem when creating the local application data directory and preparing the initial configuration", e); + return; + } + + /// Configue and start logging + log4net.Config.XmlConfigurator.Configure(new System.IO.FileInfo(locAppDataDir + log4netConfigFName)); + log.Info("Entering application."); + + /// Load the local settings + if (Program.LocalSettings == null) return; /// Fatal error + LocalSettings.Load(); + + System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(LocalSettings.Language); + + /// This belongs to Application.Run(new MainWnd()) ... + /// and should be executed before opening 'loginDlg' + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + + /// Ensure that there is at least one bench in the configuration + while (Program.LocalSettings.testBenches.GetLength(0) == 0) + { + log.Warn("No test benches in the local configuration -> display an appropriate dialog."); + + /// Ask what to do, ask for the password, open 'DatabaseSetingsDlg' and continue on OK + if (new Forms.NoBenchOrDatabaseDlg { Message = Strings.NoBenchMsg }.ShowDialog() != DialogResult.OK || + new Forms.EnterPasswordDlg { Password = AdminPassword }.ShowDialog() == DialogResult.Cancel || + new BenchesDlg().ShowDialog() == DialogResult.Cancel) + { + return; /// Exit program + } + + log.Warn("Loading the local settings again."); + LocalSettings.Load(); + } + + /// User login + bool retryLogin = true; /// true = stay in a login loop + do { + LoginDlgWithBenchSelection loginDlgBenchSelection; + if (LocalSettings.LastBenchName != null) + { + loginDlgBenchSelection = new LoginDlgWithBenchSelection(LocalSettings.LastBenchName); + } + else + { + loginDlgBenchSelection = new LoginDlgWithBenchSelection(); + } + DialogResult dr = loginDlgBenchSelection.ShowDialog(); + + if (dr == DialogResult.Cancel) + { + return; /// Login canceled --> Exit application + } + else + { + for (int i = 0; i < LocalSettings.BenchesCount; i++) + { + if (LocalSettings.TestBenches[i].BenchName == loginDlgBenchSelection.BenchName) + { + Entities.User loadedUser = null; + try + { + bool authorized = false; + + /// Load user from the UsersAndGroupsDB database + loadedUser = Entities.User.LoadUserByName(loginDlgBenchSelection.User, + LocalSettings.TestBenches[i].UsersDBSettings); + if (loadedUser != null) + { + authorized = loadedUser.Authorize(loginDlgBenchSelection.User, loginDlgBenchSelection.Password); + } + + if (authorized) + { + log.InfoFormat("Password accepted, bench '{0}' parameters loaded.", LocalSettings.TestBenches[i].BenchName); + + /// Copy the selected bench settings to CurrentBench. + /// Clone() guarantees that current bench settings wont be modified + /// when user modifies the database settings in DatabaseSettingsDlg. + CurrentBench = (DatabaseSettings)LocalSettings.TestBenches[i].Clone(); + + /// Save the selection to local settings + LocalSettings.LastBenchName = CurrentBench.BenchName; + + retryLogin = false; + break; + } + + if (retryLogin) + { + /// Close Fluent NHibernate + MessageBox.Show(Strings.Invalid_user_password_or_bench, Strings.Error, MessageBoxButtons.OK); + } + } + catch (Exception e) + { + /// Database connect failed, ask what to do + switch ((new Forms.NoBenchOrDatabaseDlg { Message = Strings.NoDatabaseMsg, ShowRetry = true }).ShowDialog()) + { + case DialogResult.Abort: return; /// Exit program + case DialogResult.Retry: break; /// Retry the loop + default: + /// Open 'DatabaseSetingsDlg' and retry DB connect on OK + if (new Forms.EnterPasswordDlg { Password = AdminPassword } + .ShowDialog() == DialogResult.Cancel || + new BenchesDlg().ShowDialog() == DialogResult.Cancel) + { + return; /// Exit program + } + LocalSettings.Load(); + break; /// Retry the loop + } + } + } // if benchname is OK + } // for all benches in local settings loop + } // not Canceled + } //do + while (retryLogin); + + /// + /// Load the last procedure or create a new, default one + /// + if (LocalSettings.LastProcedureName != null) + { + IList listOfProcedures = FluentCommon.CreateSession(Database.Procedures) + .CreateQuery("FROM Procedure WHERE Name = :procName") + .SetParameter("procName", LocalSettings.LastProcedureName) + .List(); + + if (listOfProcedures.Count == 1) + { + log.InfoFormat("Pre-selecting the procedure {0}", LocalSettings.LastProcedureName); + SelectedProcedure = listOfProcedures[0]; + } + } + + /// Open the main application window + log.Info("Creating the main window"); + MainWnd = new MainWnd(); + log.Info("Opening the main window"); + Application.Run(MainWnd); + + /// Save local settings + log.Info("The main window was closed, saving the local parameters"); + LocalSettings.Save(); + + /// Close Fluent NHibernate + /// Todo + + log.Info("Exiting application."); + } + } +} \ No newline at end of file diff --git a/TestBenchFramework/Properties/AssemblyInfo.cs b/TestBenchFramework/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..17f275f55 --- /dev/null +++ b/TestBenchFramework/Properties/AssemblyInfo.cs @@ -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("TestBenchFramework")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Sensus")] +[assembly: AssemblyProduct("TestBenchFramework")] +[assembly: AssemblyCopyright("Copyright © 2013")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("2c13538e-15ee-48b2-af0f-2c95afb67186")] + +// 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")] diff --git a/TestBenchFramework/Properties/DataSources/TestBenchFramework.Entities.Pressure.datasource b/TestBenchFramework/Properties/DataSources/TestBenchFramework.Entities.Pressure.datasource new file mode 100644 index 000000000..f2df087bc --- /dev/null +++ b/TestBenchFramework/Properties/DataSources/TestBenchFramework.Entities.Pressure.datasource @@ -0,0 +1,10 @@ + + + + TBF.Entities.Pressure, TestBenchFramework, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + \ No newline at end of file diff --git a/TestBenchFramework/Properties/Resources.Designer.cs b/TestBenchFramework/Properties/Resources.Designer.cs new file mode 100644 index 000000000..c7bf3ebac --- /dev/null +++ b/TestBenchFramework/Properties/Resources.Designer.cs @@ -0,0 +1,113 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.18052 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace TBF.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // 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", "4.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() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [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("TBF.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap Headpic { + get { + object obj = ResourceManager.GetObject("Headpic", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap sensus_logo { + get { + object obj = ResourceManager.GetObject("sensus_logo", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap TestFailedImage { + get { + object obj = ResourceManager.GetObject("TestFailedImage", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap TestNotDoneImage { + get { + object obj = ResourceManager.GetObject("TestNotDoneImage", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap TestPassedImage { + get { + object obj = ResourceManager.GetObject("TestPassedImage", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/TestBenchFramework/Properties/Resources.resx b/TestBenchFramework/Properties/Resources.resx new file mode 100644 index 000000000..561300c8d --- /dev/null +++ b/TestBenchFramework/Properties/Resources.resx @@ -0,0 +1,136 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\Resources\sensus-logo.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\TestFailedImage.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\TestNotDoneImage.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\TestPassedImage.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\Headpic.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/TestBenchFramework/Properties/Settings.Designer.cs b/TestBenchFramework/Properties/Settings.Designer.cs new file mode 100644 index 000000000..088683a2f --- /dev/null +++ b/TestBenchFramework/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.1008 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace TBF.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.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; + } + } + } +} diff --git a/TestBenchFramework/Properties/Settings.settings b/TestBenchFramework/Properties/Settings.settings new file mode 100644 index 000000000..39645652a --- /dev/null +++ b/TestBenchFramework/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/TestBenchFramework/Resources/Headpic.png b/TestBenchFramework/Resources/Headpic.png new file mode 100644 index 0000000000000000000000000000000000000000..003fb997c570d358999f25438f814263ce0c380f GIT binary patch literal 21028 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 Ly6p*mMDi{dkZ-mRYu zbcx&24;rKez(%Oq(Hb@3OaV{GWUg$W8lA`Nn{YDpz6O4w9{9}y))luRQWD3%u;iSv zRIilYwW=&4#aY`G-jm9TCXaMUD7|r+@IuN4ko1)VmWY_N-GdNSssDYuDRhHqt;w4r z0xb_kT1}mwJY(Ru9EPXT<-3^-gcaT<5}CTo5Sb7{^sXRBUC4)|r!+s@J&DV@2|2JE zm3jxdsxNLIR$&D+DNAz*j3m~n8FZ`qttt*Q3>gNM87WXM33-0p7cxp}Low!1i zx0*f*HAcWR+Ly=Z785^ZtXL~J=tg!TeM_h;?9c{w*lJzj90TcvS%U7$#5p%zs=rnL z*|+45w<}=}!xT1M06>pAVNjoqDwL}eLB>;p-8BvO>u4*= zo-(^Ywz3bKG=#mqiA|?ohp5KJz|_`3s4X;1u&;I0*@RnpzF7k=a#HcrL6!mS#lI+b zYfav}jBzwF=7tiTXJhcK78hMbJ?|z^xc~9`!mZ~Ul?0)CUr{a-7e~8xPu=wX^HwTFG7WI*LgguY(FEU? zsH3f`y8Dn$jW^0lSjLq7X*v@cR{A3dRCH_0;5+Cnv9x0z{g%$WF*uNzXY7>T`{NOZ z9EK(gh^5syzlW9U$pcTUfx{f5(@i`|>H`N(zV{L+oiCimR}?iI@W1&Vo4?L&K!1vb z=JES>dGf!9t`2)-^TN;#m4gs;hnWi>GY5MvnEX?>#J=oNBlkEw zpDivL{fMPHMAb0UP6iaZHMl}+c63pW_#yceKF?LY_)Bwr2KzU07*0D9M`0^6ye1=$ zlBdwf)bNm4dv53l_Kil#Jk2ET2Ion{-f_vUx^UY8Yy%mZDr=0Gm&pJMLq^h z%k2yGW$%!r0xz~;+_L7n;G6NWy3dJmj7QbJV^HB|aBa>eSBFT$CwvLz8&DQxcc=M!J^B<^6(WoZ}X^7a`8>dBR8iO0(vyEL23-CRd9~`0zPMu?g z+LE$tEbyLG>?_iZuPUKbJJNwScRAK2>I}(jw5N;>>oPpmkQFSU8?39`(yD=}qK77_ z>UorcjnI2!TW8uY`YG)@dqxbYV8^oAOF+=3Kr47aPAy%{=PCBl8M2s-kPW*-cIKx+ zeZkxiVO3T(@pGyQZSD*91S6G(+#_H%oV)38hm}hI!9*GdneoxuF$+^#Wt6wnred=J zV@vHlD{E<`%2j9}ViULJjN&?Busg1a=f8UL4d^NIg$FiCZ?)&1FIJG&Fu#IgEMDaWPAl}%gHTw#hZBm2f_E0nQGo~DKecti^x`j@;8+#DUZs_qck zT9?&;Ev`|q9gNk8zSAGe0$CU4=#(~7!6LgN{I#Ak8m1<{Vpg=qi`)^Z$`YAbA(B{L zJU<%yA@eRWb1fkrt}X%`Hpwh6iFhby-b43f`jYxzpz^81KK5<<;x|_9^t= ztq9CXzI_KYP{-bss@N4rK%uui2Z@dKb(b11A-80zsBCyO{#Gr%wNY~bb=9zkVvDIm zkN)PFB2$I1iXu$qGYuC#_oDhY%LGiIg+?0K4eu>+Ua9Ipn^tQQvAMH8>Na{)IUs)`<)XI(Ws!r+Cd!@@pe;&+K=LX^Gv;raMR= zLpGKQ)QlPuxMh!IhPb>Ey)Efg+}Dpn>SJF&I5~f_!DUg(srez9e)T|pWB{I) z@63f<>#d9C@%c%j7f71J;dO~qLSdA$&Uktv@R825)fYfaV~6FYq%sqD}nM7 zkBM^(=U)#!*k>qi-MuIQsEY04Ptj64~0pMdkH1 zHd8iUt>^Y$rz1Js2bxIydP4kkQp&{E3hFc~6VH&dK7!3ph0t?8C6Bn@_VZgKV$NJY zw>#_QHpJ%F)-2sHAAhcROS?_@wkJz?QkZj~97d9ZqyE%Q>~%N7Avcpd@T4({OmcN`1LkzWlcM9dPE#ml$l5F!CH6 z?XzNGVlTeQGE&y~_G<-4b5FZlqw~{^qY)RBOSDOv`?luOMRwZ`Z+ilZGU^`d?;FYc$g@j9Omm_=m6yB_3OlYC6`vd7Rd^Q)V& zAF(#O5a}g9Y}$z?-!_@VT{#NkL!iDb=eS!Xrb{ZlvO;%XcxzIl)qqxDWKmeF(yK^w z7(aOjItcona(-Pql@{RKOi%f2I3qD$7MFHP@gE8~pF=B6-XNk_(KGvvKqd@rgJB%Z zggL`95wsP$$aVj5VV~d_-(pCV)seio`7Q7t48&(&!3iL>#${gf|7Z@1`dN!7=@UVP=*M<-Q8Z1*>%hQv+@{4eI-X)cUl=rM1DQ;nWA)D)4%qSU9|;?~>4c3Cy?{>!?_K`V~xs zT^dIq|I;vTOL`_U^6i!#ZQkwI`L`cSafb&Q%D|Xb?a#!e=te9 z9KN=_;F<=wsWhYE6jSisU(OYq`%m_U=jS0wu4sR9Xw_BEly)$|NxIF?17GOZ1(Vz) z*&jE#E_&g{D5`PmyKOSj&^PTrwDC~#z#fB&3`XM2u*64K5o%=L5WBWkPGHp_;s>h{U*Gh*(!ifC-CddRaXU{>@QTh z;Ku1d!hT~dtx_t4V5-x2-UWru}}mTB6=Rz$5Fr%IPhK4-G;0XXd;O{|UPSQ%S? zLA;WjXWxrjMg2=Qz=US(_qYDU_j$Zgm*s&bIRVgZ{nYpddu2=7UT6J+=%&iGD*gP~ zbd7einmj}?mYZk0Pa8`0sy>C_t!8wvZ|H{$#pa}tU|7FC;ub^BT$dJx6^6ae9K%u) zu#pHYkN5WCCGxOrFkv(Ro>rH~{@`S)mZwVTT=gb#r|~!bIyjLx&2PTnXZ#B5F1pZAUZ z*CqHPWg8gr#U8^6jfKY#uzqmm0^|Z}bhfaz$W!u^$#74F1Hn1f`qh=0G~?oyrxkQ5 zV*pgN_?a-s=_kxa9&-b1aGN&{lwi3%cV{G^^Jv7#q}iMdvzpYKe7bonpVyn-AkG`% zM5i3~>)E8GCr7oPvg&r3rx~gmV+qW%Qr&uFsKRJGR(W>^}L|?&Ux+u*fT?F8`8r-!A~yr79bCR%Ro(jY@W{ew>A3o4ZZ#(BWmP6a{P#0zQ+1>%W_uv zbp7;PYo@Y{MKdXdUM5DvUzv^n*L$B%@0^VqJ7jeOpe8TtFQ_r>jKXR1!zPay^L`HB zhl7!&){DM{?HS54%>!Youy>Z1+tYlTX?-0LFYb-*bxCnDZET#pEeFjf!n6+F`wl&L zHP?xpc8#TbTQF}A_g)_U(dtL}>-p6rO4^`wBorO28rHtCz;fLVo>xos<{nq%L}^iN z*|u=H_VWiXX~#A1KUleN^=eOPd?K*F0vG4H8J(4_rF41!@2%2f%4$qnlsXEH*bP|u z;D>9Hk82(jZj2PvIK!fBWY)9FC=u(l#E|geL=3%XpJhUNSsC6VZN|fjl%HH*_B>j1 zf;uRs-T`veMY+Jp2bAvSl32~dOqhmGMy7U#>yA0m&VbTKeO;vrm;r$fJ8 z4{>$5Cg9Pd$MI052?+Wt4*?1Scol><794oM#cKz0gXYVi*jZS|bnBT~JL|tpNP$nw zS$#R#D{CQIUz;fC?SCR@58t95W>BDnMgjPdNR~AP3Cpd9T68LTQ)NYI&8l}ySt<)& zT-h!|$IXV;;mg1<=+-01*>}h9xclSP{wjxKX{LV7X}uU@-sMYk0V^nHtjXE9mJy~- zIl-)m%vn3=Tc$h)ZRQ}w3k;6d6i$|C7(CB18X72}hCtM6P%GFNdB24o1&*E>GQH84)I)RwItIXc$O^C-s6FPYifO9FSj|MLyrL#rt z!A1vT>A_4m!3jER=xf_f)`5 z%By}66pv0J?3}T>WSnj+$$%^Tr*s0i;fg=;RN`=L5V zn4~rCbe-rjcfZlpMqXvr@(1(-a}HzQkEP9oh5W|n>B?ZTkg~VTILu5dZa!SlXeKW; z)bUikEf**JOhEt(i~>xBl?A5>Wuv#7LTIqK32Aga!E6T7*8*5_t#+20_Fj@&XO696 zJsGgj&Kmt>CzgQN9AQv)Vuj+JBim=FkKd#H8X2Gx6#eipxTL$znI{5irZA ztyX;JyS|^Ghe^rtdTPkq?W)kUG0Z;A@2UKsm&EtaN?H8xuk|no;kP9AM(7`tuKC~J z{@=-|gWPG>to6^?|D&|ka&o)ul*N1h@FDwOOYrSe8p0@j-T&&Ge_G!3|4k78*SPAR zk$V3BUh`Zb`B$I(uZYJ_m>4%}$o=>= W^zDMibdKYagZq4bsQm84Z~q5b1cLnl literal 0 HcmV?d00001 diff --git a/TestBenchFramework/Resources/Strings.Designer.cs b/TestBenchFramework/Resources/Strings.Designer.cs new file mode 100644 index 000000000..addc52895 --- /dev/null +++ b/TestBenchFramework/Resources/Strings.Designer.cs @@ -0,0 +1,2145 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.18444 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace TBF.Resources { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // 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", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Strings { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Strings() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [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("TBF.Resources.Strings", typeof(Strings).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to <none>. + /// + internal static string _none_ { + get { + return ResourceManager.GetString("_none_", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to (offline). + /// + internal static string _offline { + get { + return ResourceManager.GetString("_offline", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Activity. + /// + internal static string Activity { + get { + return ResourceManager.GetString("Activity", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to &Add >. + /// + internal static string Add { + get { + return ResourceManager.GetString("Add", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Add. + /// + internal static string AddBtnText { + get { + return ResourceManager.GetString("AddBtnText", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Administrator. + /// + internal static string Administrator { + get { + return ResourceManager.GetString("Administrator", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Approval info.. + /// + internal static string Approval_info { + get { + return ResourceManager.GetString("Approval_info", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Arrangements of tested meters. + /// + internal static string Arrangement_of_meters { + get { + return ResourceManager.GetString("Arrangement_of_meters", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Arrangement of tests. + /// + internal static string Arrangement_of_tests { + get { + return ResourceManager.GetString("Arrangement_of_tests", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Available results:. + /// + internal static string Available_results { + get { + return ResourceManager.GetString("Available_results", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to < Back. + /// + internal static string BackBtnText { + get { + return ResourceManager.GetString("BackBtnText", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Balance. + /// + internal static string Balance { + get { + return ResourceManager.GetString("Balance", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Bench. + /// + internal static string Bench_chdr { + get { + return ResourceManager.GetString("Bench_chdr", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Test bench is not running, however you can change the settings to resolve the problem.. + /// + internal static string Bench_is_not_running { + get { + return ResourceManager.GetString("Bench_is_not_running", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Test bench name conflict, use another name please. + /// + internal static string Bench_name_conflict_Use_another_name_pls { + get { + return ResourceManager.GetString("Bench_name_conflict_Use_another_name_pls", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Bench parameters. + /// + internal static string Bench_parameters { + get { + return ResourceManager.GetString("Bench_parameters", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Calibration Specialist. + /// + internal static string Calibration_Specialist { + get { + return ResourceManager.GetString("Calibration_Specialist", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cancel. + /// + internal static string CancelBtnText { + get { + return ResourceManager.GetString("CancelBtnText", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Clear results. + /// + internal static string Clear_results { + get { + return ResourceManager.GetString("Clear_results", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Clear. + /// + internal static string ClearBtnText { + get { + return ResourceManager.GetString("ClearBtnText", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to close. + /// + internal static string close { + get { + return ResourceManager.GetString("close", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Close emptying valve. + /// + internal static string Close_emptying_valve { + get { + return ResourceManager.GetString("Close_emptying_valve", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Close. + /// + internal static string CloseBtnText { + get { + return ResourceManager.GetString("CloseBtnText", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Combined meters. + /// + internal static string Combined_meters { + get { + return ResourceManager.GetString("Combined_meters", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Component. + /// + internal static string Component { + get { + return ResourceManager.GetString("Component", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Configuration. + /// + internal static string Configuration { + get { + return ResourceManager.GetString("Configuration", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Configure. + /// + internal static string Configure { + get { + return ResourceManager.GetString("Configure", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Configure test benches (password required). + /// + internal static string ConfigureDatabaseText { + get { + return ResourceManager.GetString("ConfigureDatabaseText", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Confirmation. + /// + internal static string Confirmation { + get { + return ResourceManager.GetString("Confirmation", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Connection string. + /// + internal static string Connection_string { + get { + return ResourceManager.GetString("Connection_string", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Copy. + /// + internal static string CopyBtnText { + get { + return ResourceManager.GetString("CopyBtnText", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Corrected. + /// + internal static string Corrected { + get { + return ResourceManager.GetString("Corrected", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Correction [g]. + /// + internal static string Correction_g { + get { + return ResourceManager.GetString("Correction_g", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Correction [l/h]. + /// + internal static string Correction_lph { + get { + return ResourceManager.GetString("Correction_lph", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Correction [mbar]. + /// + internal static string Correction_mbar { + get { + return ResourceManager.GetString("Correction_mbar", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Create DB. + /// + internal static string Create_DB { + get { + return ResourceManager.GetString("Create_DB", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Database type. + /// + internal static string Database_type { + get { + return ResourceManager.GetString("Database_type", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The database was successfully created!. + /// + internal static string DB_was_successfully_created { + get { + return ResourceManager.GetString("DB_was_successfully_created", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The database will be overwritten. + /// + internal static string DB_will_be_overwritten { + get { + return ResourceManager.GetString("DB_will_be_overwritten", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Description. + /// + internal static string DescriptionColHdr { + get { + return ResourceManager.GetString("DescriptionColHdr", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Detection completed. + /// + internal static string Detection_completed { + get { + return ResourceManager.GetString("Detection_completed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Detection threshold [%]. + /// + internal static string DetectionThresholdPct { + get { + return ResourceManager.GetString("DetectionThresholdPct", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Diverter. + /// + internal static string Diverter { + get { + return ResourceManager.GetString("Diverter", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Do you want to proceed?. + /// + internal static string Do_you_want_to_proceed { + get { + return ResourceManager.GetString("Do_you_want_to_proceed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Do you want to save the procedure?. + /// + internal static string Do_you_want_to_save_the_procedure { + get { + return ResourceManager.GetString("Do_you_want_to_save_the_procedure", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Down. + /// + internal static string DownBtnText { + get { + return ResourceManager.GetString("DownBtnText", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Duration [s]. + /// + internal static string Duration_s { + get { + return ResourceManager.GetString("Duration_s", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Edit. + /// + internal static string EditBtnText { + get { + return ResourceManager.GetString("EditBtnText", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Emergency STOP. + /// + internal static string Emergency_STOP { + get { + return ResourceManager.GetString("Emergency_STOP", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Emptying. + /// + internal static string Emptying_chdr { + get { + return ResourceManager.GetString("Emptying_chdr", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Emptying ({0}: step {1}/{2}). + /// + internal static string Emptying_i_n { + get { + return ResourceManager.GetString("Emptying_i_n", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Emptying the tank. + /// + internal static string Emptying_tank { + get { + return ResourceManager.GetString("Emptying_tank", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Emptying valve. + /// + internal static string Emptying_valve { + get { + return ResourceManager.GetString("Emptying_valve", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Enter password. + /// + internal static string Enter_password { + get { + return ResourceManager.GetString("Enter_password", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Err. cor. - [%]. + /// + internal static string Err_cor_neg_pct_chdr { + get { + return ResourceManager.GetString("Err_cor_neg_pct_chdr", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Err. cor. +[%]. + /// + internal static string Err_cor_pos_pct_chdr { + get { + return ResourceManager.GetString("Err_cor_pos_pct_chdr", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Err. Limit - [%]. + /// + internal static string Err_limit_neg_pct_chdr { + get { + return ResourceManager.GetString("Err_limit_neg_pct_chdr", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Err. Limit + [%]. + /// + internal static string Err_limit_pos_pct_chdr { + get { + return ResourceManager.GetString("Err_limit_pos_pct_chdr", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Error. + /// + internal static string Error { + get { + return ResourceManager.GetString("Error", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Error loading users from the database:. + /// + internal static string Error_loading_users_from_the_database { + get { + return ResourceManager.GetString("Error_loading_users_from_the_database", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Error while creating the database. Reason: . + /// + internal static string Error_while_creating_DB_Reason { + get { + return ResourceManager.GetString("Error_while_creating_DB_Reason", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Exit. + /// + internal static string ExitBtnText { + get { + return ResourceManager.GetString("ExitBtnText", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to NOK. + /// + internal static string Failed { + get { + return ResourceManager.GetString("Failed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Failed to create a sample database:. + /// + internal static string Failed_to_create_a_sample_database { + get { + return ResourceManager.GetString("Failed_to_create_a_sample_database", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Failed to export the database:. + /// + internal static string Failed_to_export_the_database { + get { + return ResourceManager.GetString("Failed_to_export_the_database", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Feeding. + /// + internal static string Feeding_chdr { + get { + return ResourceManager.GetString("Feeding_chdr", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Fill the test bench with water?. + /// + internal static string Fill_with_water { + get { + return ResourceManager.GetString("Fill_with_water", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Finish. + /// + internal static string FinishBtnText { + get { + return ResourceManager.GetString("FinishBtnText", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Flow [m3/h]. + /// + internal static string Flow_m3h { + get { + return ResourceManager.GetString("Flow_m3h", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Flow Selection. + /// + internal static string Flow_selection { + get { + return ResourceManager.GetString("Flow_selection", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Get mass of water in the tank. + /// + internal static string Get_mass_of_water_in_the_tank { + get { + return ResourceManager.GetString("Get_mass_of_water_in_the_tank", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Head of Lab. + /// + internal static string Head_of_Lab { + get { + return ResourceManager.GetString("Head_of_Lab", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Horizontally. + /// + internal static string Horizontally { + get { + return ResourceManager.GetString("Horizontally", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Ignore. + /// + internal static string Ignore { + get { + return ResourceManager.GetString("Ignore", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Invalid password. + /// + internal static string Invalid_password { + get { + return ResourceManager.GetString("Invalid_password", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Invalid user, password, or bench. + /// + internal static string Invalid_user_password_or_bench { + get { + return ResourceManager.GetString("Invalid_user_password_or_bench", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Invalid username or password. + /// + internal static string Invalid_username_or_password { + get { + return ResourceManager.GetString("Invalid_username_or_password", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Loading the procedure. + /// + internal static string Loading_the_procedure { + get { + return ResourceManager.GetString("Loading_the_procedure", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Lock. + /// + internal static string LockBtnText { + get { + return ResourceManager.GetString("LockBtnText", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Logging. + /// + internal static string Logging { + get { + return ResourceManager.GetString("Logging", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Maintenance Specialist. + /// + internal static string Maintenance_Specialist { + get { + return ResourceManager.GetString("Maintenance_Specialist", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Make tank empty. + /// + internal static string Make_tank_empty { + get { + return ResourceManager.GetString("Make_tank_empty", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Mass [kg]. + /// + internal static string Mass_kg { + get { + return ResourceManager.GetString("Mass_kg", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to (max. _X_ alphanumeric characters). + /// + internal static string MaxChars { + get { + return ResourceManager.GetString("MaxChars", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Measure the mass. + /// + internal static string Measure_the_mass { + get { + return ResourceManager.GetString("Measure_the_mass", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Measured. + /// + internal static string Measured { + get { + return ResourceManager.GetString("Measured", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Measuring the weight. + /// + internal static string Measuring_the_weight { + get { + return ResourceManager.GetString("Measuring_the_weight", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Test method. + /// + internal static string Method_chdr { + get { + return ResourceManager.GetString("Method_chdr", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Test method selection. + /// + internal static string Method_selection { + get { + return ResourceManager.GetString("Method_selection", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Metrological class. + /// + internal static string Metrological_class { + get { + return ResourceManager.GetString("Metrological_class", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Metrologist. + /// + internal static string Metrologist { + get { + return ResourceManager.GetString("Metrologist", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Metrology. + /// + internal static string Metrology { + get { + return ResourceManager.GetString("Metrology", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Mode. + /// + internal static string Mode { + get { + return ResourceManager.GetString("Mode", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Name. + /// + internal static string Name { + get { + return ResourceManager.GetString("Name", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to PBench. + /// + internal static string New_bench_path_name { + get { + return ResourceManager.GetString("New_bench_path_name", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to PFeed. + /// + internal static string New_feeding_path_name { + get { + return ResourceManager.GetString("New_feeding_path_name", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to - Copy. + /// + internal static string New_name_copy { + get { + return ResourceManager.GetString("New_name_copy", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to PQ. + /// + internal static string New_output_path_name { + get { + return ResourceManager.GetString("New_output_path_name", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Procedure. + /// + internal static string New_procedure_name { + get { + return ResourceManager.GetString("New_procedure_name", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to PSens. + /// + internal static string New_sensors_path_name { + get { + return ResourceManager.GetString("New_sensors_path_name", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Test. + /// + internal static string New_test_name { + get { + return ResourceManager.GetString("New_test_name", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to New transition name. + /// + internal static string New_transition_name { + get { + return ResourceManager.GetString("New_transition_name", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to New Tab. + /// + internal static string NewTabBtnText { + get { + return ResourceManager.GetString("NewTabBtnText", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Next >. + /// + internal static string NextBtnText { + get { + return ResourceManager.GetString("NextBtnText", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to no. + /// + internal static string no { + get { + return ResourceManager.GetString("no", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to No test bench in the program configuration.. + /// + internal static string NoBenchMsg { + get { + return ResourceManager.GetString("NoBenchMsg", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to No. + /// + internal static string NoBtn { + get { + return ResourceManager.GetString("NoBtn", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot connect to the database.. + /// + internal static string NoDatabaseMsg { + get { + return ResourceManager.GetString("NoDatabaseMsg", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to <nothing to configure>. + /// + internal static string nothing_to_configure { + get { + return ResourceManager.GetString("nothing_to_configure", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Notification. + /// + internal static string Notification { + get { + return ResourceManager.GetString("Notification", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Nr.. + /// + internal static string Nr { + get { + return ResourceManager.GetString("Nr", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to OK. + /// + internal static string OkBtnText { + get { + return ResourceManager.GetString("OkBtnText", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to open. + /// + internal static string open { + get { + return ResourceManager.GetString("open", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Output. + /// + internal static string Output_chdr { + get { + return ResourceManager.GetString("Output_chdr", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to P in. + /// + internal static string P_in { + get { + return ResourceManager.GetString("P_in", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to P out. + /// + internal static string P_out { + get { + return ResourceManager.GetString("P_out", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Parameters. + /// + internal static string Parameters { + get { + return ResourceManager.GetString("Parameters", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Parent. + /// + internal static string Parent { + get { + return ResourceManager.GetString("Parent", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to OK. + /// + internal static string Passed { + get { + return ResourceManager.GetString("Passed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Password. + /// + internal static string Password { + get { + return ResourceManager.GetString("Password", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Please change the following settings:. + /// + internal static string Please_change_the_following_settings { + get { + return ResourceManager.GetString("Please_change_the_following_settings", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Please select a cycle, a_test or empty. + /// + internal static string Please_select_a_cycle_a_test_or_empty { + get { + return ResourceManager.GetString("Please_select_a_cycle_a_test_or_empty", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Please select a procedure. + /// + internal static string Please_select_a_procedure { + get { + return ResourceManager.GetString("Please_select_a_procedure", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Please select a test. + /// + internal static string Please_select_a_test { + get { + return ResourceManager.GetString("Please_select_a_test", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Please, select a test bench. + /// + internal static string PLs_select_testbench { + get { + return ResourceManager.GetString("PLs_select_testbench", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Power [%]. + /// + internal static string PowerPct { + get { + return ResourceManager.GetString("PowerPct", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Pressure [bar]. + /// + internal static string Pressure_bar { + get { + return ResourceManager.GetString("Pressure_bar", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Pressure meter. + /// + internal static string Pressure_meter { + get { + return ResourceManager.GetString("Pressure_meter", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Printer. + /// + internal static string Printer { + get { + return ResourceManager.GetString("Printer", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Procedure. + /// + internal static string Procedure { + get { + return ResourceManager.GetString("Procedure", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Procedures. + /// + internal static string Procedures { + get { + return ResourceManager.GetString("Procedures", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Producer. + /// + internal static string Producer { + get { + return ResourceManager.GetString("Producer", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Progress. + /// + internal static string Progress { + get { + return ResourceManager.GetString("Progress", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Properties. + /// + internal static string Properties { + get { + return ResourceManager.GetString("Properties", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Pulses per liter. + /// + internal static string PulsesPerLtr { + get { + return ResourceManager.GetString("PulsesPerLtr", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Pump. + /// + internal static string Pump { + get { + return ResourceManager.GetString("Pump", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Purging. + /// + internal static string Purging { + get { + return ResourceManager.GetString("Purging", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Purging ({0}: step {1}/{2}). + /// + internal static string Purging_i_n { + get { + return ResourceManager.GetString("Purging_i_n", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Q from [l/h]. + /// + internal static string Q_from_lph { + get { + return ResourceManager.GetString("Q_from_lph", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Q from [m3/h]. + /// + internal static string Q_from_m3h { + get { + return ResourceManager.GetString("Q_from_m3h", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Q-Set Method. + /// + internal static string Q_set_method_chdr { + get { + return ResourceManager.GetString("Q_set_method_chdr", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Q to [l/h]. + /// + internal static string Q_to_lph { + get { + return ResourceManager.GetString("Q_to_lph", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Q to [m3/h]. + /// + internal static string Q_to_m3h { + get { + return ResourceManager.GetString("Q_to_m3h", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Qn. + /// + internal static string Qn { + get { + return ResourceManager.GetString("Qn", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Question. + /// + internal static string Question { + get { + return ResourceManager.GetString("Question", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Rate of change [%]. + /// + internal static string RateOfChangePct { + get { + return ResourceManager.GetString("RateOfChangePct", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Ready. + /// + internal static string Ready { + get { + return ResourceManager.GetString("Ready", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Red. type. + /// + internal static string Red_type_chdr { + get { + return ResourceManager.GetString("Red_type_chdr", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Reference. + /// + internal static string Reference { + get { + return ResourceManager.GetString("Reference", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Reg. valve. + /// + internal static string Reg_valve { + get { + return ResourceManager.GetString("Reg_valve", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Relative Q from. + /// + internal static string RelativeQfrom { + get { + return ResourceManager.GetString("RelativeQfrom", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Relative Q to. + /// + internal static string RelativeQto { + get { + return ResourceManager.GetString("RelativeQto", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to < &Remove. + /// + internal static string Remove { + get { + return ResourceManager.GetString("Remove", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to << R&emove all. + /// + internal static string Remove_all { + get { + return ResourceManager.GetString("Remove_all", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Remove. + /// + internal static string RemoveBtnText { + get { + return ResourceManager.GetString("RemoveBtnText", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Remove Tab. + /// + internal static string RemoveTabBtnText { + get { + return ResourceManager.GetString("RemoveTabBtnText", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Rename Tab. + /// + internal static string RenameTabBtnText { + get { + return ResourceManager.GetString("RenameTabBtnText", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Repeats nr.. + /// + internal static string Repeats_nr_chdr { + get { + return ResourceManager.GetString("Repeats_nr_chdr", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You must restart to apply these changes. + /// + internal static string Restart_To_Apply_Changes { + get { + return ResourceManager.GetString("Restart_To_Apply_Changes", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Retry connection to the database. + /// + internal static string RetryDatabaseText { + get { + return ResourceManager.GetString("RetryDatabaseText", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to ROI Detection in Progress. + /// + internal static string ROI_Detection_in_Progress { + get { + return ResourceManager.GetString("ROI_Detection_in_Progress", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Selected results:. + /// + internal static string Selected_results { + get { + return ResourceManager.GetString("Selected_results", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Sensor . + /// + internal static string Sensor_ { + get { + return ResourceManager.GetString("Sensor_", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Sensors. + /// + internal static string Sensors { + get { + return ResourceManager.GetString("Sensors", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Sensors. + /// + internal static string Sensors_chdr { + get { + return ResourceManager.GetString("Sensors_chdr", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Set flow. + /// + internal static string Set_flow { + get { + return ResourceManager.GetString("Set_flow", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Set route. + /// + internal static string Set_route { + get { + return ResourceManager.GetString("Set_route", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Setting the flow. + /// + internal static string Setting_the_flow { + get { + return ResourceManager.GetString("Setting_the_flow", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Start the pump. + /// + internal static string Start_the_pump { + get { + return ResourceManager.GetString("Start_the_pump", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Start the test. + /// + internal static string Start_the_test { + get { + return ResourceManager.GetString("Start_the_test", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Starting the cameras. + /// + internal static string Starting_the_cameras { + get { + return ResourceManager.GetString("Starting_the_cameras", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Stop the pump. + /// + internal static string Stop_the_pump { + get { + return ResourceManager.GetString("Stop_the_pump", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Stop the test. + /// + internal static string Stop_the_test { + get { + return ResourceManager.GetString("Stop_the_test", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Stopping. + /// + internal static string Stopping { + get { + return ResourceManager.GetString("Stopping", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to . + /// + internal static string String1 { + get { + return ResourceManager.GetString("String1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Switching flow detection. + /// + internal static string Switching_flow_detection { + get { + return ResourceManager.GetString("Switching_flow_detection", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to T div.. + /// + internal static string T_div { + get { + return ResourceManager.GetString("T_div", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to T in. + /// + internal static string T_in { + get { + return ResourceManager.GetString("T_in", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to T out. + /// + internal static string T_out { + get { + return ResourceManager.GetString("T_out", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Target Q [m3/h]. + /// + internal static string TargetQ { + get { + return ResourceManager.GetString("TargetQ", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Tarring. + /// + internal static string Tarring { + get { + return ResourceManager.GetString("Tarring", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Test. + /// + internal static string Test { + get { + return ResourceManager.GetString("Test", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Test bench. + /// + internal static string Test_bench { + get { + return ResourceManager.GetString("Test_bench", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Test Bench Components Configuration. + /// + internal static string Test_Bench_Components_Configuration { + get { + return ResourceManager.GetString("Test_Bench_Components_Configuration", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Test Bench Databases Specification. + /// + internal static string Test_Bench_Databases_Specification { + get { + return ResourceManager.GetString("Test_Bench_Databases_Specification", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Test bench is controlled by this computer. + /// + internal static string Test_bench_is_controlled_by_this_computer { + get { + return ResourceManager.GetString("Test_bench_is_controlled_by_this_computer", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Test bench name. + /// + internal static string Test_bench_name { + get { + return ResourceManager.GetString("Test_bench_name", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Test bench number. + /// + internal static string Test_bench_number { + get { + return ResourceManager.GetString("Test_bench_number", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Test. + /// + internal static string Test_chdr { + get { + return ResourceManager.GetString("Test_chdr", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Test completed. + /// + internal static string Test_completed { + get { + return ResourceManager.GetString("Test_completed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Test connection. + /// + internal static string Test_connection { + get { + return ResourceManager.GetString("Test_connection", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Test in progress. + /// + internal static string Test_in_progress { + get { + return ResourceManager.GetString("Test_in_progress", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Test. + /// + internal static string Test_measured_corrected { + get { + return ResourceManager.GetString("Test_measured_corrected", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Test method. + /// + internal static string Test_method { + get { + return ResourceManager.GetString("Test_method", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Test name. + /// + internal static string Test_name { + get { + return ResourceManager.GetString("Test_name", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Test preparation. + /// + internal static string Test_preparation { + get { + return ResourceManager.GetString("Test_preparation", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Test start ({0}: step {1}/{2}). + /// + internal static string Test_start_sequence_i_n { + get { + return ResourceManager.GetString("Test_start_sequence_i_n", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Test stop ({0}: step {1}/{2}). + /// + internal static string Test_stop_sequence_i_n { + get { + return ResourceManager.GetString("Test_stop_sequence_i_n", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Test time [s]. + /// + internal static string Test_time_s_chdr { + get { + return ResourceManager.GetString("Test_time_s_chdr", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Tester. + /// + internal static string Tester { + get { + return ResourceManager.GetString("Tester", resourceCulture); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap testFailedImage { + get { + object obj = ResourceManager.GetObject("testFailedImage", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized string similar to Testing Specialist. + /// + internal static string Testing_Specialist { + get { + return ResourceManager.GetString("Testing_Specialist", resourceCulture); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap testNotDoneImage { + get { + object obj = ResourceManager.GetObject("testNotDoneImage", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap testPassedImage { + get { + object obj = ResourceManager.GetObject("testPassedImage", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized string similar to Tests are columns. + /// + internal static string Tests_are_columns { + get { + return ResourceManager.GetString("Tests_are_columns", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Tests are rows. + /// + internal static string Tests_are_rows { + get { + return ResourceManager.GetString("Tests_are_rows", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Toler. red. [%]. + /// + internal static string Tol_red_pct_chdr { + get { + return ResourceManager.GetString("Tol_red_pct_chdr", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Transition - End. + /// + internal static string TransitionEnd_chdr { + get { + return ResourceManager.GetString("TransitionEnd_chdr", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Transitions. + /// + internal static string Transitions { + get { + return ResourceManager.GetString("Transitions", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Transition - Start. + /// + internal static string TransitionStart_chdr { + get { + return ResourceManager.GetString("TransitionStart_chdr", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Type. + /// + internal static string Type { + get { + return ResourceManager.GetString("Type", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unhandled error occured in . + /// + internal static string Unhandled_error_occured_in_ { + get { + return ResourceManager.GetString("Unhandled_error_occured_in_", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unlock. + /// + internal static string UnlockBtnText { + get { + return ResourceManager.GetString("UnlockBtnText", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Up. + /// + internal static string UpBtnText { + get { + return ResourceManager.GetString("UpBtnText", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to User : . + /// + internal static string User_ { + get { + return ResourceManager.GetString("User_", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to User Login. + /// + internal static string User_Login { + get { + return ResourceManager.GetString("User_Login", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to User name. + /// + internal static string User_name { + get { + return ResourceManager.GetString("User_name", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Username. + /// + internal static string Username { + get { + return ResourceManager.GetString("Username", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to This Username has already been taken. Please choose another one.. + /// + internal static string Username_taken { + get { + return ResourceManager.GetString("Username_taken", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Users and groups. + /// + internal static string Users_and_groups { + get { + return ResourceManager.GetString("Users_and_groups", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Version. + /// + internal static string Version { + get { + return ResourceManager.GetString("Version", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Vertically. + /// + internal static string Vertically { + get { + return ResourceManager.GetString("Vertically", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Volume and error limit selection. + /// + internal static string Volume_and_error_selection { + get { + return ResourceManager.GetString("Volume_and_error_selection", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Volume [l]. + /// + internal static string Volume_ltr_chdr { + get { + return ResourceManager.GetString("Volume_ltr_chdr", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Warning. + /// + internal static string Warning { + get { + return ResourceManager.GetString("Warning", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Water meter data. + /// + internal static string Water_meter_data { + get { + return ResourceManager.GetString("Water_meter_data", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Water meter types. + /// + internal static string Water_meter_types { + get { + return ResourceManager.GetString("Water_meter_types", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Water meters. + /// + internal static string Water_meters { + get { + return ResourceManager.GetString("Water_meters", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to yes. + /// + internal static string yes { + get { + return ResourceManager.GetString("yes", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Yes. + /// + internal static string YesBtn { + get { + return ResourceManager.GetString("YesBtn", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Zeroing. + /// + internal static string Zeroing_chdr { + get { + return ResourceManager.GetString("Zeroing_chdr", resourceCulture); + } + } + } +} diff --git a/TestBenchFramework/Resources/Strings.de.Designer.cs b/TestBenchFramework/Resources/Strings.de.Designer.cs new file mode 100644 index 000000000..e69de29bb diff --git a/TestBenchFramework/Resources/Strings.de.resx b/TestBenchFramework/Resources/Strings.de.resx new file mode 100644 index 000000000..7f35f2551 --- /dev/null +++ b/TestBenchFramework/Resources/Strings.de.resx @@ -0,0 +1,738 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Fehler + + + Fehler beim Laden der Benutzer aus der Datenbank. + + + Fehler beim Erzeugen der Bespiel-Ddaten. + + + Fehler beim Exportieren der Datenbank. + + + Ungueltiger Benutzername, Passwort oder Prüfstand + + + Passwort + + + Bitte wählen Sie einen Prüfstand aus. + + + Bitte starten Sie die Anwendung erneut um die Änderungen zu übernehmen. + + + Prüfstandsdaten + + + Benutzername + + + Warnung + + + (maximal _X_ alphanumerische Zeichen) + + + Dieser Benutzername ist bereits vergeben. Bitte wählen Sie einen anderen. + + + geschl. + + + Klappe + + + Beh.Leeren + + + Name + + + offen + + + Pumpe + + + P ein. + + + P aus. + + + Q von + + + Q bis + + + IDM + + + Reg.Ventil + + + Waage + + + Messs. + + + T Klappe + + + T ein. + + + T aus. + + + Drucksensor + + + Dauer [s] + + + Nein + + + ja + + + PBank + + + PS + + + PQ + + + Prüfung + + + PMess + + + Prüfpunkt + + + - Kopie + + + Benutzername + + + Anmelden + + + Neu + + + Abbrechen + + + Kopieren + + + Abwärts + + + Bearbeiten + + + OK + + + Löschen + + + Aufwärts + + + Beenden + + + Ändern + + + Beschreibung + + + Prüfung + + + Prüfvorlagen + + + Prüfpunkt + + + Prüfstrecke + + + Leeren + + + Fehl. Korr.- [%] + + + Fehl. Korr.+ [%] + + + Fehlergrenze - [%] + + + Fehlergrenze + [%] + + + Eingang + + + Prüfenvahren + + + Regelstrecke + + + Q von [l/h] + + + Q von [m3/h] + + + Q-Set Methode + + + Q bis [l/h] + + + Q bis [m3/h] + + + Reduktionsart + + + Wiederh. Nr. + + + Abtastsysteme + + + Prüfpunkt + + + Tol. Abzug [%] + + + Volumen [l] + + + Nullstellen + + + Dauer [s] + + + Metr.Daten + + + Benutzer : + + + Die Prüfstation läuft nicht. Sie können die Einstellungen ändern, um das Problem zu löschen. + + + Der Prüfstationsname ist ungültig. Bitte wählen Sie einen anderen Namen. + + + Prüfstation konfigurieren (Passwort erforderlich) + + + Bestätigung + + + korrigiert + + + Korrektur [g] + + + Korrektur [l/h] + + + Korrektur [mbar] + + + Die Datenbank wurde erfolgreich erstellt. + + + Die vorhandene Datenbank wird überschrieben. + + + Möchten Sie fortfahren? + + + Möchten Sie den Prüfvorgang speichern? + + + Passwort eingeben. + + + Fehler beim Erzeugen der Datenbank. + + + Beenden + + + Durchfluss [m³/h] + + + Ungültiges Passwort + + + Ungültiger Benutzername oder Passwort + + + Abschließen + + + Masse [kg] + + + Gemessen + + + Es ist keine Prüfstation in der Programmkonfiguration definiert. + + + Datenbankverbindung konnte nicht hergestellt werden. + + + Benachrichtigung + + + Nr. + + + Bitte ändern Sie die folgenden Einstellungen: + + + Druck [bar] + + + Eigenschaften + + + Datenbankverbindung wiederherstellen + + + Es trat ein unbehandelter Fehler auf in + + + (Getrennt) + + + Administrator + + + Kalibriertechniker + + + Laborleiter + + + Wartungstechniker + + + Messtechniker + + + Prüfer + + + Prüftechniker + + + schließe das Leeren-Ventil + + + Ermittle das Gewicht des Wassers im Tank + + + Ignorieren + + + Laden des Prüfvorgangs + + + Tank leeren + + + wiegen + + + Wählen Sie einen Prüfvorgang + + + Bitte wählen Sie eine Prüfung aus. + + + Befüllen + + + Fertig + + + setze Durchfluss + + + Setze Route + + + Starte die Pumpe + + + Starte die Prüfung + + + am stoppen + + + Stoppe die Pumpe + + + Stoppe die Prüfung + + + Tara setzen + + + Prüfung läuft + + + Prüfvorlage + + + < Zurück + + + Weiter > + + + <kein> + + + Messsensoren + + + Prüfenvahren + + + Ergebnise leeren + + + Konfigurieren + + + Arrangement_of_meters + + + Arrangement_of_tests + + + Horizontal + + + Prüfpunkte sind Spalten + + + Prüfpunkte sind Zeilen + + + Vertikal + + + Konfiguration + + + NiO + + + iO + + + Leeren + + + Tank entleeren + + + Wiegen + + + Prüfdurchfluss anfahren + + + Prüfpunkt fertiggestellt + + + Prüfpunktvorbereitung + + + Prüfstand befüllen ({0}/{1}) + + + Prüfstand leeren ({0}/{1}) + + + Beenden + + + Umschaltpunkt suchen + + + Aktivität + + + Verlauf + + + Ende + + + Ziel Q [m3/h] + + + Zulassungszeichen + + + Metr. Klasse + + + Hersteller + + + Zählers + + + Drucker + + + Version + + + Prüfstand Nr. + + + <nothing to configure> + + + Füllen mit Wasser ? + + + Nein + + + Frage + + + Ja + + + Prüfstand Parameter + + + Verbindungszeichenfolge + + + Datenbank erzeugen + + + Datenbank Typ + + + Prüfstand wird von diesem Computer gesteuert + + + Prüfstandsname + + + Teste Verbindung + + + Benutzer und Gruppen + + + Wasserzähler Daten + + + Wasserzähler Typen + + + Protokoll + + + Modus + + + Parameter + + + übergeordnete Komponente + + + Type + + + Prüfstandskomponenten Konfiguration + + + Übergänge + + + Komponente + + + Schwellwert [%] + + + Impulse pro Liter + + + Änderungsrate [%] + + + Relatives Q von + + + Relatives Q bis + + + Ubergang - Ende + + + Ubergang - Start + + \ No newline at end of file diff --git a/TestBenchFramework/Resources/Strings.resx b/TestBenchFramework/Resources/Strings.resx new file mode 100644 index 000000000..1cdf7db64 --- /dev/null +++ b/TestBenchFramework/Resources/Strings.resx @@ -0,0 +1,814 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Confirmation + + + Do you want to save the procedure? + + + Error + + + Error loading users from the database: + + + Failed to create a sample database: + + + Failed to export the database: + + + Invalid user, password, or bench + + + Password + + + Please, select a test bench + + + You must restart to apply these changes + + + Test bench + + + User name + + + Warning + + + (max. _X_ alphanumeric characters) + + + This Username has already been taken. Please choose another one. + + + close + + + Diverter + + + Emptying valve + + + Name + + + open + + + Pump + + + P in + + + P out + + + Q from [m3/h] + + + Q to [m3/h] + + + Reference + + + Reg. valve + + + Balance + + + Sensor + + + T div. + + + T in + + + T out + + + Pressure meter + + + Duration [s] + + + no + + + yes + + + PBench + + + PFeed + + + PQ + + + Procedure + + + PSens + + + Test + + + - Copy + + + Correction [g] + + + Nr. + + + Mass [kg] + + + Add + + + Cancel + + + Close + + + Lock + + + Remove + + + Unlock + + + OK + + + Correction [l/h] + + + Correction [mbar] + + + Flow [m3/h] + + + Pressure [bar] + + + Invalid username or password + + + Username + + + User Login + + + Copy + + + Down + + + Edit + + + Up + + + Cannot connect to the database. + + + Configure test benches (password required) + + + Exit + + + Retry connection to the database + + + Enter password + + + Invalid password + + + Test bench name conflict, use another name please + + + The database was successfully created! + + + The database will be overwritten + + + Do you want to proceed? + + + Notification + + + No test bench in the program configuration. + + + Description + + + Procedures + + + Procedure + + + Test + + + Corrected + + + Measured + + + Test + + + Test bench is not running, however you can change the settings to resolve the problem. + + + Volume [l] + + + Emptying + + + Q-Set Method + + + Repeats nr. + + + Test + + + Zeroing + + + Bench + + + Err. cor. - [%] + + + Err. cor. +[%] + + + Err. Limit - [%] + + + Err. Limit + [%] + + + Feeding + + + Output + + + Q from [l/h] + + + Q to [l/h] + + + Red. type + + + Sensors + + + Toler. red. [%] + + + Test time [s] + + + Error while creating the database. Reason: + + + Metrology + + + Please change the following settings: + + + Properties + + + Unhandled error occured in + + + User : + + + (offline) + + + Administrator + + + Calibration Specialist + + + Head of Lab + + + Maintenance Specialist + + + Metrologist + + + Tester + + + Testing Specialist + + + Close emptying valve + + + Get mass of water in the tank + + + Ignore + + + Loading the procedure + + + Make tank empty + + + Measure the mass + + + Please select a procedure + + + Please select a test + + + Purging + + + Ready + + + Set flow + + + Set route + + + Start the pump + + + Start the test + + + Stopping + + + Stop the pump + + + Stop the test + + + Tarring + + + Test in progress + + + < Back + + + Finish + + + Next > + + + Flow Selection + + + Test name + + + Test method + + + Relative Q from + + + Relative Q to + + + Target Q [m3/h] + + + Combined meters + + + Detection threshold [%] + + + Rate of change [%] + + + Pulses per liter + + + Component + + + <none> + + + Test method selection + + + Sensors + + + Test method + + + Volume and error limit selection + + + + testFailedImage.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + testNotDoneImage.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + testPassedImage.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + Clear results + + + Configure + + + Arrangements of tested meters + + + Arrangement of tests + + + Horizontally + + + Tests are columns + + + Tests are rows + + + Vertically + + + Configuration + + + NOK + + + OK + + + Clear + + + Emptying the tank + + + Measuring the weight + + + Setting the flow + + + Test completed + + + Test preparation + + + Purging ({0}: step {1}/{2}) + + + Emptying ({0}: step {1}/{2}) + + + Switching flow detection + + + Activity + + + Progress + + + + + + Please select a cycle, a_test or empty + + + Approval info. + + + Metrological class + + + Producer + + + Qn + + + Water meters + + + Printer + + + Version + + + Test bench number + + + <nothing to configure> + + + Fill the test bench with water? + + + No + + + Question + + + Yes + + + Bench parameters + + + Connection string + + + Create DB + + + Database type + + + Test Bench Databases Specification + + + Test bench is controlled by this computer + + + Test bench name + + + Test connection + + + Users and groups + + + Water meter data + + + Water meter types + + + Logging + + + Mode + + + Parameters + + + Parent + + + Type + + + Test Bench Components Configuration + + + Transitions + + + New Tab + + + Remove Tab + + + Rename Tab + + + New transition name + + + Power [%] + + + ROI Detection in Progress + + + Detection completed + + + Emergency STOP + + + Transition - End + + + Transition - Start + + + Starting the cameras + + + Test start ({0}: step {1}/{2}) + + + Test stop ({0}: step {1}/{2}) + + + &Add > + + + Available results: + + + < &Remove + + + << R&emove all + + + Selected results: + + \ No newline at end of file diff --git a/TestBenchFramework/Resources/Strings.sk.resx b/TestBenchFramework/Resources/Strings.sk.resx new file mode 100644 index 000000000..43d4b6faa --- /dev/null +++ b/TestBenchFramework/Resources/Strings.sk.resx @@ -0,0 +1,288 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + zavri + + + Klapka + + + Vypúšťací ventil + + + Chyba + + + Nepodarilo sa načítať používateľov z databázy: + + + Nepodarilo sa vytvoriť vzorovú databázu: + + + Nepodarilo sa exportovať databázu: + + + Neplatný používateľ, heslo alebo meno stanice + + + Názov + + + otvor + + + Heslo + + + Čerpadlo + + + P vst. + + + P výst. + + + Q od + + + Q do + + + Etalón + + + Reg. ventil + + + Aby sa zmenilo nastavenie jazyka musíte preštartovať program. + + + Váha + + + Senzor + + + Testovacia stanica + + + T kl. + + + T vst. + + + T výst. + + + Meno používateľa + + + Tlakomer + + + Doba [s] + + + nie + + + áno + + + PStol + + + PNapaj. + + + PQ + + + Procedúra + + + PSens + + + Test + + + - kópia + + + Parametre stanice + + + Reťazec na vytvorenie spojenia + + + Vytvor DB + + + Typ databázy + + + Procedúry + + + Specifikácia databáz stanice + + + Stanica je riadená týmto počítačom + + + Názov stanice + + + Test spojenia + + + Používatelia a skupiny + + + Water meter data + + + Typy vodomerov + + + Logovanie + + + Režim + + + Parametre + + + Nadradený komponent + + + + + + Typ + + + Konfigurácia komponentov stanice + + \ No newline at end of file diff --git a/TestBenchFramework/Resources/TestFailedImage.png b/TestBenchFramework/Resources/TestFailedImage.png new file mode 100644 index 0000000000000000000000000000000000000000..efe0770a1912e9e51d52be87ef49c09cb0aef471 GIT binary patch literal 263 zcmeAS@N?(olHy`uVBq!ia0vp^;vmey1|%P7U0DF6*pj^6T^Rm@;DWu&Cj&(|3p^r= z85sBugD~Uq{1qucLG}_)Usv{fOw0lb46NpB76XN*c)B=-cpQH_)ljIxfP>|5ul|PZ zU;guN+VY)y<0Yl$f(Z*J>phF$DDJ#eogdm5Cb9HG>Ysw#-`2~&+8kkysH)-Ix|Q|X zwT==oO`r2NRZ60HXMZq8Jur+nnZJ2%WpAUX+rejNZZb{dyXlf9FDbq0_X#y4t1}I@ zwn_=l=dvb>uswAmZ}8dfKwp z^BV3QXuk0J!dmwN{W}MQcL=>R(vwo&xX@K+<)kxB0&4c}`Q;Tmqh2?3W#<+bDl?~;cQJ@9)t$NPzv;Bg8;?sIaMF<~Tjerula<~6M>U-DlRZygUcu3C^kvRt z%_EmQZijX!J@_k@yIYJ`VRphsD}BS%9%aqPlLOC~Y`SexIsMR4t!vj#a;2ZV41cUh#f`nBF9Bdj(tfTjHkm9#Rg` ocg?3CHC}3F%E0iiJR{ey-Ol^Oy=(PPfKFoYboFyt=akR{07jcyl>h($ literal 0 HcmV?d00001 diff --git a/TestBenchFramework/Resources/sensus-logo.png b/TestBenchFramework/Resources/sensus-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..7e98708a5e11281bf629619f121fd32e857c035c GIT binary patch literal 21342 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 + + en + + + TestBench-SQLite + true + + SQLite + SQLite.db + + + SQLite + SQLite.db + + + SQLite + SQLite.db + + + SQLite + SQLite.db + + + SQLite + SQLite.db + + + + TestBench-MySQL + true + + MySql + SERVER=localhost; DATABASE=sensor; UID=root; PASSWORD=; + + + MySql + SERVER=localhost; DATABASE=sensor; UID=root; PASSWORD=; + + + MySql + SERVER=localhost; DATABASE=sensor; UID=root; PASSWORD=; + + + MySql + SERVER=localhost; DATABASE=sensor; UID=root; PASSWORD=; + + + MySql + SERVER=localhost; DATABASE=sensor; UID=root; PASSWORD=; + + + + TestBench-SQLite + \ No newline at end of file diff --git a/TestBenchFramework/SampleConfig/fuzhou150.sql b/TestBenchFramework/SampleConfig/fuzhou150.sql new file mode 100644 index 000000000..9696e17cb --- /dev/null +++ b/TestBenchFramework/SampleConfig/fuzhou150.sql @@ -0,0 +1,742 @@ +-- phpMyAdmin SQL Dump +-- version 3.4.5 +-- http://www.phpmyadmin.net +-- +-- Host: localhost +-- Generation Time: Mar 16, 2014 at 05:28 PM +-- Server version: 5.5.16 +-- PHP Version: 5.3.8 + +SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO"; +SET time_zone = "+00:00"; + + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; + +-- +-- Database: `fuzhou150` +-- + +-- -------------------------------------------------------- + +-- +-- Table structure for table `benchpath` +-- + +CREATE TABLE IF NOT EXISTS `benchpath` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `ItemNr` int(11) DEFAULT NULL, + `Name` varchar(255) DEFAULT NULL, + `Qfrom` float DEFAULT NULL, + `Qto` float DEFAULT NULL, + `TempIn` varchar(255) DEFAULT NULL, + `TempOut` varchar(255) DEFAULT NULL, + `PressIn` varchar(255) DEFAULT NULL, + `PressOut` varchar(255) DEFAULT NULL, + `ValvesOpen` varchar(8000) DEFAULT NULL, + `ValvesClose` varchar(8000) DEFAULT NULL, + PRIMARY KEY (`Id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=6 ; + +-- +-- Dumping data for table `benchpath` +-- + +INSERT INTO `benchpath` (`Id`, `ItemNr`, `Name`, `Qfrom`, `Qto`, `TempIn`, `TempOut`, `PressIn`, `PressOut`, `ValvesOpen`, `ValvesClose`) VALUES +(1, 0, '', 0, 0, '---', '---', '---', '---', '', 'VL12;VM1;VM2;VM3'), +(2, 1, 'Bench-all', 0, 400, 'T1', 'T2', 'D1', 'D2', 'VL12', 'VM1;VM2;VM3'), +(3, 2, 'Bench-WM1', 0, 400, 'T1', 'T2', 'D1', 'D2', 'VL12;VM2;VM3', 'VM1'), +(4, 3, 'Bench-WM2', 0, 400, 'T1', 'T2', 'D1', 'D2', 'VL12;VM1;VM3', 'VM2'), +(5, 4, 'Bench-WM3', 0, 400, 'T1', 'T2', 'D1', 'D2', 'VL12;VM1;VM2', 'VM3'); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `component` +-- + +CREATE TABLE IF NOT EXISTS `component` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `Name` varchar(255) DEFAULT NULL, + `ClassName` varchar(255) DEFAULT NULL, + `ParentName` varchar(255) DEFAULT NULL, + `ItemNr` int(11) DEFAULT NULL, + `Mode` varchar(255) DEFAULT NULL, + `Logging` varchar(255) DEFAULT NULL, + `Parameters` varchar(8000) DEFAULT NULL, + PRIMARY KEY (`Id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=83 ; + +-- +-- Dumping data for table `component` +-- + +INSERT INTO `component` (`Id`, `Name`, `ClassName`, `ParentName`, `ItemNr`, `Mode`, `Logging`, `Parameters`) VALUES +(1, 'CB', 'ControlBoard', NULL, 0, 'Normal', 'Off', '\r\n\r\n 1\r\n'), +(2, 'W1', 'MettlerToledoBalanceSN', NULL, 1, 'Normal', 'Off', '\r\n\r\n 3\r\n 2400\r\n Even\r\n 7\r\n One\r\n XOnXOff\r\n 3000\r\n'), +(3, 'W2', 'MettlerToledoBalanceSN', NULL, 2, 'Normal', 'Off', '\r\n\r\n 4\r\n 2400\r\n Even\r\n 7\r\n One\r\n XOnXOff\r\n 150\r\n'), +(4, 'Ambient', 'Greco Ambient', NULL, 3, 'Normal', 'Off', '\r\n\r\n 9\r\n 19200\r\n None\r\n 8\r\n One\r\n None\r\n'), +(5, 'Camera1', 'IdcCamera', NULL, 4, 'Simulate', 'Off', '\r\n\r\n 21\r\n 57600\r\n 0.5\r\n'), +(6, 'Camera2', 'IdcCamera', NULL, 5, 'Simulate', 'Off', '\r\n\r\n 22\r\n 57600\r\n 0.5\r\n'), +(7, 'Camera3', 'IdcCamera', NULL, 6, 'Simulate', 'Off', '\r\n\r\n 23\r\n 57600\r\n 0.5\r\n'), +(8, 'Camera4', 'IdcCamera', NULL, 7, 'Simulate', 'Off', '\r\n\r\n 24\r\n 57600\r\n 0.5\r\n'), +(9, 'Camera5', 'IdcCamera', NULL, 8, 'Simulate', 'Off', '\r\n\r\n 25\r\n 57600\r\n 0.5\r\n'), +(10, 'Camera6', 'IdcCamera', NULL, 9, 'Simulate', 'Off', '\r\n\r\n 26\r\n 57600\r\n 0.5\r\n'), +(11, 'I1', 'FlowMeter', 'CB', 10, 'Normal', 'Off', '\r\n\r\n 1\r\n 350\r\n'), +(12, 'I2', 'FlowMeter', 'CB', 11, 'Normal', 'Off', '\r\n\r\n 2\r\n 50\r\n'), +(13, 'I3', 'FlowMeter', 'CB', 12, 'Normal', 'Off', '\r\n\r\n 3\r\n 7\r\n'), +(14, 'I4', 'FlowMeter', 'CB', 13, 'Normal', 'Off', '\r\n\r\n 4\r\n 0.5\r\n'), +(15, 'VIR1', 'RegulationValve', 'CB', 14, 'Normal', 'Off', '\r\n\r\n 1\r\n 100\r\n 500\r\n 20\r\n'), +(16, 'VIR2', 'RegulationValve', 'CB', 15, 'Normal', 'Off', '\r\n\r\n 2\r\n 100\r\n 500\r\n 20\r\n'), +(17, 'VIR3', 'RegulationValve', 'CB', 16, 'Normal', 'Off', '\r\n\r\n 3\r\n 100\r\n 500\r\n 20\r\n'), +(18, 'VIR41', 'RegulationValve', 'CB', 17, 'Normal', 'Off', '\r\n\r\n 4\r\n 100\r\n 500\r\n 20\r\n'), +(19, 'VIR42', 'RegulationValve', 'CB', 18, 'Normal', 'Off', '\r\n\r\n 5\r\n 100\r\n 500\r\n 20\r\n'), +(20, 'T1', 'TempMeter', 'CB', 19, 'Normal', 'Off', '\r\n\r\n 0\r\n -21.0116\r\n 0.0017727\r\n 6.8422E-10\r\n -7.40415E-16\r\n 0\r\n'), +(21, 'T2', 'TempMeter', 'CB', 20, 'Normal', 'Off', '\r\n\r\n 1\r\n -21.0116\r\n 0.0017727\r\n 6.8422E-10\r\n -7.40415E-16\r\n 0\r\n'), +(22, 'T3', 'TempMeter', 'CB', 21, 'Normal', 'Off', '\r\n\r\n 2\r\n -21.0116\r\n 0.0017727\r\n 6.8422E-10\r\n -7.40415E-16\r\n 0\r\n'), +(23, 'T4', 'TempMeter', 'CB', 22, 'Normal', 'Off', '\r\n\r\n 3\r\n -21.0116\r\n 0.0017727\r\n 6.8422E-10\r\n -7.40415E-16\r\n 0\r\n'), +(24, 'T5', 'TempMeter', 'CB', 23, 'Normal', 'Off', '\r\n\r\n 4\r\n -21.0116\r\n 0.0017727\r\n 6.8422E-10\r\n -7.40415E-16\r\n 0\r\n'), +(25, 'T6', 'TempMeter', 'CB', 24, 'Normal', 'Off', '\r\n\r\n 5\r\n -21.0116\r\n 0.0017727\r\n 6.8422E-10\r\n -7.40415E-16\r\n 0\r\n'), +(26, 'D1', 'PressureMeter', 'CB', 25, 'Normal', 'Off', '\r\n\r\n 0\r\n 98\r\n'), +(27, 'D2', 'PressureMeter', 'CB', 26, 'Normal', 'Off', '\r\n\r\n 1\r\n 99\r\n'), +(28, 'Div1', 'Diverter', 'CB', 27, 'Normal', 'Off', '\r\n\r\n 34\r\n'), +(29, 'Div2', 'Diverter', 'CB', 28, 'Normal', 'Off', '\r\n\r\n 35\r\n'), +(30, 'Div3', 'Diverter', 'CB', 29, 'Normal', 'Off', '\r\n\r\n 36\r\n'), +(31, 'VL11', 'Valve', 'CB', 30, 'Normal', 'Off', '\r\n\r\n 2\r\n \r\n false\r\n 0\r\n 0\r\n'), +(32, 'VL13', 'Valve', 'CB', 31, 'Normal', 'Off', '\r\n\r\n 3\r\n \r\n false\r\n 0\r\n 0\r\n'), +(33, 'VL4', 'Valve', 'CB', 32, 'Normal', 'Off', '\r\n\r\n 4\r\n \r\n false\r\n 0\r\n 0\r\n'), +(34, 'VZ6', 'Valve', 'CB', 33, 'Normal', 'Off', '\r\n\r\n 5\r\n \r\n false\r\n 0\r\n 0\r\n'), +(35, 'VZ7', 'Valve', 'CB', 34, 'Normal', 'Off', '\r\n\r\n 6\r\n \r\n false\r\n 0\r\n 0\r\n'), +(36, 'VP5', 'Valve', 'CB', 35, 'Normal', 'Off', '\r\n\r\n 7\r\n \r\n false\r\n 0\r\n 0\r\n'), +(37, 'VP6', 'Valve', 'CB', 36, 'Normal', 'Off', '\r\n\r\n 8\r\n \r\n false\r\n 0\r\n 0\r\n'), +(38, 'VL12', 'Valve', 'CB', 37, 'Normal', 'Off', '\r\n\r\n 9\r\n \r\n false\r\n 0\r\n 0\r\n'), +(39, 'VZ14', 'Valve', 'CB', 38, 'Normal', 'Off', '\r\n\r\n 10\r\n \r\n false\r\n 0\r\n 0\r\n'), +(40, 'VI11', 'Valve', 'CB', 39, 'Normal', 'Off', '\r\n\r\n 11\r\n \r\n false\r\n 0\r\n 0\r\n'), +(41, 'VI12', 'Valve', 'CB', 40, 'Normal', 'Off', '\r\n\r\n 12\r\n \r\n false\r\n 0\r\n 0\r\n'), +(42, 'VI13', 'Valve', 'CB', 41, 'Normal', 'Off', '\r\n\r\n 13\r\n \r\n false\r\n 0\r\n 0\r\n'), +(43, 'VI21', 'Valve', 'CB', 42, 'Normal', 'Off', '\r\n\r\n 14\r\n \r\n false\r\n 0\r\n 0\r\n'), +(44, 'VI22', 'Valve', 'CB', 43, 'Normal', 'Off', '\r\n\r\n 15\r\n VI21\r\n false\r\n 0\r\n 0\r\n'), +(45, 'VI2p', 'Valve', 'CB', 44, 'Normal', 'Off', '\r\n\r\n 16\r\n \r\n false\r\n 0\r\n 0\r\n'), +(46, 'VI31', 'Valve', 'CB', 45, 'Normal', 'Off', '\r\n\r\n 17\r\n \r\n false\r\n 0\r\n 0\r\n'), +(47, 'VI32', 'Valve', 'CB', 46, 'Normal', 'Off', '\r\n\r\n 18\r\n VI31\r\n false\r\n 0\r\n 0\r\n'), +(48, 'VI3p', 'Valve', 'CB', 47, 'Normal', 'Off', '\r\n\r\n 19\r\n \r\n false\r\n 0\r\n 0\r\n'), +(49, 'VI41', 'Valve', 'CB', 48, 'Normal', 'Off', '\r\n\r\n 20\r\n \r\n false\r\n 0\r\n 0\r\n'), +(50, 'VI42', 'Valve', 'CB', 49, 'Normal', 'Off', '\r\n\r\n 21\r\n \r\n false\r\n 0\r\n 0\r\n'), +(51, 'VI43', 'Valve', 'CB', 50, 'Normal', 'Off', '\r\n\r\n 22\r\n \r\n false\r\n 0\r\n 0\r\n'), +(52, 'VI4p', 'Valve', 'CB', 51, 'Normal', 'Off', '\r\n\r\n 23\r\n \r\n false\r\n 0\r\n 0\r\n'), +(53, 'VB1', 'Valve', 'CB', 52, 'Normal', 'Off', '\r\n\r\n 24\r\n \r\n false\r\n 0\r\n 0\r\n'), +(54, 'VB1a', 'Valve', 'CB', 53, 'Normal', 'Off', '\r\n\r\n 25\r\n VB1\r\n false\r\n -2\r\n 2\r\n'), +(55, 'VB2', 'Valve', 'CB', 54, 'Normal', 'Off', '\r\n\r\n 26\r\n \r\n false\r\n 0\r\n 0\r\n'), +(56, 'VB2a', 'Valve', 'CB', 55, 'Normal', 'Off', '\r\n\r\n 27\r\n VB2\r\n false\r\n -2\r\n 2\r\n'), +(57, 'VM1', 'Valve', 'CB', 56, 'Normal', 'Off', '\r\n\r\n 28\r\n \r\n false\r\n 0\r\n 0\r\n'), +(58, 'VM2', 'Valve', 'CB', 57, 'Normal', 'Off', '\r\n\r\n 29\r\n \r\n false\r\n 0\r\n 0\r\n'), +(59, 'VM3', 'Valve', 'CB', 58, 'Normal', 'Off', '\r\n\r\n 30\r\n \r\n false\r\n 0\r\n 0\r\n'), +(60, 'Pump1', 'Pump', 'CB', 59, 'Normal', 'Off', '\r\n\r\n 32\r\n \r\n false\r\n'), +(61, 'Pump2', 'Pump', 'CB', 60, 'Normal', 'Off', '\r\n\r\n 37\r\n \r\n false\r\n'), +(62, 'Pump3', 'Pump', 'CB', 61, 'Normal', 'Off', '\r\n\r\n 38\r\n \r\n false\r\n'), +(63, 'Pump4', 'Pump', 'CB', 62, 'Normal', 'Off', '\r\n\r\n 33\r\n \r\n false\r\n'), +(64, 'Pump5', 'Pump', 'CB', 63, 'Normal', 'Off', '\r\n\r\n 39\r\n \r\n false\r\n'), +(65, 'Bench-ID', 'Bench-ID', NULL, 64, 'Normal', 'Off', '\r\n\r\n 1\r\n'), +(66, 'Results2Printer', 'BasicResultsPrinter', NULL, 65, 'Normal', 'Off', '\r\n'), +(67, 'Results2Disk', 'BasicResultsWriter', NULL, 66, 'Normal', 'Off', '\r\n'), +(68, 'FlyingStartMassCollection', 'Flying-Start-Collection', NULL, 67, 'Normal', 'Off', '\r\n'), +(69, 'CombinedMeters', 'CombinedMeters', NULL, 68, 'Normal', 'Off', '\r\n'), +(70, 'CombinedWithDetection', 'CombinedWithDetection', NULL, 69, 'Normal', 'Off', '\r\n'), +(71, 'Sick1', 'RegisterReader', 'CB', 70, 'Normal', 'Off', '\r\n\r\n 1\r\n'), +(72, 'Sick2', 'RegisterReader', 'CB', 71, 'Normal', 'Off', '\r\n\r\n 2\r\n'), +(73, 'Sick3', 'RegisterReader', 'CB', 72, 'Normal', 'Off', '\r\n\r\n 3\r\n'), +(74, 'Sick4', 'RegisterReader', 'CB', 73, 'Normal', 'Off', '\r\n\r\n 4\r\n'), +(75, 'Sick5', 'RegisterReader', 'CB', 74, 'Normal', 'Off', '\r\n\r\n 5\r\n'), +(76, 'Sick6', 'RegisterReader', 'CB', 75, 'Normal', 'Off', '\r\n\r\n 6\r\n'), +(77, 'WaterMeter1', 'WaterMeter', NULL, 76, 'Normal', 'Off', '\r\n\r\n \r\n 2.5\r\n \r\n A\r\n'), +(78, 'WaterMeter2', 'WaterMeter', NULL, 77, 'Normal', 'Off', '\r\n\r\n \r\n 2.5\r\n \r\n A\r\n'), +(79, 'WaterMeter3', 'WaterMeter', NULL, 78, 'Normal', 'Off', '\r\n\r\n \r\n 2.5\r\n \r\n A\r\n'), +(80, 'WaterMeter4', 'WaterMeter', NULL, 79, 'Normal', 'Off', '\r\n\r\n \r\n 2.5\r\n \r\n A\r\n'), +(81, 'WaterMeter5', 'WaterMeter', NULL, 80, 'Normal', 'Off', '\r\n\r\n \r\n 2.5\r\n \r\n A\r\n'), +(82, 'WaterMeter6', 'WaterMeter', NULL, 81, 'Normal', 'Off', '\r\n\r\n \r\n 2.5\r\n \r\n A\r\n'); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `componentprocedure` +-- + +CREATE TABLE IF NOT EXISTS `componentprocedure` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `CmpntName` varchar(255) DEFAULT NULL, + `Parameters` varchar(8000) DEFAULT NULL, + `Procedure_id` int(11) DEFAULT NULL, + PRIMARY KEY (`Id`), + KEY `Procedure_id` (`Procedure_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=31 ; + +-- +-- Dumping data for table `componentprocedure` +-- + +INSERT INTO `componentprocedure` (`Id`, `CmpntName`, `Parameters`, `Procedure_id`) VALUES +(1, 'WaterMeter1', '\r\n\r\n \r\n 2.5\r\n \r\n A\r\n', 1), +(2, 'WaterMeter2', '\r\n\r\n \r\n 2.5\r\n \r\n A\r\n', 1), +(3, 'WaterMeter3', '\r\n\r\n \r\n 2.5\r\n \r\n A\r\n', 1), +(4, 'WaterMeter4', '\r\n\r\n \r\n 2.5\r\n \r\n A\r\n', 1), +(5, 'WaterMeter5', '\r\n\r\n \r\n 2.5\r\n \r\n A\r\n', 1), +(6, 'WaterMeter6', '\r\n\r\n \r\n 2.5\r\n \r\n A\r\n', 1), +(7, 'Sick1', '\r\n\r\n 5\r\n', 1), +(8, 'Sick2', '\r\n\r\n 5\r\n', 1), +(9, 'Sick3', '\r\n\r\n 5\r\n', 1), +(10, 'Sick4', '\r\n\r\n 5\r\n', 1), +(11, 'Sick5', '\r\n\r\n 5\r\n', 1), +(12, 'Sick6', '\r\n\r\n 5\r\n', 1), +(25, 'Camera1', NULL, 1), +(26, 'Camera2', NULL, 1), +(27, 'Camera3', NULL, 1), +(28, 'Camera4', NULL, 1), +(29, 'Camera5', NULL, 1), +(30, 'Camera6', NULL, 1); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `componenttest` +-- + +CREATE TABLE IF NOT EXISTS `componenttest` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `CmpntName` varchar(255) DEFAULT NULL, + `Parameters` varchar(8000) DEFAULT NULL, + `Test_id` int(11) DEFAULT NULL, + PRIMARY KEY (`Id`), + KEY `Test_id` (`Test_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=5 ; + +-- +-- Dumping data for table `componenttest` +-- + +INSERT INTO `componenttest` (`Id`, `CmpntName`, `Parameters`, `Test_id`) VALUES +(1, 'CombinedWithDetection', '\r\n\r\n 3\r\n -0.4\r\n -0.2\r\n 0.05\r\n 0.25\r\n', 1), +(2, 'CombinedWithDetection', '\r\n\r\n 3\r\n -0.4\r\n -0.2\r\n 0.05\r\n 0.25\r\n', 2); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `feedingpath` +-- + +CREATE TABLE IF NOT EXISTS `feedingpath` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `ItemNr` int(11) DEFAULT NULL, + `Name` varchar(255) DEFAULT NULL, + `Qfrom` float DEFAULT NULL, + `Qto` float DEFAULT NULL, + `Pump` varchar(255) DEFAULT NULL, + `ValvesOpen` varchar(8000) DEFAULT NULL, + `ValvesClose` varchar(8000) DEFAULT NULL, + PRIMARY KEY (`Id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=7 ; + +-- +-- Dumping data for table `feedingpath` +-- + +INSERT INTO `feedingpath` (`Id`, `ItemNr`, `Name`, `Qfrom`, `Qto`, `Pump`, `ValvesOpen`, `ValvesClose`) VALUES +(1, 0, '', 0, 0, '---', '', 'VL11;VL13;VL4;VZ6;VZ7;Pump1;Pump2;Pump3;Pump4;Pump5'), +(2, 1, 'Feed-0-10', 0.1, 10, 'Pump4', 'VL13;VZ6;Pump4', 'VL11;VL4;VZ7;Pump1;Pump2;Pump3;Pump5'), +(3, 2, 'Feed-10-60', 10, 60, 'Pump3', 'VL11;Pump3', 'VL13;VL4;VZ6;VZ7;Pump1;Pump2;Pump4;Pump5'), +(4, 3, 'Feed-60-200', 60, 200, 'Pump1', 'VL11;Pump1', 'VL13;VL4;VZ6;VZ7;Pump2;Pump3;Pump4;Pump5'), +(5, 4, 'Feed-200-350', 200, 350, 'Pump1', 'VL11;Pump1;Pump2', 'VL13;VL4;VZ6;VZ7;Pump3;Pump4;Pump5'), +(6, 5, 'Feed-tower', 0, 0, 'Pump5', 'VL13;VL4;Pump5', 'VL11;VZ6;VZ7;Pump1;Pump2;Pump3;Pump4'); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `group` +-- + +CREATE TABLE IF NOT EXISTS `group` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `Gid` int(11) DEFAULT NULL, + `Name` varchar(255) DEFAULT NULL, + `User_id` int(11) DEFAULT NULL, + PRIMARY KEY (`Id`), + KEY `User_id` (`User_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=8 ; + +-- +-- Dumping data for table `group` +-- + +INSERT INTO `group` (`Id`, `Gid`, `Name`, `User_id`) VALUES +(1, 0, 'Tester', 1), +(2, 1, 'Testing Specialist', 1), +(3, 2, 'Head of Lab', 1), +(4, 3, 'Maintenance Specialist', 1), +(5, 4, 'Metrologist', 1), +(6, 5, 'Calibration Specialist', 1), +(7, 6, 'Administrator', 1); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `measurementcorrection` +-- + +CREATE TABLE IF NOT EXISTS `measurementcorrection` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `Measurement` float DEFAULT NULL, + `Correction` float DEFAULT NULL, + `Component_id` int(11) DEFAULT NULL, + PRIMARY KEY (`Id`), + KEY `Component_id` (`Component_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `meterspath` +-- + +CREATE TABLE IF NOT EXISTS `meterspath` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `ItemNr` int(11) DEFAULT NULL, + `Name` varchar(255) DEFAULT NULL, + `Qfrom` float DEFAULT NULL, + `Qto` float DEFAULT NULL, + `Sensor1` varchar(255) DEFAULT NULL, + `Sensor2` varchar(255) DEFAULT NULL, + `Sensor3` varchar(255) DEFAULT NULL, + `Sensor4` varchar(255) DEFAULT NULL, + `Sensor5` varchar(255) DEFAULT NULL, + `Sensor6` varchar(255) DEFAULT NULL, + PRIMARY KEY (`Id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=3 ; + +-- +-- Dumping data for table `meterspath` +-- + +INSERT INTO `meterspath` (`Id`, `ItemNr`, `Name`, `Qfrom`, `Qto`, `Sensor1`, `Sensor2`, `Sensor3`, `Sensor4`, `Sensor5`, `Sensor6`) VALUES +(1, 0, 'Sicks', 0, 350, 'Sick1', 'Sick2', 'Sick3', 'Sick4', 'Sick5', 'Sick6'), +(2, 1, 'Cameras', 0, 350, 'Camera1', 'Camera2', 'Camera3', 'Camera4', 'Camera5', 'Camera6'); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `metertestresult` +-- + +CREATE TABLE IF NOT EXISTS `metertestresult` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `SerialNr` varchar(255) DEFAULT NULL, + `VolumeStart` float DEFAULT NULL, + `VolumeEnd` float DEFAULT NULL, + `VolumeMeter` float DEFAULT NULL, + `VolumeRef` float DEFAULT NULL, + `VolumeErrorPct` float DEFAULT NULL, + `PulsesMeter` float DEFAULT NULL, + `PulsesMaster` float DEFAULT NULL, + `Time` float DEFAULT NULL, + `TestResult_id` int(11) DEFAULT NULL, + PRIMARY KEY (`Id`), + KEY `TestResult_id` (`TestResult_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=7 ; + +-- +-- Dumping data for table `metertestresult` +-- + +INSERT INTO `metertestresult` (`Id`, `SerialNr`, `VolumeStart`, `VolumeEnd`, `VolumeMeter`, `VolumeRef`, `VolumeErrorPct`, `PulsesMeter`, `PulsesMaster`, `Time`, `TestResult_id`) VALUES +(1, 'wm1', 0, 0, 1, 48.7303, -97.9479, 5, 7222, 40.898, 1), +(2, 'wm2', 0, 0, 0, 0, -100, 0, 0, 40.898, 1), +(3, 'wm3', 0, 0, 0, 0, -100, 0, 0, 40.898, 1), +(4, 'wm4', 0, 0, 0, 0, -100, 0, 0, 40.898, 1), +(5, 'wm5', 0, 0, 0, 0, -100, 0, 0, 40.898, 1), +(6, 'wm6', 0, 0, 0, 0, -100, 0, 0, 40.898, 1); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `outputpath` +-- + +CREATE TABLE IF NOT EXISTS `outputpath` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `ItemNr` int(11) DEFAULT NULL, + `Name` varchar(255) DEFAULT NULL, + `Qfrom` float DEFAULT NULL, + `Qto` float DEFAULT NULL, + `RegulValve` varchar(255) DEFAULT NULL, + `FlowMeter` varchar(255) DEFAULT NULL, + `Diverter` varchar(255) DEFAULT NULL, + `TempDiv` varchar(255) DEFAULT NULL, + `Balance` varchar(255) DEFAULT NULL, + `EmptyTankValve` varchar(255) DEFAULT NULL, + `ValvesOpen` varchar(8000) DEFAULT NULL, + `ValvesClose` varchar(8000) DEFAULT NULL, + PRIMARY KEY (`Id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=8 ; + +-- +-- Dumping data for table `outputpath` +-- + +INSERT INTO `outputpath` (`Id`, `ItemNr`, `Name`, `Qfrom`, `Qto`, `RegulValve`, `FlowMeter`, `Diverter`, `TempDiv`, `Balance`, `EmptyTankValve`, `ValvesOpen`, `ValvesClose`) VALUES +(1, 0, '', 0, 0, '---', '---', '---', '---', '---', '---', '', 'VI11;VI12;VI13;VI21;VI2p;VI31;VI3p;VI41;VI42;VI43;VI4p'), +(2, 1, 'PQ-0-0.16', 0, 0.16, 'VIR42', 'I4', 'Div3', 'T5', 'W2', 'VB2', 'VI41;VI42', 'VI11;VI12;VI13;VI21;VI31;VI43'), +(3, 2, 'PQ-0.16-0.37', 0.16, 0.37, 'VIR41', 'I4', 'Div3', 'T5', 'W2', 'VB2', 'VI41;VI43', 'VI11;VI12;VI13;VI21;VI31;VI42'), +(4, 3, 'PQ-0.37-4', 0.37, 4, 'VIR3', 'I3', 'Div2', 'T4', 'W2', 'VB2', 'VI31', 'VI11;VI12;VI13;VI21;VI41;VI42;VI43'), +(5, 4, 'PQ-4-40', 4, 40, 'VIR2', 'I2', 'Div1', 'T3', 'W1', 'VB1', 'VI13;VI21', 'VI11;VI12;VI31;VI41;VI42;VI43'), +(6, 5, 'PQ-40-250', 40, 250, 'VIR1', 'I1', 'Div1', 'T3', 'W1', 'VB1', 'VI11;VI13', 'VI12;VI21;VI31;VI41;VI42;VI43'), +(7, 6, 'PQ-250-350', 250, 350, 'VIR1', 'I1', 'Div1', 'T3', 'W1', 'VB1', 'VI11;VI12;VI13', 'VI21;VI31;VI41;VI42;VI43'); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `procedure` +-- + +CREATE TABLE IF NOT EXISTS `procedure` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `ItemNr` int(11) DEFAULT NULL, + `Name` varchar(255) DEFAULT NULL, + `Description` varchar(255) DEFAULT NULL, + `CreationUser` varchar(255) DEFAULT NULL, + `CreationTime` datetime DEFAULT NULL, + `LastChgUser` varchar(255) DEFAULT NULL, + `LastChgTime` datetime DEFAULT NULL, + `LongDescription` varchar(255) DEFAULT NULL, + `Watermeters` varchar(255) DEFAULT NULL, + `DataEntry` varchar(255) DEFAULT NULL, + `ResultsPrinter` varchar(255) DEFAULT NULL, + `ResultsWriter` varchar(255) DEFAULT NULL, + PRIMARY KEY (`Id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=3 ; + +-- +-- Dumping data for table `procedure` +-- + +INSERT INTO `procedure` (`Id`, `ItemNr`, `Name`, `Description`, `CreationUser`, `CreationTime`, `LastChgUser`, `LastChgTime`, `LongDescription`, `Watermeters`, `DataEntry`, `ResultsPrinter`, `ResultsWriter`) VALUES +(1, 0, 'MTK3', '', 'admin', '2014-03-12 08:11:05', 'admin', '2014-03-13 19:58:42', '', '', NULL, 'Results2Printer', 'Results2Disk'); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `purgeend` +-- + +CREATE TABLE IF NOT EXISTS `purgeend` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `ItemNr` int(11) DEFAULT NULL, + `Duration` int(11) DEFAULT NULL, + `ValvesOpen` varchar(8000) DEFAULT NULL, + `ValvesClose` varchar(8000) DEFAULT NULL, + `RegulValvesPct` varchar(255) DEFAULT NULL, + `Procedure_id` int(11) DEFAULT NULL, + PRIMARY KEY (`Id`), + KEY `Procedure_id` (`Procedure_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `purgestart` +-- + +CREATE TABLE IF NOT EXISTS `purgestart` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `ItemNr` int(11) DEFAULT NULL, + `Duration` int(11) DEFAULT NULL, + `ValvesOpen` varchar(8000) DEFAULT NULL, + `ValvesClose` varchar(8000) DEFAULT NULL, + `RegulValvesPct` varchar(255) DEFAULT NULL, + `Procedure_id` int(11) DEFAULT NULL, + PRIMARY KEY (`Id`), + KEY `Procedure_id` (`Procedure_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=7 ; + +-- +-- Dumping data for table `purgestart` +-- + +INSERT INTO `purgestart` (`Id`, `ItemNr`, `Duration`, `ValvesOpen`, `ValvesClose`, `RegulValvesPct`, `Procedure_id`) VALUES +(1, 0, 5, 'VL13', '', '0;0;0;0;0', 1), +(2, 1, 6, '', 'VL4', '0;0;0;0;0', 1), +(3, 2, 7, '', '', '0;0;0;0;0', 1); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `test` +-- + +CREATE TABLE IF NOT EXISTS `test` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `ItemNr` int(11) DEFAULT NULL, + `Name` varchar(255) DEFAULT NULL, + `Qfrom` float DEFAULT NULL, + `Qto` float DEFAULT NULL, + `Volume` float DEFAULT NULL, + `TstTime` float DEFAULT NULL, + `Repeats` int(11) DEFAULT NULL, + `Emptying` tinyint(1) DEFAULT NULL, + `Zeroing` tinyint(1) DEFAULT NULL, + `Method` varchar(255) DEFAULT NULL, + `ErrLimLo` float DEFAULT NULL, + `ErrLimHi` float DEFAULT NULL, + `TolerRed` double DEFAULT NULL, + `RedType` varchar(255) DEFAULT NULL, + `FeedingPath` varchar(255) DEFAULT NULL, + `BenchPath` varchar(255) DEFAULT NULL, + `OutputPath` varchar(255) DEFAULT NULL, + `MetersPath` varchar(255) DEFAULT NULL, + `Procedure_id` int(11) DEFAULT NULL, + PRIMARY KEY (`Id`), + KEY `Procedure_id` (`Procedure_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=7 ; + +-- +-- Dumping data for table `test` +-- + +INSERT INTO `test` (`Id`, `ItemNr`, `Name`, `Qfrom`, `Qto`, `Volume`, `TstTime`, `Repeats`, `Emptying`, `Zeroing`, `Method`, `ErrLimLo`, `ErrLimHi`, `TolerRed`, `RedType`, `FeedingPath`, `BenchPath`, `OutputPath`, `MetersPath`, `Procedure_id`) VALUES +(1, 0, 'QA1', 3, 3.3, 52.5, 60, 1, 0, 0, 'FlyingStartMassCollection', -5, 5, 0.20000000298023224, 'Fix', 'Feed-10-60', 'Bench-all', 'PQ-0.37-4', 'Sicks', 1), +(2, 1, 'QA2', 5, 5.5, 58.3333, 40, 1, 0, 0, 'FlyingStartMassCollection', -2, 2, 0.20000000298023224, 'Fix', 'Feed-10-60', 'Bench-all', 'PQ-4-40', 'Sicks', 1); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `testresult` +-- + +CREATE TABLE IF NOT EXISTS `testresult` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `Name` varchar(255) DEFAULT NULL, + `TestName` varchar(255) DEFAULT NULL, + `Qfrom` float DEFAULT NULL, + `Qto` float DEFAULT NULL, + `Volume` float DEFAULT NULL, + `TstTime` float DEFAULT NULL, + `Repeats` int(11) DEFAULT NULL, + `Emptying` tinyint(1) DEFAULT NULL, + `Zeroing` tinyint(1) DEFAULT NULL, + `Method` varchar(255) DEFAULT NULL, + `ErrLimLo` float DEFAULT NULL, + `ErrLimHi` float DEFAULT NULL, + `FeedingPath` varchar(4000) DEFAULT NULL, + `BenchPath` varchar(4000) DEFAULT NULL, + `OutputPath` varchar(4000) DEFAULT NULL, + `MetersPath` varchar(4000) DEFAULT NULL, + `TimeStart` datetime DEFAULT NULL, + `TimeEnd` datetime DEFAULT NULL, + `RepetitionNr` int(11) DEFAULT NULL, + `AmbientTempAve` float DEFAULT NULL, + `AmbientPressAve` float DEFAULT NULL, + `AmbientHumiAve` float DEFAULT NULL, + `PressInAvrg` float DEFAULT NULL, + `PressInStart` float DEFAULT NULL, + `PressInEnd` float DEFAULT NULL, + `PressOutAvrg` float DEFAULT NULL, + `PressOutStart` float DEFAULT NULL, + `PressOutEnd` float DEFAULT NULL, + `TempInAvrg` float DEFAULT NULL, + `TempInStart` float DEFAULT NULL, + `TempInEnd` float DEFAULT NULL, + `TempOutAvrg` float DEFAULT NULL, + `TempOutStart` float DEFAULT NULL, + `TempOutEnd` float DEFAULT NULL, + `TempDivAvrg` float DEFAULT NULL, + `TempDivStart` float DEFAULT NULL, + `TempDivEnd` float DEFAULT NULL, + `MassStartRaw` float DEFAULT NULL, + `MassStart` float DEFAULT NULL, + `MassEndRaw` float DEFAULT NULL, + `MassEnd` float DEFAULT NULL, + `MassDiff` float DEFAULT NULL, + `DensityIn` float DEFAULT NULL, + `DensityOut` float DEFAULT NULL, + `DensityDiv` float DEFAULT NULL, + `FlowMass` float DEFAULT NULL, + `FlowVolume` float DEFAULT NULL, + `VolumeCTV` float DEFAULT NULL, + `VolumeMaster` float DEFAULT NULL, + `Time` float DEFAULT NULL, + `ErrorMaster` float DEFAULT NULL, + `PulsesMaster` float DEFAULT NULL, + `ConstMaster` float DEFAULT NULL, + `TimeDivStart0` float DEFAULT NULL, + `TimeDivStart1` float DEFAULT NULL, + `TimeDivStart2` float DEFAULT NULL, + `TimeDivStart3` float DEFAULT NULL, + `TimeDivStart4` float DEFAULT NULL, + `TimeDivStart5` float DEFAULT NULL, + `TimeDivEnd0` float DEFAULT NULL, + `TimeDivEnd1` float DEFAULT NULL, + `TimeDivEnd2` float DEFAULT NULL, + `TimeDivEnd3` float DEFAULT NULL, + `TimeDivEnd4` float DEFAULT NULL, + `TimeDivEnd5` float DEFAULT NULL, + PRIMARY KEY (`Id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ; + +-- +-- Dumping data for table `testresult` +-- + +INSERT INTO `testresult` (`Id`, `Name`, `TestName`, `Qfrom`, `Qto`, `Volume`, `TstTime`, `Repeats`, `Emptying`, `Zeroing`, `Method`, `ErrLimLo`, `ErrLimHi`, `FeedingPath`, `BenchPath`, `OutputPath`, `MetersPath`, `TimeStart`, `TimeEnd`, `RepetitionNr`, `AmbientTempAve`, `AmbientPressAve`, `AmbientHumiAve`, `PressInAvrg`, `PressInStart`, `PressInEnd`, `PressOutAvrg`, `PressOutStart`, `PressOutEnd`, `TempInAvrg`, `TempInStart`, `TempInEnd`, `TempOutAvrg`, `TempOutStart`, `TempOutEnd`, `TempDivAvrg`, `TempDivStart`, `TempDivEnd`, `MassStartRaw`, `MassStart`, `MassEndRaw`, `MassEnd`, `MassDiff`, `DensityIn`, `DensityOut`, `DensityDiv`, `FlowMass`, `FlowVolume`, `VolumeCTV`, `VolumeMaster`, `Time`, `ErrorMaster`, `PulsesMaster`, `ConstMaster`, `TimeDivStart0`, `TimeDivStart1`, `TimeDivStart2`, `TimeDivStart3`, `TimeDivStart4`, `TimeDivStart5`, `TimeDivEnd0`, `TimeDivEnd1`, `TimeDivEnd2`, `TimeDivEnd3`, `TimeDivEnd4`, `TimeDivEnd5`) VALUES +(1, 'QA2', 'QA2', 5, 5.5, 58.3333, 40, 1, 0, 0, 'FlyingStartMassCollection', -2, 2, 'Feed-10-60', 'Bench-all', 'PQ-4-40', 'Sicks', '2014-03-13 20:10:51', '2014-03-13 20:11:43', 1, 24.74, 987.95, 27.78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.9, 1.9, 57.75, 57.75, 55.85, 999.843, 999.843, 999.843, 4916.13, 5065.65, 55.9163, 57.5486, 40.898, 2.91916, 8287, 0.00674747, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `transitionsequence` +-- + +CREATE TABLE IF NOT EXISTS `transitionsequence` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `ItemNr` int(11) DEFAULT NULL, + `Name` varchar(255) DEFAULT NULL, + `Description` varchar(255) DEFAULT NULL, + PRIMARY KEY (`Id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `transitionstep` +-- + +CREATE TABLE IF NOT EXISTS `transitionstep` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `ItemNr` int(11) DEFAULT NULL, + `Duration` int(11) DEFAULT NULL, + `ValvesOpen` varchar(8000) DEFAULT NULL, + `ValvesClose` varchar(8000) DEFAULT NULL, + `RegulValvesPct` varchar(255) DEFAULT NULL, + `TransitionSequence_id` int(11) DEFAULT NULL, + PRIMARY KEY (`Id`), + KEY `TransitionSequence_id` (`TransitionSequence_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `user` +-- + +CREATE TABLE IF NOT EXISTS `user` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `Name` varchar(255) DEFAULT NULL, + `Password` varchar(255) DEFAULT NULL, + `Description` varchar(255) DEFAULT NULL, + `LastPwChange` datetime DEFAULT NULL, + PRIMARY KEY (`Id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ; + +-- +-- Dumping data for table `user` +-- + +INSERT INTO `user` (`Id`, `Name`, `Password`, `Description`, `LastPwChange`) VALUES +(1, 'admin', 'af242843887f3bdcc52e485483356eaccd37ba67a35941530bd195a8310fc7d5aca8560576dfb62ad5a4bd2df789a5e8be068e62e7c976d6eeed8d63abbd9909', 'Administrator', '2014-03-07 21:01:44'); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `watermeter` +-- + +CREATE TABLE IF NOT EXISTS `watermeter` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `Serial` varchar(255) DEFAULT NULL, + `WMType_id` int(11) DEFAULT NULL, + PRIMARY KEY (`Id`), + KEY `WMType_id` (`WMType_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `wmtype` +-- + +CREATE TABLE IF NOT EXISTS `wmtype` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `CreateTime` datetime DEFAULT NULL, + `CreateUserName` varchar(255) DEFAULT NULL, + `CreateDescription` varchar(255) DEFAULT NULL, + `Name` varchar(255) DEFAULT NULL, + `PulseRate` float DEFAULT NULL, + PRIMARY KEY (`Id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; + +-- +-- Constraints for dumped tables +-- + +-- +-- Constraints for table `componentprocedure` +-- +ALTER TABLE `componentprocedure` + ADD CONSTRAINT `FKA4EE67E2C1B693F2` FOREIGN KEY (`Procedure_id`) REFERENCES `procedure` (`Id`); + +-- +-- Constraints for table `componenttest` +-- +ALTER TABLE `componenttest` + ADD CONSTRAINT `FK4933B35E048BC68` FOREIGN KEY (`Test_id`) REFERENCES `test` (`Id`); + +-- +-- Constraints for table `group` +-- +ALTER TABLE `group` + ADD CONSTRAINT `FKFBBA8E27F90D2266` FOREIGN KEY (`User_id`) REFERENCES `user` (`Id`); + +-- +-- Constraints for table `measurementcorrection` +-- +ALTER TABLE `measurementcorrection` + ADD CONSTRAINT `FK2E70F3322F02977E` FOREIGN KEY (`Component_id`) REFERENCES `component` (`Id`); + +-- +-- Constraints for table `metertestresult` +-- +ALTER TABLE `metertestresult` + ADD CONSTRAINT `FK1CE41B064BD6C9B6` FOREIGN KEY (`TestResult_id`) REFERENCES `testresult` (`Id`); + +-- +-- Constraints for table `purgeend` +-- +ALTER TABLE `purgeend` + ADD CONSTRAINT `FK14832B1AC1B693F2` FOREIGN KEY (`Procedure_id`) REFERENCES `procedure` (`Id`); + +-- +-- Constraints for table `purgestart` +-- +ALTER TABLE `purgestart` + ADD CONSTRAINT `FKDC8627F9C1B693F2` FOREIGN KEY (`Procedure_id`) REFERENCES `procedure` (`Id`); + +-- +-- Constraints for table `test` +-- +ALTER TABLE `test` + ADD CONSTRAINT `FKCC127866C1B693F2` FOREIGN KEY (`Procedure_id`) REFERENCES `procedure` (`Id`); + +-- +-- Constraints for table `transitionstep` +-- +ALTER TABLE `transitionstep` + ADD CONSTRAINT `FK5F10122DC1B62014` FOREIGN KEY (`TransitionSequence_id`) REFERENCES `transitionsequence` (`Id`); + +-- +-- Constraints for table `watermeter` +-- +ALTER TABLE `watermeter` + ADD CONSTRAINT `FKA968A8E699BF9B30` FOREIGN KEY (`WMType_id`) REFERENCES `wmtype` (`Id`); + +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; diff --git a/TestBenchFramework/SampleConfig/gwz-1-new.sql b/TestBenchFramework/SampleConfig/gwz-1-new.sql new file mode 100644 index 000000000..e2bb8e307 --- /dev/null +++ b/TestBenchFramework/SampleConfig/gwz-1-new.sql @@ -0,0 +1,1754 @@ +-- phpMyAdmin SQL Dump +-- version 3.4.5 +-- http://www.phpmyadmin.net +-- +-- Host: localhost +-- Generation Time: Mar 09, 2014 at 10:17 PM +-- Server version: 5.5.16 +-- PHP Version: 5.3.8 + +SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO"; +SET time_zone = "+00:00"; + + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; + +-- +-- Database: `gwz-1` +-- + +-- -------------------------------------------------------- + +-- +-- Table structure for table `benchpath` +-- + +CREATE TABLE IF NOT EXISTS `benchpath` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `ItemNr` int(11) DEFAULT NULL, + `Name` varchar(255) DEFAULT NULL, + `Qfrom` float DEFAULT NULL, + `Qto` float DEFAULT NULL, + `TempIn` varchar(255) DEFAULT NULL, + `TempOut` varchar(255) DEFAULT NULL, + `PressIn` varchar(255) DEFAULT NULL, + `PressOut` varchar(255) DEFAULT NULL, + `ValvesOpen` varchar(8000) DEFAULT NULL, + `ValvesClose` varchar(8000) DEFAULT NULL, + PRIMARY KEY (`Id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=9 ; + +-- +-- Dumping data for table `benchpath` +-- + +INSERT INTO `benchpath` (`Id`, `ItemNr`, `Name`, `Qfrom`, `Qto`, `TempIn`, `TempOut`, `PressIn`, `PressOut`, `ValvesOpen`, `ValvesClose`) VALUES +(1, 1, 'PBank1', 0.01, 0.03, 'T1', 'T2', 'Druck1', 'Druck2', 'VL13;VL12', ''), +(2, 2, 'PBank2', 0.03, 250, 'T1', 'T2', 'Druck1', 'Druck2', 'VL11;VL12;VI12', ''), +(3, 3, 'PBank3', 0.02, 12, 'T5', 'T2', 'Druck3', 'Druck4', 'VI21;VI22', 'VM1;VM2;VM3;VM4'), +(4, 4, 'PBank4', 0.02, 15, 'T5', 'T2', 'Druck3', 'Druck4', 'VI21;VI22;VM2;VM3', 'VM1;VM4'), +(5, 5, 'PBank5', 0.02, 18, 'T5', 'T2', 'Druck3', 'Druck4', 'VI21;VI22;VM1;VM3', 'VM2;VM4'), +(6, 6, 'PBank6', 0.02, 18, 'T5', 'T2', 'Druck3', 'Druck4', 'VI21;VI22;VM1;VM2', 'VM3;VM4'), +(7, 7, 'PBank7', 0.02, 5, 'T5', 'T2', 'Druck3', 'Druck4', 'VL21', ''), +(8, 0, '', 0, 0, '---', '---', '---', '---', '', ''); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `component` +-- + +CREATE TABLE IF NOT EXISTS `component` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `Name` varchar(255) DEFAULT NULL, + `ClassName` varchar(255) DEFAULT NULL, + `ParentName` varchar(255) DEFAULT NULL, + `ItemNr` int(11) DEFAULT NULL, + `Mode` varchar(255) DEFAULT NULL, + `Logging` varchar(255) DEFAULT NULL, + `Parameters` varchar(8000) DEFAULT NULL, + PRIMARY KEY (`Id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=75 ; + +-- +-- Dumping data for table `component` +-- + +INSERT INTO `component` (`Id`, `Name`, `ClassName`, `ParentName`, `ItemNr`, `Mode`, `Logging`, `Parameters`) VALUES +(1, 'CB', 'ControlBoard', NULL, 0, 'Simulate', 'Off', '\r\n\r\n 1\r\n'), +(2, 'W1', 'MettlerToledoBalanceSN', NULL, 1, 'Simulate', 'Off', '\r\n\r\n 11\r\n 2400\r\n Even\r\n 7\r\n One\r\n XOnXOff\r\n 3000\r\n'), +(3, 'W2', 'MettlerToledoBalanceSN', NULL, 2, 'Simulate', 'Off', '\r\n\r\n 10\r\n 2400\r\n Even\r\n 7\r\n One\r\n XOnXOff\r\n 150\r\n'), +(4, 'Luft', 'Greco Ambient', NULL, 3, 'Simulate', 'Off', '\r\n\r\n 6\r\n 19200\r\n None\r\n 8\r\n One\r\n None\r\n'), +(5, 'I1', 'FlowMeter', 'CB', 4, 'Normal', 'Off', '\r\n\r\n 1\r\n 200\r\n'), +(6, 'I2', 'FlowMeter', 'CB', 5, 'Normal', 'Off', '\r\n\r\n 2\r\n 20\r\n'), +(7, 'I3', 'FlowMeter', 'CB', 6, 'Normal', 'Off', '\r\n\r\n 3\r\n 3\r\n'), +(8, 'I4', 'FlowMeter', 'CB', 7, 'Normal', 'Off', '\r\n\r\n 4\r\n 0.25\r\n'), +(9, 'Druck1', 'PressureMeter', 'CB', 8, 'Normal', 'Off', '\r\n\r\n 0\r\n 78\r\n'), +(10, 'Druck2', 'PressureMeter', 'CB', 9, 'Normal', 'Off', '\r\n\r\n 1\r\n 81\r\n'), +(11, 'Druck3', 'PressureMeter', 'CB', 10, 'Normal', 'Off', '\r\n\r\n 2\r\n 11\r\n'), +(12, 'Druck4', 'PressureMeter', 'CB', 11, 'Normal', 'Off', '\r\n\r\n 3\r\n 82\r\n'), +(13, 'T1', 'TempMeter', 'CB', 12, 'Normal', 'Off', '\r\n\r\n 0\r\n -20.14631\r\n 0.00177572737\r\n 7.601795E-10\r\n -1.237E-15\r\n 0\r\n'), +(14, 'T2', 'TempMeter', 'CB', 13, 'Normal', 'Off', '\r\n\r\n 1\r\n -20.13342\r\n 0.001777626\r\n 7.41529E-10\r\n -1.066678E-15\r\n 0\r\n'), +(15, 'T3', 'TempMeter', 'CB', 14, 'Normal', 'Off', '\r\n\r\n 2\r\n -20.138031\r\n 0.00177645753\r\n 7.68710429E-10\r\n -1.307915E-15\r\n 0\r\n'), +(16, 'T4', 'TempMeter', 'CB', 15, 'Normal', 'Off', '\r\n\r\n 3\r\n -20.1234074\r\n 0.00177655893\r\n 7.53911156E-10\r\n 1.13868757E-15\r\n 0\r\n'), +(17, 'T5', 'TempMeter', 'CB', 16, 'Normal', 'Off', '\r\n\r\n 4\r\n -20.0712757\r\n 0.00177105656\r\n 9.751451E-10\r\n -3.51362E-15\r\n 0\r\n'), +(18, 'RV1', 'RegulationValve', 'CB', 17, 'Normal', 'Off', '\r\n\r\n 1\r\n 100\r\n 500\r\n 10\r\n'), +(19, 'RV2', 'RegulationValve', 'CB', 18, 'Normal', 'Off', '\r\n\r\n 2\r\n 100\r\n 500\r\n 3\r\n'), +(20, 'RV3', 'RegulationValve', 'CB', 19, 'Normal', 'Off', '\r\n\r\n 3\r\n 100\r\n 500\r\n 10\r\n'), +(21, 'RV4', 'RegulationValve', 'CB', 20, 'Normal', 'Off', '\r\n\r\n 4\r\n 100\r\n 500\r\n 30\r\n'), +(22, 'RV5', 'RegulationValve', 'CB', 21, 'Normal', 'Off', '\r\n\r\n 5\r\n 100\r\n 500\r\n 10\r\n'), +(23, 'DIV1', 'Diverter', 'CB', 22, 'Normal', 'Off', '\r\n\r\n 34\r\n'), +(24, 'DIV2', 'Diverter', 'CB', 23, 'Normal', 'Off', '\r\n\r\n 35\r\n'), +(25, 'DIV3', 'Diverter', 'CB', 24, 'Normal', 'Off', '\r\n\r\n 36\r\n'), +(26, 'VL11', 'Valve', 'CB', 25, 'Normal', 'Off', '\r\n\r\n 0\r\n \r\n false\r\n'), +(27, 'VL13', 'Valve', 'CB', 26, 'Normal', 'Off', '\r\n\r\n 1\r\n \r\n false\r\n'), +(28, 'VL21', 'Valve', 'CB', 27, 'Normal', 'Off', '\r\n\r\n 2\r\n \r\n false\r\n'), +(29, 'VL23', 'Valve', 'CB', 28, 'Normal', 'Off', '\r\n\r\n 3\r\n \r\n false\r\n'), +(30, 'VZ1', 'Valve', 'CB', 29, 'Normal', 'Off', '\r\n\r\n 4\r\n \r\n false\r\n'), +(31, 'VP2', 'Valve', 'CB', 30, 'Normal', 'Off', '\r\n\r\n 5\r\n \r\n false\r\n'), +(32, 'VP4', 'Valve', 'CB', 31, 'Normal', 'Off', '\r\n\r\n 6\r\n \r\n false\r\n'), +(33, 'VP5', 'Valve', 'CB', 32, 'Normal', 'Off', '\r\n\r\n 7\r\n \r\n false\r\n'), +(34, 'VP6', 'Valve', 'CB', 33, 'Normal', 'Off', '\r\n\r\n 8\r\n \r\n false\r\n'), +(35, 'VL12', 'Valve', 'CB', 34, 'Normal', 'Off', '\r\n\r\n 9\r\n \r\n false\r\n'), +(36, 'VL22', 'Valve', 'CB', 35, 'Normal', 'Off', '\r\n\r\n 10\r\n \r\n false\r\n'), +(37, 'VI11', 'Valve', 'CB', 36, 'Normal', 'Off', '\r\n\r\n 11\r\n \r\n false\r\n'), +(38, 'VI12', 'Valve', 'CB', 37, 'Normal', 'Off', '\r\n\r\n 12\r\n \r\n false\r\n'), +(39, 'VI13', 'Valve', 'CB', 38, 'Normal', 'Off', '\r\n\r\n 13\r\n \r\n false\r\n'), +(40, 'VI21', 'Valve', 'CB', 39, 'Normal', 'Off', '\r\n\r\n 14\r\n \r\n false\r\n'), +(41, 'VI22', 'Valve', 'CB', 40, 'Normal', 'Off', '\r\n\r\n 15\r\n \r\n false\r\n'), +(42, 'VI2P', 'Valve', 'CB', 41, 'Normal', 'Off', '\r\n\r\n 16\r\n \r\n false\r\n'), +(43, 'VI31', 'Valve', 'CB', 42, 'Normal', 'Off', '\r\n\r\n 17\r\n \r\n false\r\n'), +(44, 'VI32', 'Valve', 'CB', 43, 'Normal', 'Off', '\r\n\r\n 18\r\n \r\n false\r\n'), +(45, 'VI3P', 'Valve', 'CB', 44, 'Normal', 'Off', '\r\n\r\n 19\r\n \r\n false\r\n'), +(46, 'VI41', 'Valve', 'CB', 45, 'Normal', 'Off', '\r\n\r\n 20\r\n \r\n false\r\n'), +(47, 'VI42', 'Valve', 'CB', 46, 'Normal', 'Off', '\r\n\r\n 21\r\n \r\n false\r\n'), +(48, 'VI43', 'Valve', 'CB', 47, 'Normal', 'Off', '\r\n\r\n 22\r\n \r\n false\r\n'), +(49, 'VI4P', 'Valve', 'CB', 48, 'Normal', 'Off', '\r\n\r\n 23\r\n \r\n false\r\n'), +(50, 'VB1', 'Valve', 'CB', 49, 'Normal', 'Off', '\r\n\r\n 24\r\n \r\n false\r\n'), +(51, 'VB1a', 'Valve', 'CB', 50, 'Normal', 'Off', '\r\n\r\n 25\r\n VB1\r\n false\r\n -2\r\n 2\r\n'), +(52, 'VB2', 'Valve', 'CB', 51, 'Normal', 'Off', '\r\n\r\n 26\r\n \r\n false\r\n'), +(53, 'VB2a', 'Valve', 'CB', 52, 'Normal', 'Off', '\r\n\r\n 27\r\n VB2\r\n false\r\n -2\r\n 2\r\n'), +(54, 'VM1', 'Valve', 'CB', 53, 'Normal', 'Off', '\r\n\r\n 28\r\n \r\n false\r\n'), +(55, 'VM2', 'Valve', 'CB', 54, 'Normal', 'Off', '\r\n\r\n 29\r\n \r\n false\r\n'), +(56, 'VM3', 'Valve', 'CB', 55, 'Normal', 'Off', '\r\n\r\n 30\r\n \r\n false\r\n'), +(57, 'VM4', 'Valve', 'CB', 56, 'Normal', 'Off', '\r\n\r\n 31\r\n \r\n false\r\n'), +(58, 'Pumpe1', 'Pump', 'CB', 57, 'Normal', 'Off', '\r\n\r\n 32\r\n \r\n false\r\n'), +(59, 'Block', 'Valve', 'CB', 58, 'Normal', 'Off', '\r\n\r\n 33\r\n \r\n false\r\n'), +(60, 'VZ8', 'Valve', 'CB', 59, 'Normal', 'Off', '\r\n\r\n 37\r\n \r\n false\r\n'), +(61, 'Sick1', 'RegisterReader', 'CB', 60, 'Normal', 'Off', '\r\n\r\n 1\r\n'), +(62, 'Sick2', 'RegisterReader', 'CB', 61, 'Normal', 'Off', '\r\n\r\n 2\r\n'), +(63, 'Sick3', 'RegisterReader', 'CB', 62, 'Normal', 'Off', '\r\n\r\n 3\r\n'), +(64, 'Kamera', 'IdcCamera', NULL, 63, 'Simulate', 'Off', '\r\n\r\n 20\r\n 57600\r\n 0.5\r\n'), +(65, 'Fliegender Start-Stopp', 'Flying-Start-Collection', NULL, 64, 'Normal', 'Off', '\r\n'), +(66, 'Verbund', 'CombinedMeters', NULL, 65, 'Normal', 'Off', '\r\n'), +(67, 'Basic Results', 'BasicResultsWriter', NULL, 66, 'Normal', 'Off', '\r\n'), +(68, 'Advanced Results', 'ResultsPrinter4Munich', NULL, 67, 'Normal', 'Off', '\r\n'), +(69, 'Verbund-steig-fall', 'CombinedWithDetection', NULL, 68, 'Normal', 'Off', '\r\n'), +(70, 'Pruefstand-ID', 'Bench-ID', NULL, 69, 'Normal', 'Off', '\r\n\r\n 1\r\n'), +(71, 'Zähler 1', 'WaterMeter', NULL, 70, 'Normal', 'Off', '\r\n\r\n \r\n 2.5\r\n \r\n A\r\n'), +(72, 'Zähler 2', 'WaterMeter', NULL, 71, 'Normal', 'Off', '\r\n\r\n \r\n 2.5\r\n \r\n A\r\n'), +(73, 'Zähler 3', 'WaterMeter', NULL, 72, 'Normal', 'Off', '\r\n\r\n \r\n 2.5\r\n \r\n A\r\n'), +(74, 'Dateneingabe', 'DataEntryForm-Munich', NULL, 73, 'Normal', 'Off', '\r\n\r\n Protokoll Werkprüfung\r\n Protokoll 2<--\r\n Protokoll 3<--\r\n'); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `componentprocedure` +-- + +CREATE TABLE IF NOT EXISTS `componentprocedure` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `CmpntName` varchar(255) DEFAULT NULL, + `Parameters` varchar(8000) DEFAULT NULL, + `Procedure_id` int(11) DEFAULT NULL, + PRIMARY KEY (`Id`), + KEY `Procedure_id` (`Procedure_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=29 ; + +-- +-- Dumping data for table `componentprocedure` +-- + +INSERT INTO `componentprocedure` (`Id`, `CmpntName`, `Parameters`, `Procedure_id`) VALUES +(1, 'Sick1', '\r\n\r\n 1\r\n', 15), +(2, 'Sick2', '\r\n\r\n 36.4\r\n', 15), +(3, 'Sick3', '\r\n\r\n 1\r\n', 15), +(10, 'Sick1', '\r\n\r\n 1\r\n', 17), +(11, 'Sick2', '\r\n\r\n 36.4\r\n', 17), +(12, 'Sick3', '\r\n\r\n 1\r\n', 17), +(16, 'Sick1', '\r\n\r\n 1\r\n', 18), +(17, 'Sick2', '\r\n\r\n 36.4\r\n', 18), +(18, 'Sick3', '\r\n\r\n 1\r\n', 18), +(22, 'Sick1', '\r\n\r\n 1\r\n', 21), +(23, 'Sick2', '\r\n\r\n 36.4\r\n', 21), +(24, 'Sick3', '\r\n\r\n 1\r\n', 21), +(25, 'Zähler 1', '\r\n\r\n Elster\r\n 15\r\n D97 / 6.132.41\r\n B\r\n', 15), +(26, 'Zähler 2', '\r\n\r\n Elster\r\n 2.5\r\n D82 / 6.131.42\r\n A\r\n', 15), +(27, 'Zähler 3', '\r\n\r\n \r\n 2.5\r\n \r\n A\r\n', 15), +(28, 'Advanced Results', '\r\n\r\n 4/13\r\n Verbund\r\n 81793\r\n 2014\r\n', 15); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `componenttest` +-- + +CREATE TABLE IF NOT EXISTS `componenttest` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `CmpntName` varchar(255) DEFAULT NULL, + `Parameters` varchar(8000) DEFAULT NULL, + `Test_id` int(11) DEFAULT NULL, + PRIMARY KEY (`Id`), + KEY `Test_id` (`Test_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=26 ; + +-- +-- Dumping data for table `componenttest` +-- + +INSERT INTO `componenttest` (`Id`, `CmpntName`, `Parameters`, `Test_id`) VALUES +(9, 'Verbund mit Det.', '\r\n\r\n 4\r\n 5\r\n -0.7\r\n -0.5\r\n 0.05\r\n 0.1\r\n', 36), +(10, 'Verbund-steig-fall', '\r\n\r\n 3\r\n -0.3\r\n -0.1\r\n 0.1\r\n 0.25\r\n', 35), +(11, 'Verbund-steig-fall', '\r\n\r\n 1\r\n 0.05\r\n 0.15\r\n 0.1\r\n 2\r\n', 36), +(16, 'Verbund-steig-fall', '\r\n\r\n 3\r\n -0.2\r\n 0\r\n 0.05\r\n 0.25\r\n', 41), +(17, 'Verbund-steig-fall', '\r\n\r\n 1\r\n 0\r\n 0.2\r\n 0.05\r\n 0.25\r\n', 42), +(20, 'Verbund-steig-fall', '\r\n\r\n 3\r\n -0.3\r\n -0.1\r\n 0.1\r\n 0.25\r\n', 45), +(21, 'Verbund-steig-fall', '\r\n\r\n 1\r\n 0.05\r\n 0.15\r\n 0.1\r\n 2\r\n', 46), +(24, 'Verbund-steig-fall', '\r\n\r\n 3\r\n -0.3\r\n -0.1\r\n 0.1\r\n 0.25\r\n', 49), +(25, 'Verbund-steig-fall', '\r\n\r\n 1\r\n 0.05\r\n 0.15\r\n 0.1\r\n 2\r\n', 50); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `feedingpath` +-- + +CREATE TABLE IF NOT EXISTS `feedingpath` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `ItemNr` int(11) DEFAULT NULL, + `Name` varchar(255) DEFAULT NULL, + `Qfrom` float DEFAULT NULL, + `Qto` float DEFAULT NULL, + `Pump` varchar(255) DEFAULT NULL, + `ValvesOpen` varchar(8000) DEFAULT NULL, + `ValvesClose` varchar(8000) DEFAULT NULL, + PRIMARY KEY (`Id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=5 ; + +-- +-- Dumping data for table `feedingpath` +-- + +INSERT INTO `feedingpath` (`Id`, `ItemNr`, `Name`, `Qfrom`, `Qto`, `Pump`, `ValvesOpen`, `ValvesClose`) VALUES +(1, 1, 'PS1', 0.01, 0.03, '---', 'VZ1', ''), +(2, 3, 'PS2', 0.03, 250, '---', 'VZ1', ''), +(3, 2, 'PS3', 0.01, 5, 'Pumpe1', 'VP2', ''), +(4, 0, '', 0, 0, '---', 'VZ1', 'VL11;VL13;VL21;VL23;VP2;VP4;VP5;VP6;VL12;VL22;VI11;VI12;VI13;VI21;VI22;VI2P;VI31;VI32;VI3P;VI41;VI42;VI43;VI4P;VB1;VB1a;VB2;VB2a;VM1;VM2;VM3;VM4;Pumpe1;Block;VZ8'); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `group` +-- + +CREATE TABLE IF NOT EXISTS `group` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `Gid` int(11) DEFAULT NULL, + `Name` varchar(255) DEFAULT NULL, + `User_id` int(11) DEFAULT NULL, + PRIMARY KEY (`Id`), + KEY `User_id` (`User_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=8 ; + +-- +-- Dumping data for table `group` +-- + +INSERT INTO `group` (`Id`, `Gid`, `Name`, `User_id`) VALUES +(1, 0, 'Testers', 2), +(2, 1, 'Testing Specialists', 1), +(3, 2, 'Head Of Lab', 1), +(4, 3, 'Maintenance Specialists', 1), +(5, 4, 'Metrologists', 1), +(6, 5, 'Calibration Specialists', 1), +(7, 6, 'Administrators', 1); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `measurementcorrection` +-- + +CREATE TABLE IF NOT EXISTS `measurementcorrection` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `Measurement` float DEFAULT NULL, + `Correction` float DEFAULT NULL, + `Component_id` int(11) DEFAULT NULL, + PRIMARY KEY (`Id`), + KEY `Component_id` (`Component_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `meterspath` +-- + +CREATE TABLE IF NOT EXISTS `meterspath` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `ItemNr` int(11) DEFAULT NULL, + `Name` varchar(255) DEFAULT NULL, + `Qfrom` float DEFAULT NULL, + `Qto` float DEFAULT NULL, + `Sensor1` varchar(255) DEFAULT NULL, + `Sensor2` varchar(255) DEFAULT NULL, + `Sensor3` varchar(255) DEFAULT NULL, + PRIMARY KEY (`Id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ; + +-- +-- Dumping data for table `meterspath` +-- + +INSERT INTO `meterspath` (`Id`, `ItemNr`, `Name`, `Qfrom`, `Qto`, `Sensor1`, `Sensor2`, `Sensor3`) VALUES +(1, 0, 'PMess1', 0.01, 300, 'Sick1', 'Sick2', 'Sick3'); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `metertestresult` +-- + +CREATE TABLE IF NOT EXISTS `metertestresult` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `SerialNr` varchar(255) DEFAULT NULL, + `VolumeStart` float DEFAULT NULL, + `VolumeEnd` float DEFAULT NULL, + `VolumeMeter` float DEFAULT NULL, + `VolumeRef` float DEFAULT NULL, + `VolumeErrorPct` float DEFAULT NULL, + `PulsesMeter` float DEFAULT NULL, + `PulsesMaster` float DEFAULT NULL, + `Time` float DEFAULT NULL, + `TestResult_id` int(11) DEFAULT NULL, + PRIMARY KEY (`Id`), + KEY `TestResult_id` (`TestResult_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=706 ; + +-- +-- Dumping data for table `metertestresult` +-- + +INSERT INTO `metertestresult` (`Id`, `SerialNr`, `VolumeStart`, `VolumeEnd`, `VolumeMeter`, `VolumeRef`, `VolumeErrorPct`, `PulsesMeter`, `PulsesMaster`, `Time`, `TestResult_id`) VALUES +(1, 'wm1', 0, 0, 142, 200.256, -29.0907, 142, 72051, 45.712, 1), +(2, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.712, 1), +(3, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.712, 1), +(4, 'wm1', 0, 0, 362, 59.9706, 503.629, 362, 143864, 104.98, 2), +(5, 'wm2', 0, 0, 0, 0, -100, 0, 0, 104.98, 2), +(6, 'wm3', 0, 0, 0, 0, -100, 0, 0, 104.98, 2), +(7, 'wm1', 0, 0, 141, 200.27, -29.5951, 141, 72046, 45.705, 3), +(8, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.705, 3), +(9, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.705, 3), +(10, 'wm1', 0, 0, 361, 60.1188, 500.478, 361, 143933, 104.919, 4), +(11, 'wm2', 0, 0, 0, 0, -100, 0, 0, 104.919, 4), +(12, 'wm3', 0, 0, 0, 0, -100, 0, 0, 104.919, 4), +(13, 'wm1', 0, 0, 141, 200.38, -29.6335, 141, 72078, 45.707, 5), +(14, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.707, 5), +(15, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.707, 5), +(16, 'wm1', 0, 0, 362, 60.0895, 502.435, 362, 143850, 104.938, 6), +(17, 'wm2', 0, 0, 0, 0, -100, 0, 0, 104.938, 6), +(18, 'wm3', 0, 0, 0, 0, -100, 0, 0, 104.938, 6), +(19, 'wm1', 0, 0, 5.6, 199.069, -97.1869, 56, 71576, 45.673, 7), +(20, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.673, 7), +(21, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.673, 7), +(25, 'wm1', 0, 0, 1.9, 190.598, -99.0031, 19, 68552, 45.822, 8), +(26, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.822, 8), +(27, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.822, 8), +(28, 'wm1', 0, 0, 1.9, 190.521, -99.0027, 19, 68543, 45.956, 9), +(29, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.956, 9), +(30, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.956, 9), +(31, 'wm1', 0, 0, 190, 190.39, -0.204866, 19, 68517, 45.988, 10), +(32, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.988, 10), +(33, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.988, 10), +(34, 'wm1', 0, 0, 190, 190.643, -0.337179, 19, 68558, 45.839, 11), +(35, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.839, 11), +(36, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.839, 11), +(37, 'wm1', 0, 0, 50, 39.8137, 25.5851, 5, 119374, 99.47, 12), +(38, 'wm2', 0, 0, 0, 0, -100, 0, 0, 99.47, 12), +(39, 'wm3', 0, 0, 0, 0, -100, 0, 0, 99.47, 12), +(40, 'wm1', 0, 0, 190, 190.549, -0.288296, 19, 68558, 45.834, 13), +(41, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.834, 13), +(42, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.834, 13), +(43, 'wm1', 0, 0, 50, 42.4429, 17.8054, 5, 119438, 99.653, 14), +(44, 'wm2', 0, 0, 0, 0, -100, 0, 0, 99.653, 14), +(45, 'wm3', 0, 0, 0, 0, -100, 0, 0, 99.653, 14), +(46, 'wm1', 0, 0, 190, 190.532, -0.279457, 19, 68518, 45.838, 15), +(47, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.838, 15), +(48, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.838, 15), +(49, 'wm1', 0, 0, 50, 42.5645, 17.4688, 5, 119409, 99.689, 16), +(50, 'wm2', 0, 0, 0, 0, -100, 0, 0, 99.689, 16), +(51, 'wm3', 0, 0, 0, 0, -100, 0, 0, 99.689, 16), +(52, 'wm1', 0, 0, 190, 190.678, -0.355387, 19, 68569, 45.876, 17), +(53, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.876, 17), +(54, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.876, 17), +(55, 'wm1', 0, 0, 190, 190.508, -0.266501, 19, 68525, 45.844, 18), +(56, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.844, 18), +(57, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.844, 18), +(58, 'wm1', 0, 0, 200, 200.696, -0.346793, 20, 72203, 45.812, 19), +(59, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.812, 19), +(60, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.812, 19), +(61, 'wm1', 0, 0, 190, 190.62, -0.32514, 19, 68555, 45.85, 20), +(62, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.85, 20), +(63, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.85, 20), +(64, 'wm1', 0, 0, 190, 190.701, -0.36741, 19, 68578, 45.85, 21), +(65, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.85, 21), +(66, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.85, 21), +(67, 'wm1', 0, 0, 190, 191.073, -0.561429, 19, 68623, 45.841, 22), +(68, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.841, 22), +(69, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.841, 22), +(70, 'wm1', 0, 0, 190, 190.796, -0.416979, 19, 68502, 45.864, 23), +(71, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.864, 23), +(72, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.864, 23), +(73, 'wm1', 0, 0, 190, 190.875, -0.458495, 19, 68548, 45.842, 24), +(74, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.842, 24), +(75, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.842, 24), +(76, 'wm1', 0, 0, 190, 190.967, -0.506622, 19, 68554, 45.847, 25), +(77, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.847, 25), +(78, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.847, 25), +(79, 'wm1', 0, 0, 190, 190.841, -0.4405, 19, 68537, 45.837, 26), +(80, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.837, 26), +(81, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.837, 26), +(82, 'wm1', 0, 0, 50, 50.0062, -0.0123505, 5, 119527, 99.841, 27), +(83, 'wm2', 0, 0, 0, 0, -100, 0, 0, 99.841, 27), +(84, 'wm3', 0, 0, 0, 0, -100, 0, 0, 99.841, 27), +(85, 'wm1', 0, 0, 50, 50.0312, -0.0623848, 5, 119563, 99.871, 28), +(86, 'wm2', 0, 0, 0, 0, -100, 0, 0, 99.871, 28), +(87, 'wm3', 0, 0, 0, 0, -100, 0, 0, 99.871, 28), +(88, 'wm1', 0, 0, 50, -113.154, -100, 5, 119370, 87.146, 29), +(89, 'wm2', 0, 0, 0, 0, -100, 0, 0, 87.146, 29), +(90, 'wm3', 0, 0, 0, 0, -100, 0, 0, 87.146, 29), +(91, 'wm1', 0, 0, 0, 19.0219, -100, 8, 6841, 64.05, 30), +(92, 'wm2', 0, 0, 0, 0, -100, 0, 0, 64.05, 30), +(93, 'wm3', 0, 0, 0, 0, -100, 0, 0, 64.05, 30), +(94, 'wm1', 0, 0, 0, 14.8243, -100, 3, 5327, 64.246, 31), +(95, 'wm2', 0, 0, 0, 0, -100, 0, 0, 64.246, 31), +(96, 'wm3', 0, 0, 0, 0, -100, 0, 0, 64.246, 31), +(97, 'wm1', 0, 0, 0, 14.7066, -100, 3, 5276, 64.346, 32), +(98, 'wm2', 0, 0, 0, 0, -100, 0, 0, 64.346, 32), +(99, 'wm3', 0, 0, 0, 0, -100, 0, 0, 64.346, 32), +(100, 'wm1', 0, 0, 0, 17.0307, -100, 4, 6120, 64.316, 33), +(101, 'wm2', 0, 0, 0, 0, -100, 0, 0, 64.316, 33), +(102, 'wm3', 0, 0, 0, 0, -100, 0, 0, 64.316, 33), +(103, 'wm1', 0, 0, 0, 14.9433, -100, 5, 5361, 64.328, 34), +(104, 'wm2', 0, 0, 0, 0, -100, 0, 0, 64.328, 34), +(105, 'wm3', 0, 0, 0, 0, -100, 0, 0, 64.328, 34), +(106, 'wm1', 0, 0, 0, 35.6131, -100, 34, 12773, 71.015, 35), +(107, 'wm2', 0, 0, 0, 0, -100, 0, 0, 71.015, 35), +(108, 'wm3', 0, 0, 0, 0, -100, 0, 0, 71.015, 35), +(109, 'wm1', 0, 0, 0, 37.8982, -100, 33, 13603, 71.007, 36), +(110, 'wm2', 0, 0, 0, 0, -100, 0, 0, 71.007, 36), +(111, 'wm3', 0, 0, 0, 0, -100, 0, 0, 71.007, 36), +(112, 'wm1', 0, 0, 0, 39.3708, -100, 28, 14121, 71.024, 37), +(113, 'wm2', 0, 0, 0, 0, -100, 0, 0, 71.024, 37), +(114, 'wm3', 0, 0, 0, 0, -100, 0, 0, 71.024, 37), +(115, 'wm1', 0, 0, 0, 38.3891, -100, 29, 13768, 71.021, 38), +(116, 'wm2', 0, 0, 0, 0, -100, 0, 0, 71.021, 38), +(117, 'wm3', 0, 0, 0, 0, -100, 0, 0, 71.021, 38), +(118, 'wm1', 0, 0, 0, 39.7502, -100, 32, 14268, 71.013, 39), +(119, 'wm2', 0, 0, 0, 0, -100, 0, 0, 71.013, 39), +(120, 'wm3', 0, 0, 0, 0, -100, 0, 0, 71.013, 39), +(121, 'wm1', 0, 0, 0, 59.1279, -100, 42, 21226, 69.587, 40), +(122, 'wm2', 0, 0, 0, 0, -100, 0, 0, 69.587, 40), +(123, 'wm3', 0, 0, 0, 0, -100, 0, 0, 69.587, 40), +(124, 'wm1', 0, 0, 0, 58.214, -100, 42, 20898, 69.564, 41), +(125, 'wm2', 0, 0, 0, 0, -100, 0, 0, 69.564, 41), +(126, 'wm3', 0, 0, 0, 0, -100, 0, 0, 69.564, 41), +(127, 'wm1', 0, 0, 0, 59.3587, -100, 43, 21309, 69.548, 42), +(128, 'wm2', 0, 0, 0, 0, -100, 0, 0, 69.548, 42), +(129, 'wm3', 0, 0, 0, 0, -100, 0, 0, 69.548, 42), +(130, 'wm1', 0, 0, 0, 58.2055, -100, 46, 20895, 69.524, 43), +(131, 'wm2', 0, 0, 0, 0, -100, 0, 0, 69.524, 43), +(132, 'wm3', 0, 0, 0, 0, -100, 0, 0, 69.524, 43), +(133, 'wm1', 0, 0, 0, 59.1874, -100, 43, 21230, 69.545, 44), +(134, 'wm2', 0, 0, 0, 0, -100, 0, 0, 69.545, 44), +(135, 'wm3', 0, 0, 0, 0, -100, 0, 0, 69.545, 44), +(136, 'wm1', 0, 0, 0, 79.3873, -100, 59, 28489, 69.226, 45), +(137, 'wm2', 0, 0, 0, 0, -100, 0, 0, 69.226, 45), +(138, 'wm3', 0, 0, 0, 0, -100, 0, 0, 69.226, 45), +(139, 'wm1', 0, 0, 0, 79.5877, -100, 54, 28566, 69.211, 46), +(140, 'wm2', 0, 0, 0, 0, -100, 0, 0, 69.211, 46), +(141, 'wm3', 0, 0, 0, 0, -100, 0, 0, 69.211, 46), +(142, 'wm1', 0, 0, 0, 78.178, -100, 57, 28060, 69.281, 47), +(143, 'wm2', 0, 0, 0, 0, -100, 0, 0, 69.281, 47), +(144, 'wm3', 0, 0, 0, 0, -100, 0, 0, 69.281, 47), +(145, 'wm1', 0, 0, 0, 79.4592, -100, 55, 28520, 69.18, 48), +(146, 'wm2', 0, 0, 0, 0, -100, 0, 0, 69.18, 48), +(147, 'wm3', 0, 0, 0, 0, -100, 0, 0, 69.18, 48), +(148, 'wm1', 0, 0, 0, 79.4478, -100, 60, 28510, 69.189, 49), +(149, 'wm2', 0, 0, 0, 0, -100, 0, 0, 69.189, 49), +(150, 'wm3', 0, 0, 0, 0, -100, 0, 0, 69.189, 49), +(151, 'wm1', 0, 0, 0, 119.112, -100, 85, 42785, 72.154, 50), +(152, 'wm2', 0, 0, 0, 0, -100, 0, 0, 72.154, 50), +(153, 'wm3', 0, 0, 0, 0, -100, 0, 0, 72.154, 50), +(154, 'wm1', 0, 0, 0, 119.29, -100, 85, 42845, 71.198, 51), +(155, 'wm2', 0, 0, 0, 0, -100, 0, 0, 71.198, 51), +(156, 'wm3', 0, 0, 0, 0, -100, 0, 0, 71.198, 51), +(157, 'wm1', 0, 0, 0, 119.209, -100, 86, 42822, 71.207, 52), +(158, 'wm2', 0, 0, 0, 0, -100, 0, 0, 71.207, 52), +(159, 'wm3', 0, 0, 0, 0, -100, 0, 0, 71.207, 52), +(160, 'wm1', 0, 0, 0, 119.434, -100, 87, 42891, 71.225, 53), +(161, 'wm2', 0, 0, 0, 0, -100, 0, 0, 71.225, 53), +(162, 'wm3', 0, 0, 0, 0, -100, 0, 0, 71.225, 53), +(163, 'wm1', 0, 0, 0, 119.206, -100, 87, 42826, 71.469, 54), +(164, 'wm2', 0, 0, 0, 0, -100, 0, 0, 71.469, 54), +(165, 'wm3', 0, 0, 0, 0, -100, 0, 0, 71.469, 54), +(166, 'wm1', 0, 0, 1410, 200.559, 603.034, 141, 7203, 44.567, 55), +(167, 'wm2', 0, 0, 0, 0, -100, 0, 0, 44.567, 55), +(168, 'wm3', 0, 0, 0, 0, -100, 0, 0, 44.567, 55), +(169, 'wm1', 0, 0, 1410, 200.571, 602.991, 141, 72032, 45.788, 56), +(170, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.788, 56), +(171, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.788, 56), +(172, 'wm1', 0, 0, 1400, 187.698, 645.881, 140, 71532, 45.616, 57), +(173, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.616, 57), +(174, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.616, 57), +(175, 'wm1', 0, 0, 1430, 186.342, 667.405, 143, 72077, 45.594, 58), +(176, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.594, 58), +(177, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.594, 58), +(178, 'wm1', 0, 0, 1420, 186.346, 662.024, 142, 72081, 45.602, 59), +(179, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.602, 59), +(180, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.602, 59), +(181, 'wm1', 0, 0, 1430, 200.703, 612.496, 143, 72079, 45.59, 60), +(182, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.59, 60), +(183, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.59, 60), +(184, 'wm1', 0, 0, 0, 989.503, -100, 705, 359760, 227.074, 61), +(185, 'wm2', 0, 0, 0, 0, -100, 0, 0, 227.074, 61), +(186, 'wm3', 0, 0, 0, 0, -100, 0, 0, 227.074, 61), +(187, 'wm1', 0, 0, 0, 1001.3, -100, 705, 359717, 227.025, 62), +(188, 'wm2', 0, 0, 0, 0, -100, 0, 0, 227.025, 62), +(189, 'wm3', 0, 0, 0, 0, -100, 0, 0, 227.025, 62), +(190, 'wm1', 0, 0, 0, 1002.82, -100, 705, 360253, 227.033, 63), +(191, 'wm2', 0, 0, 0, 0, -100, 0, 0, 227.033, 63), +(192, 'wm3', 0, 0, 0, 0, -100, 0, 0, 227.033, 63), +(193, 'wm1', 0, 0, 0, 1001.29, -100, 704, 359646, 227.044, 64), +(194, 'wm2', 0, 0, 0, 0, -100, 0, 0, 227.044, 64), +(195, 'wm3', 0, 0, 0, 0, -100, 0, 0, 227.044, 64), +(196, 'wm1', 0, 0, 0, 1002.58, -100, 705, 360167, 227.036, 65), +(197, 'wm2', 0, 0, 0, 0, -100, 0, 0, 227.036, 65), +(198, 'wm3', 0, 0, 0, 0, -100, 0, 0, 227.036, 65), +(199, 'wm1', 0, 0, 0, 1001.43, -100, 704, 359748, 227.023, 66), +(200, 'wm2', 0, 0, 0, 0, -100, 0, 0, 227.023, 66), +(201, 'wm3', 0, 0, 0, 0, -100, 0, 0, 227.023, 66), +(202, 'wm1', 0, 0, 1000, 1001.3, -0.130122, 704, 359716, 227.032, 67), +(203, 'wm2', 0, 0, 0, 0, -100, 0, 0, 227.032, 67), +(204, 'wm3', 0, 0, 0, 0, -100, 0, 0, 227.032, 67), +(205, 'wm1', 0, 0, 1001.42, 1002.83, -0.140678, 705, 360271, 227.041, 68), +(206, 'wm2', 0, 0, 0, 0, -100, 0, 0, 227.041, 68), +(207, 'wm3', 0, 0, 0, 0, -100, 0, 0, 227.041, 68), +(208, 'wm1', 0, 0, 1000, 1001.36, -0.135966, 704, 359725, 227.076, 69), +(209, 'wm2', 0, 0, 0, 0, -100, 0, 0, 227.076, 69), +(210, 'wm3', 0, 0, 0, 0, -100, 0, 0, 227.076, 69), +(211, 'wm1', 0, 0, 1000, 1001.25, -0.125136, 704, 359693, 227.051, 70), +(212, 'wm2', 0, 0, 0, 0, -100, 0, 0, 227.051, 70), +(213, 'wm3', 0, 0, 0, 0, -100, 0, 0, 227.051, 70), +(214, 'wm1', 0, 0, 1000, 1001.2, -0.119632, 704, 359685, 227.011, 71), +(215, 'wm2', 0, 0, 0, 0, -100, 0, 0, 227.011, 71), +(216, 'wm3', 0, 0, 0, 0, -100, 0, 0, 227.011, 71), +(217, 'wm1', 0, 0, 99.4318, 98.3085, 1.14262, 70, 235168, 348.14, 72), +(218, 'wm2', 0, 0, 0, 0, -100, 0, 0, 348.14, 72), +(219, 'wm3', 0, 0, 0, 0, -100, 0, 0, 348.14, 72), +(220, 'wm1', 0, 0, 99.4318, 98.2879, 1.16382, 70, 235024, 347.978, 73), +(221, 'wm2', 0, 0, 0, 0, -100, 0, 0, 347.978, 73), +(222, 'wm3', 0, 0, 0, 0, -100, 0, 0, 347.978, 73), +(223, 'wm1', 0, 0, 100.852, 99.8041, 1.05024, 71, 238677, 347.982, 74), +(224, 'wm2', 0, 0, 0, 0, -100, 0, 0, 347.982, 74), +(225, 'wm3', 0, 0, 0, 0, -100, 0, 0, 347.982, 74), +(226, 'wm1', 0, 0, 113.636, 98.5252, 15.3374, 80, 235575, 348.083, 75), +(227, 'wm2', 0, 0, 0, 0, -100, 0, 0, 348.083, 75), +(228, 'wm3', 0, 0, 0, 0, -100, 0, 0, 348.083, 75), +(229, 'wm1', 0, 0, 166.193, 99.9431, 66.2878, 117, 238973, 348.062, 76), +(230, 'wm2', 0, 0, 0, 0, -100, 0, 0, 348.062, 76), +(231, 'wm3', 0, 0, 0, 0, -100, 0, 0, 348.062, 76), +(232, 'wm1', 0, 0, 1410, 200.627, 602.798, 141, 72052, 45.611, 77), +(233, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.611, 77), +(234, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.611, 77), +(235, 'wm1', 0, 0, 1000, 1001.49, -0.149094, 704, 359781, 227.05, 78), +(236, 'wm2', 0, 0, 0, 0, -100, 0, 0, 227.05, 78), +(237, 'wm3', 0, 0, 0, 0, -100, 0, 0, 227.05, 78), +(238, 'wm1', 0, 0, 1000, 1001.43, -0.142637, 704, 359761, 227.05, 79), +(239, 'wm2', 0, 0, 0, 0, -100, 0, 0, 227.05, 79), +(240, 'wm3', 0, 0, 0, 0, -100, 0, 0, 227.05, 79), +(241, 'wm1', 0, 0, 1002.84, 1001.4, 0.143683, 706, 359700, 227.053, 80), +(242, 'wm2', 0, 0, 0, 0, -100, 0, 0, 227.053, 80), +(243, 'wm3', 0, 0, 0, 0, -100, 0, 0, 227.053, 80), +(244, 'wm1', 0, 0, 1000, 1001.56, -0.155696, 704, 359828, 227.003, 81), +(245, 'wm2', 0, 0, 0, 0, -100, 0, 0, 227.003, 81), +(246, 'wm3', 0, 0, 0, 0, -100, 0, 0, 227.003, 81), +(247, 'wm1', 0, 0, 1000, 1001.35, -0.135193, 704, 359701, 227.042, 82), +(248, 'wm2', 0, 0, 0, 0, -100, 0, 0, 227.042, 82), +(249, 'wm3', 0, 0, 0, 0, -100, 0, 0, 227.042, 82), +(250, 'wm1', 0, 0, 99.4318, 98.314, 1.13703, 70, 235067, 349.559, 83), +(251, 'wm2', 0, 0, 0, 0, -100, 0, 0, 349.559, 83), +(252, 'wm3', 0, 0, 0, 0, -100, 0, 0, 349.559, 83), +(253, 'wm1', 0, 0, 99.4318, 98.2718, 1.18042, 70, 234977, 349.421, 84), +(254, 'wm2', 0, 0, 0, 0, -100, 0, 0, 349.421, 84), +(255, 'wm3', 0, 0, 0, 0, -100, 0, 0, 349.421, 84), +(256, 'wm1', 0, 0, 100.852, 99.7588, 1.09611, 71, 238564, 349.376, 85), +(257, 'wm2', 0, 0, 0, 0, -100, 0, 0, 349.376, 85), +(258, 'wm3', 0, 0, 0, 0, -100, 0, 0, 349.376, 85), +(259, 'wm1', 0, 0, 99.4318, 98.4383, 1.00923, 70, 235362, 349.416, 86), +(260, 'wm2', 0, 0, 0, 0, -100, 0, 0, 349.416, 86), +(261, 'wm3', 0, 0, 0, 0, -100, 0, 0, 349.416, 86), +(262, 'wm1', 0, 0, 100.852, 99.8505, 1.00323, 71, 238786, 349.366, 87), +(263, 'wm2', 0, 0, 0, 0, -100, 0, 0, 349.366, 87), +(264, 'wm3', 0, 0, 0, 0, -100, 0, 0, 349.366, 87), +(265, 'wm1', 0, 0, 1065.34, 0, -100, 750, 360027, 227.383, 88), +(266, 'wm2', 0, 0, 0, 0, -100, 0, 0, 227.383, 88), +(267, 'wm3', 0, 0, 0, 0, -100, 0, 0, 227.383, 88), +(268, 'wm1', 0, 0, 1410, 200.609, 602.86, 141, 72048, 45.529, 89), +(269, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.529, 89), +(270, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.529, 89), +(271, 'wm1', 0, 0, 1420, 199.108, 613.18, 142, 71515, 45.508, 90), +(272, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.508, 90), +(273, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.508, 90), +(274, 'wm1', 0, 0, 1420, 200.65, 607.699, 142, 72044, 45.525, 91), +(275, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.525, 91), +(276, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.525, 91), +(277, 'wm1', 0, 0, 1420, 200.581, 607.943, 142, 72038, 45.531, 92), +(278, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.531, 92), +(279, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.531, 92), +(280, 'wm1', 0, 0, 1400, 199.228, 602.713, 140, 71552, 45.516, 93), +(281, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.516, 93), +(282, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.516, 93), +(283, 'wm1', 0, 0, 1800, 200.088, 799.605, 180, 71883, 51.546, 94), +(284, 'wm2', 0, 0, 13620, 201.24, 6668.03, 1362, 72297, 51.546, 94), +(285, 'wm3', 0, 0, 0, 0, -100, 0, 0, 51.546, 94), +(286, 'wm1', 0, 0, 1803.5, 201.596, 0, 179, 71845, 47.865, 95), +(287, 'wm2', 0, 0, 0, 201.596, 0, 1424, 72366, 47.865, 95), +(288, NULL, 0, 0, 1803.5, 201.596, -100, 0, 0, 47.865, 95), +(289, 'wm1', 0, 0, 543.097, 602.379, 0, 542, 215922, 153.747, 96), +(290, 'wm2', 0, 0, 59.7737, 602.379, 0, 4029, 216302, 153.747, 96), +(291, NULL, 0, 0, 602.871, 602.379, -100, 0, 0, 153.747, 96), +(292, 'wm1', 0, 0, 161.217, 200.829, 0, 160, 71536, 228.42, 97), +(293, 'wm2', 0, 0, 40.1069, 200.829, 0, 2703, 72051, 228.42, 97), +(294, NULL, 0, 0, 201.324, 200.829, -100, 0, 0, 228.42, 97), +(295, 'wm1', 0, 0, 539.861, 602.315, 0, 539, 216039, 143.349, 98), +(296, 'wm2', 0, 0, 62.3862, 602.315, 0, 4205, 216322, 143.349, 98), +(297, NULL, 0, 0, 602.247, 602.315, -100, 0, 0, 143.349, 98), +(298, 'wm1', 0, 0, 162.342, 200.79, 0, 161, 71484, 228.798, 99), +(299, 'wm2', 0, 0, 39.6096, 200.79, 0, 2669, 72038, 228.798, 99), +(300, NULL, 0, 0, 201.952, 200.79, -100, 0, 0, 228.798, 99), +(301, 'wm1', 0, 0, 0, 100.469, 0, 0, 16776800, 306.062, 100), +(302, 'wm2', 0, 0, 99.1319, 100.469, 0, 6683, 240176, 306.062, 100), +(303, NULL, 0, 0, 99.1319, 100.469, -100, 0, 0, 306.062, 100), +(304, 'wm1', 0, 0, 64.0209, 100.63, 0, 63, 236649, 125.141, 101), +(305, 'wm2', 0, 0, 37.3474, 100.63, 0, 2517, 240385, 125.141, 101), +(306, NULL, 0, 0, 101.368, 100.63, -100, 0, 0, 125.141, 101), +(307, 'wm1', 0, 0, 540.281, 602.188, 0, 539, 215872, 143.575, 102), +(308, 'wm2', 0, 0, 61.8944, 602.188, 0, 4172, 216331, 143.575, 102), +(309, NULL, 0, 0, 602.175, 602.188, -100, 0, 0, 143.575, 102), +(310, 'wm1', 0, 0, 160.017, 200.86, 0, 159, 71622, 229.251, 103), +(311, 'wm2', 0, 0, 39.8327, 200.86, 0, 2684, 72037, 229.251, 103), +(312, NULL, 0, 0, 199.849, 200.86, -100, 0, 0, 229.251, 103), +(313, 'wm1', 0, 0, 0, 100.438, 0, 0, 16776900, 338.589, 104), +(314, 'wm2', 0, 0, 99.0655, 100.438, 0, 6678, 240137, 338.589, 104), +(315, NULL, 0, 0, 99.0655, 100.438, -100, 0, 0, 338.589, 104), +(316, 'wm1', 0, 0, 63.1665, 100.639, 0, 62, 236049, 124.339, 105), +(317, 'wm2', 0, 0, 37.3833, 100.639, 0, 2519, 240351, 124.339, 105), +(318, NULL, 0, 0, 100.55, 100.639, -100, 0, 0, 124.339, 105), +(319, 'wm1', 0, 0, 539.968, 602.378, 0, 539, 215998, 143.511, 106), +(320, 'wm2', 0, 0, 62.1642, 602.378, 0, 4191, 216374, 143.511, 106), +(321, NULL, 0, 0, 602.132, 602.378, -100, 0, 0, 143.511, 106), +(322, 'wm1', 0, 0, 160.774, 200.842, 0, 160, 71733, 229.662, 107), +(323, 'wm2', 0, 0, 40.1103, 200.842, 0, 2703, 72045, 229.662, 107), +(324, NULL, 0, 0, 200.884, 200.842, -100, 0, 0, 229.662, 107), +(325, 'wm1', 0, 0, 541.727, 602.268, 0, 540, 215697, 142.272, 108), +(326, 'wm2', 0, 0, 61.7283, 602.268, 0, 4161, 216343, 142.272, 108), +(327, NULL, 0, 0, 603.456, 602.268, -100, 0, 0, 142.272, 108), +(328, 'wm1', 0, 0, 161.883, 200.809, 0, 161, 71688, 227.334, 109), +(329, 'wm2', 0, 0, 39.8706, 200.809, 0, 2687, 72050, 227.334, 109), +(330, NULL, 0, 0, 201.753, 200.809, -100, 0, 0, 227.334, 109), +(331, 'wm1', 0, 0, 0, 100.452, 0, 0, 16777200, 303.052, 110), +(332, 'wm2', 0, 0, 99.1244, 100.452, 0, 6683, 240196, 303.052, 110), +(333, NULL, 0, 0, 99.1244, 100.452, -100, 0, 0, 303.052, 110), +(334, 'wm1', 0, 0, 59.9333, 100.63, 0, 59, 236755, 123.913, 111), +(335, 'wm2', 0, 0, 39.6961, 100.63, 0, 2676, 240465, 123.913, 111), +(336, NULL, 0, 0, 99.6293, 100.63, -100, 0, 0, 123.913, 111), +(337, 'wm1', 0, 0, 557.026, 601.566, 0, 556, 215744, 141.812, 112), +(338, 'wm2', 0, 0, 44.2035, 601.566, 0, 2980, 216121, 141.812, 112), +(339, NULL, 0, 0, 601.229, 601.566, -100, 0, 0, 141.812, 112), +(340, 'wm1', 0, 0, 540.17, 573.441, 0, 539, 215673, 141.843, 113), +(341, 'wm2', 0, 0, 61.4893, 573.441, 0, 4145, 216103, 141.843, 113), +(342, NULL, 0, 0, 601.659, 573.441, -100, 0, 0, 141.843, 113), +(343, 'wm1', 0, 0, 163.388, 200.576, 0, 163, 71857, 227.385, 114), +(344, 'wm2', 0, 0, 38.3645, 200.576, 0, 2586, 72011, 227.385, 114), +(345, NULL, 0, 0, 201.752, 200.576, -100, 0, 0, 227.385, 114), +(346, 'wm1', 0, 0, 0, 100.307, 0, 0, 16777100, 327.749, 115), +(347, 'wm2', 0, 0, 99.0589, 100.307, 0, 6678, 240098, 327.749, 115), +(348, NULL, 0, 0, 99.0589, 100.307, -100, 0, 0, 327.749, 115), +(349, 'wm1', 0, 0, 52.1295, 100.396, 0, 52, 239733, 124.195, 116), +(350, 'wm2', 0, 0, 47.3139, 100.396, 0, 3189, 240255, 124.195, 116), +(351, NULL, 0, 0, 99.4434, 100.396, -100, 0, 0, 124.195, 116), +(352, 'wm1', 0, 0, 557.773, 601.589, 0, 556, 215452, 142.352, 117), +(353, 'wm2', 0, 0, 44.6397, 601.589, 0, 3009, 216089, 142.352, 117), +(354, NULL, 0, 0, 602.413, 601.589, -100, 0, 0, 142.352, 117), +(355, 'wm1', 0, 0, 164.399, 200.602, 0, 163, 71416, 228.639, 118), +(356, 'wm2', 0, 0, 34.6523, 200.602, 0, 2335, 71988, 228.639, 118), +(357, NULL, 0, 0, 199.051, 200.602, -100, 0, 0, 228.639, 118), +(358, 'wm1', 0, 0, 0, 100.3, 0, 0, 16776800, 334.338, 119), +(359, 'wm2', 0, 0, 98.9856, 100.3, 0, 6673, 240094, 334.338, 119), +(360, NULL, 0, 0, 98.9856, 100.3, -100, 0, 0, 334.338, 119), +(361, 'wm1', 0, 0, 55.8177, 100.388, 0, 55, 236818, 122.406, 120), +(362, 'wm2', 0, 0, 43.7202, 100.388, 0, 2946, 240200, 122.406, 120), +(363, NULL, 0, 0, 99.538, 100.388, -100, 0, 0, 122.406, 120), +(364, 'wm1', 0, 0, 556.23, 601.44, 0, 555, 215658, 143.394, 121), +(365, 'wm2', 0, 0, 44.9828, 601.44, 0, 3032, 216077, 143.394, 121), +(366, NULL, 0, 0, 601.213, 601.44, -100, 0, 0, 143.394, 121), +(367, 'wm1', 0, 0, 163.633, 200.636, 0, 162, 71310, 227.823, 122), +(368, 'wm2', 0, 0, 35.0535, 200.636, 0, 2362, 71987, 227.823, 122), +(369, NULL, 0, 0, 198.687, 200.636, -100, 0, 0, 227.823, 122), +(370, 'wm1', 0, 0, 72.6003, 100.304, 0, 71, 234833, 327.562, 123), +(371, 'wm2', 0, 0, 26.5379, 100.304, 0, 1788, 239960, 327.562, 123), +(372, NULL, 0, 0, 99.1382, 100.304, -100, 0, 0, 327.562, 123), +(373, 'wm1', 0, 0, 58.5186, 100.385, 0, 57, 234099, 123.939, 124), +(374, 'wm2', 0, 0, 41.0619, 100.385, 0, 2767, 240208, 123.939, 124), +(375, NULL, 0, 0, 99.5805, 100.385, -100, 0, 0, 123.939, 124), +(376, 'wm1', 0, 0, 75.3241, 99.9558, 0, 73, 232934, 140.349, 125), +(377, 'wm2', 0, 0, 2666.08, 99.9558, 0, 2665, 240253, 140.349, 125), +(378, NULL, 0, 0, 2741.4, 99.9558, 2642.61, 0, 0, 140.349, 125), +(379, 'wm1', 0, 0, 489.792, 504.357, 0, 488, 17970, 45.555, 126), +(380, 'wm2', 0, 0, 462.179, 504.357, 0, 462, 18029, 45.555, 126), +(381, NULL, 0, 0, 951.972, 504.357, 88.7494, 0, 0, 45.555, 126), +(382, 'wm1', 0, 0, 82.0731, -0.00400604, 0, 72, 210923, 141.941, 127), +(383, 'wm2', 0, 0, 675.712, -0.00400604, 0, 601, 213848, 141.941, 127), +(384, NULL, 0, 0, 757.785, -0.00400604, 100, 0, 0, 141.941, 127), +(385, 'wm1', 0, 0, 98.6875, 100.371, 0, 97, 236187, 138.923, 128), +(386, 'wm2', 0, 0, 545.886, 100.371, 0, 544, 239466, 138.923, 128), +(387, NULL, 0, 0, 644.573, 100.371, 542.19, 0, 0, 138.923, 128), +(388, 'wm1', 0, 0, 490.496, 504.323, 0, 489, 17979, 47.722, 129), +(389, 'wm2', 0, 0, 449.746, 504.323, 0, 448, 17964, 47.722, 129), +(390, NULL, 0, 0, 940.242, 504.323, 86.4366, 0, 0, 47.722, 129), +(391, 'wm1', 0, 0, 74.2185, 100.377, 0, 73, 236351, 139.708, 130), +(392, 'wm2', 0, 0, 26.0858, 100.377, 0, 949, 240164, 139.708, 130), +(393, NULL, 0, 0, 100.304, 100.377, -0.0721921, 0, 0, 139.708, 130), +(394, 'wm1', 0, 0, 75.1074, 100.372, 0, 74, 236753, 139.606, 131), +(395, 'wm2', 0, 0, 24.9824, 100.372, 0, 909, 240201, 139.606, 131), +(396, NULL, 0, 0, 100.09, 100.372, -0.281415, 0, 0, 139.606, 131), +(397, 'wm1', 0, 0, 492.546, 503.6, 0, 492, 18012, 50.305, 132), +(398, 'wm2', 0, 0, 12.0006, 503.6, 0, 436, 17998, 50.305, 132), +(399, NULL, 0, 0, 504.547, 503.6, 0.18799, 0, 0, 50.305, 132), +(400, 'wm1', 0, 0, 77.6625, 100.363, 0, 77, 238250, 137.485, 133), +(401, 'wm2', 0, 0, 25.5386, 100.363, 0, 928, 239885, 137.485, 133), +(402, NULL, 0, 0, 103.201, 100.363, 2.82741, 0, 0, 137.485, 133), +(403, 'wm1', 0, 0, 75.623, 100.359, 0, 74, 235132, 141.199, 134), +(404, 'wm2', 0, 0, 24.7192, 100.359, 0, 899, 240081, 141.199, 134), +(405, NULL, 0, 0, 100.342, 100.359, -0.0170743, 0, 0, 141.199, 134), +(406, 'wm1', 0, 0, 75.605, 100.366, 0, 74, 235192, 141.235, 135), +(407, 'wm2', 0, 0, 24.7174, 100.366, 0, 899, 240102, 141.235, 135), +(408, NULL, 0, 0, 100.322, 100.366, -0.0431846, 0, 0, 141.235, 135), +(409, 'wm1', 0, 0, 75.5147, 100.362, 0, 74, 235473, 141.167, 136), +(410, 'wm2', 0, 0, 24.7436, 100.362, 0, 900, 240115, 141.167, 136), +(411, NULL, 0, 0, 100.258, 100.362, -0.103241, 0, 0, 141.167, 136), +(412, 'wm1', 0, 0, 75.4228, 100.36, 0, 74, 235758, 141.205, 137), +(413, 'wm2', 0, 0, 24.708, 100.36, 0, 898, 239925, 141.205, 137), +(414, NULL, 0, 0, 100.131, 100.36, -0.228191, 0, 0, 141.205, 137), +(415, 'wm1', 0, 0, 491.526, 504.026, 0, 490, 17979, 45.287, 138), +(416, 'wm2', 0, 0, 12.6683, 504.026, 0, 460, 17991, 45.287, 138), +(417, NULL, 0, 0, 504.194, 504.026, 0.0334405, 0, 0, 45.287, 138), +(418, 'wm1', 0, 0, 489.815, 503.921, 0, 489, 18000, 53.029, 139), +(419, 'wm2', 0, 0, 11.188, 503.921, 0, 406, 17975, 53.029, 139), +(420, NULL, 0, 0, 501.003, 503.921, -0.578981, 0, 0, 53.029, 139), +(421, 'wm1', 0, 0, 488.217, 504.187, 0, 488, 18028, 46.504, 140), +(422, 'wm2', 0, 0, 13.5857, 504.187, 0, 494, 18017, 46.504, 140), +(423, NULL, 0, 0, 501.802, 504.187, -0.47295, 0, 0, 46.504, 140), +(424, 'wm1', 0, 0, 492.708, 0, 0, 492, 18073, 46.696, 141), +(425, 'wm2', 0, 0, 13.5107, 0, 0, 491, 18070, 46.696, 141), +(426, NULL, 0, 0, 506.218, 0, 100, 0, 0, 46.696, 141), +(427, 'wm1', 0, 0, 487.947, 504.17, 0, 487, 18001, 46.473, 142), +(428, 'wm2', 0, 0, 13.513, 504.17, 0, 491, 18004, 46.473, 142), +(429, NULL, 0, 0, 501.46, 504.17, -0.537467, 0, 0, 46.473, 142), +(430, 'wm1', 0, 0, 74.6587, 100.373, 0, 74, 238169, 141.214, 143), +(431, 'wm2', 0, 0, 25.5406, 100.373, 0, 928, 239855, 141.214, 143), +(432, NULL, 0, 0, 100.199, 100.373, -0.172598, 0, 0, 141.214, 143), +(433, 'wm1', 0, 0, 74.9823, 100.358, 0, 74, 237145, 141.271, 144), +(434, 'wm2', 0, 0, 25.4422, 100.358, 0, 925, 240009, 141.271, 144), +(435, NULL, 0, 0, 100.424, 100.358, 0.066253, 0, 0, 141.271, 144), +(436, 'wm1', 0, 0, 74.3745, 100.363, 0, 73, 235854, 139.594, 145), +(437, 'wm2', 0, 0, 26.0476, 100.363, 0, 947, 240008, 139.594, 145), +(438, NULL, 0, 0, 100.422, 100.363, 0.058488, 0, 0, 139.594, 145), +(439, 'wm1', 0, 0, 74.6596, 100.368, 0, 74, 238170, 139.621, 146), +(440, 'wm2', 0, 0, 26.0331, 100.368, 0, 947, 240140, 139.621, 146), +(441, NULL, 0, 0, 100.693, 100.368, 0.323303, 0, 0, 139.621, 146), +(442, 'wm1', 0, 0, 73.2231, 100.381, 0, 72, 236290, 136.57, 147), +(443, 'wm2', 0, 0, 26.7173, 100.381, 0, 971, 239931, 136.57, 147), +(444, NULL, 0, 0, 99.9404, 100.381, -0.438539, 0, 0, 136.57, 147), +(445, 'wm1', 0, 0, 78.0386, 100.37, 0, 76, 234015, 141.259, 148), +(446, 'wm2', 0, 0, 25.6718, 100.37, 0, 933, 239918, 141.259, 148), +(447, NULL, 0, 0, 103.71, 100.37, 3.32821, 0, 0, 141.259, 148), +(448, 'wm1', 0, 0, 74.6587, 100.375, 0, 74, 238173, 141.35, 149), +(449, 'wm2', 0, 0, 25.6336, 100.375, 0, 932, 240019, 141.35, 149), +(450, NULL, 0, 0, 100.292, 100.375, -0.0825531, 0, 0, 141.35, 149), +(451, 'wm1', 0, 0, 492.365, 504.625, 0, 491, 17980, 52.841, 150), +(452, 'wm2', 0, 0, 11.25, 504.625, 0, 409, 18008, 52.841, 150), +(453, NULL, 0, 0, 503.615, 504.625, -0.200126, 0, 0, 52.841, 150), +(454, 'wm1', 0, 0, 491.381, 504.69, 0, 491, 18021, 46.735, 151), +(455, 'wm2', 0, 0, 13.7752, 504.69, 0, 501, 18020, 46.735, 151), +(456, NULL, 0, 0, 505.157, 504.69, 0.0923647, 0, 0, 46.735, 151), +(457, 'wm1', 0, 0, 27.5599, 50.1737, 0, 13, 56655, 188.906, 152), +(458, 'wm2', 0, 0, 49.5245, 50.1737, 0, 1802, 120062, 188.906, 152), +(459, NULL, 0, 0, 77.0843, 50.1737, 53.6348, 0, 0, 188.906, 152), +(460, 'wm1', 0, 0, 0, 50.1733, 0, 0, 16759000, 115.456, 153), +(461, 'wm2', 0, 0, 49.7609, 50.1733, 0, 1810, 120090, 115.456, 153), +(462, NULL, 0, 0, 49.7609, 50.1733, -0.821942, 0, 0, 115.456, 153), +(466, 'wm1', 0, 0, 0, 50.1685, 0, 0, 16759600, 99.018, 154), +(467, 'wm2', 0, 0, 49.7571, 50.1685, 0, 1810, 120133, 99.018, 154), +(468, NULL, 0, 0, 49.7571, 50.1685, -0.820005, 0, 0, 99.018, 154), +(469, 'wm1', 0, 0, 0, 50.1626, 0, 0, 16658100, 96.306, 155), +(470, 'wm2', 0, 0, 50.0808, 50.1626, 0, 1822, 120151, 96.306, 155), +(471, NULL, 0, 0, 50.0808, 50.1626, -0.163181, 0, 0, 96.306, 155), +(472, 'wm1', 0, 0, 49.905, 50.1651, 0, 49, 117977, 131.275, 156), +(473, 'wm2', 0, 0, 0.871778, 50.1651, 0, 30, 113595, 131.275, 156), +(474, NULL, 0, 0, 50.7768, 50.1651, 1.21934, 0, 0, 131.275, 156), +(475, 'wm1', 0, 0, 0, 50.1782, 0, 0, 16775900, 98.471, 157), +(476, 'wm2', 0, 0, 49.8067, 50.1782, 0, 1812, 120144, 98.471, 157), +(477, NULL, 0, 0, 49.8067, 50.1782, -0.740387, 0, 0, 98.471, 157), +(478, 'wm1', 0, 0, 47.7762, 50.1848, 0, 47, 118256, 99.223, 158), +(479, 'wm2', 0, 0, 6.77178, 50.1848, 0, 245, 119481, 99.223, 158), +(480, NULL, 0, 0, 54.548, 50.1848, 8.69418, 0, 0, 99.223, 158), +(481, 'wm1', 0, 0, 74.1062, 100.354, 0, 73, 236704, 140.713, 159), +(482, 'wm2', 0, 0, 26.1197, 100.354, 0, 950, 240100, 140.713, 159), +(483, NULL, 0, 0, 100.226, 100.354, -0.127919, 0, 0, 140.713, 159), +(484, 'wm1', 0, 0, 74.2084, 100.374, 0, 73, 236381, 140.877, 160), +(485, 'wm2', 0, 0, 26.1285, 100.374, 0, 950, 240022, 140.877, 160), +(486, NULL, 0, 0, 100.337, 100.374, -0.0366976, 0, 0, 140.877, 160), +(487, 'wm1', 0, 0, 74.1989, 100.373, 0, 74, 239647, 140.826, 161), +(488, 'wm2', 0, 0, 26.1314, 100.373, 0, 951, 240245, 140.826, 161), +(489, NULL, 0, 0, 100.33, 100.373, -0.0427862, 0, 0, 140.826, 161), +(490, 'wm1', 0, 0, 74.1353, 100.376, 0, 73, 236615, 140.842, 162), +(491, 'wm2', 0, 0, 26.0834, 100.376, 0, 949, 240185, 140.842, 162), +(492, NULL, 0, 0, 100.219, 100.376, -0.157146, 0, 0, 140.842, 162), +(493, 'wm1', 0, 0, 74.2927, 100.37, 0, 73, 236113, 140.91, 163), +(494, 'wm2', 0, 0, 26.0364, 100.37, 0, 947, 240110, 140.91, 163), +(495, NULL, 0, 0, 100.329, 100.37, -0.0412443, 0, 0, 140.91, 163), +(496, 'wm1', 0, 0, 495.357, 504.056, 0, 495, 18025, 42.394, 164), +(497, 'wm2', 0, 0, 13.6965, 504.056, 0, 498, 18018, 42.394, 164), +(498, NULL, 0, 0, 509.053, 504.056, 0.991396, 0, 0, 42.394, 164), +(499, 'wm1', 0, 0, 498.714, 503.279, 0, 497, 17976, 42.413, 165), +(500, 'wm2', 0, 0, 13.6895, 503.279, 0, 497, 17991, 42.413, 165), +(501, NULL, 0, 0, 512.404, 503.279, 1.81312, 0, 0, 42.413, 165), +(502, 'wm1', 0, 0, 490.305, 503.794, 0, 489, 17991, 42.458, 166), +(503, 'wm2', 0, 0, 13.6253, 503.794, 0, 495, 18004, 42.458, 166), +(504, NULL, 0, 0, 503.93, 503.794, 0.0269924, 0, 0, 42.458, 166), +(505, 'wm1', 0, 0, 489.302, 502.942, 0, 488, 17990, 42.43, 167), +(506, 'wm2', 0, 0, 13.6734, 502.942, 0, 496, 17976, 42.43, 167), +(507, NULL, 0, 0, 502.975, 502.942, 0.00666853, 0, 0, 42.43, 167), +(508, 'wm1', 0, 0, 491.288, 503.876, 0, 489, 17955, 42.466, 168), +(509, 'wm2', 0, 0, 13.6536, 503.876, 0, 496, 18003, 42.466, 168), +(510, NULL, 0, 0, 504.941, 503.876, 0.21141, 0, 0, 42.466, 168), +(511, 'wm1', 0, 0, 0, 50.1636, 0, 0, 16751600, 91.977, 169), +(512, 'wm2', 0, 0, 49.8958, 50.1636, 0, 1815, 120147, 91.977, 169), +(513, NULL, 0, 0, 49.8958, 50.1636, -0.533731, 0, 0, 91.977, 169), +(514, 'wm1', 0, 0, 0, 50.1793, 0, 0, 16751600, 91.859, 170), +(515, 'wm2', 0, 0, 49.8929, 50.1793, 0, 1815, 120153, 91.859, 170), +(516, NULL, 0, 0, 49.8929, 50.1793, -0.570654, 0, 0, 91.859, 170), +(517, 'wm1', 0, 0, 0, 50.1736, 0, 0, 16664800, 93.553, 171), +(518, 'wm2', 0, 0, 49.8341, 50.1736, 0, 1812, 120091, 93.553, 171), +(519, NULL, 0, 0, 49.8341, 50.1736, -0.676682, 0, 0, 93.553, 171), +(520, 'wm1', 0, 0, 1.8742, 50.1676, 0, 1, 64147, 92.725, 172), +(521, 'wm2', 0, 0, 49.7989, 50.1676, 0, 1812, 120179, 92.725, 172), +(522, NULL, 0, 0, 51.673, 50.1676, 3.00085, 0, 0, 92.725, 172), +(523, 'wm1', 0, 0, 0, 50.1676, 0, 0, 16767800, 94.104, 173), +(524, 'wm2', 0, 0, 49.8321, 50.1676, 0, 1813, 120158, 94.104, 173), +(525, NULL, 0, 0, 49.8321, 50.1676, -0.668642, 0, 0, 94.104, 173), +(526, 'wm1', 0, 0, 49.2621, 50.1722, 0, 48, 117100, 113.708, 174), +(527, 'wm2', 0, 0, 1.97506, 50.1722, 0, 70, 117016, 113.708, 174), +(528, NULL, 0, 0, 51.2372, 50.1722, 2.12265, 0, 0, 113.708, 174), +(529, 'wm1', 0, 0, 49.5521, 50.1769, 0, 49, 118842, 114.165, 175), +(530, 'wm2', 0, 0, 1.35864, 50.1769, 0, 48, 116646, 114.165, 175), +(531, NULL, 0, 0, 50.9107, 50.1769, 1.46246, 0, 0, 114.165, 175), +(532, 'wm1', 0, 0, 50.3895, 50.1726, 0, 50, 119249, 115.974, 176), +(533, 'wm2', 0, 0, 0.979079, 50.1726, 0, 35, 118025, 115.974, 176), +(534, NULL, 0, 0, 51.3686, 50.1726, 2.38378, 0, 0, 115.974, 176), +(535, 'wm1', 0, 0, 49.9235, 50.1733, 0, 49, 117955, 117.023, 177), +(536, 'wm2', 0, 0, 0.974843, 50.1733, 0, 34, 115151, 117.023, 177), +(537, NULL, 0, 0, 50.8983, 50.1733, 1.445, 0, 0, 117.023, 177), +(538, 'wm1', 0, 0, 49.7678, 50.1693, 0, 49, 118324, 114.351, 178), +(539, 'wm2', 0, 0, 1.42521, 50.1693, 0, 50, 115828, 114.351, 178), +(540, NULL, 0, 0, 51.193, 50.1693, 2.04042, 0, 0, 114.351, 178), +(541, 'wm1', 0, 0, 71.9354, 100.371, 0, 71, 237188, 131.394, 179), +(542, 'wm2', 0, 0, 28.5036, 100.371, 0, 1037, 240190, 131.394, 179), +(543, NULL, 0, 0, 100.439, 100.371, 0.0675517, 0, 0, 131.394, 179), +(544, 'wm1', 0, 0, 73.7589, 100.378, 0, 72, 234559, 139.926, 180), +(545, 'wm2', 0, 0, 26.7775, 100.378, 0, 974, 240116, 139.926, 180), +(546, NULL, 0, 0, 100.536, 100.378, 0.158155, 0, 0, 139.926, 180), +(547, 'wm1', 0, 0, 493.198, 0, 0, 492, 18065, 42.743, 181), +(548, 'wm2', 0, 0, 496.192, 0, 0, 496, 18102, 42.743, 181), +(549, NULL, 0, 0, 989.39, 0, 100, 0, 0, 42.743, 181), +(550, 'wm1', 0, 0, 106.428, 100.47, 0, 106, 35903, 67.678, 182), +(551, 'wm2', 0, 0, 17.4985, 100.47, 0, 16, 32961, 67.678, 182), +(552, NULL, 0, 0, 123.927, 100.47, 23.3465, 0, 0, 67.678, 182), +(553, 'wm1', 0, 0, 0, 50.1727, 0, 0, 16703200, 97.673, 183), +(554, 'wm2', 0, 0, 1811.81, 50.1727, 0, 1811, 120157, 97.673, 183), +(555, NULL, 0, 0, 1811.81, 50.1727, 3511.15, 0, 0, 97.673, 183), +(556, 'wm1', 0, 0, 35.6682, 50.2214, 0, 35, 118063, 65.623, 184), +(557, 'wm2', 0, 0, 536.7, 50.2214, 0, 535, 119936, 65.623, 184), +(558, NULL, 0, 0, 572.368, 50.2214, 1039.69, 0, 0, 65.623, 184), +(559, 'wm1', 0, 0, 591.655, 606.406, 0, 591, 21646, 28.282, 185), +(560, 'wm2', 0, 0, 15.6427, 606.406, 0, 569, 21655, 28.282, 185), +(561, NULL, 0, 0, 607.298, 606.406, 0.147111, 0, 0, 28.282, 185), +(562, 'wm1', 0, 0, 170.954, 200.698, 0, 170, 71668, 94.607, 186), +(563, 'wm2', 0, 0, 29.8979, 200.698, 0, 1087, 71985, 94.607, 186), +(564, NULL, 0, 0, 200.851, 200.698, 0.0762261, 0, 0, 94.607, 186), +(565, 'wm1', 0, 0, 594.796, 604.97, 0, 594, 21643, 28.098, 187), +(566, 'wm2', 0, 0, 14.4853, 604.97, 0, 526, 21620, 28.098, 187), +(567, NULL, 0, 0, 609.281, 604.97, 0.712705, 0, 0, 28.098, 187), +(568, 'wm1', 0, 0, 175.906, 200.643, 0, 175, 71699, 94.872, 188), +(569, 'wm2', 0, 0, 26.9631, 200.643, 0, 980, 71963, 94.872, 188), +(570, NULL, 0, 0, 202.869, 200.643, 1.1091, 0, 0, 94.872, 188), +(571, 'wm1', 0, 0, 0, 100.291, 0, 0, 16635600, 200.285, 189), +(572, 'wm2', 0, 0, 99.5408, 100.291, 0, 3623, 240188, 200.285, 189), +(573, NULL, 0, 0, 99.5408, 100.291, -0.748225, 0, 0, 200.285, 189), +(574, 'wm1', 0, 0, 97.9918, 100.314, 0, 97, 237751, 226.58, 190), +(575, 'wm2', 0, 0, 3.8521, 100.314, 0, 139, 238098, 226.58, 190), +(576, NULL, 0, 0, 101.844, 100.314, 1.52492, 0, 0, 226.58, 190), +(577, 'wm1', 0, 0, 0, 50.1568, 0, 0, 16775500, 98.315, 191), +(578, 'wm2', 0, 0, 49.8346, 50.1568, 0, 1813, 120146, 98.315, 191), +(579, NULL, 0, 0, 49.8346, 50.1568, -0.642228, 0, 0, 98.315, 191), +(580, 'wm1', 0, 0, 49.1247, 50.1749, 0, 49, 119872, 116.002, 192), +(581, 'wm2', 0, 0, 1.79279, 50.1749, 0, 64, 117861, 116.002, 192), +(582, NULL, 0, 0, 50.9175, 50.1749, 1.47987, 0, 0, 116.002, 192), +(583, 'wm1', 0, 0, 72.4993, 100.348, 0, 72, 238634, 141.267, 193), +(584, 'wm2', 0, 0, 27.9995, 100.348, 0, 1019, 240246, 141.267, 193), +(585, NULL, 0, 0, 100.499, 100.348, 0.150386, 0, 0, 141.267, 193), +(586, 'wm1', 0, 0, 494.178, 504.997, 0, 493, 17997, 41.633, 194), +(587, 'wm2', 0, 0, 11.9602, 504.997, 0, 434, 17984, 41.633, 194), +(588, NULL, 0, 0, 506.138, 504.997, 0.226031, 0, 0, 41.633, 194), +(589, 'wm1', 0, 0, 0, 50.1627, 0, 0, 16661200, 97.565, 195), +(590, 'wm2', 0, 0, 49.7392, 50.1627, 0, 1809, 120112, 97.565, 195), +(591, NULL, 0, 0, 49.7392, 50.1627, -0.844329, 0, 0, 97.565, 195), +(592, 'wm1', 0, 0, 49.6052, 50.1735, 0, 48, 116289, 115.859, 196), +(593, 'wm2', 0, 0, 1.43312, 50.1735, 0, 51, 117493, 115.859, 196), +(594, NULL, 0, 0, 51.0384, 50.1735, 1.72377, 0, 0, 115.859, 196), +(595, 'wm1', 0, 0, 0, 100.294, 0, 0, 16640800, 195.803, 197), +(596, 'wm2', 0, 0, 99.5411, 100.294, 0, 3622, 240122, 195.803, 197), +(597, NULL, 0, 0, 99.5411, 100.294, -0.750601, 0, 0, 195.803, 197), +(598, 'wm1', 0, 0, 98.7868, 100.305, 0, 98, 238268, 229.086, 198), +(599, 'wm2', 0, 0, 3.14719, 100.305, 0, 113, 236915, 229.086, 198), +(600, NULL, 0, 0, 101.934, 100.305, 1.62398, 0, 0, 229.086, 198), +(601, 'wm1', 0, 0, 176.134, 200.654, 0, 176, 72017, 94.671, 199), +(602, 'wm2', 0, 0, 29.5001, 200.654, 0, 1073, 72018, 94.671, 199), +(603, NULL, 0, 0, 205.635, 200.654, 2.48213, 0, 0, 94.671, 199), +(604, 'wm1', 0, 0, 591.956, 606.727, 0, 591, 21635, 28.131, 200), +(605, 'wm2', 0, 0, 14.2884, 606.727, 0, 520, 21666, 28.131, 200), +(606, NULL, 0, 0, 606.244, 606.727, -0.0795022, 0, 0, 28.131, 200), +(607, 'wm1', 0, 0, 0, 100.287, 0, 0, 16704700, 209.122, 201), +(608, 'wm2', 0, 0, 99.3867, 100.287, 0, 3617, 240153, 209.122, 201), +(609, NULL, 0, 0, 99.3867, 100.287, -0.897473, 0, 0, 209.122, 201), +(610, 'wm1', 0, 0, 98.913, 100.298, 0, 98, 237960, 233.016, 202), +(611, 'wm2', 0, 0, 3.03071, 100.298, 0, 109, 237308, 233.016, 202), +(612, NULL, 0, 0, 101.944, 100.298, 1.64045, 0, 0, 233.016, 202), +(613, 'wm1', 0, 0, 171.998, 200.67, 0, 171, 71652, 94.471, 203), +(614, 'wm2', 0, 0, 28.5873, 200.67, 0, 1040, 72030, 94.471, 203), +(615, NULL, 0, 0, 200.585, 200.67, -0.0424223, 0, 0, 94.471, 203), +(616, 'wm1', 0, 0, 591.501, 606.742, 0, 590, 21616, 28.114, 204), +(617, 'wm2', 0, 0, 14.2498, 606.742, 0, 518, 21642, 28.114, 204), +(618, NULL, 0, 0, 605.751, 606.742, -0.163396, 0, 0, 28.114, 204), +(619, 'wm1', 0, 0, 0, 100.276, 0, 0, 16652900, 202.784, 205), +(620, 'wm2', 0, 0, 99.4533, 100.276, 0, 3619, 240131, 202.784, 205), +(621, NULL, 0, 0, 99.4533, 100.276, -0.820459, 0, 0, 202.784, 205), +(622, 'wm1', 0, 0, 99.9299, 100.296, 0, 99, 237940, 235.554, 206), +(623, 'wm2', 0, 0, 2.00189, 100.296, 0, 72, 237312, 235.554, 206), +(624, NULL, 0, 0, 101.932, 100.296, 1.63113, 0, 0, 235.554, 206), +(625, 'wm1', 0, 0, 175.047, 200.603, 0, 174, 71640, 94.605, 207), +(626, 'wm2', 0, 0, 29.7242, 200.603, 0, 1081, 72007, 94.605, 207), +(627, NULL, 0, 0, 204.771, 200.603, 2.07753, 0, 0, 94.605, 207), +(628, 'wm1', 0, 0, 592.301, 607.594, 0, 592, 21661, 28.149, 208), +(629, 'wm2', 0, 0, 14.2505, 607.594, 0, 518, 21642, 28.149, 208), +(630, NULL, 0, 0, 606.551, 607.594, -0.171686, 0, 0, 28.149, 208), +(631, 'wm1', 0, 0, 1.40603, 100.278, 0, 1, 170840, 200.653, 209), +(632, 'wm2', 0, 0, 99.6419, 100.278, 0, 3626, 240142, 200.653, 209), +(633, NULL, 0, 0, 101.048, 100.278, 0.768322, 0, 0, 200.653, 209), +(634, 'wm1', 0, 0, 98.8428, 100.299, 0, 98, 238131, 230.112, 210), +(635, 'wm2', 0, 0, 3.03594, 100.299, 0, 109, 236901, 230.112, 210), +(636, NULL, 0, 0, 101.879, 100.299, 1.57492, 0, 0, 230.112, 210), +(637, 'wm1', 0, 0, 170.595, 200.688, 0, 169, 71398, 93.603, 211), +(638, 'wm2', 0, 0, 29.5682, 200.688, 0, 1075, 71986, 93.603, 211), +(639, NULL, 0, 0, 200.164, 200.688, -0.261361, 0, 0, 93.603, 211), +(640, 'wm1', 0, 0, 592.476, 607.612, 0, 591, 21618, 27.98, 212), +(641, 'wm2', 0, 0, 14.2427, 607.612, 0, 517, 21612, 27.98, 212), +(642, NULL, 0, 0, 606.719, 607.612, -0.14703, 0, 0, 27.98, 212), +(643, 'wm1', 0, 0, 0, 100.278, 0, 0, 16591200, 203.845, 213), +(644, 'wm2', 0, 0, 99.4047, 100.278, 0, 3618, 240182, 203.845, 213), +(645, NULL, 0, 0, 99.4047, 100.278, -0.870893, 0, 0, 203.845, 213), +(646, 'wm1', 0, 0, 99.2103, 100.308, 0, 98, 237252, 227.893, 214), +(647, 'wm2', 0, 0, 2.76914, 100.308, 0, 100, 238284, 227.893, 214), +(648, NULL, 0, 0, 101.979, 100.308, 1.66658, 0, 0, 227.893, 214), +(649, 'wm1', 0, 0, 171.026, 200.671, 0, 171, 72060, 93.412, 215), +(650, 'wm2', 0, 0, 28.7562, 200.671, 0, 1046, 72021, 93.412, 215), +(651, NULL, 0, 0, 199.782, 200.671, -0.442676, 0, 0, 93.412, 215), +(652, 'wm1', 0, 0, 592.246, 607.195, 0, 592, 21662, 27.925, 216), +(653, 'wm2', 0, 0, 14.2289, 607.195, 0, 517, 21632, 27.925, 216), +(654, NULL, 0, 0, 606.475, 607.195, -0.118593, 0, 0, 27.925, 216), +(655, 'wm1', 0, 0, 0, 100.326, 0, 0, 16777200, 209.388, 217), +(656, 'wm2', 0, 0, 99.368, 100.326, 0, 3616, 240131, 209.388, 217), +(657, NULL, 0, 0, 99.368, 100.326, -0.95479, 0, 0, 209.388, 217), +(658, 'wm1', 0, 0, 102.572, 100.321, 0, 102, 238857, 210.931, 218), +(659, 'wm2', 0, 0, 1.47127, 100.321, 0, 53, 237712, 210.931, 218), +(660, NULL, 0, 0, 104.043, 100.321, 3.71036, 0, 0, 210.931, 218), +(661, 'wm1', 0, 0, 197.851, 200.303, 0, 197, 71758, 94.603, 219), +(662, 'wm2', 0, 0, 2.05631, 200.303, 0, 74, 71250, 94.603, 219), +(663, NULL, 0, 0, 199.907, 200.303, -0.197736, 0, 0, 94.603, 219), +(664, 'wm1', 0, 0, 591.737, 606.845, 0, 591, 21643, 27.943, 220), +(665, 'wm2', 0, 0, 14.1732, 606.845, 0, 514, 21590, 27.943, 220), +(666, NULL, 0, 0, 605.911, 606.845, -0.154055, 0, 0, 27.943, 220), +(667, 'wm1', 0, 0, 0, 100.3, 0, 0, 16642100, 208.729, 221), +(668, 'wm2', 0, 0, 99.4487, 100.3, 0, 3619, 240136, 208.729, 221), +(669, NULL, 0, 0, 99.4487, 100.3, -0.848394, 0, 0, 208.729, 221), +(670, 'wm1', 0, 0, 1.4469, 100.293, 0, 1, 166020, 194.083, 222), +(671, 'wm2', 0, 0, 99.4679, 100.293, 0, 3620, 240173, 194.083, 222), +(672, NULL, 0, 0, 100.915, 100.293, 0.620384, 0, 0, 194.083, 222), +(673, 'wm1', 0, 0, 95.3968, 100.315, 0, 95, 239196, 211.811, 223), +(674, 'wm2', 0, 0, 6.45348, 100.315, 0, 234, 239268, 211.811, 223), +(675, NULL, 0, 0, 101.85, 100.315, 1.53025, 0, 0, 211.811, 223), +(676, 'wm1', 0, 0, 169.789, 200.655, 0, 169, 71734, 94.481, 224), +(677, 'wm2', 0, 0, 29.878, 200.655, 0, 1087, 72032, 94.481, 224), +(678, NULL, 0, 0, 199.667, 200.655, -0.49205, 0, 0, 94.481, 224), +(679, 'wm1', 0, 0, 592.175, 607.261, 0, 591, 21626, 27.954, 225), +(680, 'wm2', 0, 0, 14.2112, 607.261, 0, 516, 21615, 27.954, 225), +(681, NULL, 0, 0, 606.386, 607.261, -0.144079, 0, 0, 27.954, 225), +(682, 'wm1', 0, 0, 592.641, 605.56, 0, 591, 21610, 27.953, 226), +(683, 'wm2', 0, 0, 14.2564, 605.56, 0, 518, 21631, 27.953, 226), +(684, NULL, 0, 0, 606.897, 605.56, 0.220844, 0, 0, 27.953, 226), +(685, 'wm1', 0, 0, 169.261, 0, 0, 168, 71656, 94.672, 227), +(686, 'wm2', 0, 0, 30.4505, 0, 0, 1107, 72103, 94.672, 227), +(687, NULL, 0, 0, 199.712, 0, 100, 0, 0, 94.672, 227), +(688, 'wm1', 0, 0, 1.61949, 100.281, 0, 1, 148317, 207.996, 228), +(689, 'wm2', 0, 0, 99.4225, 100.281, 0, 3618, 240133, 207.996, 228), +(690, NULL, 0, 0, 101.042, 100.281, 0.758816, 0, 0, 207.996, 228), +(691, 'wm1', 0, 0, 96.0356, 100.317, 0, 96, 240100, 218.832, 229), +(692, 'wm2', 0, 0, 5.76275, 100.317, 0, 209, 239314, 218.832, 229), +(693, NULL, 0, 0, 101.798, 100.317, 1.47672, 0, 0, 218.832, 229), +(694, 'wm1', 0, 0, 592.175, 597.12, 0, 591, 21629, 27.8, 230), +(695, 'wm2', 0, 0, 15.018, 597.12, 0, 546, 21646, 27.8, 230), +(696, NULL, 0, 0, 607.193, 597.12, 1.68695, 0, 0, 27.8, 230), +(697, 'wm1', 0, 0, 194.911, 200.652, 0, 194, 71733, 93.052, 231), +(698, 'wm2', 0, 0, 5.86159, 200.652, 0, 212, 71610, 93.052, 231), +(699, NULL, 0, 0, 200.773, 200.652, 0.0600991, 0, 0, 93.052, 231), +(700, 'wm1', 0, 0, 1.62847, 100.288, 0, 1, 147503, 203.888, 232), +(701, 'wm2', 0, 0, 118.379, 100.288, 0, 4307, 240093, 203.888, 232), +(702, NULL, 0, 0, 120.007, 100.288, 19.6628, 0, 0, 203.888, 232), +(703, 'wm1', 0, 0, 99.5546, 100.301, 0, 99, 238844, 227.927, 233), +(704, 'wm2', 0, 0, 2.34684, 100.301, 0, 84, 236176, 227.927, 233), +(705, NULL, 0, 0, 101.901, 100.301, 1.59609, 0, 0, 227.927, 233); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `outputpath` +-- + +CREATE TABLE IF NOT EXISTS `outputpath` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `ItemNr` int(11) DEFAULT NULL, + `Name` varchar(255) DEFAULT NULL, + `Qfrom` float DEFAULT NULL, + `Qto` float DEFAULT NULL, + `RegulValve` varchar(255) DEFAULT NULL, + `FlowMeter` varchar(255) DEFAULT NULL, + `Diverter` varchar(255) DEFAULT NULL, + `TempDiv` varchar(255) DEFAULT NULL, + `Balance` varchar(255) DEFAULT NULL, + `EmptyTankValve` varchar(255) DEFAULT NULL, + `ValvesOpen` varchar(8000) DEFAULT NULL, + `ValvesClose` varchar(8000) DEFAULT NULL, + PRIMARY KEY (`Id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=8 ; + +-- +-- Dumping data for table `outputpath` +-- + +INSERT INTO `outputpath` (`Id`, `ItemNr`, `Name`, `Qfrom`, `Qto`, `RegulValve`, `FlowMeter`, `Diverter`, `TempDiv`, `Balance`, `EmptyTankValve`, `ValvesOpen`, `ValvesClose`) VALUES +(1, 1, 'PQ1', 0.01, 0.75, 'RV4', 'I4', 'DIV3', 'T5', 'W2', 'VB2', 'VI41;VI42', ''), +(2, 2, 'PQ2', 0.075, 0.18, 'RV5', 'I4', 'DIV3', 'T5', 'W2', 'VB2', 'VI41;VI43', ''), +(3, 3, 'PQ3', 0.18, 3, 'RV3', 'I3', 'DIV2', 'T3', 'W2', 'VB2', 'VI31;VI32', ''), +(4, 4, 'PQ4', 3, 19, 'RV2', 'I2', 'DIV1', 'T4', 'W1', 'VB1', 'VI13;VI21;VI22', ''), +(5, 5, 'PQ5', 19, 160, 'RV1', 'I1', 'DIV1', 'T4', 'W1', 'VB1', 'VI11;VI13', 'VI12'), +(6, 6, 'PQ6', 160, 210, 'RV1', 'I1', 'DIV1', 'T4', 'W1', 'VB1', 'VI11;VI12;VI13', ''), +(7, 0, '', 0, 0, '---', '---', '---', '---', '---', '---', '', ''); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `procedure` +-- + +CREATE TABLE IF NOT EXISTS `procedure` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `ItemNr` int(11) DEFAULT NULL, + `Name` varchar(255) DEFAULT NULL, + `Description` varchar(255) DEFAULT NULL, + `CreationUser` varchar(255) DEFAULT NULL, + `CreationTime` datetime DEFAULT NULL, + `LastChgUser` varchar(255) DEFAULT NULL, + `LastChgTime` datetime DEFAULT NULL, + `LongDescription` varchar(255) DEFAULT NULL, + `Watermeters` varchar(255) DEFAULT NULL, + `PulsesPerLtr` float DEFAULT '0', + `PulsesPerLtr2` float DEFAULT '0', + `DataEntry` varchar(255) DEFAULT NULL, + `ResultsPrinter` varchar(255) DEFAULT NULL, + `ResultsWriter` varchar(255) DEFAULT NULL, + PRIMARY KEY (`Id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=22 ; + +-- +-- Dumping data for table `procedure` +-- + +INSERT INTO `procedure` (`Id`, `ItemNr`, `Name`, `Description`, `CreationUser`, `CreationTime`, `LastChgUser`, `LastChgTime`, `LongDescription`, `Watermeters`, `PulsesPerLtr`, `PulsesPerLtr2`, `DataEntry`, `ResultsPrinter`, `ResultsWriter`) VALUES +(7, 0, 'Prüfung1', 'test1 meistream50', 'admin', '2014-01-21 08:21:49', 'admin', '2014-01-23 18:09:43', '', '', 0.1, 0, NULL, NULL, NULL), +(8, 1, 'Prüfung2', '', 'admin', '2014-01-21 14:46:58', 'admin', '2014-01-23 14:23:32', '', '', 1, 0, NULL, NULL, NULL), +(10, 2, 'Test 1', 'Karsten Test meistream50', 'admin', '2014-01-22 14:42:31', 'admin', '2014-01-23 14:23:45', '', '', 1, 0, NULL, NULL, NULL), +(11, 3, 'TestIgor', 'flowrates', 'admin', '2014-01-22 15:38:37', 'admin', '2014-01-23 14:23:58', '', '', 0, 0, NULL, NULL, NULL), +(12, 4, 'Prüfung3', 'bigline', 'admin', '2014-01-22 16:55:21', 'admin', '2014-01-23 14:24:30', '', '', 0.1, 0, NULL, NULL, NULL), +(13, 5, 'TEST VERIFICATION', '', 'admin', '2014-01-23 09:20:49', 'admin', '2014-01-23 16:38:55', '', '', 0.704, 0, NULL, NULL, NULL), +(14, 6, 'QN 15 HY', 'Kompakt D92 / 6.131.33', 'admin', '2014-01-24 08:51:59', 'admin', '2014-01-27 13:26:08', '', '', 1, 67.422, NULL, 'Advanced Results', NULL), +(15, 7, 'DN80', 'DN80 Verbundwasserzahler', 'admin', '2014-01-24 13:39:20', 'admin', '2014-02-20 12:08:59', '', '', 0, 0, 'Dateneingabe', 'Advanced Results', NULL), +(17, 0, '89189', 'Hydromete Qn40', 'admin', '2014-02-11 17:52:16', 'admin', '2014-02-12 08:54:30', '', '', 0, 0, NULL, 'Advanced Results', NULL), +(18, 0, '89189 - A', 'QN 40 DN80 Verbundwasserzahler', 'admin', '2014-02-12 09:26:19', 'admin', '2014-02-12 13:52:04', '', '', 0, 0, NULL, 'Advanced Results', NULL), +(19, 10, 'Prüfung4', '', 'admin', '2014-02-12 10:20:56', 'admin', '2014-02-12 10:20:56', NULL, NULL, 0, 0, NULL, NULL, NULL), +(20, 11, 'Prüfung5', '', 'admin', '2014-02-12 10:21:13', 'admin', '2014-02-12 10:21:25', '', '', 0, 0, NULL, NULL, NULL), +(21, 0, '89189 - A - Kopie', 'QN 40 DN80 Verbundwasserzahler', 'admin', '2014-02-12 15:47:50', 'admin', '2014-02-12 17:00:38', '', '', 0, 0, NULL, 'Advanced Results', NULL); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `purgeend` +-- + +CREATE TABLE IF NOT EXISTS `purgeend` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `ItemNr` int(11) DEFAULT NULL, + `Duration` int(11) DEFAULT NULL, + `ValvesOpen` varchar(8000) DEFAULT NULL, + `ValvesClose` varchar(8000) DEFAULT NULL, + `RegulValvesPct` varchar(255) DEFAULT ';;;;', + `Procedure_id` int(11) DEFAULT NULL, + PRIMARY KEY (`Id`), + KEY `Procedure_id` (`Procedure_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=11 ; + +-- +-- Dumping data for table `purgeend` +-- + +INSERT INTO `purgeend` (`Id`, `ItemNr`, `Duration`, `ValvesOpen`, `ValvesClose`, `RegulValvesPct`, `Procedure_id`) VALUES +(1, 0, 5, '', '', '10;20;30;40;50', 7), +(2, 0, 5, 'VP5;VP6', '', '0;0;30;0;0', 14), +(3, 1, 25, 'VP5;VP6', '', '0;0;0;0;0', 14), +(4, 2, 5, '', 'VP5', '0;0;0;0;0', 14), +(5, 0, 5, 'VI3P;VB1;VB2', 'VL11;VL13;VL21;VL23;VZ1;VP2;VP4;VP5;VP6;VL12;VL22;VI11;VI12;VI13;VI21;VI22;VI2P;VI31;VI32;VI41;VI42;VI43;VI4P', '0;0;0;0;0', 18), +(6, 1, 125, 'VP5;VP6', '', '0;0;0;0;0', 18), +(7, 2, 5, '', 'VP5;VP6;VB1;VB2', '0;0;0;0;0', 18), +(8, 0, 5, 'VI3P;VB1;VB2', 'VL11;VL13;VL21;VL23;VZ1;VP2;VP4;VP5;VP6;VL12;VL22;VI11;VI12;VI13;VI21;VI22;VI2P;VI31;VI32;VI41;VI42;VI43;VI4P', '0;0;0;0;0', 21), +(9, 1, 125, 'VP5;VP6', '', '0;0;0;0;0', 21), +(10, 2, 5, '', 'VP5;VP6;VB1;VB2', '0;0;0;0;0', 21); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `purgestart` +-- + +CREATE TABLE IF NOT EXISTS `purgestart` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `ItemNr` int(11) DEFAULT NULL, + `Duration` int(11) DEFAULT NULL, + `ValvesOpen` varchar(8000) DEFAULT NULL, + `ValvesClose` varchar(8000) DEFAULT NULL, + `RegulValvesPct` varchar(255) DEFAULT ';;;;', + `Procedure_id` int(11) DEFAULT NULL, + PRIMARY KEY (`Id`), + KEY `Procedure_id` (`Procedure_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=62 ; + +-- +-- Dumping data for table `purgestart` +-- + +INSERT INTO `purgestart` (`Id`, `ItemNr`, `Duration`, `ValvesOpen`, `ValvesClose`, `RegulValvesPct`, `Procedure_id`) VALUES +(1, 1, 10, 'VL13;VZ1;VL12;VI11;VI12;VI13;VI21;VI22;VI31;VI32;VI41;VI42;VI43;VB1;VB1a;VB2;VB2a', 'VL21', '50;40;30;20;10', 7), +(2, 0, 10, 'VL13;VZ1;VL12;VI11;VI12;VI13;VI21;VI22;VI31;VI32;VI41;VI42;VI43;VB1;VB1a;VB2;VB2a', 'VL21', '0;0;0;0;0', 7), +(3, 2, 10, 'VL11;VZ1;VL12;VI11;VI12;VI13;VI21;VI22;VI31;VI32;VI41;VI42;VI43;VB1;VB1a;VB2;VB2a', 'VL13;VL21', '0;0;0;0;0', 7), +(4, 3, 5, 'VZ1', 'VL11;VL13;VL21;VL12;VI11;VI12;VI13;VI21;VI22;VI31;VI32;VI41;VI42;VI43;VB1;VB1a;VB2;VB2a', '0;0;0;0;0', 7), +(5, 0, 5, '', '', '0;0;0;0;0', 11), +(6, 0, 20, 'VL13;VZ1;VL12;VI11;VI12;VI13;VI21;VI22;VI31;VI32;VI41;VI42;VI43;VB1;VB2', '', '5;5;5;5;5', 13), +(7, 1, 10, 'VL13;VZ1;VL12;VI11;VI12;VI32', 'VL11', '0;0;0;0;0', 13), +(8, 2, 5, 'VL11;VL13;VZ1;VL12;VI11;VI12;VI32', '', '0;0;0;0;0', 13), +(9, 3, 10, 'VL11;VL13;VZ1;VI11;VI12', 'VL12', '0;0;0;0;0', 13), +(10, 4, 25, 'VL11;VL13;VZ1;VL12;VI11;VI12', '', '0;0;0;0;0', 13), +(11, 5, 5, 'VL11;VL13;VZ1;VL12', 'VI11;VI12', '0;0;0;0;0', 13), +(12, 6, 5, '', 'VL11;VL13;VL21;VL23;VZ1;VP2;VP4;VP5;VP6;VL12;VL22;VI11;VI12;VI13;VI21;VI22;VI31;VI32;VI41;VI42;VI43;VI4P;VB1;VB2', '0;0;0;0;0', 13), +(13, 0, 10, 'VL13', '', '0;0;0;0;0', 15), +(14, 0, 10, 'VL13;VL23;VL12;VI11;VI12;VI13', '', '25;25;25;25;25', 14), +(15, 1, 30, 'VL13', 'VL12;VI11;VI12;VI13', '30;40;40;40;40', 14), +(16, 2, 20, 'VL11;VL12;VI21;VI22;VI31;VI32;VI41;VI42;VI43;VB1;VB2', 'VL13', '15;40;40;40;80', 14), +(17, 3, 15, 'VL11;VL12;VI11;VI13;VI21;VI22;VI31;VI32;VI41;VI42;VI43;VB1;VB2', '', '15;40;40;40;40', 14), +(18, 4, 8, 'VL11;VL12;VI21;VI22;VI31;VI32;VI41;VI42;VI43;VB1;VB2', 'VI11;VI13', '15;60;60;60;80', 14), +(19, 5, 8, 'VL11;VL12;VI21;VI22;VI31;VI32;VI41;VI42;VI43;VB1;VB2', '', '15;40;40;40;40', 14), +(20, 6, 2, 'VL11;VI21;VI22;VI31;VI32;VI41;VI42;VI43;VB1;VB2', 'VL12', '15;40;40;40;40', 14), +(21, 7, 28, 'VL11;VL12;VI11;VI13;VI21;VI22;VI31;VI32;VI41;VI42;VI43;VB1;VB2', '', '15;40;40;40;40', 14), +(22, 8, 2, 'VL11;VI11;VI13;VI21;VI22;VI31;VI32;VI41;VI42;VI43;VB1;VB2', 'VL12', '15;40;40;40;40', 14), +(23, 9, 15, 'VL11;VL12;VI11;VI13;VI21;VI22;VI31;VI32;VI41;VI42;VI43;VB1;VB2', '', '15;40;40;40;40', 14), +(24, 10, 5, 'VZ1', 'VL11;VL13;VL21;VL23;VP2;VP4;VP5;VP6;VL12;VL22;VI11;VI12;VI13;VI21;VI22;VI31;VI32;VI41;VI42;VI43;VI4P;VB1;VB2;VM1;VM2;VM3;VM4;Pumpe1;Block', '0;0;0;0;0', 14), +(25, 0, 10, 'VL13;VL12;VI11;VI12;VI13;VB1;VB2', '', '0;0;0;0;0', 17), +(26, 1, 30, 'VL13', 'VL12', '10;10;10;10;0', 17), +(27, 2, 20, 'VL11;VL12;VI13;VI21;VI22;VI31;VI32;VI41;VI42;VI43', 'VL13;VI11;VI12', '0;0;0;0;0', 17), +(28, 3, 15, '', 'VI13', '0;0;0;0;0', 17), +(29, 4, 8, 'VI13', '', '0;0;0;0;0', 17), +(30, 5, 8, '', 'VI21', '0;0;0;0;0', 17), +(31, 6, 2, 'VI21', '', '0;0;0;0;0', 17), +(32, 7, 28, 'VL12', '', '0;0;0;0;0', 17), +(33, 8, 2, '', 'VL12', '0;0;0;0;0', 17), +(34, 9, 15, 'VL11;VL12;VI11;VI12;VI13', '', '0;0;0;0;0', 17), +(35, 10, 2, '', 'VL11;VL13;VL21;VL23;VZ1;VP2;VP4;VP5;VP6;VL12;VL22;VI11;VI12;VI13;VI21;VI22;VI2P;VI31;VI32;VI3P;VI41;VI42;VI43;VI4P;VB1;VB2', '0;0;0;0;0', 17), +(36, 0, 20, 'VL13;VL12;VI11;VI12;VI13;VB1;VB2', '', '0;0;0;0;0', 18), +(37, 1, 30, '', 'VL12', '0;0;0;0;0', 18), +(38, 2, 20, 'VL11;VL12;VI21;VI22;VI31;VI32;VI41;VI42;VI43', 'VL13;VI11;VI12', '0;0;0;0;0', 18), +(39, 3, 15, 'VI11;VI12', '', '0;0;0;0;0', 18), +(40, 5, 8, 'VI11', 'VI12', '0;0;0;0;0', 18), +(41, 6, 8, '', '', '0;0;0;0;0', 18), +(42, 7, 2, '', 'VI11;VI12', '0;0;0;0;0', 18), +(43, 8, 28, '', '', '0;0;0;0;0', 18), +(44, 9, 2, '', 'VI21', '0;0;0;0;0', 18), +(45, 10, 15, 'VI11;VI12;VI21', '', '0;0;0;0;0', 18), +(46, 12, 5, '', 'VL11;VL13;VL21;VL23;VZ1;VP2;VP4;VP5;VP6;VL12;VL22;VI11;VI12;VI13;VI21;VI22;VI2P;VI31;VI32;VI3P;VI41;VI42;VI43;VI4P;VB1;VB2', '0;0;0;0;0', 18), +(47, 4, 5, '', 'VI11', '0;0;0;0;0', 18), +(48, 11, 5, '', 'VI11', '0;0;0;0;0', 18), +(49, 0, 20, 'VL13;VL12;VI11;VI12;VI13;VB1;VB2', '', '0;0;0;0;0', 21), +(50, 1, 30, '', 'VL12', '0;0;0;0;0', 21), +(51, 2, 20, 'VL11;VL12;VI21;VI22;VI31;VI32;VI41;VI42;VI43', 'VL13;VI11;VI12', '0;0;0;0;0', 21), +(52, 3, 15, 'VI11;VI12', '', '0;0;0;0;0', 21), +(53, 4, 5, '', 'VI11', '0;0;0;0;0', 21), +(54, 5, 8, 'VI11', 'VI12', '0;0;0;0;0', 21), +(55, 6, 8, '', '', '0;0;0;0;0', 21), +(56, 7, 2, '', 'VI11;VI12', '0;0;0;0;0', 21), +(57, 8, 28, '', '', '0;0;0;0;0', 21), +(58, 9, 2, '', 'VI21', '0;0;0;0;0', 21), +(59, 10, 15, 'VI11;VI12;VI21', '', '0;0;0;0;0', 21), +(60, 11, 5, '', 'VI11', '0;0;0;0;0', 21), +(61, 12, 5, '', 'VL11;VL13;VL21;VL23;VZ1;VP2;VP4;VP5;VP6;VL12;VL22;VI11;VI12;VI13;VI21;VI22;VI2P;VI31;VI32;VI3P;VI41;VI42;VI43;VI4P;VB1;VB2', '0;0;0;0;0', 21); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `test` +-- + +CREATE TABLE IF NOT EXISTS `test` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `ItemNr` int(11) DEFAULT NULL, + `Name` varchar(255) DEFAULT NULL, + `Qfrom` float DEFAULT NULL, + `Qto` float DEFAULT NULL, + `Volume` float DEFAULT NULL, + `TstTime` float DEFAULT NULL, + `Repeats` int(11) DEFAULT NULL, + `Emptying` tinyint(1) DEFAULT NULL, + `Zeroing` tinyint(1) DEFAULT NULL, + `Method` varchar(255) DEFAULT NULL, + `ErrLimLo` float DEFAULT NULL, + `ErrLimHi` float DEFAULT NULL, + `TolerRed` double DEFAULT NULL, + `RedType` varchar(255) DEFAULT NULL, + `FeedingPath` varchar(255) DEFAULT NULL, + `BenchPath` varchar(255) DEFAULT NULL, + `OutputPath` varchar(255) DEFAULT NULL, + `MetersPath` varchar(255) DEFAULT NULL, + `Procedure_id` int(11) DEFAULT NULL, + PRIMARY KEY (`Id`), + KEY `Procedure_id` (`Procedure_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=53 ; + +-- +-- Dumping data for table `test` +-- + +INSERT INTO `test` (`Id`, `ItemNr`, `Name`, `Qfrom`, `Qto`, `Volume`, `TstTime`, `Repeats`, `Emptying`, `Zeroing`, `Method`, `ErrLimLo`, `ErrLimHi`, `TolerRed`, `RedType`, `FeedingPath`, `BenchPath`, `OutputPath`, `MetersPath`, `Procedure_id`) VALUES +(15, 0, 'Qn', 15, 16, 200, 46.4516, 5, 1, 0, 'Verbund', 0, 2, 0, 'Fix', 'PS2', 'PBank2', 'PQ4', 'PMess1', 7), +(16, 1, 'Qt', 2, 2.2, 60, 102.857, 5, 1, 0, 'Fliegender Start-Stopp', 0, 5, 0, 'Fix', 'PS2', 'PBank2', 'PQ3', 'PMess1', 7), +(17, 2, 'Qmin', 1, 1.2, 20, 65.4545, 1, 1, 0, 'Fliegender Start-Stopp', 2, 0, 0.20000000298023224, 'Fix', 'PS2', 'PBank2', 'PQ3', '', 7), +(18, 0, 'Qmin', 1, 1.1, 30, 102.857, 1, 0, 0, 'Fliegender Start-Stopp', 2, 0, 0.20000000298023224, 'Fix', 'PS2', 'PBank2', 'PQ3', '', 8), +(19, 0, 'Qn', 12, 16, 200, 51.4286, 1, 0, 0, 'Fliegender Start-Stopp', 5, 0, 0.20000000298023224, 'Fix', 'PS2', 'PBank2', 'PQ4', '', 10), +(20, 1, 'Qt', 2.5, 3.5, 100, 120, 1, 0, 0, 'Fliegender Start-Stopp', 0, 0, 0.20000000298023224, 'Fix', 'PS2', 'PBank2', 'PQ3', '', 10), +(21, 0, 'Prüfpunkt1', 1, 1.2, 20, 65.4545, 5, 0, 0, 'Fliegender Start-Stopp', 0, 2, 0.20000000298023224, 'Fix', 'PS2', 'PBank2', 'PQ4', 'PMess1', 11), +(22, 1, 'Prüfpunkt2', 2, 2.1, 40, 70.2439, 5, 0, 0, 'Fliegender Start-Stopp', 0, 2, 0.20000000298023224, 'Fix', 'PS2', 'PBank2', 'PQ4', 'PMess1', 11), +(23, 2, 'Prüfpunkt3', 3.1, 3.2, 60, 68.5714, 5, 0, 0, 'Fliegender Start-Stopp', 0, 2, 0.20000000298023224, 'Fix', 'PS2', 'PBank2', 'PQ4', 'PMess1', 11), +(24, 3, 'Prüfpunkt4', 4.1, 4.3, 80, 68.5714, 5, 0, 0, 'Fliegender Start-Stopp', 0, 2, 0.20000000298023224, 'Fix', 'PS2', 'PBank2', 'PQ4', 'PMess1', 11), +(25, 4, 'Prüfpunkt5', 6, 6.1, 120, 71.405, 5, 0, 0, 'Fliegender Start-Stopp', 0, 2, 0.20000000298023224, 'Fix', 'PS2', 'PBank2', 'PQ4', 'PMess1', 11), +(26, 0, 'Prüfpunkt1', 15, 17, 200, 45, 4, 0, 0, 'Fliegender Start-Stopp', 2, 0, 0.20000000298023224, 'Fix', 'PS2', 'PBank2', 'PQ5', 'PMess1', 12), +(27, 0, 'Prüfpunkt1', 15, 16, 1000, 232.258, 5, 1, 0, 'Fliegender Start-Stopp', 0, 2, 0.20000000298023224, 'Fix', 'PS2', 'PBank2', 'PQ4', 'PMess1', 13), +(28, 1, 'Prüfpunkt2', 1, 1.1, 100, 342.857, 5, 1, 0, 'Fliegender Start-Stopp', 0, 2, 0.20000000298023224, 'Fix', 'PS2', 'PBank2', 'PQ3', 'PMess1', 13), +(29, 0, 'Qmax', 15, 16, 600, 139.355, 1, 0, 0, 'Verbund', 0, 2, 0.20000000298023224, 'Fix', 'PS2', 'PBank2', 'PQ4', 'PMess1', 14), +(30, 1, 'Qt', 3, 3.2, 200, 232.258, 1, 0, 0, 'Verbund', 0, 2, 0.20000000298023224, 'Fix', 'PS2', 'PBank2', 'PQ4', 'PMess1', 14), +(31, 2, 'Qsteig', 0.9, 1, 100, 378.947, 1, 1, 0, 'Verbund', 0, 5, 0.20000000298023224, 'Fix', 'PS2', 'PBank2', 'PQ3', 'PMess1', 14), +(32, 3, 'Qfall', 2.8, 3, 100, 124.138, 1, 1, 0, 'Verbund', 0, 5, 0.20000000298023224, 'Fix', 'PS2', 'PBank2', 'PQ3', 'PMess1', 14), +(33, 2, 'Q1', 2.4, 2.6, 100, 144, 1, 1, 0, 'Verbund', -2, 2, 0.20000000298023224, 'Fix', 'PS2', 'PBank2', 'PQ3', 'PMess1', 15), +(34, 3, 'Q2', 38, 44, 500, 43.9024, 1, 1, 0, 'Verbund', -2, 2, 0.20000000298023224, 'Fix', 'PS2', 'PBank2', 'PQ5', 'PMess1', 15), +(35, 0, 'Qsteig', 1, 1.2, 50, 163.636, 1, 1, 0, 'Verbund-steig-fall', -2, 2, 0.20000000298023224, 'Fix', 'PS2', 'PBank2', 'PQ3', 'PMess1', 15), +(36, 1, 'Qfall', 2.8, 3, 50, 62.069, 1, 1, 0, 'Verbund-steig-fall', -2, 2, 0.20000000298023224, 'Fix', 'PS2', 'PBank2', 'PQ3', 'PMess1', 15), +(41, 2, 'Qsteig', 1, 1.2, 100, 327.273, 1, 1, 0, 'Verbund-steig-fall', 5, 5, 0.20000000298023224, 'Fix', 'PS2', 'PBank2', 'PQ3', 'PMess1', 17), +(42, 3, 'Qfall', 2.8, 3, 100, 124.138, 1, 1, 0, 'Verbund-steig-fall', 5, 5, 0.20000000298023224, 'Fix', 'PS2', 'PBank2', 'PQ3', 'PMess1', 17), +(43, 1, 'Q1', 7.5, 7.8, 200, 94.1177, 1, 1, 0, 'Verbund', -2, 2, 0.20000000298023224, 'Fix', 'PS2', 'PBank2', 'PQ4', 'PMess1', 17), +(44, 0, 'Q2', 76, 84, 600, 27, 1, 1, 0, 'Verbund', -2, 2, 0.20000000298023224, 'Fix', 'PS2', 'PBank2', 'PQ5', 'PMess1', 17), +(45, 0, 'Qsteig', 1, 1.2, 100, 327.273, 1, 1, 0, 'Verbund-steig-fall', -2, 2, 0.20000000298023224, 'Fix', 'PS2', 'PBank2', 'PQ3', 'PMess1', 18), +(46, 1, 'Qfall', 2.8, 3, 100, 124.138, 1, 1, 0, 'Verbund-steig-fall', -2, 2, 0.20000000298023224, 'Fix', 'PS2', 'PBank2', 'PQ3', 'PMess1', 18), +(47, 2, 'Qt', 7.5, 7.8, 200, 94.1177, 1, 1, 0, 'Verbund', -2, 2, 0.20000000298023224, 'Fix', 'PS2', 'PBank2', 'PQ4', 'PMess1', 18), +(48, 3, 'Qmax', 76, 84, 600, 27, 1, 1, 0, 'Verbund', -2, 2, 0.20000000298023224, 'Fix', 'PS2', 'PBank2', 'PQ5', 'PMess1', 18), +(49, 2, 'Qsteig', 1, 1.2, 100, 327.273, 1, 1, 0, 'Verbund-steig-fall', -2, 2, 0.20000000298023224, 'Fix', 'PS2', 'PBank2', 'PQ3', 'PMess1', 21), +(50, 3, 'Qfall', 2.8, 3, 100, 124.138, 1, 1, 0, 'Verbund-steig-fall', -2, 2, 0.20000000298023224, 'Fix', 'PS2', 'PBank2', 'PQ3', 'PMess1', 21), +(51, 1, 'Qt', 7.5, 7.8, 200, 94.1177, 1, 1, 0, 'Verbund', -2, 2, 0.20000000298023224, 'Fix', 'PS2', 'PBank2', 'PQ4', 'PMess1', 21), +(52, 0, 'Qmax', 76, 84, 600, 27, 1, 1, 0, 'Verbund', -2, 2, 0.20000000298023224, 'Fix', 'PS2', 'PBank2', 'PQ5', 'PMess1', 21); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `testresult` +-- + +CREATE TABLE IF NOT EXISTS `testresult` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `Name` varchar(255) NOT NULL, + `TestName` varchar(255) NOT NULL, + `Qfrom` float NOT NULL, + `Qto` float NOT NULL, + `Volume` float NOT NULL, + `TstTime` float NOT NULL, + `Repeats` int(11) NOT NULL, + `Emptying` tinyint(4) NOT NULL, + `Zeroing` tinyint(4) NOT NULL, + `Method` varchar(255) NOT NULL, + `ErrLimLo` float NOT NULL, + `ErrLimHi` float NOT NULL, + `FeedingPath` varchar(4000) NOT NULL, + `BenchPath` varchar(4000) NOT NULL, + `OutputPath` varchar(4000) NOT NULL, + `MetersPath` varchar(4000) NOT NULL, + `TimeStart` datetime DEFAULT NULL, + `TimeEnd` datetime DEFAULT NULL, + `RepetitionNr` int(11) DEFAULT NULL, + `AmbientTempAve` float DEFAULT NULL, + `AmbientPressAve` float DEFAULT NULL, + `AmbientHumiAve` float DEFAULT NULL, + `PressInAvrg` float DEFAULT NULL, + `PressInStart` float DEFAULT NULL, + `PressInEnd` float DEFAULT NULL, + `PressOutAvrg` float DEFAULT NULL, + `PressOutStart` float DEFAULT NULL, + `PressOutEnd` float DEFAULT NULL, + `TempInAvrg` float DEFAULT NULL, + `TempInStart` float DEFAULT NULL, + `TempInEnd` float DEFAULT NULL, + `TempOutAvrg` float DEFAULT NULL, + `TempOutStart` float DEFAULT NULL, + `TempOutEnd` float DEFAULT NULL, + `TempDivAvrg` float DEFAULT NULL, + `TempDivStart` float DEFAULT NULL, + `TempDivEnd` float DEFAULT NULL, + `MassStartRaw` float DEFAULT NULL, + `MassStart` float DEFAULT NULL, + `MassEndRaw` float DEFAULT NULL, + `MassEnd` float DEFAULT NULL, + `MassDiff` float DEFAULT NULL, + `DensityIn` float DEFAULT NULL, + `DensityOut` float DEFAULT NULL, + `DensityDiv` float DEFAULT NULL, + `FlowMass` float DEFAULT NULL, + `FlowVolume` float DEFAULT NULL, + `VolumeCTV` float DEFAULT NULL, + `VolumeMaster` float DEFAULT NULL, + `Time` float DEFAULT NULL, + `ErrorMaster` float DEFAULT NULL, + `PulsesMaster` float DEFAULT NULL, + `ConstMaster` float DEFAULT NULL, + `TimeDivStart0` float DEFAULT NULL, + `TimeDivStart1` float DEFAULT NULL, + `TimeDivStart2` float DEFAULT NULL, + `TimeDivStart3` float DEFAULT NULL, + `TimeDivStart4` float DEFAULT NULL, + `TimeDivStart5` float DEFAULT NULL, + `TimeDivEnd0` float DEFAULT NULL, + `TimeDivEnd1` float DEFAULT NULL, + `TimeDivEnd2` float DEFAULT NULL, + `TimeDivEnd3` float DEFAULT NULL, + `TimeDivEnd4` float DEFAULT NULL, + `TimeDivEnd5` float DEFAULT NULL, + `Test_id` int(11) DEFAULT NULL, + PRIMARY KEY (`Id`), + KEY `Test_id` (`Test_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=234 ; + +-- +-- Dumping data for table `testresult` +-- + +INSERT INTO `testresult` (`Id`, `Name`, `TestName`, `Qfrom`, `Qto`, `Volume`, `TstTime`, `Repeats`, `Emptying`, `Zeroing`, `Method`, `ErrLimLo`, `ErrLimHi`, `FeedingPath`, `BenchPath`, `OutputPath`, `MetersPath`, `TimeStart`, `TimeEnd`, `RepetitionNr`, `AmbientTempAve`, `AmbientPressAve`, `AmbientHumiAve`, `PressInAvrg`, `PressInStart`, `PressInEnd`, `PressOutAvrg`, `PressOutStart`, `PressOutEnd`, `TempInAvrg`, `TempInStart`, `TempInEnd`, `TempOutAvrg`, `TempOutStart`, `TempOutEnd`, `TempDivAvrg`, `TempDivStart`, `TempDivEnd`, `MassStartRaw`, `MassStart`, `MassEndRaw`, `MassEnd`, `MassDiff`, `DensityIn`, `DensityOut`, `DensityDiv`, `FlowMass`, `FlowVolume`, `VolumeCTV`, `VolumeMaster`, `Time`, `ErrorMaster`, `PulsesMaster`, `ConstMaster`, `TimeDivStart0`, `TimeDivStart1`, `TimeDivStart2`, `TimeDivStart3`, `TimeDivStart4`, `TimeDivStart5`, `TimeDivEnd0`, `TimeDivEnd1`, `TimeDivEnd2`, `TimeDivEnd3`, `TimeDivEnd4`, `TimeDivEnd5`, `Test_id`) VALUES +(1, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-21 17:41:57', '2014-01-21 17:42:54', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.1818, 17.198, 17.17, 17.1656, 17.183, 17.155, 17.2016, 17.227, 17.181, 0.05, 0.05, 201.15, 201.15, 201.1, 1000.35, 1000.35, 1000.34, 15837.4, 15839.2, 201.237, 201.122, 45.712, -0.0570204, 72404, 0.00277936, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(2, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-21 17:43:11', '2014-01-21 17:45:07', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.1555, 17.162, 17.152, 17.1364, 17.144, 17.132, 17.5829, 17.91, 17.487, 0, 0, 60.133, 60.133, 60.133, 1000.35, 1000.35, 1000.27, 2062.1, 2062.55, 60.1737, 60.1463, 104.98, -0.0455428, 144351, 0.000416857, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16), +(3, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-21 17:49:21', '2014-01-21 17:50:18', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.2002, 17.222, 17.183, 17.182, 17.199, 17.168, 17.2144, 17.235, 17.194, 0, 0, 201.133, 201.133, 201.133, 1000.34, 1000.35, 1000.34, 15842.5, 15842, 201.271, 201.128, 45.705, -0.071127, 72406, 0.00277976, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(4, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-21 17:50:31', '2014-01-21 17:52:28', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.1553, 17.168, 17.147, 17.1358, 17.151, 17.128, 17.5125, 17.846, 17.436, 3.26133, 3.26133, 63.514, 63.514, 60.2527, 1000.35, 1000.35, 1000.29, 2067.4, 2063.75, 60.2934, 60.1463, 104.919, -0.244041, 144351, 0.000417686, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16), +(5, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-21 17:54:04', '2014-01-21 17:55:01', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.1507, 17.157, 17.146, 17.1317, 17.139, 17.127, 17.1593, 17.17, 17.147, 0, 0, 201.15, 201.15, 201.15, 1000.35, 1000.35, 1000.35, 15843.1, 15840.9, 201.286, 201.122, 45.707, -0.0812647, 72404, 0.00278004, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(6, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-21 17:55:14', '2014-01-21 17:57:12', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.1391, 17.141, 17.136, 17.1179, 17.121, 17.115, 17.4528, 17.727, 17.403, 3.363, 3.363, 63.6217, 63.6217, 60.2587, 1000.35, 1000.36, 1000.3, 2067.23, 2063.39, 60.2992, 60.1467, 104.938, -0.252975, 144352, 0.000417723, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16), +(7, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-22 09:13:46', '2014-01-22 09:14:43', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18.8708, 19.804, 18.321, 19.4739, 20.842, 18.646, 20.0805, 21.682, 18.94, 0, 0, 201.15, 201.15, 201.15, 1000.03, 999.913, 999.789, 15854.9, 15852.9, 201.375, 201.125, 45.673, -0.123957, 72405, 0.00278123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(8, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-22 09:30:27', '2014-01-22 09:31:24', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.7432, 17.782, 17.721, 17.7499, 17.793, 17.725, 17.8648, 17.989, 17.775, 0, 0, 201.15, 201.15, 201.15, 1000.25, 1000.24, 1000.22, 15803.3, 15801.1, 201.308, 201.122, 45.822, -0.0923222, 72404, 0.00278034, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(9, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-22 09:44:48', '2014-01-22 09:45:45', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.2819, 17.314, 17.248, 17.2901, 17.331, 17.254, 17.3612, 17.457, 17.291, 0, 0, 201.1, 201.1, 201.1, 1000.33, 1000.33, 1000.31, 15753.3, 15754.2, 201.241, 201.111, 45.956, -0.0647607, 72400, 0.00277958, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(10, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-22 09:54:30', '2014-01-22 09:55:27', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.1931, 17.237, 17.156, 17.2, 17.254, 17.161, 17.2767, 17.379, 17.212, 0, 0, 201.05, 201.05, 201.05, 1000.34, 1000.34, 1000.33, 15738.5, 15743.9, 201.188, 201.119, 45.988, -0.0341599, 72403, 0.00277873, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(11, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-22 10:11:13', '2014-01-22 10:12:09', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.1765, 17.23, 17.137, 17.1807, 17.234, 17.139, 17.2987, 17.466, 17.189, 0, 0, 201.2, 201.2, 201.2, 1000.35, 1000.35, 1000.33, 15801.4, 15795.3, 201.338, 201.122, 45.839, -0.106966, 72404, 0.00278075, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(12, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-22 10:12:23', '2014-01-22 10:14:13', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.102, 17.107, 17.104, 17.1125, 17.109, 17.125, 17.6444, 18.254, 17.504, 0, 0, 48.118, 48.118, 48.118, 1000.36, 1000.36, 1000.26, 1741.48, 2177.09, 48.1503, 60.1542, 99.47, 24.9299, 144370, 0.00033352, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16), +(13, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-22 10:24:14', '2014-01-22 10:25:11', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.1366, 17.172, 17.106, 17.1396, 17.197, 17.107, 17.2267, 17.342, 17.155, 0, 0, 201.1, 201.1, 201.1, 1000.35, 1000.35, 1000.34, 15795.3, 15796.8, 201.236, 201.119, 45.834, -0.0579684, 72403, 0.00277939, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(14, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-22 10:25:25', '2014-01-22 10:27:16', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.0878, 17.087, 17.089, 17.0902, 17.084, 17.103, 17.5711, 18.084, 17.455, 0, 0, 51.2683, 51.2683, 51.2683, 1000.36, 1000.36, 1000.28, 1852.09, 2173.09, 51.3026, 60.1542, 99.653, 17.2537, 144370, 0.000355355, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16), +(15, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-22 10:31:24', '2014-01-22 10:32:21', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.1506, 17.152, 17.161, 17.1276, 17.132, 17.136, 17.1659, 17.207, 17.152, 0, 0, 201.2, 201.2, 201.2, 1000.35, 1000.36, 1000.35, 15801.7, 15795.4, 201.336, 201.119, 45.838, -0.107422, 72403, 0.00278077, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(16, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-22 10:32:35', '2014-01-22 10:34:26', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.1924, 17.174, 17.209, 17.1736, 17.15, 17.195, 17.5562, 17.921, 17.499, 0, 0, 51.4273, 51.4273, 51.4273, 1000.34, 1000.35, 1000.28, 1857.16, 2172.32, 51.4624, 60.1546, 99.689, 16.8903, 144371, 0.00035646, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16), +(17, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-22 10:40:35', '2014-01-22 10:41:32', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.2396, 17.245, 17.237, 17.2284, 17.238, 17.222, 17.2562, 17.276, 17.242, 0, 0, 201.2, 201.2, 201.2, 1000.34, 1000.34, 1000.33, 15788.6, 15782.3, 201.339, 201.119, 45.876, -0.109186, 72403, 0.00278081, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(18, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-22 10:41:45', '2014-01-22 10:42:42', 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.2369, 17.24, 17.233, 17.2221, 17.223, 17.22, 17.239, 17.24, 17.24, 0, 0, 201.15, 201.15, 201.15, 1000.34, 1000.34, 1000.34, 15795.7, 15793.3, 201.289, 201.119, 45.844, -0.0842349, 72403, 0.00278012, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(19, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-22 10:42:55', '2014-01-22 10:43:52', 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.2012, 17.216, 17.181, 17.1943, 17.21, 17.176, 17.2148, 17.228, 17.202, 0, 0, 201.117, 201.117, 201.117, 1000.34, 1000.34, 1000.34, 15804.2, 15804.6, 201.255, 201.122, 45.812, -0.0658179, 72404, 0.00277961, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(20, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-22 10:44:05', '2014-01-22 10:45:02', 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.1431, 17.16, 17.128, 17.1348, 17.153, 17.118, 17.1586, 17.178, 17.141, 0.0166667, 0.0166667, 201.2, 201.2, 201.183, 1000.35, 1000.35, 1000.35, 15796.3, 15791.3, 201.319, 201.119, 45.85, -0.0992674, 72403, 0.00278054, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(21, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-22 10:45:15', '2014-01-22 10:46:12', 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.1021, 17.114, 17.094, 17.0894, 17.101, 17.079, 17.1112, 17.123, 17.101, 0, 0, 201.2, 201.2, 201.2, 1000.36, 1000.36, 1000.36, 15797.6, 15791.1, 201.334, 201.117, 45.85, -0.108127, 72402, 0.00278078, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(22, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-22 13:30:40', '2014-01-22 13:31:36', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.2618, 17.308, 17.226, 17.3, 17.394, 17.247, 17.6104, 17.992, 17.382, 0, 0, 201.133, 201.133, 201.133, 998.731, 998.724, 998.669, 15795.5, 15794.4, 201.598, 201.119, 45.841, -0.237233, 72403, 0.00278438, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(23, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-22 13:31:49', '2014-01-22 13:32:45', 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.1934, 17.202, 17.186, 17.1978, 17.216, 17.184, 17.2435, 17.281, 17.217, 0, 0, 201.2, 201.2, 201.2, 998.743, 998.742, 998.734, 15792.8, 15786.5, 201.661, 201.119, 45.864, -0.268477, 72403, 0.00278526, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(24, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-22 13:32:58', '2014-01-22 13:33:54', 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.1658, 17.173, 17.158, 17.1658, 17.176, 17.157, 17.1913, 17.206, 17.18, 0, 0, 201.15, 201.15, 201.15, 998.748, 998.748, 998.743, 15796.4, 15794, 201.61, 201.119, 45.842, -0.243115, 72403, 0.00278455, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(25, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-22 13:34:07', '2014-01-22 13:35:04', 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.1447, 17.15, 17.139, 17.1406, 17.147, 17.136, 17.1617, 17.17, 17.155, 0, 0, 201.233, 201.233, 201.233, 998.752, 998.752, 998.749, 15801.3, 15792.5, 201.692, 201.122, 45.847, -0.282612, 72404, 0.00278565, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(26, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-22 13:35:17', '2014-01-22 13:36:14', 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.1352, 17.136, 17.137, 17.1284, 17.13, 17.128, 17.1452, 17.147, 17.144, 0, 0, 201.15, 201.15, 201.15, 998.753, 998.754, 998.752, 15798.2, 15796, 201.608, 201.122, 45.837, -0.241088, 72404, 0.00278449, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(27, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-22 13:36:30', '2014-01-22 13:38:23', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.1575, 17.144, 17.166, 17.1557, 17.132, 17.176, 17.8218, 18.699, 17.611, 0, 0, 60.2617, 60.2617, 60.2617, 998.749, 998.75, 998.63, 2172.88, 2168.98, 60.3993, 60.1538, 99.841, -0.406466, 144369, 0.000418367, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16), +(28, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-22 13:38:37', '2014-01-22 13:40:28', 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.1742, 17.172, 17.178, 17.1969, 17.185, 17.207, 17.5216, 17.568, 17.487, 0, 0, 60.2737, 60.2737, 60.2737, 998.746, 998.742, 998.685, 2172.65, 2168.35, 60.4117, 60.1542, 99.871, -0.426323, 144370, 0.000418451, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16), +(29, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-22 13:40:41', '2014-01-22 13:44:13', 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.1814, 17.18, 17.179, 17.2121, 17.208, 17.215, 17.4733, 17.479, 17.469, 0, 0, -119.212, -119.212, -119.212, 998.745, 998.74, 998.693, -4924.63, 2169.62, -119.485, 52.5204, 87.146, 0.1, 126049, -0.000947925, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16), +(30, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-22 16:02:00', '2014-01-22 16:03:15', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.4985, 17.532, 17.456, 17.7711, 17.797, 17.76, 18.1239, 18.126, 18.063, 0.7, 0.7, 20.75, 20.75, 20.05, 998.689, 998.64, 998.575, 1126.93, 1128.49, 20.098, 20.0778, 64.05, -0.100578, 7228, 0.00278057, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21), +(31, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-22 16:03:26', '2014-01-22 16:04:41', 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.4188, 17.423, 17.399, 17.7271, 17.753, 17.701, 17.9281, 18, 17.874, 20.8, 20.8, 40.8667, 40.8667, 20.0667, 998.703, 998.648, 998.611, 1124.43, 1125.05, 20.1145, 20.0778, 64.246, -0.182746, 7228, 0.00278286, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21), +(32, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-22 16:04:52', '2014-01-22 16:06:07', 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.3671, 17.385, 17.358, 17.6452, 17.667, 17.616, 17.8033, 17.841, 17.767, 40.9, 40.9, 61, 61, 20.1, 998.712, 998.662, 998.634, 1124.55, 1123.3, 20.1476, 20.0778, 64.346, -0.34679, 7228, 0.00278744, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21), +(33, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-22 16:06:18', '2014-01-22 16:07:33', 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.3574, 17.358, 17.353, 17.5951, 17.61, 17.599, 17.7199, 17.748, 17.698, 61.05, 61.05, 81.1167, 81.1167, 20.0667, 998.714, 998.672, 998.649, 1123.2, 1123.83, 20.1141, 20.0778, 64.316, -0.180379, 7228, 0.0027828, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21), +(34, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-22 16:07:44', '2014-01-22 16:08:58', 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.3483, 17.349, 17.343, 17.5803, 17.599, 17.556, 17.6685, 17.682, 17.657, 81.15, 81.15, 101.25, 101.25, 20.1, 998.716, 998.674, 998.658, 1124.86, 1123.62, 20.1474, 20.0778, 64.328, -0.345629, 7228, 0.00278741, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21), +(35, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-22 16:09:21', '2014-01-22 16:10:43', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.3572, 17.356, 17.353, 17.5227, 17.544, 17.525, 17.6173, 17.646, 17.583, 101.25, 101.25, 141.45, 141.45, 40.2, 998.714, 998.685, 998.667, 2037.88, 2035.06, 40.2944, 40.1444, 71.015, -0.372169, 14452, 0.00278815, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22), +(36, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-22 16:10:54', '2014-01-22 16:12:16', 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.3371, 17.346, 17.333, 17.4815, 17.521, 17.451, 17.5445, 17.568, 17.519, 141.45, 141.45, 181.617, 181.617, 40.1667, 998.718, 998.692, 998.681, 2036.42, 2035.15, 40.2607, 40.1417, 71.007, -0.295629, 14451, 0.00278601, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22), +(37, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-22 16:12:27', '2014-01-22 16:13:49', 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.3189, 17.323, 17.319, 17.4144, 17.429, 17.407, 17.4837, 17.5, 17.469, 181.65, 181.65, 221.85, 221.85, 40.2, 998.721, 998.704, 998.692, 2037.62, 2034.81, 40.2937, 40.1444, 71.024, -0.370349, 14452, 0.0027881, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22), +(38, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-22 16:14:00', '2014-01-22 16:15:22', 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.317, 17.321, 17.313, 17.3955, 17.409, 17.39, 17.4482, 17.459, 17.439, 221.85, 221.85, 262.05, 262.05, 40.2, 998.721, 998.707, 998.698, 2037.71, 2034.75, 40.2935, 40.1417, 71.021, -0.376722, 14451, 0.00278828, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22), +(39, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-22 16:15:33', '2014-01-22 16:16:55', 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.3006, 17.309, 17.299, 17.3899, 17.4, 17.385, 17.4324, 17.436, 17.426, 262.1, 262.1, 302.267, 302.267, 40.1667, 998.724, 998.708, 998.701, 2036.25, 2034.98, 40.26, 40.1417, 71.013, -0.293995, 14451, 0.00278597, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22), +(40, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-22 16:17:15', '2014-01-22 16:18:35', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.3041, 17.311, 17.3, 17.3716, 17.393, 17.357, 17.415, 17.427, 17.401, 302.3, 302.3, 362.55, 362.55, 60.25, 998.724, 998.712, 998.704, 3116.96, 3115.38, 60.3898, 60.2194, 69.587, -0.282152, 21679, 0.00278564, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23), +(41, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-22 16:18:46', '2014-01-22 16:20:06', 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.292, 17.295, 17.291, 17.3415, 17.356, 17.331, 17.3764, 17.387, 17.365, 362.6, 362.6, 422.85, 422.85, 60.25, 998.726, 998.717, 998.711, 3117.99, 3116.41, 60.3895, 60.2194, 69.564, -0.281667, 21679, 0.00278562, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23), +(42, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-22 16:20:17', '2014-01-22 16:21:37', 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.2851, 17.293, 17.278, 17.3302, 17.338, 17.328, 17.3581, 17.362, 17.359, 422.9, 422.9, 483.15, 483.15, 60.25, 998.727, 998.719, 998.714, 3118.71, 3117.13, 60.3894, 60.2194, 69.548, -0.281465, 21679, 0.00278562, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23), +(43, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-22 16:21:48', '2014-01-22 16:23:08', 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.2673, 17.274, 17.259, 17.3324, 17.329, 17.316, 17.3468, 17.355, 17.342, 483.2, 483.2, 543.45, 543.45, 60.25, 998.73, 998.719, 998.716, 3119.78, 3118.2, 60.3894, 60.2194, 69.524, -0.281453, 21679, 0.00278562, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23), +(44, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-22 16:23:19', '2014-01-22 16:24:39', 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.2602, 17.263, 17.254, 17.3006, 17.31, 17.297, 17.3294, 17.338, 17.324, 543.45, 543.45, 603.75, 603.75, 60.3, 998.731, 998.724, 998.719, 3121.43, 3117.26, 60.4392, 60.2194, 69.545, -0.363607, 21679, 0.00278791, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23), +(45, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-22 16:25:00', '2014-01-22 16:26:20', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.248, 17.253, 17.242, 17.288, 17.295, 17.275, 17.3215, 17.324, 17.313, 603.75, 603.75, 684.117, 684.117, 80.3667, 998.733, 998.726, 998.72, 4179.36, 4175.74, 80.5521, 80.2972, 69.226, -0.316373, 28907, 0.00278659, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24), +(46, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-22 16:26:31', '2014-01-22 16:27:51', 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.2481, 17.242, 17.243, 17.2722, 17.271, 17.275, 17.3024, 17.31, 17.3, 684.15, 684.15, 764.5, 764.5, 80.3499, 998.733, 998.729, 998.724, 4179.39, 4176.5, 80.535, 80.2944, 69.211, -0.298715, 28906, 0.0027861, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24), +(47, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-22 16:28:02', '2014-01-22 16:29:22', 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.2303, 17.236, 17.227, 17.2607, 17.271, 17.254, 17.2948, 17.3, 17.286, 764.55, 764.55, 844.9, 844.9, 80.3501, 998.737, 998.731, 998.725, 4175.18, 4172.28, 80.535, 80.2944, 69.281, -0.298743, 28906, 0.0027861, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24), +(48, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-22 16:29:33', '2014-01-22 16:30:53', 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.2214, 17.225, 17.218, 17.2451, 17.25, 17.238, 17.2773, 17.283, 17.273, 844.9, 844.9, 925.25, 925.25, 80.3499, 998.738, 998.734, 998.728, 4181.26, 4178.38, 80.5346, 80.2944, 69.18, -0.298233, 28906, 0.00278609, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24), +(49, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-22 16:31:04', '2014-01-22 16:32:24', 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.2209, 17.22, 17.221, 17.2358, 17.239, 17.236, 17.2663, 17.268, 17.263, 925.25, 925.25, 1005.62, 1005.62, 80.3667, 998.738, 998.736, 998.73, 4181.59, 4177.83, 80.5513, 80.2944, 69.189, -0.318895, 28906, 0.00278666, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24), +(50, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-22 16:32:44', '2014-01-22 16:34:07', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.2195, 17.226, 17.212, 17.2277, 17.23, 17.23, 17.2623, 17.265, 17.259, 1005.65, 1005.65, 1126.07, 1126.07, 120.417, 998.738, 998.737, 998.731, 6007.98, 6008.4, 120.693, 120.425, 72.154, -0.222163, 43353, 0.00278396, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25), +(51, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-22 16:34:18', '2014-01-22 16:35:40', 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.2095, 17.218, 17.203, 17.22, 17.22, 17.215, 17.2511, 17.255, 17.247, 1126.1, 1126.1, 1246.53, 1246.53, 120.433, 998.74, 998.738, 998.733, 6089.5, 6089.36, 120.71, 120.431, 71.198, -0.231234, 43355, 0.00278422, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25), +(52, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-22 16:35:51', '2014-01-22 16:37:13', 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.1967, 17.199, 17.193, 17.2102, 17.214, 17.204, 17.2379, 17.245, 17.234, 1246.55, 1246.55, 1366.97, 1366.97, 120.417, 998.742, 998.74, 998.735, 6087.88, 6088.59, 120.693, 120.431, 71.207, -0.217208, 43355, 0.00278382, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25), +(53, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-22 16:37:24', '2014-01-22 16:38:46', 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.1888, 17.19, 17.189, 17.2037, 17.201, 17.192, 17.2271, 17.228, 17.224, 1367, 1367, 1487.45, 1487.45, 120.45, 998.744, 998.741, 998.737, 6088.02, 6087.05, 120.726, 120.431, 71.225, -0.2446, 43355, 0.00278459, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25), +(54, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-22 16:38:58', '2014-01-22 16:40:19', 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.1873, 17.188, 17.188, 17.19, 17.192, 17.19, 17.2222, 17.224, 17.219, 1487.5, 1487.5, 1607.9, 1607.9, 120.4, 998.744, 998.744, 998.738, 6064.73, 6066.13, 120.676, 120.428, 71.469, -0.205397, 43354, 0.0027835, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25), +(55, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-22 17:02:12', '2014-01-22 17:03:08', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.0874, 17.097, 17.081, 17.0734, 17.085, 17.065, 17.1019, 17.109, 17.095, 15.1, 15.1, 216.233, 216.233, 201.133, 998.762, 998.764, 998.759, 16247, 16245.2, 201.59, 201.111, 44.567, -0.237371, 7240, 0.0278439, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26), +(56, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-22 17:57:43', '2014-01-22 17:58:40', 1, 21.81, 948.212, 29.9233, 0, 0, 0, 0, 0, 0, 17.1047, 17.122, 17.09, 17.0985, 17.122, 17.083, 17.1413, 17.185, 17.114, -17.05, -17.05, 184.1, 184.1, 201.15, 998.759, 998.76, 998.752, 15815.1, 15812.9, 201.607, 201.122, 45.788, -0.240582, 72404, 0.00278448, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(57, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-23 08:44:35', '2014-01-23 08:45:32', 1, 23.45, 950.68, 26.0282, 0, 0, 0, 0, 0, 0, 18.453, 19.041, 18.037, 19.1917, 20.404, 18.331, 20.0359, 21.914, 18.711, 0, 0, 189.483, 189.483, 189.483, 998.513, 998.37, 998.199, 14954, 15872.7, 189.988, 201.125, 45.616, 5.86181, 72405, 0.00262397, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(58, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-23 08:50:09', '2014-01-23 08:51:06', 2, 23.5362, 950.676, 26.7004, 0, 0, 0, 0, 0, 0, 17.6413, 17.64, 17.65, 17.6502, 17.655, 17.655, 17.6828, 17.695, 17.677, 0, 0, 186.75, 186.75, 186.75, 998.663, 998.662, 998.656, 14745.4, 15880.6, 187.193, 201.128, 45.594, 7.44413, 72406, 0.00258532, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(59, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-23 08:55:42', '2014-01-23 08:56:38', 3, 23.62, 950.554, 26.6455, 0, 0, 0, 0, 0, 0, 17.416, 17.47, 17.361, 17.4474, 17.493, 17.395, 17.4955, 17.54, 17.442, 0, 0, 186.75, 186.75, 186.75, 998.704, 998.698, 998.689, 14742.8, 15877.8, 187.186, 201.128, 45.602, 7.44806, 72406, 0.00258523, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(60, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-23 08:56:55', '2014-01-23 08:57:51', 4, 23.623, 950.795, 26.392, 0, 0, 0, 0, 0, 0, 17.2409, 17.284, 17.2, 17.2702, 17.312, 17.222, 17.3208, 17.373, 17.266, -22.55, -22.55, 178.6, 178.6, 201.15, 998.735, 998.73, 998.721, 15883.7, 15882, 201.613, 201.128, 45.59, -0.24084, 72406, 0.00278448, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(61, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-23 09:31:37', '2014-01-23 09:35:35', 1, 23.5322, 951.066, 27.0611, 0, 0, 0, 0, 0, 0, 17.1355, 17.562, 17.05, 17.1693, 17.66, 17.047, 17.2724, 17.93, 17.091, 0, 0, 989.017, 989.017, 989.017, 998.753, 998.747, 998.729, 15679.7, 15871.7, 991.277, 1001.12, 227.074, 0.993456, 360405, 0.00275045, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27), +(62, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-23 09:49:45', '2014-01-23 09:53:43', 1, 23.4289, 951.307, 27.749, 0, 0, 0, 0, 0, 0, 17.0658, 17.192, 17.039, 17.0687, 17.222, 17.031, 17.106, 17.246, 17.054, -0.3, -0.3, 1000.65, 1000.65, 1000.95, 998.765, 998.765, 998.758, 15872.4, 15875.2, 1003.22, 1001.13, 227.025, -0.208551, 360406, 0.00278358, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27), +(63, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-23 09:58:22', '2014-01-23 10:02:20', 1, 23.3655, 951.275, 27.6753, 0, 0, 0, 0, 0, 0, 17.0131, 17.017, 17.007, 17.0014, 17.006, 16.996, 17.0201, 17.025, 17.01, 34.1, 34.1, 1035.08, 1035.08, 1000.98, 998.775, 998.777, 998.773, 15872.3, 15874.6, 1003.24, 1001.12, 227.033, -0.210986, 360405, 0.00278365, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27), +(64, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-23 10:04:51', '2014-01-23 10:08:49', 2, 23.2715, 951.288, 27.3465, 0, 0, 0, 0, 0, 0, 16.996, 16.998, 16.995, 16.9819, 16.985, 16.981, 17.0011, 17.004, 17.002, 32.9, 32.9, 1034.05, 1034.05, 1001.15, 998.778, 998.78, 998.777, 15874.2, 15873.8, 1003.41, 1001.12, 227.044, -0.227527, 360404, 0.00278411, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27), +(65, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-23 10:11:24', '2014-01-23 10:15:22', 3, 23.1503, 951.305, 27.0103, 0, 0, 0, 0, 0, 0, 16.9938, 16.995, 16.993, 16.9781, 16.978, 16.98, 16.9963, 16.996, 16.996, 33.15, 33.15, 1034.13, 1034.13, 1000.98, 998.778, 998.781, 998.778, 15872.1, 15874.3, 1003.24, 1001.12, 227.036, -0.210841, 360404, 0.00278365, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27), +(66, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-23 10:17:57', '2014-01-23 10:21:55', 4, 23.0528, 951.479, 27.0146, 0, 0, 0, 0, 0, 0, 16.9936, 16.993, 16.994, 16.9767, 16.977, 16.977, 16.9958, 16.998, 16.997, 32.85, 32.85, 1033.85, 1033.85, 1001, 998.778, 998.781, 998.778, 15873.3, 15875.3, 1003.25, 1001.12, 227.023, -0.212212, 360405, 0.00278369, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27), +(67, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-23 10:32:46', '2014-01-23 10:36:44', 1, 22.836, 951.592, 27.534, 0, 0, 0, 0, 0, 0, 16.999, 17, 16.999, 16.9772, 16.978, 16.977, 16.9958, 16.998, 16.994, 33.3, 33.3, 1034.27, 1034.27, 1000.97, 998.777, 998.781, 998.778, 15872.1, 15874.6, 1003.22, 1001.12, 227.032, -0.20891, 360405, 0.00278359, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27), +(68, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-23 10:39:14', '2014-01-23 10:43:12', 2, 22.7173, 951.711, 27.5574, 0, 0, 0, 0, 0, 0, 17.0003, 16.999, 17.001, 16.9784, 16.977, 16.979, 16.9973, 16.996, 16.998, 32.95, 32.95, 1033.9, 1033.9, 1000.95, 998.777, 998.781, 998.777, 15871.2, 15874, 1003.2, 1001.12, 227.041, -0.207258, 360405, 0.00278355, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27), +(69, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-23 10:45:43', '2014-01-23 10:49:41', 3, 22.5937, 951.647, 27.4176, 0, 0, 0, 0, 0, 0, 17.0002, 17, 16.999, 16.9784, 16.978, 16.979, 16.9972, 16.997, 16.996, 33.05, 33.05, 1034.05, 1034.05, 1001, 998.777, 998.781, 998.777, 15869.6, 15871.6, 1003.25, 1001.12, 227.076, -0.212249, 360405, 0.00278369, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27), +(70, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-23 10:52:16', '2014-01-23 10:56:15', 4, 22.526, 951.594, 27.5806, 0, 0, 0, 0, 0, 0, 17.0014, 17.002, 17.003, 16.9788, 16.978, 16.979, 16.9989, 16.997, 16.998, 33, 33, 1033.98, 1033.98, 1000.98, 998.777, 998.781, 998.777, 15871.1, 15873.4, 1003.24, 1001.13, 227.051, -0.210299, 360406, 0.00278363, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27), +(71, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-23 10:58:49', '2014-01-23 11:02:47', 5, 22.4358, 951.725, 27.4002, 0, 0, 0, 0, 0, 0, 17.0043, 17.003, 17.004, 16.981, 16.979, 16.982, 16.9999, 16.997, 17, 33.15, 33.15, 1034.1, 1034.1, 1000.95, 998.776, 998.78, 998.777, 15873.3, 15876.1, 1003.2, 1001.13, 227.011, -0.207021, 360406, 0.00278354, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27), +(72, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-23 11:03:27', '2014-01-23 11:09:25', 1, 22.381, 951.688, 27.6094, 0, 0, 0, 0, 0, 0, 17.0359, 17.014, 17.041, 17.0425, 16.99, 17.078, 17.8152, 18.731, 17.476, -0.0136667, -0.0136667, 100.162, 100.162, 100.175, 998.771, 998.769, 998.632, 1035.88, 1034.83, 100.402, 100.073, 348.14, -0.327396, 240176, 0.000418035, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28), +(73, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-23 11:10:11', '2014-01-23 11:16:10', 2, 22.3575, 951.648, 27.5311, 0, 0, 0, 0, 0, 0, 17.0517, 17.046, 17.055, 17.1016, 17.084, 17.111, 17.4316, 17.448, 17.426, 5.42533, 5.42533, 105.64, 105.64, 100.215, 998.768, 998.759, 998.701, 1036.77, 1035.31, 100.443, 100.073, 347.978, -0.367552, 240176, 0.000418204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28), +(74, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-23 11:16:58', '2014-01-23 11:22:57', 3, 22.3472, 951.517, 27.2686, 0, 0, 0, 0, 0, 0, 17.0592, 17.054, 17.062, 17.125, 17.114, 17.13, 17.4365, 17.429, 17.444, 5.60667, 5.60667, 105.809, 105.809, 100.203, 998.767, 998.755, 998.7, 1036.63, 1035.29, 100.431, 100.073, 347.982, -0.356025, 240176, 0.000418155, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28), +(75, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-23 11:23:45', '2014-01-23 11:29:44', 4, 22.3489, 951.527, 27.0005, 0, 0, 0, 0, 0, 0, 17.0613, 17.058, 17.063, 17.1369, 17.133, 17.135, 17.4475, 17.442, 17.454, 5.24433, 5.24433, 105.465, 105.465, 100.221, 998.766, 998.753, 998.698, 1036.52, 1034.99, 100.449, 100.073, 348.083, -0.374469, 240176, 0.000418233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28), +(76, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-23 11:30:31', '2014-01-23 11:36:30', 5, 22.3677, 951.481, 26.8638, 0, 0, 0, 0, 0, 0, 17.0642, 17.061, 17.069, 17.142, 17.133, 17.15, 17.4536, 17.454, 17.452, 5.583, 5.583, 105.801, 105.801, 100.218, 998.766, 998.752, 998.697, 1036.55, 1035.06, 100.446, 100.073, 348.062, -0.371238, 240176, 0.000418219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28), +(77, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-23 14:36:43', '2014-01-23 14:37:40', 1, 22.1304, 950.107, 27.0682, 0, 0, 0, 0, 0, 0, 17.1687, 17.174, 17.16, 17.167, 17.175, 17.159, 17.2108, 17.23, 17.196, 33.1, 33.1, 234.25, 234.25, 201.15, 998.747, 998.748, 998.74, 15876.4, 15874.5, 201.61, 201.125, 45.611, -0.240383, 72405, 0.00278447, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(78, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-23 14:40:03', '2014-01-23 14:44:01', 1, 22.1172, 950.109, 27.9356, 0, 0, 0, 0, 0, 0, 17.1405, 17.13, 17.147, 17.1268, 17.119, 17.13, 17.1458, 17.145, 17.148, 33.5, 33.5, 1034.45, 1034.45, 1000.95, 998.752, 998.755, 998.751, 15870.6, 15873.4, 1003.23, 1001.12, 227.05, -0.209839, 360405, 0.00278362, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27), +(79, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-23 14:46:33', '2014-01-23 14:50:32', 2, 22.0557, 950.031, 27.9047, 0, 0, 0, 0, 0, 0, 17.0877, 17.134, 17.062, 17.0744, 17.123, 17.045, 17.0975, 17.145, 17.066, 32.7, 32.7, 1033.65, 1033.65, 1000.95, 998.762, 998.764, 998.76, 15870.6, 15873.4, 1003.22, 1001.12, 227.05, -0.208928, 360405, 0.00278359, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27), +(80, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-23 14:53:06', '2014-01-23 14:57:04', 3, 22.0006, 950.123, 27.87, 0, 0, 0, 0, 0, 0, 17.0567, 17.057, 17.05, 17.0369, 17.036, 17.031, 17.0565, 17.055, 17.051, 33.3, 33.3, 1034.4, 1034.4, 1001.1, 998.767, 998.77, 998.767, 15872.8, 15873.2, 1003.36, 1001.12, 227.053, -0.22323, 360405, 0.00278399, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27), +(81, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-23 14:59:35', '2014-01-23 15:03:33', 4, 21.9671, 950.105, 27.9426, 0, 0, 0, 0, 0, 0, 17.0501, 17.049, 17.051, 17.0276, 17.027, 17.029, 17.0484, 17.049, 17.048, 33, 33, 1033.9, 1033.9, 1000.9, 998.768, 998.772, 998.768, 15873.1, 15876.6, 1003.16, 1001.12, 227.003, -0.203403, 360404, 0.00278344, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27), +(82, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-23 15:06:08', '2014-01-23 15:10:06', 5, 21.9451, 950.152, 27.9535, 0, 0, 0, 0, 0, 0, 17.054, 17.051, 17.056, 17.0309, 17.029, 17.033, 17.0513, 17.05, 17.052, 32.9, 32.9, 1033.95, 1033.95, 1001.05, 998.768, 998.771, 998.768, 15872.7, 15873.9, 1003.31, 1001.12, 227.042, -0.218131, 360405, 0.00278385, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27), +(83, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-23 15:10:28', '2014-01-23 15:16:28', 1, 21.9423, 950.104, 28.1947, 0, 0, 0, 0, 0, 0, 17.0873, 17.059, 17.095, 17.0896, 17.038, 17.125, 17.8578, 19.567, 17.514, 0.236667, 0.236667, 100.459, 100.459, 100.223, 998.762, 998.761, 998.624, 1032.16, 1030.62, 100.45, 100.073, 349.559, -0.375704, 240175, 0.000418238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28), +(84, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-23 15:17:15', '2014-01-23 15:23:15', 2, 21.9366, 950.112, 28.259, 0, 0, 0, 0, 0, 0, 17.1022, 17.095, 17.109, 17.1503, 17.13, 17.167, 17.4923, 17.505, 17.492, 5.38167, 5.38167, 105.599, 105.599, 100.217, 998.759, 998.751, 998.69, 1032.51, 1031.03, 100.446, 100.073, 349.421, -0.371126, 240175, 0.000418219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28), +(85, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-23 15:24:03', '2014-01-23 15:30:04', 3, 21.9112, 950.105, 28.1581, 0, 0, 0, 0, 0, 0, 17.1102, 17.109, 17.115, 17.176, 17.173, 17.182, 17.4962, 17.494, 17.504, 5.20133, 5.20133, 105.405, 105.405, 100.203, 998.758, 998.746, 998.689, 1032.5, 1031.16, 100.432, 100.073, 349.376, -0.357995, 240175, 0.000418164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28), +(86, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-23 15:30:52', '2014-01-23 15:36:52', 4, 21.9089, 950.05, 27.8639, 0, 0, 0, 0, 0, 0, 17.1158, 17.116, 17.115, 17.1856, 17.182, 17.212, 17.5053, 17.509, 17.515, 5.57667, 5.57667, 105.799, 105.799, 100.222, 998.757, 998.744, 998.688, 1032.58, 1031.04, 100.451, 100.073, 349.416, -0.376725, 240175, 0.000418242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28), +(87, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-23 15:37:40', '2014-01-23 15:43:40', 5, 21.9101, 950.054, 27.8539, 0, 0, 0, 0, 0, 0, 17.117, 17.118, 17.121, 17.1896, 17.193, 17.191, 17.5014, 17.507, 17.499, 5.59267, 5.59267, 105.795, 105.795, 100.202, 998.756, 998.744, 998.688, 1032.52, 1031.19, 100.431, 100.073, 349.366, -0.356905, 240175, 0.000418159, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28), +(88, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-23 16:33:16', '2014-01-23 16:37:14', 1, 22.2809, 950.137, 29.0679, 0, 0, 0, 0, 0, 0, 17.1094, 17.109, 17.104, 17.0906, 17.089, 17.087, 17.1091, 17.107, 17.108, 1.15, 1.15, 1.15, 1.15, 0, 998.758, 998.761, 998.758, 0, 15850.1, 0, 1001.12, 227.383, 0.1, 360405, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27), +(89, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-23 16:50:04', '2014-01-23 16:51:00', 1, 22.2748, 950.052, 29.2155, 0, 0, 0, 0, 0, 0, 17.0772, 17.076, 17.077, 17.0559, 17.056, 17.056, 17.0756, 17.077, 17.075, 33.05, 33.05, 234.2, 234.2, 201.15, 998.763, 998.767, 998.764, 15905, 15903.3, 201.606, 201.128, 45.529, -0.237072, 72406, 0.00278438, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(90, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-23 16:53:00', '2014-01-23 16:53:57', 2, 22.28, 950.177, 29.1289, 0, 0, 0, 0, 0, 0, 17.077, 17.075, 17.079, 17.054, 17.053, 17.056, 17.0725, 17.073, 17.073, 33.5667, 33.5667, 234.7, 234.7, 201.133, 998.763, 998.767, 998.764, 15911, 15910.6, 201.589, 201.128, 45.508, -0.228773, 72406, 0.00278415, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(91, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-23 16:55:57', '2014-01-23 16:56:54', 3, 22.2762, 950.3, 29.1878, 0, 0, 0, 0, 0, 0, 17.0771, 17.077, 17.078, 17.0544, 17.053, 17.056, 17.072, 17.072, 17.072, 33, 33, 234.2, 234.2, 201.2, 998.763, 998.767, 998.764, 15910.4, 15904.4, 201.656, 201.125, 45.525, -0.263217, 72405, 0.00278511, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(92, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-23 16:58:54', '2014-01-23 16:59:50', 4, 22.2625, 950.295, 29.23, 0, 0, 0, 0, 0, 0, 17.0783, 17.078, 17.077, 17.054, 17.054, 17.054, 17.0734, 17.073, 17.074, 33.45, 33.45, 234.6, 234.6, 201.15, 998.763, 998.768, 998.764, 15904.3, 15902.6, 201.606, 201.128, 45.531, -0.23705, 72406, 0.00278438, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(93, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-23 17:01:50', '2014-01-23 17:02:47', 5, 22.25, 950.2, 29.2922, 0, 0, 0, 0, 0, 0, 17.0784, 17.078, 17.079, 17.0549, 17.054, 17.056, 17.0739, 17.073, 17.076, 32.9667, 32.9667, 234.117, 234.117, 201.15, 998.763, 998.767, 998.764, 15909.6, 15907.8, 201.606, 201.128, 45.516, -0.23705, 72406, 0.00278438, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(94, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-23 18:11:56', '2014-01-23 18:12:59', 1, 21.6157, 950.069, 29.512, 0, 0, 0, 0, 0, 0, 17.1888, 17.242, 17.155, 17.1899, 17.236, 17.157, 17.2798, 17.427, 17.206, -0.05, -0.05, 200.9, 200.9, 200.95, 998.744, 998.744, 998.728, 14034.5, 14037.6, 201.41, 200.994, 51.546, -0.206317, 72358, 0.00278352, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(95, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-24 09:49:41', '2014-01-24 09:50:40', 1, 22.6, 948.534, 27.64, 0, 0, 0, 0, 0, 0, 18.5668, 19.343, 18.13, 19.4426, 21.161, 18.427, 20.1827, 21.875, 18.962, 0, 0, 201.05, 201.05, 201.05, 998.491, 998.32, 998.168, 15121.3, 15123.2, 201.596, 201.075, 47.865, -0.258345, 72387, 0.00278497, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(96, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-24 09:54:08', '2014-01-24 09:56:52', 1, 22.5919, 948.819, 29.9135, 0, 0, 0, 0, 0, 0, 17.7907, 17.86, 17.737, 17.8374, 17.969, 17.763, 17.9082, 18.042, 17.815, 302.75, 302.75, 903.683, 903.683, 600.933, 998.636, 998.628, 998.615, 14070.9, 14072.4, 602.379, 600.997, 153.747, -0.229386, 216359, 0.00278416, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29), +(97, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-24 09:57:48', '2014-01-24 10:01:47', 1, 22.5884, 948.599, 30.4115, 0, 0, 0, 0, 0, 0, 17.7214, 17.708, 17.735, 17.7629, 17.732, 17.776, 17.7996, 17.785, 17.816, 903.75, 903.75, 1104.1, 1104.1, 200.35, 998.649, 998.641, 998.634, 3157.6, 3155.59, 200.829, 200.222, 228.42, -0.302252, 72080, 0.0027862, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30), +(98, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-24 10:08:47', '2014-01-24 10:11:21', 1, 22.5246, 948.847, 30.101, 0, 0, 0, 0, 0, 0, 17.6874, 17.777, 17.624, 17.7124, 17.833, 17.631, 17.7955, 17.983, 17.687, 1104.15, 1104.15, 1705.03, 1705.03, 600.883, 998.655, 998.65, 998.635, 15090.3, 15094.9, 602.315, 601.067, 143.349, -0.207279, 216384, 0.00278355, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29), +(99, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-24 10:12:21', '2014-01-24 10:16:20', 1, 22.5002, 948.827, 31.126, 0, 0, 0, 0, 0, 0, 17.5736, 17.588, 17.548, 17.6089, 17.608, 17.593, 17.6488, 17.655, 17.637, 1705.1, 1705.1, 1905.42, 1905.42, 200.317, 998.675, 998.669, 998.662, 3151.86, 3150.38, 200.79, 200.222, 228.798, -0.282879, 72080, 0.00278566, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30), +(100, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-24 10:17:13', '2014-01-24 10:22:31', 1, 22.4694, 948.939, 31.3745, 0, 0, 0, 0, 0, 0, 17.5237, 17.546, 17.493, 17.6182, 17.601, 17.625, 18.0608, 18.404, 17.923, 5.674, 5.674, 105.906, 105.906, 100.232, 998.684, 998.667, 998.586, 1178.96, 1177.21, 100.469, 100.083, 306.062, -0.383661, 240200, 0.000418271, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31), +(101, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-24 10:24:03', '2014-01-24 10:26:19', 1, 22.4202, 949.037, 30.8028, 0, 0, 0, 0, 0, 0, 17.4585, 17.498, 17.435, 17.5486, 17.6, 17.496, 17.744, 17.816, 17.688, 5.60467, 5.60467, 105.998, 105.998, 100.394, 998.696, 998.68, 998.645, 2888.08, 2882.56, 100.63, 100.202, 125.141, -0.425557, 240484, 0.000418447, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32), +(102, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-24 11:27:34', '2014-01-24 11:30:09', 1, 22.2572, 949.084, 29.9756, 0, 0, 0, 0, 0, 0, 17.3901, 17.615, 17.313, 17.4633, 17.94, 17.316, 17.6353, 18.542, 17.388, 1905.45, 1905.45, 2506.23, 2506.23, 600.784, 998.708, 998.695, 998.664, 15064, 15071.2, 602.188, 601.069, 143.575, -0.185765, 216385, 0.00278295, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29), +(103, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-24 11:33:10', '2014-01-24 11:37:10', 1, 22.2358, 949.059, 30.417, 0, 0, 0, 0, 0, 0, 17.2012, 17.2, 17.197, 17.2137, 17.208, 17.216, 17.244, 17.239, 17.25, 23.4, 23.4, 223.8, 223.8, 200.4, 998.742, 998.74, 998.734, 3146.94, 3144.15, 200.86, 200.222, 229.251, -0.317324, 72080, 0.00278662, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30), +(104, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-24 11:38:48', '2014-01-24 11:44:38', 1, 22.2371, 949.064, 29.9864, 0, 0, 0, 0, 0, 0, 17.2171, 17.207, 17.227, 17.2649, 17.223, 17.296, 17.7839, 18.155, 17.642, 5.552, 5.552, 105.759, 105.759, 100.207, 998.739, 998.73, 998.637, 1065.44, 1064.03, 100.438, 100.075, 338.589, -0.361469, 240180, 0.000418178, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31), +(105, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-24 11:46:13', '2014-01-24 11:48:28', 1, 22.2581, 949.068, 28.5927, 0, 0, 0, 0, 0, 0, 17.2312, 17.252, 17.219, 17.2727, 17.301, 17.246, 17.4753, 17.517, 17.454, 5.552, 5.552, 105.959, 105.959, 100.407, 998.736, 998.729, 998.693, 2907.1, 2901.22, 100.639, 100.204, 124.339, -0.431722, 240490, 0.000418473, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32), +(106, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-24 12:02:16', '2014-01-24 12:04:50', 1, 22.5164, 949.085, 27.5738, 0, 0, 0, 0, 0, 0, 17.2041, 17.274, 17.172, 17.215, 17.334, 17.169, 17.3073, 17.613, 17.213, 223.8, 223.8, 824.8, 824.8, 601, 998.741, 998.739, 998.723, 15076.2, 15078, 602.378, 601.072, 143.511, -0.216843, 216386, 0.00278381, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29), +(107, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-24 12:05:51', '2014-01-24 12:09:51', 1, 22.5944, 949.109, 27.5323, 0, 0, 0, 0, 0, 0, 17.1726, 17.166, 17.171, 17.1775, 17.165, 17.175, 17.2016, 17.196, 17.208, 824.85, 824.85, 1025.23, 1025.23, 200.383, 998.747, 998.746, 998.742, 3141.05, 3138.53, 200.842, 200.222, 229.662, -0.308402, 72080, 0.00278637, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30), +(108, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-24 13:07:48', '2014-01-24 13:10:21', 1, 23.0909, 949.002, 26.2842, 0, 0, 0, 0, 0, 0, 17.2331, 17.429, 17.175, 17.2812, 17.719, 17.182, 17.4027, 18.026, 17.225, 1025.25, 1025.25, 1626.13, 1626.13, 600.883, 998.736, 998.728, 998.706, 15204.5, 15209.4, 602.268, 601.075, 142.272, -0.198164, 216387, 0.00278329, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29), +(109, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-24 13:11:21', '2014-01-24 13:15:19', 1, 23.1303, 948.951, 26.183, 0, 0, 0, 0, 0, 0, 17.1652, 17.161, 17.166, 17.177, 17.161, 17.179, 17.202, 17.195, 17.209, 1626.2, 1626.2, 1826.55, 1826.55, 200.35, 998.748, 998.746, 998.742, 3172.69, 3170.71, 200.809, 200.225, 227.334, -0.290581, 72081, 0.00278587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30), +(110, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-24 13:16:22', '2014-01-24 13:21:36', 1, 23.1949, 948.915, 26.1312, 0, 0, 0, 0, 0, 0, 17.1793, 17.175, 17.175, 17.2394, 17.196, 17.259, 17.883, 18.531, 17.64, 5.227, 5.227, 105.449, 105.449, 100.222, 998.746, 998.735, 998.619, 1190.55, 1188.91, 100.452, 100.084, 303.052, -0.366476, 240202, 0.000418199, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31), +(111, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-24 13:23:09', '2014-01-24 13:25:25', 1, 23.3193, 948.973, 26.3648, 0, 0, 0, 0, 0, 0, 17.1846, 17.197, 17.179, 17.226, 17.26, 17.202, 17.4636, 17.515, 17.43, 5.561, 5.561, 105.96, 105.96, 100.399, 998.745, 998.737, 998.695, 2916.87, 2911.32, 100.63, 100.208, 123.913, -0.418833, 240500, 0.000418419, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32), +(112, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-24 14:03:10', '2014-01-24 14:05:43', 1, 23.6351, 948.813, 26.7518, 155.811, 155.886, 155.911, 141.568, 141.71, 141.343, 10.5715, 10.6832, 10.5338, 10.621, 10.7674, 10.562, 10.6782, 10.7867, 10.6027, 196.25, 196.25, 796.983, 796.983, 600.733, 999.65, 999.645, 999.639, 15250, 15241.4, 601.566, 600.394, 141.812, -0.194703, 216142, 0.0027832, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29), +(113, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-24 14:55:04', '2014-01-24 14:57:37', 1, 24.3689, 948.904, 28.2572, 155.805, 155.828, 155.811, 141.454, 141.788, 141.235, 10.5344, 10.604, 10.4959, 10.5674, 10.6485, 10.5277, 10.6463, 10.8516, 10.563, 0, 0, 572.65, 572.65, 572.65, 999.653, 999.65, 999.642, 14534, 15238, 573.441, 600.392, 141.843, 4.6999, 216141, 0.00265309, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29), +(114, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-24 14:58:38', '2014-01-24 15:02:36', 1, 24.4131, 948.846, 28.5036, 155.913, 155.893, 155.986, 159.13, 158.947, 159.16, 10.5067, 10.4905, 10.5103, 10.5614, 10.5151, 10.589, 10.5935, 10.5522, 10.6172, 572.7, 572.7, 773, 773, 200.3, 999.656, 999.651, 999.647, 3171.19, 3167.67, 200.576, 200.078, 227.385, -0.248582, 72028, 0.0027847, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30), +(115, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-24 15:03:45', '2014-01-24 15:09:24', 1, 24.4372, 948.986, 28.6013, 155.93, 155.957, 155.975, 157.52, 157.461, 157.645, 10.5299, 10.5266, 10.532, 10.6805, 10.5908, 10.7206, 11.6102, 12.0364, 11.4289, 0.081, 0.081, 100.249, 100.249, 100.168, 999.654, 999.639, 999.543, 1100.24, 1098.97, 100.307, 100.052, 327.749, -0.254171, 240125, 0.000417728, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31), +(116, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-24 15:10:58', '2014-01-24 15:13:13', 1, 24.47, 948.983, 28.7628, 155.939, 155.975, 156.009, 155.564, 155.477, 155.056, 10.555, 10.5662, 10.532, 10.6734, 10.7188, 10.6341, 11.1051, 11.1928, 11.054, 5.425, 5.425, 105.682, 105.682, 100.257, 999.651, 999.64, 999.597, 2906.11, 2902.65, 100.396, 100.138, 124.195, -0.25757, 240330, 0.000417743, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32), +(117, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-27 12:49:03', '2014-01-27 12:51:36', 1, 24.3667, 937.303, 24.6681, 155.831, 155.767, 155.731, 141.339, 141.375, 140.818, 11.7791, 11.8739, 11.7424, 11.7954, 11.8166, 11.7697, 11.9446, 12.268, 11.8276, 6.4, 6.4, 607.083, 607.083, 600.683, 999.525, 999.523, 999.506, 15190.9, 15183.4, 601.589, 600.386, 142.352, -0.199971, 216139, 0.00278334, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29), +(118, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-27 12:52:37', '2014-01-27 12:56:36', 1, 24.3666, 937.21, 24.9066, 155.917, 155.903, 155.874, 159.405, 159.357, 159.47, 11.6909, 11.7261, 11.6144, 11.7866, 11.7499, 11.7264, 11.8528, 11.8024, 11.815, 607.15, 607.15, 807.45, 807.45, 200.3, 999.534, 999.524, 999.516, 3153.79, 3150.34, 200.602, 200.081, 228.639, -0.259853, 72029, 0.00278501, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30), +(119, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-27 12:57:10', '2014-01-27 13:02:55', 1, 24.3852, 937.231, 25.1367, 155.991, 155.988, 155.949, 157.687, 157.582, 157.573, 11.6022, 11.6162, 11.5658, 11.7865, 11.7318, 11.822, 12.7097, 13.5891, 12.433, 0.165, 0.165, 100.314, 100.314, 100.149, 999.544, 999.524, 999.415, 1078.36, 1077.31, 100.3, 100.051, 334.338, -0.248255, 240123, 0.000417704, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31), +(120, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-27 13:04:30', '2014-01-27 13:06:44', 1, 24.3937, 937.315, 25.3005, 156.012, 156.72, 156.424, 155.735, 154.088, 156.025, 11.6393, 11.6162, 11.6595, 11.7486, 11.8022, 11.7264, 12.1113, 12.1986, 12.0887, 5.558, 5.558, 105.796, 105.796, 100.238, 999.54, 999.528, 999.487, 2948.02, 2945.19, 100.388, 100.141, 122.406, -0.246084, 240339, 0.000417695, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32), +(121, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-27 13:23:18', '2014-01-27 13:25:53', 1, 24.4548, 937.35, 25.3167, 155.877, 155.917, 155.876, 141.605, 141.611, 141.718, 11.1896, 11.5027, 11.0722, 11.3013, 11.9248, 11.1279, 11.4635, 12.4088, 11.1998, 807.45, 807.45, 1408.02, 1408.02, 600.567, 999.588, 999.576, 999.559, 15077.6, 15072.9, 601.44, 600.378, 143.394, -0.176629, 216136, 0.00278269, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29), +(122, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-27 13:26:52', '2014-01-27 13:30:51', 1, 24.4663, 937.297, 25.7032, 155.989, 155.904, 155.928, 159.459, 159.414, 159.496, 10.9305, 10.966, 10.8687, 11.0395, 11.0666, 11.0107, 11.0933, 11.1186, 11.0717, 1408.05, 1408.05, 1608.4, 1608.4, 200.35, 999.614, 999.603, 999.598, 3165.88, 3161.62, 200.636, 200.081, 227.823, -0.276792, 72029, 0.00278549, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30); +INSERT INTO `testresult` (`Id`, `Name`, `TestName`, `Qfrom`, `Qto`, `Volume`, `TstTime`, `Repeats`, `Emptying`, `Zeroing`, `Method`, `ErrLimLo`, `ErrLimHi`, `FeedingPath`, `BenchPath`, `OutputPath`, `MetersPath`, `TimeStart`, `TimeEnd`, `RepetitionNr`, `AmbientTempAve`, `AmbientPressAve`, `AmbientHumiAve`, `PressInAvrg`, `PressInStart`, `PressInEnd`, `PressOutAvrg`, `PressOutStart`, `PressOutEnd`, `TempInAvrg`, `TempInStart`, `TempInEnd`, `TempOutAvrg`, `TempOutStart`, `TempOutEnd`, `TempDivAvrg`, `TempDivStart`, `TempDivEnd`, `MassStartRaw`, `MassStart`, `MassEndRaw`, `MassEnd`, `MassDiff`, `DensityIn`, `DensityOut`, `DensityDiv`, `FlowMass`, `FlowVolume`, `VolumeCTV`, `VolumeMaster`, `Time`, `ErrorMaster`, `PulsesMaster`, `ConstMaster`, `TimeDivStart0`, `TimeDivStart1`, `TimeDivStart2`, `TimeDivStart3`, `TimeDivStart4`, `TimeDivStart5`, `TimeDivEnd0`, `TimeDivEnd1`, `TimeDivEnd2`, `TimeDivEnd3`, `TimeDivEnd4`, `TimeDivEnd5`, `Test_id`) VALUES +(123, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-27 13:32:33', '2014-01-27 13:38:12', 1, 24.4979, 937.409, 25.3508, 155.995, 156.017, 156.038, 161.118, 160.934, 161.192, 10.8131, 10.8201, 10.7985, 11.0214, 10.9981, 11.0468, 11.8933, 12.3952, 11.7065, 5.262, 5.262, 105.424, 105.424, 100.162, 999.626, 999.605, 999.512, 1100.81, 1099.61, 100.304, 100.053, 327.562, -0.251158, 240126, 0.000417716, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31), +(124, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-27 13:39:49', '2014-01-27 13:42:04', 1, 24.49, 937.333, 25.3118, 156.024, 155.662, 156.062, 154.579, 153.316, 157.252, 10.7452, 10.7967, 10.7246, 10.9408, 11.0378, 10.8485, 11.3199, 11.4487, 11.2343, 5.33767, 5.33767, 105.581, 105.581, 100.243, 999.633, 999.613, 999.574, 2911.72, 2908.72, 100.385, 100.14, 123.939, -0.24445, 240336, 0.000417688, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32), +(125, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-02-10 10:34:34', '2014-02-10 10:37:05', 1, 23.3814, 933.535, 24.0235, 155.816, 154.255, 165.099, 127.086, 126.867, 112.681, 11.4867, 12.5028, 11.1983, 12.3161, 13.4598, 11.5894, 13.4178, 15.3884, 12.3681, -0.009, -0.009, 99.7903, 99.7903, 99.7993, 999.557, 999.463, 999.325, 2559.89, 2568.78, 99.9558, 100.146, 140.349, 0.190109, 240350, 0.000415876, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33), +(126, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-02-10 10:37:31', '2014-02-10 10:38:31', 1, 23.38, 933.458, 23.5607, 155.147, 155.105, 155.165, 148.065, 148.153, 148.161, 11.0406, 11.1479, 10.948, 11.1406, 11.3749, 10.9657, 12.1197, 13.4921, 11.3639, 15, 15, 518.633, 518.633, 503.633, 999.603, 999.593, 999.486, 39799.8, 39591.7, 504.357, 501, 45.555, -0.665671, 18036, 0.0279639, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34), +(127, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-02-10 10:54:54', '2014-02-10 11:02:45', 1, 23.4246, 933.123, 23.3219, 155.617, 155.576, 155.689, 159.112, 159.045, 159.154, 10.8988, 11.1029, 10.8309, 11.3865, 11.6705, 11.1279, 12.1099, 12.6783, 11.6957, 5.546, 5.546, 5.542, 5.542, -0.00400019, 999.618, 999.567, 999.487, -0.101455, 2540.83, -0.00400604, 100.18, 141.941, 0.1, 240432, -0.0000000166618, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33), +(128, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-02-10 11:03:54', '2014-02-10 11:06:24', 1, 23.4238, 933.369, 23.5026, 155.618, 155.583, 155.659, 159.755, 159.658, 159.737, 10.8492, 11.0398, 10.7643, 11.1802, 11.2451, 11.045, 11.737, 12.0815, 11.4866, 5.542, 5.542, 105.769, 105.769, 100.227, 999.622, 999.589, 999.529, 2597.24, 2594.56, 100.371, 100.123, 138.923, -0.246894, 240296, 0.000417698, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33), +(129, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-02-10 11:06:51', '2014-02-10 11:07:50', 1, 23.4445, 933.343, 23.7755, 155.058, 155.031, 154.963, 148.861, 148.755, 148.871, 10.7121, 10.7553, 10.6652, 10.7856, 10.8936, 10.6989, 11.2167, 11.7861, 10.8606, 518.65, 518.65, 1022.27, 1022.27, 503.617, 999.636, 999.629, 999.585, 37991.3, 37789.7, 504.323, 500.944, 47.722, -0.669832, 18034, 0.0279651, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34), +(130, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-02-10 13:13:50', '2014-02-10 13:16:22', 1, 23.5781, 930.88, 22.0897, 155.456, 155.46, 155.478, 157.501, 157.365, 157.721, 11.0939, 11.8468, 10.7679, 12.3625, 13.2216, 11.6886, 13.184, 14.7368, 12.076, 5.79167, 5.79167, 106.011, 106.011, 100.219, 999.598, 999.457, 999.356, 2582.45, 2579.98, 100.377, 100.123, 139.708, -0.252391, 240296, 0.000417721, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33), +(131, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-02-10 13:23:48', '2014-02-10 13:26:19', 1, 23.6071, 930.643, 22.3375, 155.363, 155.318, 155.307, 157.705, 157.879, 157.768, 10.757, 10.948, 10.6904, 11.1593, 11.4001, 10.9495, 11.6593, 12.0003, 11.3784, 5.788, 5.788, 106.016, 106.016, 100.228, 999.632, 999.591, 999.538, 2584.56, 2581.87, 100.372, 100.123, 139.606, -0.248016, 240296, 0.000417703, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33), +(132, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-02-10 13:26:53', '2014-02-10 13:27:54', 1, 23.62, 930.617, 22.5558, 155.111, 155.153, 155.136, 149.841, 149.677, 149.921, 10.6263, 10.6832, 10.5608, 10.6902, 10.7818, 10.5962, 11.6511, 13.2212, 10.9184, 278.35, 278.35, 781.25, 781.25, 502.9, 999.644, 999.638, 999.539, 35989.3, 35845.3, 503.6, 500.889, 50.305, -0.53839, 18032, 0.0279281, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34), +(133, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-02-10 13:31:37', '2014-02-10 13:34:05', 1, 23.6456, 930.527, 22.8671, 155.489, 155.546, 155.463, 157.506, 157.511, 157.251, 10.4999, 10.5392, 10.4779, 10.6483, 10.6539, 10.6215, 11.1849, 11.3262, 11.0811, 5.399, 5.399, 105.623, 105.623, 100.224, 999.656, 999.642, 999.588, 2624.34, 2621.74, 100.363, 100.125, 137.485, -0.237601, 240300, 0.000417659, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33), +(134, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-02-10 13:35:00', '2014-02-10 13:37:33', 2, 23.6645, 930.379, 23.1497, 155.456, 155.418, 155.472, 157.88, 157.75, 157.91, 10.4526, 10.4689, 10.4437, 10.6007, 10.5998, 10.5926, 11.016, 11.0522, 10.9856, 5.337, 5.337, 105.558, 105.558, 100.221, 999.661, 999.647, 999.606, 2555.22, 2552.66, 100.359, 100.12, 141.199, -0.238051, 240289, 0.000417661, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33), +(135, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-02-10 13:38:33', '2014-02-10 13:41:05', 3, 23.67, 930.312, 22.9731, 155.484, 155.407, 155.499, 157.886, 157.785, 157.943, 10.4358, 10.4311, 10.4329, 10.5722, 10.5782, 10.5656, 10.9751, 10.9784, 10.9694, 5.692, 5.692, 105.919, 105.919, 100.227, 999.662, 999.649, 999.61, 2554.74, 2552.06, 100.366, 100.122, 141.235, -0.242772, 240293, 0.000417681, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33), +(136, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-02-10 13:42:02', '2014-02-10 13:44:34', 4, 23.6591, 930.233, 22.2285, 155.492, 155.39, 155.497, 157.898, 157.644, 157.563, 10.4236, 10.4329, 10.4275, 10.5604, 10.5656, 10.562, 10.9623, 10.9694, 10.9549, 5.705, 5.705, 105.929, 105.929, 100.224, 999.664, 999.651, 999.611, 2555.88, 2553.28, 100.362, 100.122, 141.167, -0.239011, 240293, 0.000417665, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33), +(137, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-02-10 13:45:31', '2014-02-10 13:48:03', 5, 23.6335, 930.357, 21.9714, 155.472, 155.327, 155.531, 157.901, 158.199, 157.989, 10.4169, 10.4221, 10.4113, 10.5434, 10.5548, 10.5349, 10.9381, 10.9387, 10.9351, 5.681, 5.681, 105.903, 105.903, 100.222, 999.664, 999.652, 999.614, 2555.14, 2552.58, 100.36, 100.121, 141.205, -0.237685, 240291, 0.000417659, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33), +(138, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-02-10 13:51:09', '2014-02-10 13:52:07', 1, 23.62, 930.481, 23.7909, 154.839, 154.849, 154.768, 147.469, 147.437, 147.31, 10.1477, 10.1682, 10.1178, 10.1627, 10.1836, 10.1385, 10.2193, 10.2583, 10.1934, 34.05, 34.05, 537.4, 537.4, 503.35, 999.689, 999.688, 999.682, 40012.8, 39823.8, 504.026, 500.972, 45.287, -0.605864, 18035, 0.0279471, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34), +(139, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-02-10 13:55:13', '2014-02-10 13:56:17', 2, 23.6083, 930.462, 24.0179, 155.215, 155.229, 155.163, 151.193, 151.341, 150.974, 10.0344, 10.035, 10.0296, 10.0474, 10.0538, 10.043, 10.0858, 10.0888, 10.0834, 34.3, 34.3, 537.55, 537.55, 503.25, 999.699, 999.698, 999.694, 34164.3, 34000.3, 503.921, 500.833, 53.029, -0.612646, 18030, 0.027949, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34), +(140, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-02-10 13:59:08', '2014-02-10 14:00:08', 3, 23.6, 930.469, 24.7452, 154.837, 154.865, 154.899, 147.167, 146.811, 147.117, 10.0194, 10.0206, 10.0188, 10.0313, 10.0304, 10.0286, 10.069, 10.069, 10.0672, 34.25, 34.25, 537.767, 537.767, 503.517, 999.7, 999.699, 999.696, 38978.6, 38783.8, 504.187, 501, 46.504, -0.632079, 18036, 0.0279545, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34), +(141, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-02-10 14:02:59', '2014-02-10 14:03:56', 4, 23.5944, 930.338, 24.9489, 154.81, 154.753, 154.715, 147.193, 146.833, 147.061, 10.0107, 10.017, 10.0098, 10.0212, 10.0214, 10.0196, 10.0584, 10.06, 10.0564, 34.1, 34.1, 34.1, 34.1, 0, 999.701, 999.7, 999.697, 0, 38759.2, 0, 502.75, 46.696, 0.1, 18099, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34), +(142, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-02-10 14:04:22', '2014-02-10 14:05:24', 5, 23.59, 930.411, 24.8331, 154.803, 154.877, 154.767, 147.147, 146.9, 147.23, 10.0098, 10.008, 10.0116, 10.0195, 10.0214, 10.0178, 10.0571, 10.0582, 10.0564, 33.25, 33.25, 536.75, 536.75, 503.5, 999.701, 999.7, 999.697, 39003.3, 38809.6, 504.17, 501, 46.473, -0.628687, 18036, 0.0279535, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34), +(143, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-02-10 14:58:54', '2014-02-10 15:01:27', 1, 23.4812, 929.983, 22.7254, 155.456, 155.375, 155.476, 157.693, 157.762, 157.801, 10.387, 10.7949, 10.2241, 11.2192, 11.7877, 10.6899, 12.099, 13.1959, 11.3262, 5.318, 5.318, 105.546, 105.546, 100.228, 999.667, 999.585, 999.488, 2555.13, 2552.39, 100.373, 100.12, 141.214, -0.251208, 240289, 0.000417716, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33), +(144, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-02-10 15:02:19', '2014-02-10 15:04:51', 2, 23.4816, 929.988, 22.6396, 155.45, 155.298, 155.48, 157.747, 157.419, 157.424, 10.1956, 10.2133, 10.1844, 10.4232, 10.5169, 10.3764, 10.9236, 11.0631, 10.8342, 5.274, 5.274, 105.495, 105.495, 100.221, 999.685, 999.664, 999.615, 2553.93, 2551.4, 100.358, 100.122, 141.271, -0.235052, 240293, 0.000417648, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33), +(145, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-02-10 15:18:45', '2014-02-10 15:21:16', 1, 23.44, 929.927, 22.8441, 155.45, 155.505, 155.47, 157.566, 157.71, 157.402, 10.2599, 10.4131, 10.1862, 10.5411, 10.6647, 10.4088, 11.1378, 11.4577, 10.8973, 5.405, 5.405, 105.63, 105.63, 100.225, 999.679, 999.652, 999.593, 2584.72, 2582.08, 100.363, 100.123, 139.594, -0.239653, 240295, 0.000417668, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33), +(146, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-02-10 15:22:15', '2014-02-10 15:24:48', 2, 23.4553, 929.787, 23.0913, 155.446, 155.457, 155.532, 157.553, 157.411, 157.426, 10.1816, 10.1898, 10.1826, 10.3361, 10.3349, 10.3277, 10.763, 10.8054, 10.7369, 5.337, 5.337, 105.569, 105.569, 100.232, 999.686, 999.672, 999.631, 2584.39, 2581.56, 100.368, 100.122, 139.621, -0.245199, 240293, 0.000417691, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33), +(147, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-02-10 15:26:04', '2014-02-10 15:28:32', 3, 23.4879, 929.792, 23.0006, 155.466, 155.579, 155.577, 157.272, 157.258, 157.463, 10.1784, 10.1898, 10.179, 10.3079, 10.3115, 10.3115, 10.7041, 10.7225, 10.6901, 5.293, 5.293, 105.538, 105.538, 100.245, 999.686, 999.674, 999.637, 2642.46, 2639.35, 100.381, 100.127, 136.57, -0.252974, 240304, 0.000417723, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33), +(148, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-02-10 15:29:27', '2014-02-10 15:32:00', 4, 23.5265, 929.665, 23.17, 155.441, 155.342, 155.386, 157.682, 157.499, 157.658, 10.1735, 10.179, 10.1718, 10.299, 10.2917, 10.2953, 10.6968, 10.6919, 10.7027, 5.31, 5.31, 105.544, 105.544, 100.234, 999.687, 999.675, 999.637, 2554.47, 2551.61, 100.37, 100.122, 141.259, -0.24727, 240292, 0.0004177, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33), +(149, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-02-10 15:32:57', '2014-02-10 15:35:29', 5, 23.5329, 929.67, 23.1757, 155.454, 155.464, 155.444, 157.697, 157.86, 158.195, 10.1751, 10.1736, 10.1718, 10.2979, 10.3079, 10.2863, 10.6928, 10.7009, 10.6919, 5.739, 5.739, 105.978, 105.978, 100.239, 999.686, 999.675, 999.638, 2552.96, 2549.98, 100.375, 100.122, 141.35, -0.252144, 240293, 0.00041772, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33), +(150, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-02-10 15:38:38', '2014-02-10 15:39:42', 1, 23.53, 929.661, 23.7317, 154.968, 154.94, 155.048, 151.006, 151.045, 151.125, 10.118, 10.1322, 10.0998, 10.1323, 10.1439, 10.1169, 10.1965, 10.2078, 10.1735, 33.85, 33.85, 537.8, 537.8, 503.95, 999.692, 999.69, 999.685, 34333.6, 34121.2, 504.625, 500.833, 52.841, -0.751441, 18030, 0.0279881, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34), +(151, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-02-10 15:42:33', '2014-02-10 15:43:33', 2, 23.5109, 929.591, 23.7613, 154.881, 154.842, 154.68, 147.047, 147.483, 147.039, 10.0863, 10.0854, 10.0854, 10.0967, 10.0971, 10.0953, 10.1378, 10.1357, 10.1339, 34.05, 34.05, 538.067, 538.067, 504.017, 999.694, 999.693, 999.69, 38824.4, 38589.9, 504.69, 500.972, 46.735, -0.736741, 18035, 0.0279839, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34), +(152, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-02-11 08:34:54', '2014-02-11 08:38:13', 1, 23.8203, 943.893, 26.1866, 154.687, 154.675, 154.641, 154.207, 154.188, 154.335, 12.8431, 13.7935, 12.0829, 15.8215, 17.1054, 14.2502, 16.5175, 17.9119, 15.1194, 0, 0, 50.0707, 50.0707, 50.0707, 999.399, 998.974, 998.859, 954.202, 953.712, 50.1737, 50.045, 188.906, -0.256562, 120108, 0.000417738, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35), +(153, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-02-11 10:17:54', '2014-02-11 10:20:01', 1, 23.9527, 944.364, 25.9059, 155.542, 155.53, 155.574, 147.403, 145.269, 147.945, 11.4935, 11.5027, 11.5045, 11.9845, 11.9843, 12.0492, 12.4704, 12.6043, 12.3699, 30.152, 30.152, 80.2487, 80.2487, 50.0967, 999.556, 999.501, 999.445, 1562.05, 1561.32, 50.1733, 50.0733, 115.456, -0.1992, 120176, 0.000417498, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35), +(154, 'Qsteig', 'Qsteig', 1.76569, 1.96569, 50, 96.4791, 1, 0, 0, 'Verbund-steig-fall', -2, 2, 'PS2', 'PBank2', 'PQ3', 'PMess1', '2014-02-11 14:33:34', '2014-02-11 14:35:24', 1, 22.8701, 942.78, 23.1037, 155.409, 155.5, 155.352, 143.021, 144.653, 141.529, 11.7602, 11.773, 11.7658, 12.0301, 12.0492, 12.0149, 12.4607, 12.5412, 12.4006, 50.898, 50.898, 100.99, 100.99, 50.0917, 999.527, 999.496, 999.446, 1821.18, 1821.03, 50.1685, 50.0875, 99.018, -0.161512, 120210, 0.000417341, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(155, 'Qsteig', 'Qsteig', 1.77058, 1.97058, 50, 96.2268, 1, 0, 0, 'Verbund-steig-fall', -2, 2, 'PS2', 'PBank2', 'PQ3', 'PMess1', '2014-02-11 14:45:21', '2014-02-11 14:47:11', 1, 22.83, 942.744, 22.7084, 155.315, 155.272, 155.34, 141.867, 141.411, 142.985, 11.767, 11.7694, 11.7658, 11.9904, 12.0221, 11.9825, 12.4125, 12.5034, 12.3627, 0.652, 0.652, 50.738, 50.738, 50.086, 999.526, 999.501, 999.451, 1872.26, 1872.36, 50.1626, 50.0888, 96.306, -0.147272, 120213, 0.000417281, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(156, 'Qfall', 'Qfall', 1.25781, 1.45781, 50, 132.566, 1, 0, 0, 'Verbund-steig-fall', -2, 2, 'PS2', 'PBank2', 'PQ3', 'PMess1', '2014-02-11 15:30:06', '2014-02-11 15:32:29', 1, 22.9417, 942.232, 21.9756, 155.401, 155.31, 155.482, 162.191, 162.268, 162.245, 11.6636, 11.6919, 11.6415, 11.8384, 11.8563, 11.8364, 12.2965, 12.2852, 12.278, 50.703, 50.703, 100.792, 100.792, 50.0893, 999.537, 999.518, 999.465, 1373.62, 1372.95, 50.1651, 50.065, 131.275, -0.199552, 120156, 0.0004175, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(157, 'Qsteig', 'Qsteig', 1.77459, 1.97459, 50, 96.0209, 1, 0, 0, 'Verbund-steig-fall', -2, 2, 'PS2', 'PBank2', 'PQ3', 'PMess1', '2014-02-11 15:43:35', '2014-02-11 15:45:42', 1, 23.0381, 942.202, 22.5049, 155.389, 155.442, 155.459, 142.677, 143.858, 144.353, 11.5485, 11.5658, 11.5334, 11.9184, 11.9428, 11.923, 12.3495, 12.4709, 12.2545, 1.418, 1.418, 51.52, 51.52, 50.102, 999.55, 999.509, 999.459, 1831.68, 1831.12, 50.1782, 50.0867, 98.471, -0.182508, 120208, 0.000417429, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(158, 'Qfall', 'Qfall', 1.66466, 1.86466, 50, 102.003, 1, 0, 0, 'Verbund-steig-fall', -2, 2, 'PS2', 'PBank2', 'PQ3', 'PMess1', '2014-02-11 15:49:06', '2014-02-11 15:50:56', 1, 23.05, 942.403, 22.4866, 155.495, 155.559, 155.544, 159.773, 159.836, 159.946, 11.5551, 11.5496, 11.519, 11.6635, 11.685, 11.6615, 12.061, 12.058, 12.049, 51.519, 51.519, 101.629, 101.629, 50.11, 999.549, 999.537, 999.493, 1818.09, 1817.26, 50.1848, 50.0871, 99.223, -0.194768, 120209, 0.00041748, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(159, 'Q1 (1/5)', 'Q1', 2.4, 2.6, 100, 144, 5, 1, 0, 'Verbund', -2, 2, 'PS2', 'PBank2', 'PQ3', 'PMess1', '2014-02-11 15:52:16', '2014-02-11 15:54:48', 1, 23.0715, 942.285, 22.5032, 155.5, 155.45, 155.378, 157.587, 157.382, 157.83, 11.4984, 11.5262, 11.5081, 11.6296, 11.694, 11.5912, 11.9657, 12.0274, 11.9264, 1.533, 1.533, 101.738, 101.738, 100.205, 999.555, 999.541, 999.504, 2563.64, 2561.5, 100.354, 100.121, 140.713, -0.232194, 240291, 0.000417636, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(160, 'Q1 (2/5)', 'Q1', 2.4, 2.6, 100, 144, 5, 1, 0, 'Verbund', -2, 2, 'PS2', 'PBank2', 'PQ3', 'PMess1', '2014-02-11 15:55:32', '2014-02-11 15:58:04', 2, 23.0688, 942.354, 22.4026, 155.475, 155.53, 155.475, 157.609, 157.548, 157.776, 11.4189, 11.4847, 11.3983, 11.5789, 11.6074, 11.5335, 11.9096, 11.9408, 11.8741, 1.592, 1.592, 101.817, 101.817, 100.225, 999.564, 999.547, 999.51, 2561.17, 2558.55, 100.374, 100.123, 140.877, -0.250293, 240294, 0.000417712, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(161, 'Q1 (3/5)', 'Q1', 2.4, 2.6, 100, 144, 5, 1, 0, 'Verbund', -2, 2, 'PS2', 'PBank2', 'PQ3', 'PMess1', '2014-02-11 15:58:49', '2014-02-11 16:01:20', 3, 23.0423, 942.438, 22.2702, 155.482, 155.552, 155.504, 157.586, 157.555, 157.581, 11.3581, 11.4019, 11.3046, 11.4971, 11.5209, 11.456, 11.8233, 11.8471, 11.7876, 1.58633, 1.58633, 101.812, 101.812, 100.225, 999.57, 999.555, 999.52, 2562.11, 2559.45, 100.373, 100.121, 140.826, -0.250994, 240291, 0.000417715, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(162, 'Q1 (4/5)', 'Q1', 2.4, 2.6, 100, 144, 5, 1, 0, 'Verbund', -2, 2, 'PS2', 'PBank2', 'PQ3', 'PMess1', '2014-02-11 16:02:05', '2014-02-11 16:04:36', 4, 23.0164, 942.478, 22.3321, 155.496, 155.54, 155.528, 157.598, 157.438, 157.613, 11.2548, 11.283, 11.2037, 11.3971, 11.4308, 11.3767, 11.7192, 11.7552, 11.6885, 0.783, 0.783, 101.013, 101.013, 100.23, 999.581, 999.566, 999.531, 2561.93, 2559.2, 100.376, 100.123, 140.842, -0.252582, 240295, 0.000417722, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(163, 'Q1 (5/5)', 'Q1', 2.4, 2.6, 100, 144, 5, 1, 0, 'Verbund', -2, 2, 'PS2', 'PBank2', 'PQ3', 'PMess1', '2014-02-11 16:05:20', '2014-02-11 16:07:53', 5, 23.01, 942.434, 22.5842, 155.493, 155.563, 155.519, 157.589, 157.593, 157.915, 11.1498, 11.1569, 11.1407, 11.3069, 11.3424, 11.2847, 11.6313, 11.6632, 11.6037, 1.38933, 1.38933, 101.614, 101.614, 100.225, 999.592, 999.576, 999.541, 2560.56, 2557.95, 100.37, 100.123, 140.91, -0.247055, 240294, 0.000417699, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(164, 'Q2 (1/5)', 'Q2', 38, 44, 500, 43.9024, 5, 1, 0, 'Verbund', -2, 2, 'PS2', 'PBank2', 'PQ5', 'PMess1', '2014-02-11 16:09:52', '2014-02-11 16:10:47', 1, 23.01, 942.402, 22.8181, 154.624, 154.667, 154.616, 144.794, 144.749, 144.983, 10.7788, 10.9047, 10.6328, 10.8004, 10.9314, 10.6899, 11.6261, 12.2933, 11.1547, 0, 0, 503.35, 503.35, 503.35, 999.629, 999.627, 999.541, 42743.3, 42548.5, 504.056, 501.056, 42.394, -0.595317, 18038, 0.0279441, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(165, 'Q2 (2/5)', 'Q2', 38, 44, 500, 43.9024, 5, 1, 0, 'Verbund', -2, 2, 'PS2', 'PBank2', 'PQ5', 'PMess1', '2014-02-11 16:12:32', '2014-02-11 16:13:27', 2, 23.0105, 942.356, 23.6678, 154.558, 154.61, 154.475, 144.881, 144.834, 144.899, 10.2374, 10.2565, 10.2187, 10.245, 10.2647, 10.225, 10.3434, 10.3701, 10.3052, 31.9833, 31.9833, 534.583, 534.583, 502.6, 999.681, 999.68, 999.671, 42660.5, 42529.4, 503.279, 501.056, 42.413, -0.441714, 18038, 0.027901, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(166, 'Q2 (3/5)', 'Q2', 38, 44, 500, 43.9024, 5, 1, 0, 'Verbund', -2, 2, 'PS2', 'PBank2', 'PQ5', 'PMess1', '2014-02-11 16:15:15', '2014-02-11 16:16:09', 3, 23.02, 942.357, 23.4829, 154.532, 154.535, 154.525, 144.906, 145.266, 144.559, 10.1927, 10.197, 10.1898, 10.2004, 10.2016, 10.1944, 10.2516, 10.2547, 10.2457, 31.2833, 31.2833, 534.4, 534.4, 503.117, 999.685, 999.684, 999.68, 42659.1, 42486.7, 503.794, 501.083, 42.458, -0.53805, 18039, 0.027928, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(167, 'Q2 (4/5)', 'Q2', 38, 44, 500, 43.9024, 5, 1, 0, 'Verbund', -2, 2, 'PS2', 'PBank2', 'PQ5', 'PMess1', '2014-02-11 16:17:56', '2014-02-11 16:18:51', 4, 23.02, 942.308, 23.6373, 154.536, 154.56, 154.534, 144.861, 144.84, 145.205, 10.1741, 10.1754, 10.1736, 10.1802, 10.1818, 10.1764, 10.2228, 10.2222, 10.2222, 32.5833, 32.5833, 534.85, 534.85, 502.267, 999.687, 999.686, 999.682, 42615.1, 42512.4, 502.942, 501.056, 42.43, -0.375058, 18038, 0.0278824, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(168, 'Q2 (5/5)', 'Q2', 38, 44, 500, 43.9024, 5, 1, 0, 'Verbund', -2, 2, 'PS2', 'PBank2', 'PQ5', 'PMess1', '2014-02-11 16:20:39', '2014-02-11 16:21:36', 5, 23.02, 942.412, 24.1654, 154.552, 154.447, 154.426, 144.894, 145.041, 145.161, 10.1667, 10.1682, 10.1664, 10.1713, 10.1746, 10.1692, 10.2113, 10.2168, 10.2096, 31.9667, 31.9667, 535.167, 535.167, 503.2, 999.687, 999.687, 999.683, 42658.1, 42478.7, 503.876, 501.083, 42.466, -0.554254, 18039, 0.0279326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(169, 'Qsteig (1/5)', 'Qsteig', 1.89828, 2.09828, 50, 90.0774, 5, 1, 0, 'Verbund-steig-fall', -2, 2, 'PS2', 'PBank2', 'PQ3', 'PMess1', '2014-02-11 16:45:25', '2014-02-11 16:47:07', 1, 22.9968, 942.465, 24.3667, 155.516, 155.496, 155.724, 139.825, 140.769, 137.294, 10.3055, 10.3033, 10.3105, 10.5163, 10.5169, 10.5151, 10.9801, 11.045, 10.9567, 1.573, 1.573, 51.6677, 51.6677, 50.0947, 999.675, 999.655, 999.609, 1960.72, 1960.71, 50.1636, 50.0946, 91.977, -0.137528, 120227, 0.00041724, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(170, 'Qsteig (2/5)', 'Qsteig', 1.89548, 2.09548, 50, 90.204, 5, 1, 0, 'Verbund-steig-fall', -2, 2, 'PS2', 'PBank2', 'PQ3', 'PMess1', '2014-02-11 16:50:23', '2014-02-11 16:52:08', 2, 23.01, 942.467, 23.6088, 155.512, 155.539, 155.569, 139.45, 136.863, 138.829, 10.3065, 10.3069, 10.3105, 10.4491, 10.4466, 10.4629, 10.8888, 10.9135, 10.8847, 1.358, 1.358, 51.4687, 51.4687, 50.1107, 999.674, 999.661, 999.619, 1963.86, 1963.22, 50.1793, 50.0942, 91.859, -0.169619, 120226, 0.000417375, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(171, 'Qsteig (3/5)', 'Qsteig', 1.88816, 2.08816, 50, 90.5359, 5, 1, 0, 'Verbund-steig-fall', -2, 2, 'PS2', 'PBank2', 'PQ3', 'PMess1', '2014-02-11 16:55:21', '2014-02-11 16:57:06', 3, 23.03, 942.543, 23.3817, 155.515, 155.474, 155.552, 140.272, 141.225, 139.546, 10.3064, 10.2943, 10.3177, 10.4507, 10.4394, 10.4611, 10.8811, 10.8901, 10.8883, 1.312, 1.312, 51.417, 51.417, 50.105, 999.674, 999.661, 999.619, 1928.08, 1927.59, 50.1736, 50.0921, 93.553, -0.162506, 120221, 0.000417345, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(172, 'Qsteig (4/5)', 'Qsteig', 1.87545, 2.07545, 50, 91.1185, 5, 1, 0, 'Verbund-steig-fall', -2, 2, 'PS2', 'PBank2', 'PQ3', 'PMess1', '2014-02-11 17:00:15', '2014-02-11 17:02:12', 4, 23.0435, 942.414, 23.4428, 155.529, 155.583, 155.426, 140.241, 142.093, 139.64, 10.3056, 10.3051, 10.2997, 10.4488, 10.4466, 10.4539, 10.8829, 10.8955, 10.8811, 1.306, 1.306, 51.405, 51.405, 50.099, 999.675, 999.661, 999.619, 1945.07, 1944.85, 50.1676, 50.0933, 92.725, -0.148025, 120224, 0.000417284, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(173, 'Qsteig (5/5)', 'Qsteig', 1.87301, 2.07301, 50, 91.2311, 5, 1, 0, 'Verbund-steig-fall', -2, 2, 'PS2', 'PBank2', 'PQ3', 'PMess1', '2014-02-11 17:05:21', '2014-02-11 17:07:10', 5, 23.0686, 942.27, 23.4657, 155.532, 155.499, 155.351, 140.781, 139.917, 138.477, 10.3125, 10.3069, 10.3177, 10.4468, 10.4448, 10.4557, 10.8899, 10.8901, 10.8865, 1.325, 1.325, 51.424, 51.424, 50.099, 999.674, 999.661, 999.618, 1916.56, 1916.24, 50.1676, 50.0904, 94.104, -0.153819, 120217, 0.000417309, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(174, 'Qfall (1/5)', 'Qfall', 1.56732, 1.66732, 50, 111.295, 5, 1, 0, 'Verbund-steig-fall', -2, 2, 'PS2', 'PBank2', 'PQ3', 'PMess1', '2014-02-11 17:10:56', '2014-02-11 17:13:00', 1, 23.093, 942.136, 23.4172, 155.273, 155.328, 155.382, 160.45, 160.418, 160.376, 10.3206, 10.3087, 10.3105, 10.4304, 10.4394, 10.434, 10.9015, 10.8702, 10.9207, 1.33, 1.33, 51.4337, 51.4337, 50.1037, 999.673, 999.663, 999.617, 1586.28, 1585.36, 50.1722, 50.0746, 113.708, -0.194521, 120179, 0.000417479, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(175, 'Qfall (2/5)', 'Qfall', 1.54171, 1.64171, 50, 113.086, 5, 1, 0, 'Verbund-steig-fall', -2, 2, 'PS2', 'PBank2', 'PQ3', 'PMess1', '2014-02-11 17:16:49', '2014-02-11 17:18:55', 2, 23.1054, 942.124, 23.2282, 155.218, 155.242, 155.262, 160.557, 160.61, 160.519, 10.3085, 10.3159, 10.3069, 10.4416, 10.4412, 10.443, 10.9186, 10.9081, 10.9243, 1.281, 1.281, 51.3893, 51.3893, 50.1083, 999.674, 999.662, 999.616, 1580.08, 1579.04, 50.1769, 50.0754, 114.165, -0.202272, 120181, 0.000417511, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(176, 'Qfall (3/5)', 'Qfall', 1.53782, 1.63782, 50, 113.363, 5, 1, 0, 'Verbund-steig-fall', -2, 2, 'PS2', 'PBank2', 'PQ3', 'PMess1', '2014-02-11 17:22:41', '2014-02-11 17:24:48', 3, 23.13, 942.136, 23.1746, 155.167, 155.2, 155.217, 160.806, 160.816, 160.684, 10.3251, 10.3339, 10.3249, 10.4483, 10.4539, 10.4466, 10.9223, 10.8883, 10.9189, 1.286, 1.286, 51.39, 51.39, 50.104, 999.673, 999.661, 999.615, 1555.3, 1554.37, 50.1726, 50.0742, 115.974, -0.196184, 120178, 0.000417486, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(177, 'Qfall (4/5)', 'Qfall', 1.53558, 1.63558, 50, 113.523, 5, 1, 0, 'Verbund-steig-fall', -2, 2, 'PS2', 'PBank2', 'PQ3', 'PMess1', '2014-02-11 17:28:38', '2014-02-11 17:30:48', 4, 23.1317, 942.151, 23.1959, 155.236, 155.288, 155.182, 160.864, 160.984, 160.868, 10.3215, 10.3267, 10.3123, 10.4544, 10.4665, 10.4647, 10.9235, 10.8973, 10.9351, 2.363, 2.363, 52.4677, 52.4677, 50.1047, 999.673, 999.661, 999.615, 1541.38, 1540.44, 50.1733, 50.0742, 117.023, -0.197573, 120178, 0.000417492, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(178, 'Qfall (5/5)', 'Qfall', 1.55244, 1.65244, 50, 112.329, 5, 1, 0, 'Verbund-steig-fall', -2, 2, 'PS2', 'PBank2', 'PQ3', 'PMess1', '2014-02-11 17:34:34', '2014-02-11 17:36:42', 5, 23.1429, 942.236, 23.0711, 155.151, 155.16, 155.179, 160.594, 160.621, 160.625, 10.3335, 10.3375, 10.3339, 10.4592, 10.4521, 10.4611, 10.943, 10.9171, 10.9531, 0.736, 0.736, 50.8367, 50.8367, 50.1007, 999.672, 999.66, 999.613, 1577.27, 1576.44, 50.1693, 50.0742, 114.351, -0.189658, 120178, 0.000417458, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(179, 'Q1 (1/5)', 'Q1', 2.4, 2.6, 100, 144, 5, 1, 0, 'Verbund', -2, 2, 'PS2', 'PBank2', 'PQ3', 'PMess1', '2014-02-11 17:37:45', '2014-02-11 17:40:08', 1, 23.15, 942.098, 23.4511, 155.333, 155.449, 155.345, 156.622, 156.566, 156.373, 10.346, 10.3591, 10.3249, 10.448, 10.4791, 10.4196, 10.839, 10.8919, 10.818, 1.19, 1.19, 101.424, 101.424, 100.234, 999.671, 999.661, 999.624, 2746.26, 2743.42, 100.371, 100.13, 131.394, -0.239931, 240313, 0.000417669, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(180, 'Q1 (2/5)', 'Q1', 2.4, 2.6, 100, 144, 5, 1, 0, 'Verbund', -2, 2, 'PS2', 'PBank2', 'PQ3', 'PMess1', '2014-02-11 17:40:58', '2014-02-11 17:43:29', 2, 23.1291, 942.222, 23.5566, 155.309, 155.339, 155.354, 157.425, 158.123, 157.453, 10.3236, 10.3339, 10.3177, 10.4201, 10.425, 10.416, 10.8196, 10.8162, 10.8108, 0.822, 0.822, 101.063, 101.063, 100.241, 999.673, 999.664, 999.625, 2578.98, 2575.89, 100.378, 100.12, 139.926, -0.25625, 240289, 0.000417737, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(181, 'Q2', 'Q2', 38, 44, 500, 43.9024, 1, 1, 0, 'Verbund', -2, 2, 'PS2', 'PBank2', 'PQ5', 'PMess1', '2014-02-11 18:00:00', '2014-02-11 18:00:54', 1, 23.0019, 942.224, 23.6567, 154.825, 154.73, 154.873, 145.016, 144.846, 145.388, 10.3422, 10.3375, 10.3483, 10.3448, 10.3457, 10.3511, 10.4543, 10.4927, 10.4296, 31.55, 31.55, 31.55, 31.55, 0, 999.671, 999.671, 999.661, 0, 42367.2, 0, 503.028, 42.743, 0.1, 18109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(182, 'Q1', 'Q1', 5, 5.5, 100, 68.5714, 1, 1, 0, 'Verbund', -2, 2, 'PS2', 'PBank2', 'PQ4', 'PMess1', '2014-02-11 18:03:06', '2014-02-11 18:04:24', 1, 23.0315, 942.385, 24.8615, 155.407, 155.495, 155.393, 161.744, 161.607, 161.725, 10.3912, 10.3843, 10.3987, 10.4045, 10.3908, 10.4178, 10.4655, 10.4476, 10.4801, 29.55, 29.55, 129.883, 129.883, 100.333, 999.667, 999.665, 999.66, 5337.04, 5326.4, 100.47, 100.133, 67.678, -0.335383, 36048, 0.00278713, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(183, 'Qsteig', 'Qsteig', 1.80768, 2.00768, 50, 94.3556, 1, 1, 0, 'Verbund-steig-fall', -2, 2, 'PS2', 'PBank2', 'PQ3', 'PMess1', '2014-02-11 18:08:54', '2014-02-11 18:10:43', 1, 23.0858, 942.354, 24.8067, 155.283, 155.286, 155.424, 142.298, 140.499, 142.6, 10.4658, 10.4599, 10.4743, 10.5495, 10.5241, 10.5674, 11.1111, 11.1568, 11.0811, 1.134, 1.134, 51.2377, 51.2377, 50.1037, 999.66, 999.652, 999.596, 1846.7, 1846.12, 50.1727, 50.0879, 97.673, -0.169078, 120211, 0.000417372, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(184, 'Qfall', 'Qfall', 2.60318, 2.80318, 50, 66.5883, 1, 1, 0, 'Verbund-steig-fall', -2, 2, 'PS2', 'PBank2', 'PQ3', 'PMess1', '2014-02-11 18:12:35', '2014-02-11 18:13:51', 1, 23.1369, 942.399, 24.4736, 155.305, 155.445, 155.237, 156.336, 156.039, 155.77, 10.4596, 10.4617, 10.4527, 10.5327, 10.5386, 10.5277, 10.9532, 10.9585, 10.9459, 1.253, 1.253, 51.4053, 51.4053, 50.1523, 999.66, 999.653, 999.612, 2751.3, 2750.19, 50.2214, 50.1321, 65.623, -0.177855, 120317, 0.000417409, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(185, 'Q2', 'Q2', 76, 84, 600, 27, 1, 1, 0, 'Verbund', -2, 2, 'PS2', 'PBank2', 'PQ5', 'PMess1', '2014-02-12 08:59:31', '2014-02-12 09:00:20', 1, 24.39, 947.296, 24.1278, 153.923, 153.754, 153.812, 95.265, 95.2036, 95.4415, 11.6113, 11.6793, 11.5262, 11.6889, 11.8563, 11.593, 11.938, 12.2157, 11.7428, 0.1, 0.1, 605.6, 605.6, 605.5, 999.543, 999.535, 999.507, 77073.8, 76621.2, 606.406, 601.944, 28.282, -0.735716, 21670, 0.0279837, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(186, 'Q1', 'Q1', 7.5, 7.8, 200, 94.1177, 1, 1, 0, 'Verbund', -2, 2, 'PS2', 'PBank2', 'PQ4', 'PMess1', '2014-02-12 09:02:32', '2014-02-12 09:04:18', 1, 24.3792, 947.391, 23.9491, 155.404, 155.389, 155.392, 152.634, 152.768, 152.775, 11.5368, 11.5244, 11.5298, 11.6282, 11.6237, 11.6291, 11.6907, 11.6959, 11.6815, 32.1, 32.1, 232.5, 232.5, 200.4, 999.551, 999.541, 999.534, 7625.65, 7617.83, 200.698, 200.194, 94.607, -0.251145, 72070, 0.00278477, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(187, 'Q2', 'Q2', 76, 84, 600, 27, 1, 1, 0, 'Verbund', -2, 2, 'PS2', 'PBank2', 'PQ5', 'PMess1', '2014-02-12 09:10:49', '2014-02-12 09:11:35', 1, 24.32, 947.411, 24.2856, 153.783, 154.057, 153.758, 94.1333, 94.5115, 94.5256, 10.833, 10.9444, 10.7174, 10.8866, 11.0126, 10.7873, 11.0286, 11.1763, 10.8859, 8.3, 8.3, 612.417, 612.417, 604.117, 999.624, 999.619, 999.604, 77401.2, 77130, 604.97, 602, 28.098, -0.490858, 21672, 0.0279148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(188, 'Q1', 'Q1', 7.5, 7.8, 200, 94.1177, 1, 1, 0, 'Verbund', -2, 2, 'PS2', 'PBank2', 'PQ4', 'PMess1', '2014-02-12 09:13:41', '2014-02-12 09:15:27', 1, 24.3065, 947.524, 24.5919, 155.379, 155.457, 155.42, 152.466, 152.634, 152.51, 10.501, 10.5139, 10.4887, 10.5686, 10.5728, 10.5566, 10.6229, 10.6262, 10.6153, 31.95, 31.95, 232.317, 232.317, 200.367, 999.656, 999.65, 999.645, 7603.09, 7596.55, 200.643, 200.194, 94.872, -0.223707, 72070, 0.00278401, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(189, 'Qsteig', 'Qsteig', 1.74913, 1.94913, 100, 194.686, 1, 1, 0, 'Verbund-steig-fall', -2, 2, 'PS2', 'PBank2', 'PQ3', 'PMess1', '2014-02-12 09:37:03', '2014-02-12 09:40:35', 1, 24.2442, 947.69, 24.4377, 155.554, 155.45, 155.627, 143.101, 141.828, 141.911, 10.3882, 10.4167, 10.3663, 10.7036, 10.7476, 10.7007, 11.1919, 11.3136, 11.146, -0.004, -0.004, 100.148, 100.148, 100.152, 999.667, 999.637, 999.588, 1800.16, 1798.99, 100.291, 100.086, 200.285, -0.204399, 240207, 0.00041752, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(190, 'Qfall', 'Qfall', 1.55001, 1.65001, 100, 224.998, 1, 1, 0, 'Verbund-steig-fall', -2, 2, 'PS2', 'PBank2', 'PQ3', 'PMess1', '2014-02-12 09:44:35', '2014-02-12 09:48:32', 1, 24.1984, 947.703, 24.1629, 155.388, 155.361, 155.36, 160.39, 160.502, 160.463, 10.3225, 10.3393, 10.3051, 10.5241, 10.5151, 10.5277, 11.0209, 10.9982, 11.027, 5.735, 5.735, 105.911, 105.911, 100.176, 999.673, 999.654, 999.605, 1591.64, 1590.05, 100.314, 100.076, 226.58, -0.237634, 240182, 0.000417659, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(191, 'Qsteig', 'Qsteig', 1.78364, 1.98364, 50, 95.5597, 1, 1, 0, 'Verbund-steig-fall', -2, 2, 'PS2', 'PBank2', 'PQ3', 'PMess1', '2014-02-12 09:57:10', '2014-02-12 09:58:58', 1, 24.1412, 947.677, 24.0846, 155.601, 155.597, 155.575, 142.488, 140.333, 144.089, 10.3053, 10.3195, 10.2997, 10.5556, 10.5566, 10.571, 11.0389, 11.0739, 11.0162, 4.208, 4.208, 54.2957, 54.2957, 50.0877, 999.675, 999.651, 999.603, 1834.06, 1834.07, 50.1568, 50.0879, 98.315, -0.13725, 120211, 0.000417239, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(192, 'Qfall', 'Qfall', 1.53317, 1.63317, 50, 113.696, 1, 1, 0, 'Verbund-steig-fall', -2, 2, 'PS2', 'PBank2', 'PQ3', 'PMess1', '2014-02-12 10:02:40', '2014-02-12 10:04:47', 1, 24.0515, 947.802, 23.7436, 155.431, 155.469, 155.449, 160.458, 160.443, 160.584, 10.3322, 10.3123, 10.3285, 10.4497, 10.4665, 10.4575, 10.9563, 10.9279, 10.9712, 5.618, 5.618, 55.7243, 55.7243, 50.1063, 999.672, 999.661, 999.612, 1555, 1553.99, 50.1749, 50.0737, 116.002, -0.201687, 120177, 0.000417509, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(193, 'Q1', 'Q1', 2.4, 2.6, 100, 144, 1, 1, 0, 'Verbund', -2, 2, 'PS2', 'PBank2', 'PQ3', 'PMess1', '2014-02-12 10:05:50', '2014-02-12 10:08:22', 1, 23.9531, 947.802, 23.6814, 155.421, 155.514, 155.46, 157.031, 157.067, 156.964, 10.312, 10.3429, 10.2835, 10.4556, 10.5007, 10.4142, 10.8874, 10.9477, 10.8414, 5.527, 5.527, 105.738, 105.738, 100.211, 999.674, 999.661, 999.619, 2553.73, 2551.43, 100.348, 100.12, 141.267, -0.226735, 240289, 0.000417614, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(194, 'Q2', 'Q2', 38, 44, 500, 43.9024, 1, 1, 0, 'Verbund', -2, 2, 'PS2', 'PBank2', 'PQ5', 'PMess1', '2014-02-12 10:09:16', '2014-02-12 10:10:10', 1, 23.902, 947.75, 23.669, 154.792, 154.851, 154.737, 143.91, 143.894, 143.787, 10.2125, 10.2331, 10.1952, 10.2241, 10.2538, 10.2016, 10.47, 10.7578, 10.3412, 0, 0, 504.317, 504.317, 504.317, 999.683, 999.682, 999.659, 43608.2, 43331, 504.997, 501.111, 41.633, -0.769423, 18040, 0.0279932, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(195, 'Qsteig', 'Qsteig', 1.79723, 1.99723, 50, 94.875, 1, 1, 0, 'Verbund-steig-fall', -2, 2, 'PS2', 'PBank2', 'PQ3', 'PMess1', '2014-02-12 10:26:49', '2014-02-12 10:28:38', 1, 23.5893, 947.858, 23.8378, 155.433, 155.579, 155.423, 142.132, 142.52, 142.568, 10.2835, 10.2925, 10.2889, 10.5451, 10.5746, 10.5584, 11.1332, 11.2361, 11.0559, 5.585, 5.585, 55.6787, 55.6787, 50.0937, 999.677, 999.652, 999.594, 1848.38, 1848.18, 50.1627, 50.0883, 97.565, -0.148283, 120212, 0.000417285, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(196, 'Qfall', 'Qfall', 1.54707, 1.64707, 50, 112.707, 1, 1, 0, 'Verbund-steig-fall', -2, 2, 'PS2', 'PBank2', 'PQ3', 'PMess1', '2014-02-12 10:32:21', '2014-02-12 10:34:28', 1, 23.5599, 947.953, 24.1142, 155.376, 155.4, 155.437, 160.446, 160.41, 160.515, 10.2695, 10.2619, 10.2673, 10.4222, 10.4142, 10.4611, 10.9331, 10.9117, 10.9405, 5.83, 5.83, 55.935, 55.935, 50.105, 999.678, 999.664, 999.614, 1556.88, 1555.92, 50.1735, 50.0742, 115.859, -0.197944, 120178, 0.000417493, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(197, 'Qsteig', 'Qsteig', 1.7827, 1.9827, 100, 191.215, 1, 1, 0, 'Verbund-steig-fall', -2, 2, 'PS2', 'PBank2', 'PQ3', 'PMess1', '2014-02-12 10:37:48', '2014-02-12 10:41:15', 1, 23.5118, 948.071, 24.026, 155.426, 155.426, 155.32, 142.351, 143.915, 143.703, 10.2639, 10.2691, 10.2529, 10.4627, 10.4683, 10.4701, 10.9439, 10.982, 10.9297, 5.964, 5.964, 106.121, 106.121, 100.157, 999.678, 999.66, 999.613, 1841.46, 1840.18, 100.294, 100.087, 195.803, -0.20666, 240208, 0.00041753, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(198, 'Qfall', 'Qfall', 1.53903, 1.63903, 100, 226.553, 1, 1, 0, 'Verbund-steig-fall', -2, 2, 'PS2', 'PBank2', 'PQ3', 'PMess1', '2014-02-12 10:45:12', '2014-02-12 10:49:13', 1, 23.4743, 948.079, 23.9058, 155.375, 155.295, 155.238, 160.373, 160.34, 160.357, 10.2551, 10.2601, 10.2457, 10.4046, 10.3998, 10.4304, 10.9047, 10.8829, 10.9153, 5.465, 5.465, 105.633, 105.633, 100.168, 999.679, 999.665, 999.617, 1574.11, 1572.65, 100.305, 100.075, 229.086, -0.228962, 240181, 0.000417623, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(199, 'Qt', 'Qt', 7.5, 7.8, 200, 94.1177, 1, 1, 0, 'Verbund', -2, 2, 'PS2', 'PBank2', 'PQ4', 'PMess1', '2014-02-12 10:51:21', '2014-02-12 10:53:06', 1, 23.4514, 948.345, 24.1072, 155.522, 155.494, 155.53, 152.922, 152.928, 152.944, 10.197, 10.2133, 10.1826, 10.2523, 10.2827, 10.234, 10.3794, 10.4675, 10.3142, 33.0667, 33.0667, 233.45, 233.45, 200.383, 999.684, 999.679, 999.668, 7619.86, 7612.89, 200.654, 200.2, 94.671, -0.226273, 72072, 0.00278408, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(200, 'Qmax', 'Qmax', 76, 84, 600, 27, 1, 1, 0, 'Verbund', -2, 2, 'PS2', 'PBank2', 'PQ5', 'PMess1', '2014-02-12 10:55:33', '2014-02-12 10:56:25', 1, 23.42, 948.246, 24.0592, 153.679, 153.827, 153.436, 93.9943, 93.7608, 94.2054, 10.0936, 10.098, 10.0854, 10.0982, 10.1025, 10.0935, 10.1285, 10.1375, 10.1231, 33.05, 33.05, 638.967, 638.967, 605.917, 999.694, 999.693, 999.691, 77540.8, 77032.5, 606.727, 601.944, 28.131, -0.788221, 21670, 0.0279985, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(201, 'Qsteig', 'Qsteig', 1.71164, 1.91164, 100, 198.715, 1, 1, 0, 'Verbund-steig-fall', -2, 2, 'PS2', 'PBank2', 'PQ3', 'PMess1', '2014-02-12 11:14:19', '2014-02-12 11:17:59', 1, 23.26, 948.328, 24.2585, 155.284, 155.342, 155.298, 144.515, 142.503, 144.04, 10.1462, 10.1232, 10.1412, 10.2328, 10.1854, 10.2719, 10.8296, 10.9225, 10.7982, 0.173, 0.173, 100.325, 100.325, 100.152, 999.689, 999.681, 999.624, 1724.09, 1722.9, 100.287, 100.083, 209.122, -0.203708, 240198, 0.000417517, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(202, 'Qfall', 'Qfall', 1.53217, 1.63217, 100, 227.535, 1, 1, 0, 'Verbund-steig-fall', -2, 2, 'PS2', 'PBank2', 'PQ3', 'PMess1', '2014-02-12 11:22:00', '2014-02-12 11:26:04', 1, 23.2256, 948.339, 24.2575, 155.312, 155.309, 155.406, 160.471, 160.79, 160.433, 10.1556, 10.1538, 10.1574, 10.2611, 10.2466, 10.2773, 10.7965, 10.7657, 10.8216, 5.32667, 5.32667, 105.49, 105.49, 100.163, 999.688, 999.679, 999.628, 1547.48, 1546.1, 100.298, 100.074, 233.016, -0.223972, 240177, 0.000417602, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(203, 'Qt', 'Qt', 7.5, 7.8, 200, 94.1177, 1, 1, 0, 'Verbund', -2, 2, 'PS2', 'PBank2', 'PQ4', 'PMess1', '2014-02-12 11:26:25', '2014-02-12 11:28:10', 1, 23.22, 948.378, 24.27, 155.219, 155.31, 155.242, 153.219, 153.318, 153.009, 10.1487, 10.1754, 10.1376, 10.2128, 10.2719, 10.1728, 10.4105, 10.6911, 10.2619, 19.6, 19.6, 220, 220, 200.4, 999.689, 999.683, 999.665, 7636.63, 7628.8, 200.67, 200.194, 94.471, -0.236984, 72070, 0.00278438, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(204, 'Qmax', 'Qmax', 76, 84, 600, 27, 1, 1, 0, 'Verbund', -2, 2, 'PS2', 'PBank2', 'PQ5', 'PMess1', '2014-02-12 11:30:04', '2014-02-12 11:30:46', 1, 23.21, 948.477, 24.4754, 153.567, 153.731, 153.632, 94.3636, 93.7417, 94.4694, 10.0728, 10.0782, 10.071, 10.0788, 10.0845, 10.0737, 10.1043, 10.1104, 10.0996, 33.2, 33.2, 639.133, 639.133, 605.933, 999.696, 999.695, 999.693, 77589.8, 77082.6, 606.742, 601.972, 28.114, -0.786199, 21671, 0.0279979, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(205, 'Qsteig', 'Qsteig', 1.7052, 1.9052, 100, 199.424, 1, 1, 0, 'Verbund-steig-fall', -2, 2, 'PS2', 'PBank2', 'PQ3', 'PMess1', '2014-02-12 11:47:27', '2014-02-12 11:51:01', 1, 23.1755, 948.36, 24.7173, 155.257, 155.153, 155.278, 143.449, 142.702, 142.917, 10.1396, 10.1286, 10.1448, 10.2225, 10.18, 10.252, 10.7877, 10.8811, 10.7477, 0.161333, 0.161333, 100.302, 100.302, 100.141, 999.69, 999.682, 999.629, 1777.79, 1776.8, 100.276, 100.085, 202.784, -0.190499, 240204, 0.000417462, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(206, 'Qfall', 'Qfall', 1.52073, 1.62073, 100, 229.193, 1, 1, 0, 'Verbund-steig-fall', -2, 2, 'PS2', 'PBank2', 'PQ3', 'PMess1', '2014-02-12 11:55:03', '2014-02-12 11:59:09', 1, 23.1181, 948.259, 24.6504, 155.308, 155.281, 155.276, 160.733, 160.723, 160.714, 10.1577, 10.1628, 10.1556, 10.2726, 10.2628, 10.2935, 10.7887, 10.7387, 10.8018, 5.285, 5.285, 105.445, 105.445, 100.16, 999.688, 999.678, 999.628, 1530.76, 1529.43, 100.296, 100.073, 235.554, -0.222266, 240175, 0.000417595, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(207, 'Qt', 'Qt', 7.5, 7.8, 200, 94.1177, 1, 1, 0, 'Verbund', -2, 2, 'PS2', 'PBank2', 'PQ4', 'PMess1', '2014-02-12 11:59:30', '2014-02-12 12:01:15', 1, 23.119, 948.293, 24.7455, 155.238, 155.447, 155.288, 152.898, 152.861, 152.904, 10.1451, 10.1682, 10.1322, 10.2218, 10.2863, 10.1764, 10.3962, 10.655, 10.2583, 14.1, 14.1, 214.433, 214.433, 200.333, 999.689, 999.682, 999.666, 7623.28, 7618.1, 200.603, 200.197, 94.605, -0.202484, 72071, 0.00278341, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(208, 'Qmax', 'Qmax', 76, 84, 600, 27, 1, 1, 0, 'Verbund', -2, 2, 'PS2', 'PBank2', 'PQ5', 'PMess1', '2014-02-12 12:03:08', '2014-02-12 12:03:59', 1, 23.14, 947.977, 24.7915, 153.465, 153.6, 153.285, 94.4564, 94.2222, 94.7648, 10.081, 10.0836, 10.0818, 10.0917, 10.0935, 10.0899, 10.1153, 10.1195, 10.114, 33.25, 33.25, 640.033, 640.033, 606.783, 999.695, 999.694, 999.692, 77602.1, 76990.3, 607.594, 602, 28.149, -0.920729, 21672, 0.0280359, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(209, 'Qsteig', 'Qsteig', 1.71861, 1.91861, 100, 197.953, 1, 1, 0, 'Verbund-steig-fall', -2, 2, 'PS2', 'PBank2', 'PQ3', 'PMess1', '2014-02-12 13:26:45', '2014-02-12 13:30:17', 1, 23.4412, 948.179, 25.1057, 155.065, 155.114, 154.917, 142.841, 143.897, 142.947, 10.2121, 10.2006, 10.2133, 10.3117, 10.2737, 10.3439, 10.9074, 10.9892, 10.8793, 0.044, 0.044, 100.186, 100.186, 100.142, 999.683, 999.674, 999.617, 1796.68, 1795.68, 100.278, 100.086, 200.653, -0.191135, 240206, 0.000417465, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(210, 'Qfall', 'Qfall', 1.51806, 1.61806, 100, 229.583, 1, 1, 0, 'Verbund-steig-fall', -2, 2, 'PS2', 'PBank2', 'PQ3', 'PMess1', '2014-02-12 13:34:15', '2014-02-12 13:38:17', 1, 23.4949, 948.107, 24.9742, 155.174, 155.194, 155.211, 160.313, 160.347, 160.381, 10.2278, 10.2241, 10.2313, 10.3406, 10.3259, 10.3638, 10.8677, 10.845, 10.8793, 5.303, 5.303, 105.466, 105.466, 100.163, 999.682, 999.671, 999.621, 1567.01, 1565.62, 100.299, 100.075, 230.112, -0.223879, 240179, 0.000417602, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(211, 'Qt', 'Qt', 7.5, 7.8, 200, 94.1177, 1, 1, 0, 'Verbund', -2, 2, 'PS2', 'PBank2', 'PQ4', 'PMess1', '2014-02-12 13:38:38', '2014-02-12 13:40:22', 1, 23.4903, 948.13, 24.564, 155.18, 155.209, 155.188, 152.537, 152.586, 152.546, 10.2147, 10.2475, 10.1988, 10.2924, 10.362, 10.252, 10.5027, 10.8101, 10.3448, -0.133333, -0.133333, 200.283, 200.283, 200.417, 999.683, 999.676, 999.656, 7708.09, 7699.75, 200.688, 200.2, 93.603, -0.243227, 72072, 0.00278455, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(212, 'Qmax', 'Qmax', 76, 84, 600, 27, 1, 1, 0, 'Verbund', -2, 2, 'PS2', 'PBank2', 'PQ5', 'PMess1', '2014-02-12 13:42:37', '2014-02-12 13:43:31', 1, 23.4726, 948.23, 24.52, 153.579, 153.709, 153.606, 93.6685, 92.6869, 93.277, 10.103, 10.1088, 10.0926, 10.1167, 10.1223, 10.1115, 10.1458, 10.1519, 10.1429, 33.85, 33.85, 640.65, 640.65, 606.8, 999.693, 999.692, 999.689, 78072.9, 77455.3, 607.612, 602, 27.98, -0.923675, 21672, 0.0280367, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(213, 'Qsteig', 'Qsteig', 1.71886, 1.91886, 100, 197.926, 1, 1, 0, 'Verbund-steig-fall', -2, 2, 'PS2', 'PBank2', 'PQ3', 'PMess1', '2014-02-12 14:06:03', '2014-02-12 14:09:38', 1, 23.2177, 948.149, 24.7618, 155.26, 155.196, 155.249, 143.909, 143.851, 142.847, 10.1808, 10.161, 10.188, 10.2584, 10.2106, 10.2827, 10.8351, 10.9081, 10.7964, 0.151, 0.151, 100.294, 100.294, 100.143, 999.686, 999.679, 999.624, 1768.57, 1767.55, 100.278, 100.085, 203.845, -0.192481, 240204, 0.00041747, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(214, 'Qfall', 'Qfall', 1.53412, 1.63412, 100, 227.255, 1, 1, 0, 'Verbund-steig-fall', -2, 2, 'PS2', 'PBank2', 'PQ3', 'PMess1', '2014-02-12 14:13:41', '2014-02-12 14:17:40', 1, 23.1278, 948.106, 24.7521, 155.281, 155.228, 155.422, 160.32, 160.108, 160.573, 10.2035, 10.2042, 10.1988, 10.294, 10.2881, 10.3061, 10.7839, 10.7459, 10.8, 5.412, 5.412, 105.584, 105.584, 100.172, 999.684, 999.676, 999.629, 1582.41, 1580.89, 100.308, 100.076, 227.893, -0.231154, 240182, 0.000417632, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(215, 'Qt', 'Qt', 7.5, 7.8, 200, 94.1177, 1, 1, 0, 'Verbund', -2, 2, 'PS2', 'PBank2', 'PQ4', 'PMess1', '2014-02-12 14:18:01', '2014-02-12 14:19:45', 1, 23.0791, 948.042, 24.7716, 155.209, 155.124, 155.291, 152.888, 153.043, 152.805, 10.19, 10.2115, 10.1772, 10.2465, 10.3025, 10.207, 10.4394, 10.7127, 10.298, 26.95, 26.95, 227.35, 227.35, 200.4, 999.685, 999.68, 999.662, 7723.21, 7715.39, 200.671, 200.197, 93.412, -0.235919, 72071, 0.00278435, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(216, 'Qmax', 'Qmax', 76, 84, 600, 27, 1, 1, 0, 'Verbund', -2, 2, 'PS2', 'PBank2', 'PQ5', 'PMess1', '2014-02-12 14:22:06', '2014-02-12 14:22:47', 1, 23.04, 947.835, 25.0346, 153.564, 153.381, 153.546, 93.1579, 93.3164, 92.9786, 10.1147, 10.1232, 10.107, 10.1136, 10.1205, 10.1061, 10.1427, 10.1483, 10.1393, 34.0167, 34.0167, 640.4, 640.4, 606.383, 999.692, 999.692, 999.689, 78173, 77604.3, 607.195, 601.972, 27.925, -0.860138, 21671, 0.0280188, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(217, 'Qsteig', 'Qsteig', 1.70033, 1.90033, 100, 199.963, 1, 1, 0, 'Verbund-steig-fall', -2, 2, 'PS2', 'PBank2', 'PQ3', 'PMess1', '2014-02-12 14:36:04', '2014-02-12 14:39:44', 1, 22.9438, 947.883, 24.9002, 155.971, 155.955, 156.086, 145.303, 145.655, 145.895, 10.2209, 10.2205, 10.2223, 10.3787, 10.4485, 10.3385, 11.0028, 11.2811, 10.8738, 0.084, 0.084, 100.273, 100.273, 100.189, 999.682, 999.668, 999.607, 1722.55, 1720.71, 100.326, 100.082, 209.388, -0.242983, 240197, 0.000417682, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(218, 'Qfall', 'Qfall', 1.61484, 1.71484, 100, 216.238, 1, 1, 0, 'Verbund-steig-fall', -2, 2, 'PS2', 'PBank2', 'PQ3', 'PMess1', '2014-02-12 14:43:39', '2014-02-12 14:47:21', 1, 22.9331, 947.892, 24.7242, 155.986, 156.009, 155.968, 162.829, 162.833, 162.811, 10.2418, 10.2403, 10.2259, 10.3103, 10.3133, 10.3241, 10.7765, 10.7567, 10.791, 5.281, 5.281, 105.466, 105.466, 100.185, 999.68, 999.674, 999.63, 1709.88, 1708.12, 100.321, 100.082, 210.931, -0.23837, 240197, 0.000417662, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(219, 'Qt', 'Qt', 7.5, 7.8, 200, 94.1177, 1, 1, 0, 'Verbund', -2, 2, 'PS2', 'PBank2', 'PQ4', 'PMess1', '2014-02-12 14:47:44', '2014-02-12 14:49:30', 1, 22.9628, 947.969, 24.847, 155.948, 155.964, 155.961, 160.505, 160.37, 160.531, 10.1982, 10.2475, 10.179, 10.2456, 10.3133, 10.2034, 11.5568, 14.8236, 10.4476, 5.3, 5.3, 205.333, 205.333, 200.033, 999.684, 999.68, 999.549, 7612.02, 7617.94, 200.303, 200.189, 94.603, -0.0571871, 72068, 0.00277937, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(220, 'Qmax', 'Qmax', 76, 84, 600, 27, 1, 1, 0, 'Verbund', -2, 2, 'PS2', 'PBank2', 'PQ5', 'PMess1', '2014-02-12 14:51:46', '2014-02-12 14:52:41', 1, 23.0135, 947.969, 24.69, 153.69, 153.548, 153.825, 93.8078, 92.9503, 93.8381, 10.1293, 10.1358, 10.1232, 10.1305, 10.1349, 10.1241, 10.1742, 10.179, 10.1681, 33.75, 33.75, 639.783, 639.783, 606.033, 999.691, 999.69, 999.687, 78077.5, 77550.7, 606.845, 601.944, 27.943, -0.807609, 21670, 0.0280039, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(221, 'Qsteig', 'Qsteig', 1.68967, 1.88967, 100, 201.155, 1, 1, 0, 'Verbund-steig-fall', -2, 2, 'PS2', 'PBank2', 'PQ3', 'PMess1', '2014-02-12 15:59:12', '2014-02-12 16:02:51', 1, 23.8897, 947.37, 22.6616, 155.2, 155.093, 155.148, 144.474, 144.848, 145.557, 10.2808, 10.2709, 10.2709, 10.3997, 10.3493, 10.434, 11.0613, 11.1946, 10.991, 0.027, 0.027, 100.19, 100.19, 100.163, 999.677, 999.666, 999.601, 1727.54, 1726.15, 100.3, 100.083, 208.729, -0.216529, 240198, 0.000417571, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(222, 'Qsteig', 'Qsteig', 1.80279, 2.00279, 100, 189.196, 1, 1, 0, 'Verbund-steig-fall', -2, 2, 'PS2', 'PBank2', 'PQ3', 'PMess1', '2014-02-12 16:36:22', '2014-02-12 16:39:47', 1, 24.2851, 947.275, 22.8132, 155.39, 155.324, 155.111, 141.965, 142.164, 139.672, 10.2221, 10.2097, 10.2313, 10.3243, 10.2809, 10.3565, 10.8489, 10.863, 10.8522, 0.115, 0.115, 100.272, 100.272, 100.157, 999.682, 999.673, 999.623, 1857.78, 1856.54, 100.293, 100.09, 194.083, -0.202471, 240215, 0.000417512, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL); +INSERT INTO `testresult` (`Id`, `Name`, `TestName`, `Qfrom`, `Qto`, `Volume`, `TstTime`, `Repeats`, `Emptying`, `Zeroing`, `Method`, `ErrLimLo`, `ErrLimHi`, `FeedingPath`, `BenchPath`, `OutputPath`, `MetersPath`, `TimeStart`, `TimeEnd`, `RepetitionNr`, `AmbientTempAve`, `AmbientPressAve`, `AmbientHumiAve`, `PressInAvrg`, `PressInStart`, `PressInEnd`, `PressOutAvrg`, `PressOutStart`, `PressOutEnd`, `TempInAvrg`, `TempInStart`, `TempInEnd`, `TempOutAvrg`, `TempOutStart`, `TempOutEnd`, `TempDivAvrg`, `TempDivStart`, `TempDivEnd`, `MassStartRaw`, `MassStart`, `MassEndRaw`, `MassEnd`, `MassDiff`, `DensityIn`, `DensityOut`, `DensityDiv`, `FlowMass`, `FlowVolume`, `VolumeCTV`, `VolumeMaster`, `Time`, `ErrorMaster`, `PulsesMaster`, `ConstMaster`, `TimeDivStart0`, `TimeDivStart1`, `TimeDivStart2`, `TimeDivStart3`, `TimeDivStart4`, `TimeDivStart5`, `TimeDivEnd0`, `TimeDivEnd1`, `TimeDivEnd2`, `TimeDivEnd3`, `TimeDivEnd4`, `TimeDivEnd5`, `Test_id`) VALUES +(223, 'Qfall', 'Qfall', 1.62192, 1.72192, 100, 215.321, 1, 1, 0, 'Verbund-steig-fall', -2, 2, 'PS2', 'PBank2', 'PQ3', 'PMess1', '2014-02-12 16:43:38', '2014-02-12 16:47:21', 1, 24.1921, 947.088, 23.0671, 155.421, 155.363, 155.43, 160.08, 160.18, 160.116, 10.2256, 10.2349, 10.2187, 10.3425, 10.3421, 10.362, 10.8334, 10.8072, 10.854, 5.704, 5.704, 105.883, 105.883, 100.179, 999.682, 999.671, 999.624, 1702.67, 1701.01, 100.315, 100.081, 211.811, -0.233182, 240195, 0.000417641, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(224, 'Qt', 'Qt', 7.5, 7.8, 200, 94.1177, 1, 1, 0, 'Verbund', -2, 2, 'PS2', 'PBank2', 'PQ4', 'PMess1', '2014-02-12 16:47:45', '2014-02-12 16:49:30', 1, 24.1444, 947.061, 23.1614, 155.413, 155.41, 155.451, 152.617, 152.469, 152.547, 10.2119, 10.2367, 10.2006, 10.278, 10.3439, 10.243, 10.4974, 10.839, 10.3358, -0.1, -0.1, 200.283, 200.283, 200.383, 999.683, 999.677, 999.657, 7635.19, 7627.88, 200.655, 200.192, 94.481, -0.230675, 72069, 0.0027842, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(225, 'Qmax', 'Qmax', 76, 84, 600, 27, 1, 1, 0, 'Verbund', -2, 2, 'PS2', 'PBank2', 'PQ5', 'PMess1', '2014-02-12 16:51:51', '2014-02-12 16:52:32', 1, 24.0846, 946.908, 23.2208, 153.563, 153.53, 153.415, 93.3551, 94.0705, 93.3385, 10.0966, 10.1016, 10.0908, 10.1062, 10.1133, 10.0989, 10.134, 10.1393, 10.1303, 34.0333, 34.0333, 640.483, 640.483, 606.45, 999.693, 999.693, 999.69, 78100.5, 77516.6, 607.261, 601.917, 27.954, -0.880116, 21669, 0.0280244, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(226, 'Qmax', 'Qmax', 76, 84, 600, 27, 1, 1, 0, 'Verbund', -2, 2, 'PS2', 'PBank2', 'PQ5', 'PMess1', '2014-02-12 17:05:40', '2014-02-12 17:06:25', 1, 23.8788, 946.912, 23.6535, 153.809, 153.999, 153.881, 93.788, 94.6997, 93.5672, 10.1106, 10.116, 10.1088, 10.1242, 10.1313, 10.1187, 10.1581, 10.1754, 10.1483, 8.3, 8.3, 613.05, 613.05, 604.75, 999.692, 999.691, 999.688, 77884.3, 77523, 605.56, 601.944, 27.953, -0.597057, 21670, 0.0279446, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(227, 'Qt', 'Qt', 7.5, 7.8, 200, 94.1177, 1, 1, 0, 'Verbund', -2, 2, 'PS2', 'PBank2', 'PQ4', 'PMess1', '2014-02-12 17:09:13', '2014-02-12 17:10:58', 1, 23.8151, 946.968, 23.8398, 155.32, 155.316, 155.312, 152.62, 152.507, 152.698, 10.1129, 10.1142, 10.1124, 10.1393, 10.1385, 10.1385, 10.1798, 10.179, 10.1826, 34.1, 34.1, 34.1, 34.1, 0, 999.692, 999.69, 999.686, 0, 7625.7, 0, 200.539, 94.672, 0.1, 72194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(228, 'Qsteig', 'Qsteig', 1.66617, 1.86617, 100, 203.831, 1, 1, 0, 'Verbund-steig-fall', -2, 2, 'PS2', 'PBank2', 'PQ3', 'PMess1', '2014-02-12 17:13:25', '2014-02-12 17:17:04', 1, 23.7489, 946.989, 24.0505, 155.462, 155.53, 155.532, 144.559, 144.493, 145.402, 10.1915, 10.161, 10.2024, 10.2614, 10.2124, 10.2935, 10.8504, 10.9802, 10.8018, 0.044, 0.044, 100.19, 100.19, 100.146, 999.685, 999.679, 999.622, 1733.32, 1732.23, 100.281, 100.083, 207.996, -0.197983, 240198, 0.000417493, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(229, 'Qfall', 'Qfall', 1.6237, 1.7237, 100, 215.092, 1, 1, 0, 'Verbund-steig-fall', -2, 2, 'PS2', 'PBank2', 'PQ3', 'PMess1', '2014-02-12 17:20:59', '2014-02-12 17:24:49', 1, 23.6582, 946.975, 23.9772, 155.478, 155.549, 155.485, 160.275, 160.313, 160.222, 10.1884, 10.197, 10.1772, 10.2808, 10.2791, 10.2935, 10.7763, 10.7513, 10.7892, 5.412, 5.412, 105.593, 105.593, 100.181, 999.685, 999.677, 999.63, 1648.08, 1646.39, 100.317, 100.079, 218.832, -0.23743, 240189, 0.000417658, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(230, 'Qmax', 'Qmax', 76, 84, 600, 27, 1, 1, 0, 'Verbund', -2, 2, 'PS2', 'PBank2', 'PQ5', 'PMess1', '2014-02-12 17:36:12', '2014-02-12 17:36:55', 1, 23.4641, 946.74, 23.94, 153.743, 153.917, 153.629, 92.9069, 93.1351, 92.3387, 10.3009, 10.4203, 10.2349, 10.5077, 10.8485, 10.3331, 11.2828, 12.0352, 10.7218, 0.45, 0.45, 596.75, 596.75, 596.3, 999.675, 999.656, 999.578, 77218.7, 77956.8, 597.12, 602, 27.8, 0.817288, 21672, 0.0275526, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(231, 'Qt', 'Qt', 7.5, 7.8, 200, 94.1177, 1, 1, 0, 'Verbund', -2, 2, 'PS2', 'PBank2', 'PQ4', 'PMess1', '2014-02-12 17:39:45', '2014-02-12 17:41:29', 1, 23.3967, 946.811, 24.5048, 155.434, 155.559, 155.407, 159.558, 159.461, 159.46, 10.1432, 10.1412, 10.1502, 10.1631, 10.1637, 10.1673, 10.2192, 10.2204, 10.2204, 34.05, 34.05, 234.433, 234.433, 200.383, 999.689, 999.688, 999.682, 7752.44, 7745.13, 200.652, 200.194, 93.052, -0.228237, 72070, 0.00278413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(232, 'Qsteig', 'Qsteig', 1.67471, 1.87471, 100, 202.85, 1, 1, 0, 'Verbund-steig-fall', -2, 2, 'PS2', 'PBank2', 'PQ3', 'PMess1', '2014-02-12 17:43:54', '2014-02-12 17:47:29', 1, 23.3185, 946.74, 24.0545, 155.657, 155.676, 155.426, 144.151, 143.679, 143.69, 10.1937, 10.1826, 10.1952, 10.2843, 10.2376, 10.3205, 10.944, 11.1748, 10.8396, 0.053, 0.053, 100.205, 100.205, 100.152, 999.685, 999.677, 999.613, 1768.36, 1767.18, 100.288, 100.085, 203.888, -0.202344, 240204, 0.000417511, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(233, 'Qfall', 'Qfall', 1.56802, 1.66802, 100, 222.494, 1, 1, 0, 'Verbund-steig-fall', -2, 2, 'PS2', 'PBank2', 'PQ3', 'PMess1', '2014-02-12 17:51:30', '2014-02-12 17:55:28', 1, 23.234, 946.613, 23.8995, 155.655, 155.59, 155.614, 160.994, 161.083, 161.007, 10.2128, 10.2151, 10.2024, 10.3121, 10.2935, 10.3223, 10.7987, 10.7603, 10.827, 5.298, 5.298, 105.463, 105.463, 100.165, 999.683, 999.674, 999.628, 1582.05, 1580.65, 100.301, 100.076, 227.927, -0.224035, 240182, 0.000417602, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `user` +-- + +CREATE TABLE IF NOT EXISTS `user` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `Name` varchar(255) DEFAULT NULL, + `Password` varchar(255) DEFAULT NULL, + `Description` varchar(255) DEFAULT NULL, + `LastPwChange` datetime DEFAULT NULL, + PRIMARY KEY (`Id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=3 ; + +-- +-- Dumping data for table `user` +-- + +INSERT INTO `user` (`Id`, `Name`, `Password`, `Description`, `LastPwChange`) VALUES +(1, 'admin', 'af242843887f3bdcc52e485483356eaccd37ba67a35941530bd195a8310fc7d5aca8560576dfb62ad5a4bd2df789a5e8be068e62e7c976d6eeed8d63abbd9909', 'Application administrator', '2013-12-30 12:17:19'), +(2, 'tester', '', 'tester', '2013-12-30 12:17:19'); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `watermeter` +-- + +CREATE TABLE IF NOT EXISTS `watermeter` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `Serial` varchar(255) DEFAULT NULL, + `WMType_id` int(11) DEFAULT NULL, + PRIMARY KEY (`Id`), + KEY `WMType_id` (`WMType_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `wmtype` +-- + +CREATE TABLE IF NOT EXISTS `wmtype` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `CreateTime` datetime DEFAULT NULL, + `CreateUserName` varchar(255) DEFAULT NULL, + `CreateDescription` varchar(255) DEFAULT NULL, + `Name` varchar(255) DEFAULT NULL, + `PulseRate` float DEFAULT NULL, + PRIMARY KEY (`Id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; + +-- +-- Constraints for dumped tables +-- + +-- +-- Constraints for table `componentprocedure` +-- +ALTER TABLE `componentprocedure` + ADD CONSTRAINT `FKA4EE67E2C1B693F2` FOREIGN KEY (`Procedure_id`) REFERENCES `procedure` (`Id`); + +-- +-- Constraints for table `componenttest` +-- +ALTER TABLE `componenttest` + ADD CONSTRAINT `FK4933B35E048BC68` FOREIGN KEY (`Test_id`) REFERENCES `test` (`Id`); + +-- +-- Constraints for table `group` +-- +ALTER TABLE `group` + ADD CONSTRAINT `FKFBBA8E27F90D2266` FOREIGN KEY (`User_id`) REFERENCES `user` (`Id`); + +-- +-- Constraints for table `measurementcorrection` +-- +ALTER TABLE `measurementcorrection` + ADD CONSTRAINT `FK2E70F3322F02977E` FOREIGN KEY (`Component_id`) REFERENCES `component` (`Id`); + +-- +-- Constraints for table `metertestresult` +-- +ALTER TABLE `metertestresult` + ADD CONSTRAINT `FK1CE41B064BD6C9B6` FOREIGN KEY (`TestResult_id`) REFERENCES `testresult` (`Id`); + +-- +-- Constraints for table `purgeend` +-- +ALTER TABLE `purgeend` + ADD CONSTRAINT `FK14832B1AC1B693F2` FOREIGN KEY (`Procedure_id`) REFERENCES `procedure` (`Id`); + +-- +-- Constraints for table `purgestart` +-- +ALTER TABLE `purgestart` + ADD CONSTRAINT `FKDC8627F9C1B693F2` FOREIGN KEY (`Procedure_id`) REFERENCES `procedure` (`Id`); + +-- +-- Constraints for table `test` +-- +ALTER TABLE `test` + ADD CONSTRAINT `FKCC127866C1B693F2` FOREIGN KEY (`Procedure_id`) REFERENCES `procedure` (`Id`); + +-- +-- Constraints for table `testresult` +-- +ALTER TABLE `testresult` + ADD CONSTRAINT `FKAD39033FE048BC68` FOREIGN KEY (`Test_id`) REFERENCES `test` (`Id`); + +-- +-- Constraints for table `watermeter` +-- +ALTER TABLE `watermeter` + ADD CONSTRAINT `FKA968A8E699BF9B30` FOREIGN KEY (`WMType_id`) REFERENCES `wmtype` (`Id`); + +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; diff --git a/TestBenchFramework/SampleConfig/log4netConfig.xml b/TestBenchFramework/SampleConfig/log4netConfig.xml new file mode 100644 index 000000000..3180f4e9f --- /dev/null +++ b/TestBenchFramework/SampleConfig/log4netConfig.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TestBenchFramework/SampleConfig/munich-gwz-1.sql b/TestBenchFramework/SampleConfig/munich-gwz-1.sql new file mode 100644 index 000000000..af2d2a3e8 --- /dev/null +++ b/TestBenchFramework/SampleConfig/munich-gwz-1.sql @@ -0,0 +1,1166 @@ +-- phpMyAdmin SQL Dump +-- version 3.4.5 +-- http://www.phpmyadmin.net +-- +-- Host: localhost +-- Erstellungszeit: 24. Jan 2014 um 15:40 +-- Server Version: 5.5.16 +-- PHP-Version: 5.3.8 + +SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO"; +SET time_zone = "+00:00"; + + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; + +-- +-- Datenbank: `gwz-1` +-- + +-- -------------------------------------------------------- + +-- +-- Tabellenstruktur für Tabelle `benchpath` +-- + +CREATE TABLE IF NOT EXISTS `benchpath` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `ItemNr` int(11) DEFAULT NULL, + `Name` varchar(255) DEFAULT NULL, + `Qfrom` float DEFAULT NULL, + `Qto` float DEFAULT NULL, + `TempIn` varchar(255) DEFAULT NULL, + `TempOut` varchar(255) DEFAULT NULL, + `PressIn` varchar(255) DEFAULT NULL, + `PressOut` varchar(255) DEFAULT NULL, + `ValvesOpen` varchar(8000) DEFAULT NULL, + `ValvesClose` varchar(8000) DEFAULT NULL, + PRIMARY KEY (`Id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=9 ; + +-- +-- Daten für Tabelle `benchpath` +-- + +INSERT INTO `benchpath` (`Id`, `ItemNr`, `Name`, `Qfrom`, `Qto`, `TempIn`, `TempOut`, `PressIn`, `PressOut`, `ValvesOpen`, `ValvesClose`) VALUES +(1, 1, 'PBank1', 0.01, 0.03, 'T1', 'T2', 'Druck1', 'Druck2', 'VL13;VL12', ''), +(2, 2, 'PBank2', 0.03, 250, 'T1', 'T2', 'Druck1', 'Druck2', 'VL11;VL12;VI12', ''), +(3, 3, 'PBank3', 0.02, 12, 'T5', 'T2', 'Druck3', 'Druck4', 'VI21;VI22', 'VM1;VM2;VM3;VM4'), +(4, 4, 'PBank4', 0.02, 15, 'T5', 'T2', 'Druck3', 'Druck4', 'VI21;VI22;VM2;VM3', 'VM1;VM4'), +(5, 5, 'PBank5', 0.02, 18, 'T5', 'T2', 'Druck3', 'Druck4', 'VI21;VI22;VM1;VM3', 'VM2;VM4'), +(6, 6, 'PBank6', 0.02, 18, 'T5', 'T2', 'Druck3', 'Druck4', 'VI21;VI22;VM1;VM2', 'VM3;VM4'), +(7, 7, 'PBank7', 0.02, 5, 'T5', 'T2', 'Druck3', 'Druck4', 'VL21', ''), +(8, 0, '', 0, 0, '---', '---', '---', '---', '', ''); + +-- -------------------------------------------------------- + +-- +-- Tabellenstruktur für Tabelle `component` +-- + +CREATE TABLE IF NOT EXISTS `component` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `Name` varchar(255) DEFAULT NULL, + `ClassName` varchar(255) DEFAULT NULL, + `ParentName` varchar(255) DEFAULT NULL, + `ItemNr` int(11) DEFAULT NULL, + `DebugLevel` varchar(255) DEFAULT NULL, + `LogLevel` varchar(255) DEFAULT NULL, + `Parameters` varchar(8000) DEFAULT NULL, + PRIMARY KEY (`Id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=67 ; + +-- +-- Daten für Tabelle `component` +-- + +INSERT INTO `component` (`Id`, `Name`, `ClassName`, `ParentName`, `ItemNr`, `DebugLevel`, `LogLevel`, `Parameters`) VALUES +(1, 'CB', 'ControlBoard', NULL, 0, 'Off', 'Off', '\r\n\r\n 1\r\n'), +(2, 'W1', 'MettlerToledoBalanceSN', NULL, 1, 'Off', 'Off', '\r\n\r\n 11\r\n 2400\r\n Even\r\n 7\r\n One\r\n XOnXOff\r\n 3000\r\n'), +(3, 'W2', 'MettlerToledoBalanceSN', NULL, 2, 'Off', 'Off', '\r\n\r\n 10\r\n 2400\r\n Even\r\n 7\r\n One\r\n XOnXOff\r\n 150\r\n'), +(4, 'Luft', 'Greco Ambient', NULL, 3, 'Off', 'Off', '\r\n\r\n 6\r\n 19200\r\n None\r\n 8\r\n One\r\n None\r\n'), +(5, 'I1', 'FlowMeter', 'CB', 4, 'Off', 'Off', '\r\n\r\n 1\r\n 200\r\n'), +(6, 'I2', 'FlowMeter', 'CB', 5, 'Off', 'Off', '\r\n\r\n 2\r\n 20\r\n'), +(7, 'I3', 'FlowMeter', 'CB', 6, 'Off', 'Off', '\r\n\r\n 3\r\n 3\r\n'), +(8, 'I4', 'FlowMeter', 'CB', 7, 'Off', 'Off', '\r\n\r\n 4\r\n 0.25\r\n'), +(9, 'Druck1', 'PressureMeter', 'CB', 8, 'Off', 'Off', '\r\n\r\n 0\r\n 78\r\n'), +(10, 'Druck2', 'PressureMeter', 'CB', 9, 'Off', 'Off', '\r\n\r\n 1\r\n 81\r\n'), +(11, 'Druck3', 'PressureMeter', 'CB', 10, 'Off', 'Off', '\r\n\r\n 2\r\n 11\r\n'), +(12, 'Druck4', 'PressureMeter', 'CB', 11, 'Off', 'Off', '\r\n\r\n 3\r\n 82\r\n'), +(13, 'T1', 'TempMeter', 'CB', 12, 'Off', 'Off', '\r\n\r\n 0\r\n -20.14631\r\n 0.00177572737\r\n 7.601795E-10\r\n -1.237E-15\r\n 0\r\n'), +(14, 'T2', 'TempMeter', 'CB', 13, 'Off', 'Off', '\r\n\r\n 1\r\n -20.13342\r\n 0.001777626\r\n 7.41529E-10\r\n -1.066678E-15\r\n 0\r\n'), +(15, 'T3', 'TempMeter', 'CB', 14, 'Off', 'Off', '\r\n\r\n 2\r\n -20.138031\r\n 0.00177645753\r\n 7.68710429E-10\r\n -1.307915E-15\r\n 0\r\n'), +(16, 'T4', 'TempMeter', 'CB', 15, 'Off', 'Off', '\r\n\r\n 3\r\n -20.1234074\r\n 0.00177655893\r\n 7.53911156E-10\r\n 1.13868757E-15\r\n 0\r\n'), +(17, 'T5', 'TempMeter', 'CB', 16, 'Off', 'Off', '\r\n\r\n 4\r\n -20.0712757\r\n 0.00177105656\r\n 9.751451E-10\r\n -3.51362E-15\r\n 0\r\n'), +(18, 'RV1', 'RegulationValve', 'CB', 17, 'Off', 'Off', '\r\n\r\n 1\r\n 100\r\n 500\r\n 10\r\n'), +(19, 'RV2', 'RegulationValve', 'CB', 18, 'Off', 'Off', '\r\n\r\n 2\r\n 100\r\n 500\r\n 3\r\n'), +(20, 'RV3', 'RegulationValve', 'CB', 19, 'Off', 'Off', '\r\n\r\n 3\r\n 100\r\n 500\r\n 10\r\n'), +(21, 'RV4', 'RegulationValve', 'CB', 20, 'Off', 'Off', '\r\n\r\n 4\r\n 100\r\n 500\r\n 30\r\n'), +(22, 'RV5', 'RegulationValve', 'CB', 21, 'Off', 'Off', '\r\n\r\n 5\r\n 100\r\n 500\r\n 10\r\n'), +(23, 'DIV1', 'Diverter', 'CB', 22, 'Off', 'Off', '\r\n\r\n 34\r\n'), +(24, 'DIV2', 'Diverter', 'CB', 23, 'Off', 'Off', '\r\n\r\n 35\r\n'), +(25, 'DIV3', 'Diverter', 'CB', 24, 'Off', 'Off', '\r\n\r\n 36\r\n'), +(26, 'VL11', 'Valve', 'CB', 25, 'Off', 'Off', '\r\n\r\n 0\r\n \r\n false\r\n'), +(27, 'VL13', 'Valve', 'CB', 26, 'Off', 'Off', '\r\n\r\n 1\r\n \r\n false\r\n'), +(28, 'VL21', 'Valve', 'CB', 27, 'Off', 'Off', '\r\n\r\n 2\r\n \r\n false\r\n'), +(29, 'VL23', 'Valve', 'CB', 28, 'Off', 'Off', '\r\n\r\n 3\r\n \r\n false\r\n'), +(30, 'VZ1', 'Valve', 'CB', 29, 'Off', 'Off', '\r\n\r\n 4\r\n \r\n false\r\n'), +(31, 'VP2', 'Valve', 'CB', 30, 'Off', 'Off', '\r\n\r\n 5\r\n \r\n false\r\n'), +(32, 'VP4', 'Valve', 'CB', 31, 'Off', 'Off', '\r\n\r\n 6\r\n \r\n false\r\n'), +(33, 'VP5', 'Valve', 'CB', 32, 'Off', 'Off', '\r\n\r\n 7\r\n \r\n false\r\n'), +(34, 'VP6', 'Valve', 'CB', 33, 'Off', 'Off', '\r\n\r\n 8\r\n \r\n false\r\n'), +(35, 'VL12', 'Valve', 'CB', 34, 'Off', 'Off', '\r\n\r\n 9\r\n \r\n false\r\n'), +(36, 'VL22', 'Valve', 'CB', 35, 'Off', 'Off', '\r\n\r\n 10\r\n \r\n false\r\n'), +(37, 'VI11', 'Valve', 'CB', 36, 'Off', 'Off', '\r\n\r\n 11\r\n \r\n false\r\n'), +(38, 'VI12', 'Valve', 'CB', 37, 'Off', 'Off', '\r\n\r\n 12\r\n \r\n false\r\n'), +(39, 'VI13', 'Valve', 'CB', 38, 'Off', 'Off', '\r\n\r\n 13\r\n \r\n false\r\n'), +(40, 'VI21', 'Valve', 'CB', 39, 'Off', 'Off', '\r\n\r\n 14\r\n \r\n false\r\n'), +(41, 'VI22', 'Valve', 'CB', 40, 'Off', 'Off', '\r\n\r\n 15\r\n \r\n false\r\n'), +(42, 'VI2P', 'Valve', 'CB', 41, 'Off', 'Off', '\r\n\r\n 16\r\n \r\n false\r\n'), +(43, 'VI31', 'Valve', 'CB', 42, 'Off', 'Off', '\r\n\r\n 17\r\n \r\n false\r\n'), +(44, 'VI32', 'Valve', 'CB', 43, 'Off', 'Off', '\r\n\r\n 18\r\n \r\n false\r\n'), +(45, 'VI3P', 'Valve', 'CB', 44, 'Off', 'Off', '\r\n\r\n 19\r\n \r\n false\r\n'), +(46, 'VI41', 'Valve', 'CB', 45, 'Off', 'Off', '\r\n\r\n 20\r\n \r\n false\r\n'), +(47, 'VI42', 'Valve', 'CB', 46, 'Off', 'Off', '\r\n\r\n 21\r\n \r\n false\r\n'), +(48, 'VI43', 'Valve', 'CB', 47, 'Off', 'Off', '\r\n\r\n 22\r\n \r\n false\r\n'), +(49, 'VI4P', 'Valve', 'CB', 48, 'Off', 'Off', '\r\n\r\n 23\r\n \r\n false\r\n'), +(50, 'VB1', 'Valve', 'CB', 49, 'Off', 'Off', '\r\n\r\n 24\r\n \r\n false\r\n'), +(51, 'VB1a', 'Valve', 'CB', 50, 'Off', 'Off', '\r\n\r\n 25\r\n VB1\r\n false\r\n -2\r\n 2\r\n'), +(52, 'VB2', 'Valve', 'CB', 51, 'Off', 'Off', '\r\n\r\n 26\r\n \r\n false\r\n'), +(53, 'VB2a', 'Valve', 'CB', 52, 'Off', 'Off', '\r\n\r\n 27\r\n VB2\r\n false\r\n -2\r\n 2\r\n'), +(54, 'VM1', 'Valve', 'CB', 53, 'Off', 'Off', '\r\n\r\n 28\r\n \r\n false\r\n'), +(55, 'VM2', 'Valve', 'CB', 54, 'Off', 'Off', '\r\n\r\n 29\r\n \r\n false\r\n'), +(56, 'VM3', 'Valve', 'CB', 55, 'Off', 'Off', '\r\n\r\n 30\r\n \r\n false\r\n'), +(57, 'VM4', 'Valve', 'CB', 56, 'Off', 'Off', '\r\n\r\n 31\r\n \r\n false\r\n'), +(58, 'Pumpe1', 'Pump', 'CB', 57, 'Off', 'Off', '\r\n\r\n 32\r\n \r\n false\r\n'), +(59, 'Block', 'Valve', 'CB', 58, 'Off', 'Off', '\r\n\r\n 33\r\n \r\n false\r\n'), +(60, 'VZ8', 'Valve', 'CB', 59, 'Off', 'Off', '\r\n\r\n 37\r\n \r\n false\r\n'), +(61, 'Sick1', 'RegisterReader', 'CB', 60, 'Off', 'Off', '\r\n\r\n 1\r\n'), +(62, 'Sick2', 'RegisterReader', 'CB', 61, 'Off', 'Off', '\r\n\r\n 2\r\n'), +(63, 'Sick3', 'RegisterReader', 'CB', 62, 'Off', 'Off', '\r\n\r\n 3\r\n'), +(64, 'Kamera', 'IdcCamera', NULL, 63, 'Simulate', 'Off', '\r\n\r\n 20\r\n 57600\r\n 0.5\r\n'), +(65, 'Fliegender Start-Stopp', 'Flying-Start-Collection', NULL, 64, 'Off', 'Off', '\r\n'), +(66, 'Verbund', 'CombinedMeters', NULL, 65, 'Off', 'Off', '\r\n'); + +-- -------------------------------------------------------- + +-- +-- Tabellenstruktur für Tabelle `componentprocedure` +-- + +CREATE TABLE IF NOT EXISTS `componentprocedure` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `CmpntName` varchar(255) DEFAULT NULL, + `Parameters` varchar(8000) DEFAULT NULL, + `Procedure_id` int(11) DEFAULT NULL, + PRIMARY KEY (`Id`), + KEY `Procedure_id` (`Procedure_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; + +-- -------------------------------------------------------- + +-- +-- Tabellenstruktur für Tabelle `componenttest` +-- + +CREATE TABLE IF NOT EXISTS `componenttest` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `CmpntName` varchar(255) DEFAULT NULL, + `Parameters` varchar(8000) DEFAULT NULL, + `Test_id` int(11) DEFAULT NULL, + PRIMARY KEY (`Id`), + KEY `Test_id` (`Test_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=5 ; + +-- +-- Daten für Tabelle `componenttest` +-- + +INSERT INTO `componenttest` (`Id`, `CmpntName`, `Parameters`, `Test_id`) VALUES +(1, 'Verbund', '\r\n\r\n 3.05\r\n 3.3\r\n -0.7\r\n -0.5\r\n 0\r\n 0.1\r\n', 29), +(2, 'Verbund', '\r\n\r\n 3.05\r\n 3.3\r\n -0.7\r\n -0.5\r\n 0.05\r\n 0.1\r\n', 30), +(3, 'Verbund', '\r\n\r\n 3.05\r\n 3.3\r\n -0.7\r\n -0.5\r\n 0.05\r\n 0.1\r\n', 31), +(4, 'Verbund', '\r\n\r\n 0.9\r\n 1\r\n -0.7\r\n -0.5\r\n 0.05\r\n 0.1\r\n', 32); + +-- -------------------------------------------------------- + +-- +-- Tabellenstruktur für Tabelle `feedingpath` +-- + +CREATE TABLE IF NOT EXISTS `feedingpath` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `ItemNr` int(11) DEFAULT NULL, + `Name` varchar(255) DEFAULT NULL, + `Qfrom` float DEFAULT NULL, + `Qto` float DEFAULT NULL, + `Pump` varchar(255) DEFAULT NULL, + `ValvesOpen` varchar(8000) DEFAULT NULL, + `ValvesClose` varchar(8000) DEFAULT NULL, + PRIMARY KEY (`Id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=5 ; + +-- +-- Daten für Tabelle `feedingpath` +-- + +INSERT INTO `feedingpath` (`Id`, `ItemNr`, `Name`, `Qfrom`, `Qto`, `Pump`, `ValvesOpen`, `ValvesClose`) VALUES +(1, 1, 'PS1', 0.01, 0.03, '---', 'VZ1', ''), +(2, 3, 'PS2', 0.03, 250, '---', 'VZ1', ''), +(3, 2, 'PS3', 0.01, 5, 'Pumpe1', 'VP2', ''), +(4, 0, '', 0, 0, '---', 'VZ1', 'VL11;VL13;VL21;VL23;VP2;VP4;VP5;VP6;VL12;VL22;VI11;VI12;VI13;VI21;VI22;VI2P;VI31;VI32;VI3P;VI41;VI42;VI43;VI4P;VB1;VB1a;VB2;VB2a;VM1;VM2;VM3;VM4;Pumpe1;Block;VZ8'); + +-- -------------------------------------------------------- + +-- +-- Tabellenstruktur für Tabelle `group` +-- + +CREATE TABLE IF NOT EXISTS `group` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `Gid` int(11) DEFAULT NULL, + `Name` varchar(255) DEFAULT NULL, + `User_id` int(11) DEFAULT NULL, + PRIMARY KEY (`Id`), + KEY `User_id` (`User_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=8 ; + +-- +-- Daten für Tabelle `group` +-- + +INSERT INTO `group` (`Id`, `Gid`, `Name`, `User_id`) VALUES +(1, 0, 'Testers', 2), +(2, 1, 'Testing Specialists', 1), +(3, 2, 'Head Of Lab', 1), +(4, 3, 'Maintenance Specialists', 1), +(5, 4, 'Metrologists', 1), +(6, 5, 'Calibration Specialists', 1), +(7, 6, 'Administrators', 1); + +-- -------------------------------------------------------- + +-- +-- Tabellenstruktur für Tabelle `measurementcorrection` +-- + +CREATE TABLE IF NOT EXISTS `measurementcorrection` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `Measurement` float DEFAULT NULL, + `Correction` float DEFAULT NULL, + `Component_id` int(11) DEFAULT NULL, + PRIMARY KEY (`Id`), + KEY `Component_id` (`Component_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; + +-- -------------------------------------------------------- + +-- +-- Tabellenstruktur für Tabelle `meterspath` +-- + +CREATE TABLE IF NOT EXISTS `meterspath` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `ItemNr` int(11) DEFAULT NULL, + `Name` varchar(255) DEFAULT NULL, + `Qfrom` float DEFAULT NULL, + `Qto` float DEFAULT NULL, + `Sensor1` varchar(255) DEFAULT NULL, + `Sensor2` varchar(255) DEFAULT NULL, + `Sensor3` varchar(255) DEFAULT NULL, + PRIMARY KEY (`Id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ; + +-- +-- Daten für Tabelle `meterspath` +-- + +INSERT INTO `meterspath` (`Id`, `ItemNr`, `Name`, `Qfrom`, `Qto`, `Sensor1`, `Sensor2`, `Sensor3`) VALUES +(1, 0, 'PMess1', 0.01, 300, 'Sick1', 'Sick2', 'Sick3'); + +-- -------------------------------------------------------- + +-- +-- Tabellenstruktur für Tabelle `metertestresult` +-- + +CREATE TABLE IF NOT EXISTS `metertestresult` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `SerialNr` varchar(255) DEFAULT NULL, + `VolumeStart` float DEFAULT NULL, + `VolumeEnd` float DEFAULT NULL, + `VolumeMeter` float DEFAULT NULL, + `VolumeRef` float DEFAULT NULL, + `VolumeErrorPct` float DEFAULT NULL, + `PulsesMeter` float DEFAULT NULL, + `PulsesMaster` float DEFAULT NULL, + `Time` float DEFAULT NULL, + `TestResult_id` int(11) DEFAULT NULL, + PRIMARY KEY (`Id`), + KEY `TestResult_id` (`TestResult_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=352 ; + +-- +-- Daten für Tabelle `metertestresult` +-- + +INSERT INTO `metertestresult` (`Id`, `SerialNr`, `VolumeStart`, `VolumeEnd`, `VolumeMeter`, `VolumeRef`, `VolumeErrorPct`, `PulsesMeter`, `PulsesMaster`, `Time`, `TestResult_id`) VALUES +(1, 'wm1', 0, 0, 142, 200.256, -29.0907, 142, 72051, 45.712, 1), +(2, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.712, 1), +(3, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.712, 1), +(4, 'wm1', 0, 0, 362, 59.9706, 503.629, 362, 143864, 104.98, 2), +(5, 'wm2', 0, 0, 0, 0, -100, 0, 0, 104.98, 2), +(6, 'wm3', 0, 0, 0, 0, -100, 0, 0, 104.98, 2), +(7, 'wm1', 0, 0, 141, 200.27, -29.5951, 141, 72046, 45.705, 3), +(8, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.705, 3), +(9, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.705, 3), +(10, 'wm1', 0, 0, 361, 60.1188, 500.478, 361, 143933, 104.919, 4), +(11, 'wm2', 0, 0, 0, 0, -100, 0, 0, 104.919, 4), +(12, 'wm3', 0, 0, 0, 0, -100, 0, 0, 104.919, 4), +(13, 'wm1', 0, 0, 141, 200.38, -29.6335, 141, 72078, 45.707, 5), +(14, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.707, 5), +(15, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.707, 5), +(16, 'wm1', 0, 0, 362, 60.0895, 502.435, 362, 143850, 104.938, 6), +(17, 'wm2', 0, 0, 0, 0, -100, 0, 0, 104.938, 6), +(18, 'wm3', 0, 0, 0, 0, -100, 0, 0, 104.938, 6), +(19, 'wm1', 0, 0, 5.6, 199.069, -97.1869, 56, 71576, 45.673, 7), +(20, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.673, 7), +(21, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.673, 7), +(25, 'wm1', 0, 0, 1.9, 190.598, -99.0031, 19, 68552, 45.822, 8), +(26, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.822, 8), +(27, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.822, 8), +(28, 'wm1', 0, 0, 1.9, 190.521, -99.0027, 19, 68543, 45.956, 9), +(29, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.956, 9), +(30, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.956, 9), +(31, 'wm1', 0, 0, 190, 190.39, -0.204866, 19, 68517, 45.988, 10), +(32, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.988, 10), +(33, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.988, 10), +(34, 'wm1', 0, 0, 190, 190.643, -0.337179, 19, 68558, 45.839, 11), +(35, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.839, 11), +(36, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.839, 11), +(37, 'wm1', 0, 0, 50, 39.8137, 25.5851, 5, 119374, 99.47, 12), +(38, 'wm2', 0, 0, 0, 0, -100, 0, 0, 99.47, 12), +(39, 'wm3', 0, 0, 0, 0, -100, 0, 0, 99.47, 12), +(40, 'wm1', 0, 0, 190, 190.549, -0.288296, 19, 68558, 45.834, 13), +(41, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.834, 13), +(42, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.834, 13), +(43, 'wm1', 0, 0, 50, 42.4429, 17.8054, 5, 119438, 99.653, 14), +(44, 'wm2', 0, 0, 0, 0, -100, 0, 0, 99.653, 14), +(45, 'wm3', 0, 0, 0, 0, -100, 0, 0, 99.653, 14), +(46, 'wm1', 0, 0, 190, 190.532, -0.279457, 19, 68518, 45.838, 15), +(47, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.838, 15), +(48, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.838, 15), +(49, 'wm1', 0, 0, 50, 42.5645, 17.4688, 5, 119409, 99.689, 16), +(50, 'wm2', 0, 0, 0, 0, -100, 0, 0, 99.689, 16), +(51, 'wm3', 0, 0, 0, 0, -100, 0, 0, 99.689, 16), +(52, 'wm1', 0, 0, 190, 190.678, -0.355387, 19, 68569, 45.876, 17), +(53, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.876, 17), +(54, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.876, 17), +(55, 'wm1', 0, 0, 190, 190.508, -0.266501, 19, 68525, 45.844, 18), +(56, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.844, 18), +(57, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.844, 18), +(58, 'wm1', 0, 0, 200, 200.696, -0.346793, 20, 72203, 45.812, 19), +(59, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.812, 19), +(60, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.812, 19), +(61, 'wm1', 0, 0, 190, 190.62, -0.32514, 19, 68555, 45.85, 20), +(62, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.85, 20), +(63, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.85, 20), +(64, 'wm1', 0, 0, 190, 190.701, -0.36741, 19, 68578, 45.85, 21), +(65, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.85, 21), +(66, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.85, 21), +(67, 'wm1', 0, 0, 190, 191.073, -0.561429, 19, 68623, 45.841, 22), +(68, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.841, 22), +(69, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.841, 22), +(70, 'wm1', 0, 0, 190, 190.796, -0.416979, 19, 68502, 45.864, 23), +(71, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.864, 23), +(72, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.864, 23), +(73, 'wm1', 0, 0, 190, 190.875, -0.458495, 19, 68548, 45.842, 24), +(74, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.842, 24), +(75, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.842, 24), +(76, 'wm1', 0, 0, 190, 190.967, -0.506622, 19, 68554, 45.847, 25), +(77, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.847, 25), +(78, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.847, 25), +(79, 'wm1', 0, 0, 190, 190.841, -0.4405, 19, 68537, 45.837, 26), +(80, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.837, 26), +(81, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.837, 26), +(82, 'wm1', 0, 0, 50, 50.0062, -0.0123505, 5, 119527, 99.841, 27), +(83, 'wm2', 0, 0, 0, 0, -100, 0, 0, 99.841, 27), +(84, 'wm3', 0, 0, 0, 0, -100, 0, 0, 99.841, 27), +(85, 'wm1', 0, 0, 50, 50.0312, -0.0623848, 5, 119563, 99.871, 28), +(86, 'wm2', 0, 0, 0, 0, -100, 0, 0, 99.871, 28), +(87, 'wm3', 0, 0, 0, 0, -100, 0, 0, 99.871, 28), +(88, 'wm1', 0, 0, 50, -113.154, -100, 5, 119370, 87.146, 29), +(89, 'wm2', 0, 0, 0, 0, -100, 0, 0, 87.146, 29), +(90, 'wm3', 0, 0, 0, 0, -100, 0, 0, 87.146, 29), +(91, 'wm1', 0, 0, 0, 19.0219, -100, 8, 6841, 64.05, 30), +(92, 'wm2', 0, 0, 0, 0, -100, 0, 0, 64.05, 30), +(93, 'wm3', 0, 0, 0, 0, -100, 0, 0, 64.05, 30), +(94, 'wm1', 0, 0, 0, 14.8243, -100, 3, 5327, 64.246, 31), +(95, 'wm2', 0, 0, 0, 0, -100, 0, 0, 64.246, 31), +(96, 'wm3', 0, 0, 0, 0, -100, 0, 0, 64.246, 31), +(97, 'wm1', 0, 0, 0, 14.7066, -100, 3, 5276, 64.346, 32), +(98, 'wm2', 0, 0, 0, 0, -100, 0, 0, 64.346, 32), +(99, 'wm3', 0, 0, 0, 0, -100, 0, 0, 64.346, 32), +(100, 'wm1', 0, 0, 0, 17.0307, -100, 4, 6120, 64.316, 33), +(101, 'wm2', 0, 0, 0, 0, -100, 0, 0, 64.316, 33), +(102, 'wm3', 0, 0, 0, 0, -100, 0, 0, 64.316, 33), +(103, 'wm1', 0, 0, 0, 14.9433, -100, 5, 5361, 64.328, 34), +(104, 'wm2', 0, 0, 0, 0, -100, 0, 0, 64.328, 34), +(105, 'wm3', 0, 0, 0, 0, -100, 0, 0, 64.328, 34), +(106, 'wm1', 0, 0, 0, 35.6131, -100, 34, 12773, 71.015, 35), +(107, 'wm2', 0, 0, 0, 0, -100, 0, 0, 71.015, 35), +(108, 'wm3', 0, 0, 0, 0, -100, 0, 0, 71.015, 35), +(109, 'wm1', 0, 0, 0, 37.8982, -100, 33, 13603, 71.007, 36), +(110, 'wm2', 0, 0, 0, 0, -100, 0, 0, 71.007, 36), +(111, 'wm3', 0, 0, 0, 0, -100, 0, 0, 71.007, 36), +(112, 'wm1', 0, 0, 0, 39.3708, -100, 28, 14121, 71.024, 37), +(113, 'wm2', 0, 0, 0, 0, -100, 0, 0, 71.024, 37), +(114, 'wm3', 0, 0, 0, 0, -100, 0, 0, 71.024, 37), +(115, 'wm1', 0, 0, 0, 38.3891, -100, 29, 13768, 71.021, 38), +(116, 'wm2', 0, 0, 0, 0, -100, 0, 0, 71.021, 38), +(117, 'wm3', 0, 0, 0, 0, -100, 0, 0, 71.021, 38), +(118, 'wm1', 0, 0, 0, 39.7502, -100, 32, 14268, 71.013, 39), +(119, 'wm2', 0, 0, 0, 0, -100, 0, 0, 71.013, 39), +(120, 'wm3', 0, 0, 0, 0, -100, 0, 0, 71.013, 39), +(121, 'wm1', 0, 0, 0, 59.1279, -100, 42, 21226, 69.587, 40), +(122, 'wm2', 0, 0, 0, 0, -100, 0, 0, 69.587, 40), +(123, 'wm3', 0, 0, 0, 0, -100, 0, 0, 69.587, 40), +(124, 'wm1', 0, 0, 0, 58.214, -100, 42, 20898, 69.564, 41), +(125, 'wm2', 0, 0, 0, 0, -100, 0, 0, 69.564, 41), +(126, 'wm3', 0, 0, 0, 0, -100, 0, 0, 69.564, 41), +(127, 'wm1', 0, 0, 0, 59.3587, -100, 43, 21309, 69.548, 42), +(128, 'wm2', 0, 0, 0, 0, -100, 0, 0, 69.548, 42), +(129, 'wm3', 0, 0, 0, 0, -100, 0, 0, 69.548, 42), +(130, 'wm1', 0, 0, 0, 58.2055, -100, 46, 20895, 69.524, 43), +(131, 'wm2', 0, 0, 0, 0, -100, 0, 0, 69.524, 43), +(132, 'wm3', 0, 0, 0, 0, -100, 0, 0, 69.524, 43), +(133, 'wm1', 0, 0, 0, 59.1874, -100, 43, 21230, 69.545, 44), +(134, 'wm2', 0, 0, 0, 0, -100, 0, 0, 69.545, 44), +(135, 'wm3', 0, 0, 0, 0, -100, 0, 0, 69.545, 44), +(136, 'wm1', 0, 0, 0, 79.3873, -100, 59, 28489, 69.226, 45), +(137, 'wm2', 0, 0, 0, 0, -100, 0, 0, 69.226, 45), +(138, 'wm3', 0, 0, 0, 0, -100, 0, 0, 69.226, 45), +(139, 'wm1', 0, 0, 0, 79.5877, -100, 54, 28566, 69.211, 46), +(140, 'wm2', 0, 0, 0, 0, -100, 0, 0, 69.211, 46), +(141, 'wm3', 0, 0, 0, 0, -100, 0, 0, 69.211, 46), +(142, 'wm1', 0, 0, 0, 78.178, -100, 57, 28060, 69.281, 47), +(143, 'wm2', 0, 0, 0, 0, -100, 0, 0, 69.281, 47), +(144, 'wm3', 0, 0, 0, 0, -100, 0, 0, 69.281, 47), +(145, 'wm1', 0, 0, 0, 79.4592, -100, 55, 28520, 69.18, 48), +(146, 'wm2', 0, 0, 0, 0, -100, 0, 0, 69.18, 48), +(147, 'wm3', 0, 0, 0, 0, -100, 0, 0, 69.18, 48), +(148, 'wm1', 0, 0, 0, 79.4478, -100, 60, 28510, 69.189, 49), +(149, 'wm2', 0, 0, 0, 0, -100, 0, 0, 69.189, 49), +(150, 'wm3', 0, 0, 0, 0, -100, 0, 0, 69.189, 49), +(151, 'wm1', 0, 0, 0, 119.112, -100, 85, 42785, 72.154, 50), +(152, 'wm2', 0, 0, 0, 0, -100, 0, 0, 72.154, 50), +(153, 'wm3', 0, 0, 0, 0, -100, 0, 0, 72.154, 50), +(154, 'wm1', 0, 0, 0, 119.29, -100, 85, 42845, 71.198, 51), +(155, 'wm2', 0, 0, 0, 0, -100, 0, 0, 71.198, 51), +(156, 'wm3', 0, 0, 0, 0, -100, 0, 0, 71.198, 51), +(157, 'wm1', 0, 0, 0, 119.209, -100, 86, 42822, 71.207, 52), +(158, 'wm2', 0, 0, 0, 0, -100, 0, 0, 71.207, 52), +(159, 'wm3', 0, 0, 0, 0, -100, 0, 0, 71.207, 52), +(160, 'wm1', 0, 0, 0, 119.434, -100, 87, 42891, 71.225, 53), +(161, 'wm2', 0, 0, 0, 0, -100, 0, 0, 71.225, 53), +(162, 'wm3', 0, 0, 0, 0, -100, 0, 0, 71.225, 53), +(163, 'wm1', 0, 0, 0, 119.206, -100, 87, 42826, 71.469, 54), +(164, 'wm2', 0, 0, 0, 0, -100, 0, 0, 71.469, 54), +(165, 'wm3', 0, 0, 0, 0, -100, 0, 0, 71.469, 54), +(166, 'wm1', 0, 0, 1410, 200.559, 603.034, 141, 7203, 44.567, 55), +(167, 'wm2', 0, 0, 0, 0, -100, 0, 0, 44.567, 55), +(168, 'wm3', 0, 0, 0, 0, -100, 0, 0, 44.567, 55), +(169, 'wm1', 0, 0, 1410, 200.571, 602.991, 141, 72032, 45.788, 56), +(170, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.788, 56), +(171, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.788, 56), +(172, 'wm1', 0, 0, 1400, 187.698, 645.881, 140, 71532, 45.616, 57), +(173, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.616, 57), +(174, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.616, 57), +(175, 'wm1', 0, 0, 1430, 186.342, 667.405, 143, 72077, 45.594, 58), +(176, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.594, 58), +(177, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.594, 58), +(178, 'wm1', 0, 0, 1420, 186.346, 662.024, 142, 72081, 45.602, 59), +(179, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.602, 59), +(180, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.602, 59), +(181, 'wm1', 0, 0, 1430, 200.703, 612.496, 143, 72079, 45.59, 60), +(182, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.59, 60), +(183, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.59, 60), +(184, 'wm1', 0, 0, 0, 989.503, -100, 705, 359760, 227.074, 61), +(185, 'wm2', 0, 0, 0, 0, -100, 0, 0, 227.074, 61), +(186, 'wm3', 0, 0, 0, 0, -100, 0, 0, 227.074, 61), +(187, 'wm1', 0, 0, 0, 1001.3, -100, 705, 359717, 227.025, 62), +(188, 'wm2', 0, 0, 0, 0, -100, 0, 0, 227.025, 62), +(189, 'wm3', 0, 0, 0, 0, -100, 0, 0, 227.025, 62), +(190, 'wm1', 0, 0, 0, 1002.82, -100, 705, 360253, 227.033, 63), +(191, 'wm2', 0, 0, 0, 0, -100, 0, 0, 227.033, 63), +(192, 'wm3', 0, 0, 0, 0, -100, 0, 0, 227.033, 63), +(193, 'wm1', 0, 0, 0, 1001.29, -100, 704, 359646, 227.044, 64), +(194, 'wm2', 0, 0, 0, 0, -100, 0, 0, 227.044, 64), +(195, 'wm3', 0, 0, 0, 0, -100, 0, 0, 227.044, 64), +(196, 'wm1', 0, 0, 0, 1002.58, -100, 705, 360167, 227.036, 65), +(197, 'wm2', 0, 0, 0, 0, -100, 0, 0, 227.036, 65), +(198, 'wm3', 0, 0, 0, 0, -100, 0, 0, 227.036, 65), +(199, 'wm1', 0, 0, 0, 1001.43, -100, 704, 359748, 227.023, 66), +(200, 'wm2', 0, 0, 0, 0, -100, 0, 0, 227.023, 66), +(201, 'wm3', 0, 0, 0, 0, -100, 0, 0, 227.023, 66), +(202, 'wm1', 0, 0, 1000, 1001.3, -0.130122, 704, 359716, 227.032, 67), +(203, 'wm2', 0, 0, 0, 0, -100, 0, 0, 227.032, 67), +(204, 'wm3', 0, 0, 0, 0, -100, 0, 0, 227.032, 67), +(205, 'wm1', 0, 0, 1001.42, 1002.83, -0.140678, 705, 360271, 227.041, 68), +(206, 'wm2', 0, 0, 0, 0, -100, 0, 0, 227.041, 68), +(207, 'wm3', 0, 0, 0, 0, -100, 0, 0, 227.041, 68), +(208, 'wm1', 0, 0, 1000, 1001.36, -0.135966, 704, 359725, 227.076, 69), +(209, 'wm2', 0, 0, 0, 0, -100, 0, 0, 227.076, 69), +(210, 'wm3', 0, 0, 0, 0, -100, 0, 0, 227.076, 69), +(211, 'wm1', 0, 0, 1000, 1001.25, -0.125136, 704, 359693, 227.051, 70), +(212, 'wm2', 0, 0, 0, 0, -100, 0, 0, 227.051, 70), +(213, 'wm3', 0, 0, 0, 0, -100, 0, 0, 227.051, 70), +(214, 'wm1', 0, 0, 1000, 1001.2, -0.119632, 704, 359685, 227.011, 71), +(215, 'wm2', 0, 0, 0, 0, -100, 0, 0, 227.011, 71), +(216, 'wm3', 0, 0, 0, 0, -100, 0, 0, 227.011, 71), +(217, 'wm1', 0, 0, 99.4318, 98.3085, 1.14262, 70, 235168, 348.14, 72), +(218, 'wm2', 0, 0, 0, 0, -100, 0, 0, 348.14, 72), +(219, 'wm3', 0, 0, 0, 0, -100, 0, 0, 348.14, 72), +(220, 'wm1', 0, 0, 99.4318, 98.2879, 1.16382, 70, 235024, 347.978, 73), +(221, 'wm2', 0, 0, 0, 0, -100, 0, 0, 347.978, 73), +(222, 'wm3', 0, 0, 0, 0, -100, 0, 0, 347.978, 73), +(223, 'wm1', 0, 0, 100.852, 99.8041, 1.05024, 71, 238677, 347.982, 74), +(224, 'wm2', 0, 0, 0, 0, -100, 0, 0, 347.982, 74), +(225, 'wm3', 0, 0, 0, 0, -100, 0, 0, 347.982, 74), +(226, 'wm1', 0, 0, 113.636, 98.5252, 15.3374, 80, 235575, 348.083, 75), +(227, 'wm2', 0, 0, 0, 0, -100, 0, 0, 348.083, 75), +(228, 'wm3', 0, 0, 0, 0, -100, 0, 0, 348.083, 75), +(229, 'wm1', 0, 0, 166.193, 99.9431, 66.2878, 117, 238973, 348.062, 76), +(230, 'wm2', 0, 0, 0, 0, -100, 0, 0, 348.062, 76), +(231, 'wm3', 0, 0, 0, 0, -100, 0, 0, 348.062, 76), +(232, 'wm1', 0, 0, 1410, 200.627, 602.798, 141, 72052, 45.611, 77), +(233, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.611, 77), +(234, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.611, 77), +(235, 'wm1', 0, 0, 1000, 1001.49, -0.149094, 704, 359781, 227.05, 78), +(236, 'wm2', 0, 0, 0, 0, -100, 0, 0, 227.05, 78), +(237, 'wm3', 0, 0, 0, 0, -100, 0, 0, 227.05, 78), +(238, 'wm1', 0, 0, 1000, 1001.43, -0.142637, 704, 359761, 227.05, 79), +(239, 'wm2', 0, 0, 0, 0, -100, 0, 0, 227.05, 79), +(240, 'wm3', 0, 0, 0, 0, -100, 0, 0, 227.05, 79), +(241, 'wm1', 0, 0, 1002.84, 1001.4, 0.143683, 706, 359700, 227.053, 80), +(242, 'wm2', 0, 0, 0, 0, -100, 0, 0, 227.053, 80), +(243, 'wm3', 0, 0, 0, 0, -100, 0, 0, 227.053, 80), +(244, 'wm1', 0, 0, 1000, 1001.56, -0.155696, 704, 359828, 227.003, 81), +(245, 'wm2', 0, 0, 0, 0, -100, 0, 0, 227.003, 81), +(246, 'wm3', 0, 0, 0, 0, -100, 0, 0, 227.003, 81), +(247, 'wm1', 0, 0, 1000, 1001.35, -0.135193, 704, 359701, 227.042, 82), +(248, 'wm2', 0, 0, 0, 0, -100, 0, 0, 227.042, 82), +(249, 'wm3', 0, 0, 0, 0, -100, 0, 0, 227.042, 82), +(250, 'wm1', 0, 0, 99.4318, 98.314, 1.13703, 70, 235067, 349.559, 83), +(251, 'wm2', 0, 0, 0, 0, -100, 0, 0, 349.559, 83), +(252, 'wm3', 0, 0, 0, 0, -100, 0, 0, 349.559, 83), +(253, 'wm1', 0, 0, 99.4318, 98.2718, 1.18042, 70, 234977, 349.421, 84), +(254, 'wm2', 0, 0, 0, 0, -100, 0, 0, 349.421, 84), +(255, 'wm3', 0, 0, 0, 0, -100, 0, 0, 349.421, 84), +(256, 'wm1', 0, 0, 100.852, 99.7588, 1.09611, 71, 238564, 349.376, 85), +(257, 'wm2', 0, 0, 0, 0, -100, 0, 0, 349.376, 85), +(258, 'wm3', 0, 0, 0, 0, -100, 0, 0, 349.376, 85), +(259, 'wm1', 0, 0, 99.4318, 98.4383, 1.00923, 70, 235362, 349.416, 86), +(260, 'wm2', 0, 0, 0, 0, -100, 0, 0, 349.416, 86), +(261, 'wm3', 0, 0, 0, 0, -100, 0, 0, 349.416, 86), +(262, 'wm1', 0, 0, 100.852, 99.8505, 1.00323, 71, 238786, 349.366, 87), +(263, 'wm2', 0, 0, 0, 0, -100, 0, 0, 349.366, 87), +(264, 'wm3', 0, 0, 0, 0, -100, 0, 0, 349.366, 87), +(265, 'wm1', 0, 0, 1065.34, 0, -100, 750, 360027, 227.383, 88), +(266, 'wm2', 0, 0, 0, 0, -100, 0, 0, 227.383, 88), +(267, 'wm3', 0, 0, 0, 0, -100, 0, 0, 227.383, 88), +(268, 'wm1', 0, 0, 1410, 200.609, 602.86, 141, 72048, 45.529, 89), +(269, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.529, 89), +(270, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.529, 89), +(271, 'wm1', 0, 0, 1420, 199.108, 613.18, 142, 71515, 45.508, 90), +(272, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.508, 90), +(273, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.508, 90), +(274, 'wm1', 0, 0, 1420, 200.65, 607.699, 142, 72044, 45.525, 91), +(275, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.525, 91), +(276, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.525, 91), +(277, 'wm1', 0, 0, 1420, 200.581, 607.943, 142, 72038, 45.531, 92), +(278, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.531, 92), +(279, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.531, 92), +(280, 'wm1', 0, 0, 1400, 199.228, 602.713, 140, 71552, 45.516, 93), +(281, 'wm2', 0, 0, 0, 0, -100, 0, 0, 45.516, 93), +(282, 'wm3', 0, 0, 0, 0, -100, 0, 0, 45.516, 93), +(283, 'wm1', 0, 0, 1800, 200.088, 799.605, 180, 71883, 51.546, 94), +(284, 'wm2', 0, 0, 13620, 201.24, 6668.03, 1362, 72297, 51.546, 94), +(285, 'wm3', 0, 0, 0, 0, -100, 0, 0, 51.546, 94), +(286, 'wm1', 0, 0, 1803.5, 201.596, 0, 179, 71845, 47.865, 95), +(287, 'wm2', 0, 0, 0, 201.596, 0, 1424, 72366, 47.865, 95), +(288, NULL, 0, 0, 1803.5, 201.596, -100, 0, 0, 47.865, 95), +(289, 'wm1', 0, 0, 543.097, 602.379, 0, 542, 215922, 153.747, 96), +(290, 'wm2', 0, 0, 59.7737, 602.379, 0, 4029, 216302, 153.747, 96), +(291, NULL, 0, 0, 602.871, 602.379, -100, 0, 0, 153.747, 96), +(292, 'wm1', 0, 0, 161.217, 200.829, 0, 160, 71536, 228.42, 97), +(293, 'wm2', 0, 0, 40.1069, 200.829, 0, 2703, 72051, 228.42, 97), +(294, NULL, 0, 0, 201.324, 200.829, -100, 0, 0, 228.42, 97), +(295, 'wm1', 0, 0, 539.861, 602.315, 0, 539, 216039, 143.349, 98), +(296, 'wm2', 0, 0, 62.3862, 602.315, 0, 4205, 216322, 143.349, 98), +(297, NULL, 0, 0, 602.247, 602.315, -100, 0, 0, 143.349, 98), +(298, 'wm1', 0, 0, 162.342, 200.79, 0, 161, 71484, 228.798, 99), +(299, 'wm2', 0, 0, 39.6096, 200.79, 0, 2669, 72038, 228.798, 99), +(300, NULL, 0, 0, 201.952, 200.79, -100, 0, 0, 228.798, 99), +(301, 'wm1', 0, 0, 0, 100.469, 0, 0, 16776800, 306.062, 100), +(302, 'wm2', 0, 0, 99.1319, 100.469, 0, 6683, 240176, 306.062, 100), +(303, NULL, 0, 0, 99.1319, 100.469, -100, 0, 0, 306.062, 100), +(304, 'wm1', 0, 0, 64.0209, 100.63, 0, 63, 236649, 125.141, 101), +(305, 'wm2', 0, 0, 37.3474, 100.63, 0, 2517, 240385, 125.141, 101), +(306, NULL, 0, 0, 101.368, 100.63, -100, 0, 0, 125.141, 101), +(307, 'wm1', 0, 0, 540.281, 602.188, 0, 539, 215872, 143.575, 102), +(308, 'wm2', 0, 0, 61.8944, 602.188, 0, 4172, 216331, 143.575, 102), +(309, NULL, 0, 0, 602.175, 602.188, -100, 0, 0, 143.575, 102), +(310, 'wm1', 0, 0, 160.017, 200.86, 0, 159, 71622, 229.251, 103), +(311, 'wm2', 0, 0, 39.8327, 200.86, 0, 2684, 72037, 229.251, 103), +(312, NULL, 0, 0, 199.849, 200.86, -100, 0, 0, 229.251, 103), +(313, 'wm1', 0, 0, 0, 100.438, 0, 0, 16776900, 338.589, 104), +(314, 'wm2', 0, 0, 99.0655, 100.438, 0, 6678, 240137, 338.589, 104), +(315, NULL, 0, 0, 99.0655, 100.438, -100, 0, 0, 338.589, 104), +(316, 'wm1', 0, 0, 63.1665, 100.639, 0, 62, 236049, 124.339, 105), +(317, 'wm2', 0, 0, 37.3833, 100.639, 0, 2519, 240351, 124.339, 105), +(318, NULL, 0, 0, 100.55, 100.639, -100, 0, 0, 124.339, 105), +(319, 'wm1', 0, 0, 539.968, 602.378, 0, 539, 215998, 143.511, 106), +(320, 'wm2', 0, 0, 62.1642, 602.378, 0, 4191, 216374, 143.511, 106), +(321, NULL, 0, 0, 602.132, 602.378, -100, 0, 0, 143.511, 106), +(322, 'wm1', 0, 0, 160.774, 200.842, 0, 160, 71733, 229.662, 107), +(323, 'wm2', 0, 0, 40.1103, 200.842, 0, 2703, 72045, 229.662, 107), +(324, NULL, 0, 0, 200.884, 200.842, -100, 0, 0, 229.662, 107), +(325, 'wm1', 0, 0, 541.727, 602.268, 0, 540, 215697, 142.272, 108), +(326, 'wm2', 0, 0, 61.7283, 602.268, 0, 4161, 216343, 142.272, 108), +(327, NULL, 0, 0, 603.456, 602.268, -100, 0, 0, 142.272, 108), +(328, 'wm1', 0, 0, 161.883, 200.809, 0, 161, 71688, 227.334, 109), +(329, 'wm2', 0, 0, 39.8706, 200.809, 0, 2687, 72050, 227.334, 109), +(330, NULL, 0, 0, 201.753, 200.809, -100, 0, 0, 227.334, 109), +(331, 'wm1', 0, 0, 0, 100.452, 0, 0, 16777200, 303.052, 110), +(332, 'wm2', 0, 0, 99.1244, 100.452, 0, 6683, 240196, 303.052, 110), +(333, NULL, 0, 0, 99.1244, 100.452, -100, 0, 0, 303.052, 110), +(334, 'wm1', 0, 0, 59.9333, 100.63, 0, 59, 236755, 123.913, 111), +(335, 'wm2', 0, 0, 39.6961, 100.63, 0, 2676, 240465, 123.913, 111), +(336, NULL, 0, 0, 99.6293, 100.63, -100, 0, 0, 123.913, 111), +(337, 'wm1', 0, 0, 557.026, 601.566, 0, 556, 215744, 141.812, 112), +(338, 'wm2', 0, 0, 44.2035, 601.566, 0, 2980, 216121, 141.812, 112), +(339, NULL, 0, 0, 601.229, 601.566, -100, 0, 0, 141.812, 112), +(340, 'wm1', 0, 0, 540.17, 573.441, 0, 539, 215673, 141.843, 113), +(341, 'wm2', 0, 0, 61.4893, 573.441, 0, 4145, 216103, 141.843, 113), +(342, NULL, 0, 0, 601.659, 573.441, -100, 0, 0, 141.843, 113), +(343, 'wm1', 0, 0, 163.388, 200.576, 0, 163, 71857, 227.385, 114), +(344, 'wm2', 0, 0, 38.3645, 200.576, 0, 2586, 72011, 227.385, 114), +(345, NULL, 0, 0, 201.752, 200.576, -100, 0, 0, 227.385, 114), +(346, 'wm1', 0, 0, 0, 100.307, 0, 0, 16777100, 327.749, 115), +(347, 'wm2', 0, 0, 99.0589, 100.307, 0, 6678, 240098, 327.749, 115), +(348, NULL, 0, 0, 99.0589, 100.307, -100, 0, 0, 327.749, 115), +(349, 'wm1', 0, 0, 52.1295, 100.396, 0, 52, 239733, 124.195, 116), +(350, 'wm2', 0, 0, 47.3139, 100.396, 0, 3189, 240255, 124.195, 116), +(351, NULL, 0, 0, 99.4434, 100.396, -100, 0, 0, 124.195, 116); + +-- -------------------------------------------------------- + +-- +-- Tabellenstruktur für Tabelle `outputpath` +-- + +CREATE TABLE IF NOT EXISTS `outputpath` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `ItemNr` int(11) DEFAULT NULL, + `Name` varchar(255) DEFAULT NULL, + `Qfrom` float DEFAULT NULL, + `Qto` float DEFAULT NULL, + `RegulValve` varchar(255) DEFAULT NULL, + `FlowMeter` varchar(255) DEFAULT NULL, + `Diverter` varchar(255) DEFAULT NULL, + `TempDiv` varchar(255) DEFAULT NULL, + `Balance` varchar(255) DEFAULT NULL, + `EmptyTankValve` varchar(255) DEFAULT NULL, + `ValvesOpen` varchar(8000) DEFAULT NULL, + `ValvesClose` varchar(8000) DEFAULT NULL, + PRIMARY KEY (`Id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=8 ; + +-- +-- Daten für Tabelle `outputpath` +-- + +INSERT INTO `outputpath` (`Id`, `ItemNr`, `Name`, `Qfrom`, `Qto`, `RegulValve`, `FlowMeter`, `Diverter`, `TempDiv`, `Balance`, `EmptyTankValve`, `ValvesOpen`, `ValvesClose`) VALUES +(1, 1, 'PQ1', 0.01, 0.75, 'RV4', 'I4', 'DIV3', 'T5', 'W2', 'VB2', 'VI41;VI42', ''), +(2, 2, 'PQ2', 0.075, 0.18, 'RV5', 'I4', 'DIV3', 'T5', 'W2', 'VB2', 'VI41;VI43', ''), +(3, 3, 'PQ3', 0.18, 3, 'RV3', 'I3', 'DIV2', 'T3', 'W2', 'VB2', 'VI31;VI32', ''), +(4, 4, 'PQ4', 3, 19, 'RV2', 'I2', 'DIV1', 'T4', 'W1', 'VB1', 'VI13;VI21;VI22', ''), +(5, 5, 'PQ5', 19, 160, 'RV1', 'I1', 'DIV1', 'T4', 'W1', 'VB1', 'VI11;VI13', 'VI12'), +(6, 6, 'PQ6', 160, 210, 'RV1', 'I1', 'DIV1', 'T4', 'W1', 'VB1', 'VI11;VI12;VI13', ''), +(7, 0, '', 0, 0, '---', '---', '---', '---', '---', '---', '', ''); + +-- -------------------------------------------------------- + +-- +-- Tabellenstruktur für Tabelle `procedure` +-- + +CREATE TABLE IF NOT EXISTS `procedure` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `ItemNr` int(11) DEFAULT NULL, + `Name` varchar(255) DEFAULT NULL, + `Description` varchar(255) DEFAULT NULL, + `CreationUser` varchar(255) DEFAULT NULL, + `CreationTime` datetime DEFAULT NULL, + `LastChgUser` varchar(255) DEFAULT NULL, + `LastChgTime` datetime DEFAULT NULL, + `LongDescription` varchar(255) DEFAULT NULL, + `Watermeters` varchar(255) DEFAULT NULL, + `PulsesPerLtr` float DEFAULT '0', + `PulsesPerLtr2` float DEFAULT '0', + `DataEntry` varchar(255) DEFAULT NULL, + `ResultsPrinter` varchar(255) DEFAULT NULL, + `ResultsWriter` varchar(255) DEFAULT NULL, + PRIMARY KEY (`Id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=16 ; + +-- +-- Daten für Tabelle `procedure` +-- + +INSERT INTO `procedure` (`Id`, `ItemNr`, `Name`, `Description`, `CreationUser`, `CreationTime`, `LastChgUser`, `LastChgTime`, `LongDescription`, `Watermeters`, `PulsesPerLtr`, `PulsesPerLtr2`, `DataEntry`, `ResultsPrinter`, `ResultsWriter`) VALUES +(7, 0, 'Prüfung1', 'test1 meistream50', 'admin', '2014-01-21 08:21:49', 'admin', '2014-01-23 18:09:43', '', '', 0.1, 0, NULL, NULL, NULL), +(8, 1, 'Prüfung2', '', 'admin', '2014-01-21 14:46:58', 'admin', '2014-01-23 14:23:32', '', '', 1, 0, NULL, NULL, NULL), +(10, 2, 'Test 1', 'Karsten Test meistream50', 'admin', '2014-01-22 14:42:31', 'admin', '2014-01-23 14:23:45', '', '', 1, 0, NULL, NULL, NULL), +(11, 3, 'TestIgor', 'flowrates', 'admin', '2014-01-22 15:38:37', 'admin', '2014-01-23 14:23:58', '', '', 0, 0, NULL, NULL, NULL), +(12, 4, 'Prüfung3', 'bigline', 'admin', '2014-01-22 16:55:21', 'admin', '2014-01-23 14:24:30', '', '', 0.1, 0, NULL, NULL, NULL), +(13, 5, 'TEST VERIFICATION', '', 'admin', '2014-01-23 09:20:49', 'admin', '2014-01-23 16:38:55', '', '', 0.704, 0, NULL, NULL, NULL), +(14, 6, 'Prüfung4', '', 'admin', '2014-01-24 08:51:59', 'admin', '2014-01-24 14:23:00', '', '', 1, 67.422, NULL, NULL, NULL), +(15, 7, 'Prüfung5', '', 'admin', '2014-01-24 13:39:20', 'admin', '2014-01-24 13:44:29', '', '', 0, 0, NULL, NULL, NULL); + +-- -------------------------------------------------------- + +-- +-- Tabellenstruktur für Tabelle `purgeend` +-- + +CREATE TABLE IF NOT EXISTS `purgeend` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `ItemNr` int(11) DEFAULT NULL, + `Duration` int(11) DEFAULT NULL, + `ValvesOpen` varchar(8000) DEFAULT NULL, + `ValvesClose` varchar(8000) DEFAULT NULL, + `RegulValvesPct` varchar(255) NOT NULL DEFAULT ';;;;', + `Procedure_id` int(11) DEFAULT NULL, + PRIMARY KEY (`Id`), + KEY `Procedure_id` (`Procedure_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ; + +-- +-- Daten für Tabelle `purgeend` +-- + +INSERT INTO `purgeend` (`Id`, `ItemNr`, `Duration`, `ValvesOpen`, `ValvesClose`, `RegulValvesPct`, `Procedure_id`) VALUES +(1, 0, 5, '', '', '10;20;30;40;50', 7); + +-- -------------------------------------------------------- + +-- +-- Tabellenstruktur für Tabelle `purgestart` +-- + +CREATE TABLE IF NOT EXISTS `purgestart` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `ItemNr` int(11) DEFAULT NULL, + `Duration` int(11) DEFAULT NULL, + `ValvesOpen` varchar(8000) DEFAULT NULL, + `ValvesClose` varchar(8000) DEFAULT NULL, + `RegulValvesPct` varchar(255) NOT NULL DEFAULT ';;;;', + `Procedure_id` int(11) DEFAULT NULL, + PRIMARY KEY (`Id`), + KEY `Procedure_id` (`Procedure_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=25 ; + +-- +-- Daten für Tabelle `purgestart` +-- + +INSERT INTO `purgestart` (`Id`, `ItemNr`, `Duration`, `ValvesOpen`, `ValvesClose`, `RegulValvesPct`, `Procedure_id`) VALUES +(1, 1, 10, 'VL13;VZ1;VL12;VI11;VI12;VI13;VI21;VI22;VI31;VI32;VI41;VI42;VI43;VB1;VB1a;VB2;VB2a', 'VL21', '50;40;30;20;10', 7), +(2, 0, 10, 'VL13;VZ1;VL12;VI11;VI12;VI13;VI21;VI22;VI31;VI32;VI41;VI42;VI43;VB1;VB1a;VB2;VB2a', 'VL21', '0;0;0;0;0', 7), +(3, 2, 10, 'VL11;VZ1;VL12;VI11;VI12;VI13;VI21;VI22;VI31;VI32;VI41;VI42;VI43;VB1;VB1a;VB2;VB2a', 'VL13;VL21', '0;0;0;0;0', 7), +(4, 3, 5, 'VZ1', 'VL11;VL13;VL21;VL12;VI11;VI12;VI13;VI21;VI22;VI31;VI32;VI41;VI42;VI43;VB1;VB1a;VB2;VB2a', '0;0;0;0;0', 7), +(5, 0, 5, '', '', '0;0;0;0;0', 11), +(6, 0, 20, 'VL13;VZ1;VL12;VI11;VI12;VI13;VI21;VI22;VI31;VI32;VI41;VI42;VI43;VB1;VB2', '', '5;5;5;5;5', 13), +(7, 1, 10, 'VL13;VZ1;VL12;VI11;VI12;VI32', 'VL11', '0;0;0;0;0', 13), +(8, 2, 5, 'VL11;VL13;VZ1;VL12;VI11;VI12;VI32', '', '0;0;0;0;0', 13), +(9, 3, 10, 'VL11;VL13;VZ1;VI11;VI12', 'VL12', '0;0;0;0;0', 13), +(10, 4, 25, 'VL11;VL13;VZ1;VL12;VI11;VI12', '', '0;0;0;0;0', 13), +(11, 5, 5, 'VL11;VL13;VZ1;VL12', 'VI11;VI12', '0;0;0;0;0', 13), +(12, 6, 5, '', 'VL11;VL13;VL21;VL23;VZ1;VP2;VP4;VP5;VP6;VL12;VL22;VI11;VI12;VI13;VI21;VI22;VI31;VI32;VI41;VI42;VI43;VI4P;VB1;VB2', '0;0;0;0;0', 13), +(13, 0, 10, 'VL13', '', '0;0;0;0;0', 15), +(14, 0, 10, 'VL13;VL12;VI11;VI12;VI13', '', '25;25;25;25;25', 14), +(15, 1, 30, 'VL13', 'VL12;VI11;VI12;VI13', '30;40;40;40;40', 14), +(16, 2, 20, 'VL11;VL12;VI21;VI22;VI31;VI32;VI41;VI42;VI43;VB1;VB2', 'VL13', '15;40;40;40;80', 14), +(17, 3, 15, 'VL11;VL12;VI11;VI13;VI21;VI22;VI31;VI32;VI41;VI42;VI43;VB1;VB2', '', '15;40;40;40;40', 14), +(18, 4, 8, 'VL11;VL12;VI21;VI22;VI31;VI32;VI41;VI42;VI43;VB1;VB2', 'VI11;VI13', '15;60;60;60;80', 14), +(19, 5, 8, 'VL11;VL12;VI21;VI22;VI31;VI32;VI41;VI42;VI43;VB1;VB2', '', '15;40;40;40;40', 14), +(20, 6, 2, 'VL11;VI21;VI22;VI31;VI32;VI41;VI42;VI43;VB1;VB2', 'VL12', '15;40;40;40;40', 14), +(21, 7, 28, 'VL11;VL12;VI11;VI13;VI21;VI22;VI31;VI32;VI41;VI42;VI43;VB1;VB2', '', '15;40;40;40;40', 14), +(22, 8, 2, 'VL11;VI11;VI13;VI21;VI22;VI31;VI32;VI41;VI42;VI43;VB1;VB2', 'VL12', '15;40;40;40;40', 14), +(23, 9, 15, 'VL11;VL12;VI11;VI13;VI21;VI22;VI31;VI32;VI41;VI42;VI43;VB1;VB2', '', '15;40;40;40;40', 14), +(24, 10, 5, 'VZ1', 'VL11;VL13;VL21;VL23;VP2;VP4;VP5;VP6;VL12;VL22;VI11;VI12;VI13;VI21;VI22;VI31;VI32;VI41;VI42;VI43;VI4P;VB1;VB2;VM1;VM2;VM3;VM4;Pumpe1;Block', '0;0;0;0;0', 14); + +-- -------------------------------------------------------- + +-- +-- Tabellenstruktur für Tabelle `test` +-- + +CREATE TABLE IF NOT EXISTS `test` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `ItemNr` int(11) DEFAULT NULL, + `Name` varchar(255) DEFAULT NULL, + `Qfrom` float DEFAULT NULL, + `Qto` float DEFAULT NULL, + `Volume` float DEFAULT NULL, + `TstTime` float DEFAULT NULL, + `Repeats` int(11) DEFAULT NULL, + `Emptying` tinyint(1) DEFAULT NULL, + `Zeroing` tinyint(1) DEFAULT NULL, + `Method` varchar(255) DEFAULT NULL, + `ErrLimLo` float DEFAULT NULL, + `ErrLimHi` float DEFAULT NULL, + `TolerRed` double DEFAULT NULL, + `RedType` varchar(255) DEFAULT NULL, + `FeadingPath` varchar(255) DEFAULT NULL, + `BenchPath` varchar(255) DEFAULT NULL, + `OutputPath` varchar(255) DEFAULT NULL, + `MetersPath` varchar(255) DEFAULT NULL, + `Procedure_id` int(11) DEFAULT NULL, + PRIMARY KEY (`Id`), + KEY `Procedure_id` (`Procedure_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=33 ; + +-- +-- Daten für Tabelle `test` +-- + +INSERT INTO `test` (`Id`, `ItemNr`, `Name`, `Qfrom`, `Qto`, `Volume`, `TstTime`, `Repeats`, `Emptying`, `Zeroing`, `Method`, `ErrLimLo`, `ErrLimHi`, `TolerRed`, `RedType`, `FeadingPath`, `BenchPath`, `OutputPath`, `MetersPath`, `Procedure_id`) VALUES +(15, 0, 'Qn', 15, 16, 200, 46.4516, 5, 1, 0, 'Verbund', 0, 2, 0, 'Fix', 'PS2', 'PBank2', 'PQ4', 'PMess1', 7), +(16, 1, 'Qt', 2, 2.2, 60, 102.857, 5, 1, 0, 'Fliegender Start-Stopp', 0, 5, 0, 'Fix', 'PS2', 'PBank2', 'PQ3', 'PMess1', 7), +(17, 2, 'Qmin', 1, 1.2, 20, 65.4545, 1, 1, 0, 'Fliegender Start-Stopp', 2, 0, 0.20000000298023224, 'Fix', 'PS2', 'PBank2', 'PQ3', '', 7), +(18, 0, 'Qmin', 1, 1.1, 30, 102.857, 1, 0, 0, 'Fliegender Start-Stopp', 2, 0, 0.20000000298023224, 'Fix', 'PS2', 'PBank2', 'PQ3', '', 8), +(19, 0, 'Qn', 12, 16, 200, 51.4286, 1, 0, 0, 'Fliegender Start-Stopp', 5, 0, 0.20000000298023224, 'Fix', 'PS2', 'PBank2', 'PQ4', '', 10), +(20, 1, 'Qt', 2.5, 3.5, 100, 120, 1, 0, 0, 'Fliegender Start-Stopp', 0, 0, 0.20000000298023224, 'Fix', 'PS2', 'PBank2', 'PQ3', '', 10), +(21, 0, 'Prüfpunkt1', 1, 1.2, 20, 65.4545, 5, 0, 0, 'Fliegender Start-Stopp', 0, 2, 0.20000000298023224, 'Fix', 'PS2', 'PBank2', 'PQ4', 'PMess1', 11), +(22, 1, 'Prüfpunkt2', 2, 2.1, 40, 70.2439, 5, 0, 0, 'Fliegender Start-Stopp', 0, 2, 0.20000000298023224, 'Fix', 'PS2', 'PBank2', 'PQ4', 'PMess1', 11), +(23, 2, 'Prüfpunkt3', 3.1, 3.2, 60, 68.5714, 5, 0, 0, 'Fliegender Start-Stopp', 0, 2, 0.20000000298023224, 'Fix', 'PS2', 'PBank2', 'PQ4', 'PMess1', 11), +(24, 3, 'Prüfpunkt4', 4.1, 4.3, 80, 68.5714, 5, 0, 0, 'Fliegender Start-Stopp', 0, 2, 0.20000000298023224, 'Fix', 'PS2', 'PBank2', 'PQ4', 'PMess1', 11), +(25, 4, 'Prüfpunkt5', 6, 6.1, 120, 71.405, 5, 0, 0, 'Fliegender Start-Stopp', 0, 2, 0.20000000298023224, 'Fix', 'PS2', 'PBank2', 'PQ4', 'PMess1', 11), +(26, 0, 'Prüfpunkt1', 15, 17, 200, 45, 4, 0, 0, 'Fliegender Start-Stopp', 2, 0, 0.20000000298023224, 'Fix', 'PS2', 'PBank2', 'PQ5', 'PMess1', 12), +(27, 0, 'Prüfpunkt1', 15, 16, 1000, 232.258, 5, 1, 0, 'Fliegender Start-Stopp', 0, 2, 0.20000000298023224, 'Fix', 'PS2', 'PBank2', 'PQ4', 'PMess1', 13), +(28, 1, 'Prüfpunkt2', 1, 1.1, 100, 342.857, 5, 1, 0, 'Fliegender Start-Stopp', 0, 2, 0.20000000298023224, 'Fix', 'PS2', 'PBank2', 'PQ3', 'PMess1', 13), +(29, 0, 'Qn', 15, 16, 600, 139.355, 1, 0, 0, 'Verbund', 0, 2, 0.20000000298023224, 'Fix', 'PS2', 'PBank2', 'PQ4', 'PMess1', 14), +(30, 1, 'Qt', 3, 3.2, 200, 232.258, 1, 0, 0, 'Verbund', 0, 2, 0.20000000298023224, 'Fix', 'PS2', 'PBank2', 'PQ4', 'PMess1', 14), +(31, 2, 'Qsteig', 0.9, 1, 100, 378.947, 1, 1, 0, 'Verbund', 0, 5, 0.20000000298023224, 'Fix', 'PS2', 'PBank2', 'PQ3', 'PMess1', 14), +(32, 3, 'Qfall', 2.8, 3, 100, 124.138, 1, 1, 0, 'Verbund', 0, 5, 0.20000000298023224, 'Fix', 'PS2', 'PBank2', 'PQ3', 'PMess1', 14); + +-- -------------------------------------------------------- + +-- +-- Tabellenstruktur für Tabelle `testresult` +-- + +CREATE TABLE IF NOT EXISTS `testresult` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `TimeStart` datetime DEFAULT NULL, + `TimeEnd` datetime DEFAULT NULL, + `RepetitionNr` int(11) DEFAULT NULL, + `AmbientTempAve` float DEFAULT NULL, + `AmbientPressAve` float DEFAULT NULL, + `AmbientHumiAve` float DEFAULT NULL, + `PressInAvrg` float DEFAULT NULL, + `PressInStart` float DEFAULT NULL, + `PressInEnd` float DEFAULT NULL, + `PressOutAvrg` float DEFAULT NULL, + `PressOutStart` float DEFAULT NULL, + `PressOutEnd` float DEFAULT NULL, + `TempInAvrg` float DEFAULT NULL, + `TempInStart` float DEFAULT NULL, + `TempInEnd` float DEFAULT NULL, + `TempOutAvrg` float DEFAULT NULL, + `TempOutStart` float DEFAULT NULL, + `TempOutEnd` float DEFAULT NULL, + `TempDivAvrg` float DEFAULT NULL, + `TempDivStart` float DEFAULT NULL, + `TempDivEnd` float DEFAULT NULL, + `MassStartRaw` float DEFAULT NULL, + `MassStart` float DEFAULT NULL, + `MassEndRaw` float DEFAULT NULL, + `MassEnd` float DEFAULT NULL, + `MassDiff` float DEFAULT NULL, + `DensityIn` float DEFAULT NULL, + `DensityOut` float DEFAULT NULL, + `DensityDiv` float DEFAULT NULL, + `FlowMass` float DEFAULT NULL, + `FlowVolume` float DEFAULT NULL, + `VolumeCTV` float DEFAULT NULL, + `VolumeMaster` float DEFAULT NULL, + `Time` float DEFAULT NULL, + `ErrorMaster` float DEFAULT NULL, + `PulsesMaster` float DEFAULT NULL, + `ConstMaster` float DEFAULT NULL, + `TimeDivStart0` float DEFAULT NULL, + `TimeDivStart1` float DEFAULT NULL, + `TimeDivStart2` float DEFAULT NULL, + `TimeDivStart3` float DEFAULT NULL, + `TimeDivStart4` float DEFAULT NULL, + `TimeDivStart5` float DEFAULT NULL, + `TimeDivEnd0` float DEFAULT NULL, + `TimeDivEnd1` float DEFAULT NULL, + `TimeDivEnd2` float DEFAULT NULL, + `TimeDivEnd3` float DEFAULT NULL, + `TimeDivEnd4` float DEFAULT NULL, + `TimeDivEnd5` float DEFAULT NULL, + `Test_id` int(11) DEFAULT NULL, + PRIMARY KEY (`Id`), + KEY `Test_id` (`Test_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=117 ; + +-- +-- Daten für Tabelle `testresult` +-- + +INSERT INTO `testresult` (`Id`, `TimeStart`, `TimeEnd`, `RepetitionNr`, `AmbientTempAve`, `AmbientPressAve`, `AmbientHumiAve`, `PressInAvrg`, `PressInStart`, `PressInEnd`, `PressOutAvrg`, `PressOutStart`, `PressOutEnd`, `TempInAvrg`, `TempInStart`, `TempInEnd`, `TempOutAvrg`, `TempOutStart`, `TempOutEnd`, `TempDivAvrg`, `TempDivStart`, `TempDivEnd`, `MassStartRaw`, `MassStart`, `MassEndRaw`, `MassEnd`, `MassDiff`, `DensityIn`, `DensityOut`, `DensityDiv`, `FlowMass`, `FlowVolume`, `VolumeCTV`, `VolumeMaster`, `Time`, `ErrorMaster`, `PulsesMaster`, `ConstMaster`, `TimeDivStart0`, `TimeDivStart1`, `TimeDivStart2`, `TimeDivStart3`, `TimeDivStart4`, `TimeDivStart5`, `TimeDivEnd0`, `TimeDivEnd1`, `TimeDivEnd2`, `TimeDivEnd3`, `TimeDivEnd4`, `TimeDivEnd5`, `Test_id`) VALUES +(1, '2014-01-21 17:41:57', '2014-01-21 17:42:54', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.1818, 17.198, 17.17, 17.1656, 17.183, 17.155, 17.2016, 17.227, 17.181, 0.05, 0.05, 201.15, 201.15, 201.1, 1000.35, 1000.35, 1000.34, 15837.4, 15839.2, 201.237, 201.122, 45.712, -0.0570204, 72404, 0.00277936, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(2, '2014-01-21 17:43:11', '2014-01-21 17:45:07', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.1555, 17.162, 17.152, 17.1364, 17.144, 17.132, 17.5829, 17.91, 17.487, 0, 0, 60.133, 60.133, 60.133, 1000.35, 1000.35, 1000.27, 2062.1, 2062.55, 60.1737, 60.1463, 104.98, -0.0455428, 144351, 0.000416857, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16), +(3, '2014-01-21 17:49:21', '2014-01-21 17:50:18', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.2002, 17.222, 17.183, 17.182, 17.199, 17.168, 17.2144, 17.235, 17.194, 0, 0, 201.133, 201.133, 201.133, 1000.34, 1000.35, 1000.34, 15842.5, 15842, 201.271, 201.128, 45.705, -0.071127, 72406, 0.00277976, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(4, '2014-01-21 17:50:31', '2014-01-21 17:52:28', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.1553, 17.168, 17.147, 17.1358, 17.151, 17.128, 17.5125, 17.846, 17.436, 3.26133, 3.26133, 63.514, 63.514, 60.2527, 1000.35, 1000.35, 1000.29, 2067.4, 2063.75, 60.2934, 60.1463, 104.919, -0.244041, 144351, 0.000417686, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16), +(5, '2014-01-21 17:54:04', '2014-01-21 17:55:01', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.1507, 17.157, 17.146, 17.1317, 17.139, 17.127, 17.1593, 17.17, 17.147, 0, 0, 201.15, 201.15, 201.15, 1000.35, 1000.35, 1000.35, 15843.1, 15840.9, 201.286, 201.122, 45.707, -0.0812647, 72404, 0.00278004, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(6, '2014-01-21 17:55:14', '2014-01-21 17:57:12', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.1391, 17.141, 17.136, 17.1179, 17.121, 17.115, 17.4528, 17.727, 17.403, 3.363, 3.363, 63.6217, 63.6217, 60.2587, 1000.35, 1000.36, 1000.3, 2067.23, 2063.39, 60.2992, 60.1467, 104.938, -0.252975, 144352, 0.000417723, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16), +(7, '2014-01-22 09:13:46', '2014-01-22 09:14:43', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18.8708, 19.804, 18.321, 19.4739, 20.842, 18.646, 20.0805, 21.682, 18.94, 0, 0, 201.15, 201.15, 201.15, 1000.03, 999.913, 999.789, 15854.9, 15852.9, 201.375, 201.125, 45.673, -0.123957, 72405, 0.00278123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(8, '2014-01-22 09:30:27', '2014-01-22 09:31:24', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.7432, 17.782, 17.721, 17.7499, 17.793, 17.725, 17.8648, 17.989, 17.775, 0, 0, 201.15, 201.15, 201.15, 1000.25, 1000.24, 1000.22, 15803.3, 15801.1, 201.308, 201.122, 45.822, -0.0923222, 72404, 0.00278034, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(9, '2014-01-22 09:44:48', '2014-01-22 09:45:45', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.2819, 17.314, 17.248, 17.2901, 17.331, 17.254, 17.3612, 17.457, 17.291, 0, 0, 201.1, 201.1, 201.1, 1000.33, 1000.33, 1000.31, 15753.3, 15754.2, 201.241, 201.111, 45.956, -0.0647607, 72400, 0.00277958, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(10, '2014-01-22 09:54:30', '2014-01-22 09:55:27', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.1931, 17.237, 17.156, 17.2, 17.254, 17.161, 17.2767, 17.379, 17.212, 0, 0, 201.05, 201.05, 201.05, 1000.34, 1000.34, 1000.33, 15738.5, 15743.9, 201.188, 201.119, 45.988, -0.0341599, 72403, 0.00277873, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(11, '2014-01-22 10:11:13', '2014-01-22 10:12:09', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.1765, 17.23, 17.137, 17.1807, 17.234, 17.139, 17.2987, 17.466, 17.189, 0, 0, 201.2, 201.2, 201.2, 1000.35, 1000.35, 1000.33, 15801.4, 15795.3, 201.338, 201.122, 45.839, -0.106966, 72404, 0.00278075, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(12, '2014-01-22 10:12:23', '2014-01-22 10:14:13', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.102, 17.107, 17.104, 17.1125, 17.109, 17.125, 17.6444, 18.254, 17.504, 0, 0, 48.118, 48.118, 48.118, 1000.36, 1000.36, 1000.26, 1741.48, 2177.09, 48.1503, 60.1542, 99.47, 24.9299, 144370, 0.00033352, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16), +(13, '2014-01-22 10:24:14', '2014-01-22 10:25:11', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.1366, 17.172, 17.106, 17.1396, 17.197, 17.107, 17.2267, 17.342, 17.155, 0, 0, 201.1, 201.1, 201.1, 1000.35, 1000.35, 1000.34, 15795.3, 15796.8, 201.236, 201.119, 45.834, -0.0579684, 72403, 0.00277939, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(14, '2014-01-22 10:25:25', '2014-01-22 10:27:16', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.0878, 17.087, 17.089, 17.0902, 17.084, 17.103, 17.5711, 18.084, 17.455, 0, 0, 51.2683, 51.2683, 51.2683, 1000.36, 1000.36, 1000.28, 1852.09, 2173.09, 51.3026, 60.1542, 99.653, 17.2537, 144370, 0.000355355, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16), +(15, '2014-01-22 10:31:24', '2014-01-22 10:32:21', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.1506, 17.152, 17.161, 17.1276, 17.132, 17.136, 17.1659, 17.207, 17.152, 0, 0, 201.2, 201.2, 201.2, 1000.35, 1000.36, 1000.35, 15801.7, 15795.4, 201.336, 201.119, 45.838, -0.107422, 72403, 0.00278077, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(16, '2014-01-22 10:32:35', '2014-01-22 10:34:26', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.1924, 17.174, 17.209, 17.1736, 17.15, 17.195, 17.5562, 17.921, 17.499, 0, 0, 51.4273, 51.4273, 51.4273, 1000.34, 1000.35, 1000.28, 1857.16, 2172.32, 51.4624, 60.1546, 99.689, 16.8903, 144371, 0.00035646, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16), +(17, '2014-01-22 10:40:35', '2014-01-22 10:41:32', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.2396, 17.245, 17.237, 17.2284, 17.238, 17.222, 17.2562, 17.276, 17.242, 0, 0, 201.2, 201.2, 201.2, 1000.34, 1000.34, 1000.33, 15788.6, 15782.3, 201.339, 201.119, 45.876, -0.109186, 72403, 0.00278081, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(18, '2014-01-22 10:41:45', '2014-01-22 10:42:42', 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.2369, 17.24, 17.233, 17.2221, 17.223, 17.22, 17.239, 17.24, 17.24, 0, 0, 201.15, 201.15, 201.15, 1000.34, 1000.34, 1000.34, 15795.7, 15793.3, 201.289, 201.119, 45.844, -0.0842349, 72403, 0.00278012, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(19, '2014-01-22 10:42:55', '2014-01-22 10:43:52', 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.2012, 17.216, 17.181, 17.1943, 17.21, 17.176, 17.2148, 17.228, 17.202, 0, 0, 201.117, 201.117, 201.117, 1000.34, 1000.34, 1000.34, 15804.2, 15804.6, 201.255, 201.122, 45.812, -0.0658179, 72404, 0.00277961, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(20, '2014-01-22 10:44:05', '2014-01-22 10:45:02', 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.1431, 17.16, 17.128, 17.1348, 17.153, 17.118, 17.1586, 17.178, 17.141, 0.0166667, 0.0166667, 201.2, 201.2, 201.183, 1000.35, 1000.35, 1000.35, 15796.3, 15791.3, 201.319, 201.119, 45.85, -0.0992674, 72403, 0.00278054, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(21, '2014-01-22 10:45:15', '2014-01-22 10:46:12', 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.1021, 17.114, 17.094, 17.0894, 17.101, 17.079, 17.1112, 17.123, 17.101, 0, 0, 201.2, 201.2, 201.2, 1000.36, 1000.36, 1000.36, 15797.6, 15791.1, 201.334, 201.117, 45.85, -0.108127, 72402, 0.00278078, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(22, '2014-01-22 13:30:40', '2014-01-22 13:31:36', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.2618, 17.308, 17.226, 17.3, 17.394, 17.247, 17.6104, 17.992, 17.382, 0, 0, 201.133, 201.133, 201.133, 998.731, 998.724, 998.669, 15795.5, 15794.4, 201.598, 201.119, 45.841, -0.237233, 72403, 0.00278438, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(23, '2014-01-22 13:31:49', '2014-01-22 13:32:45', 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.1934, 17.202, 17.186, 17.1978, 17.216, 17.184, 17.2435, 17.281, 17.217, 0, 0, 201.2, 201.2, 201.2, 998.743, 998.742, 998.734, 15792.8, 15786.5, 201.661, 201.119, 45.864, -0.268477, 72403, 0.00278526, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(24, '2014-01-22 13:32:58', '2014-01-22 13:33:54', 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.1658, 17.173, 17.158, 17.1658, 17.176, 17.157, 17.1913, 17.206, 17.18, 0, 0, 201.15, 201.15, 201.15, 998.748, 998.748, 998.743, 15796.4, 15794, 201.61, 201.119, 45.842, -0.243115, 72403, 0.00278455, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(25, '2014-01-22 13:34:07', '2014-01-22 13:35:04', 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.1447, 17.15, 17.139, 17.1406, 17.147, 17.136, 17.1617, 17.17, 17.155, 0, 0, 201.233, 201.233, 201.233, 998.752, 998.752, 998.749, 15801.3, 15792.5, 201.692, 201.122, 45.847, -0.282612, 72404, 0.00278565, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(26, '2014-01-22 13:35:17', '2014-01-22 13:36:14', 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.1352, 17.136, 17.137, 17.1284, 17.13, 17.128, 17.1452, 17.147, 17.144, 0, 0, 201.15, 201.15, 201.15, 998.753, 998.754, 998.752, 15798.2, 15796, 201.608, 201.122, 45.837, -0.241088, 72404, 0.00278449, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(27, '2014-01-22 13:36:30', '2014-01-22 13:38:23', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.1575, 17.144, 17.166, 17.1557, 17.132, 17.176, 17.8218, 18.699, 17.611, 0, 0, 60.2617, 60.2617, 60.2617, 998.749, 998.75, 998.63, 2172.88, 2168.98, 60.3993, 60.1538, 99.841, -0.406466, 144369, 0.000418367, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16), +(28, '2014-01-22 13:38:37', '2014-01-22 13:40:28', 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.1742, 17.172, 17.178, 17.1969, 17.185, 17.207, 17.5216, 17.568, 17.487, 0, 0, 60.2737, 60.2737, 60.2737, 998.746, 998.742, 998.685, 2172.65, 2168.35, 60.4117, 60.1542, 99.871, -0.426323, 144370, 0.000418451, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16), +(29, '2014-01-22 13:40:41', '2014-01-22 13:44:13', 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.1814, 17.18, 17.179, 17.2121, 17.208, 17.215, 17.4733, 17.479, 17.469, 0, 0, -119.212, -119.212, -119.212, 998.745, 998.74, 998.693, -4924.63, 2169.62, -119.485, 52.5204, 87.146, 0.1, 126049, -0.000947925, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16), +(30, '2014-01-22 16:02:00', '2014-01-22 16:03:15', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.4985, 17.532, 17.456, 17.7711, 17.797, 17.76, 18.1239, 18.126, 18.063, 0.7, 0.7, 20.75, 20.75, 20.05, 998.689, 998.64, 998.575, 1126.93, 1128.49, 20.098, 20.0778, 64.05, -0.100578, 7228, 0.00278057, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21), +(31, '2014-01-22 16:03:26', '2014-01-22 16:04:41', 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.4188, 17.423, 17.399, 17.7271, 17.753, 17.701, 17.9281, 18, 17.874, 20.8, 20.8, 40.8667, 40.8667, 20.0667, 998.703, 998.648, 998.611, 1124.43, 1125.05, 20.1145, 20.0778, 64.246, -0.182746, 7228, 0.00278286, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21), +(32, '2014-01-22 16:04:52', '2014-01-22 16:06:07', 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.3671, 17.385, 17.358, 17.6452, 17.667, 17.616, 17.8033, 17.841, 17.767, 40.9, 40.9, 61, 61, 20.1, 998.712, 998.662, 998.634, 1124.55, 1123.3, 20.1476, 20.0778, 64.346, -0.34679, 7228, 0.00278744, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21), +(33, '2014-01-22 16:06:18', '2014-01-22 16:07:33', 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.3574, 17.358, 17.353, 17.5951, 17.61, 17.599, 17.7199, 17.748, 17.698, 61.05, 61.05, 81.1167, 81.1167, 20.0667, 998.714, 998.672, 998.649, 1123.2, 1123.83, 20.1141, 20.0778, 64.316, -0.180379, 7228, 0.0027828, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21), +(34, '2014-01-22 16:07:44', '2014-01-22 16:08:58', 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.3483, 17.349, 17.343, 17.5803, 17.599, 17.556, 17.6685, 17.682, 17.657, 81.15, 81.15, 101.25, 101.25, 20.1, 998.716, 998.674, 998.658, 1124.86, 1123.62, 20.1474, 20.0778, 64.328, -0.345629, 7228, 0.00278741, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21), +(35, '2014-01-22 16:09:21', '2014-01-22 16:10:43', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.3572, 17.356, 17.353, 17.5227, 17.544, 17.525, 17.6173, 17.646, 17.583, 101.25, 101.25, 141.45, 141.45, 40.2, 998.714, 998.685, 998.667, 2037.88, 2035.06, 40.2944, 40.1444, 71.015, -0.372169, 14452, 0.00278815, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22), +(36, '2014-01-22 16:10:54', '2014-01-22 16:12:16', 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.3371, 17.346, 17.333, 17.4815, 17.521, 17.451, 17.5445, 17.568, 17.519, 141.45, 141.45, 181.617, 181.617, 40.1667, 998.718, 998.692, 998.681, 2036.42, 2035.15, 40.2607, 40.1417, 71.007, -0.295629, 14451, 0.00278601, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22), +(37, '2014-01-22 16:12:27', '2014-01-22 16:13:49', 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.3189, 17.323, 17.319, 17.4144, 17.429, 17.407, 17.4837, 17.5, 17.469, 181.65, 181.65, 221.85, 221.85, 40.2, 998.721, 998.704, 998.692, 2037.62, 2034.81, 40.2937, 40.1444, 71.024, -0.370349, 14452, 0.0027881, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22), +(38, '2014-01-22 16:14:00', '2014-01-22 16:15:22', 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.317, 17.321, 17.313, 17.3955, 17.409, 17.39, 17.4482, 17.459, 17.439, 221.85, 221.85, 262.05, 262.05, 40.2, 998.721, 998.707, 998.698, 2037.71, 2034.75, 40.2935, 40.1417, 71.021, -0.376722, 14451, 0.00278828, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22), +(39, '2014-01-22 16:15:33', '2014-01-22 16:16:55', 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.3006, 17.309, 17.299, 17.3899, 17.4, 17.385, 17.4324, 17.436, 17.426, 262.1, 262.1, 302.267, 302.267, 40.1667, 998.724, 998.708, 998.701, 2036.25, 2034.98, 40.26, 40.1417, 71.013, -0.293995, 14451, 0.00278597, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22), +(40, '2014-01-22 16:17:15', '2014-01-22 16:18:35', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.3041, 17.311, 17.3, 17.3716, 17.393, 17.357, 17.415, 17.427, 17.401, 302.3, 302.3, 362.55, 362.55, 60.25, 998.724, 998.712, 998.704, 3116.96, 3115.38, 60.3898, 60.2194, 69.587, -0.282152, 21679, 0.00278564, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23), +(41, '2014-01-22 16:18:46', '2014-01-22 16:20:06', 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.292, 17.295, 17.291, 17.3415, 17.356, 17.331, 17.3764, 17.387, 17.365, 362.6, 362.6, 422.85, 422.85, 60.25, 998.726, 998.717, 998.711, 3117.99, 3116.41, 60.3895, 60.2194, 69.564, -0.281667, 21679, 0.00278562, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23), +(42, '2014-01-22 16:20:17', '2014-01-22 16:21:37', 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.2851, 17.293, 17.278, 17.3302, 17.338, 17.328, 17.3581, 17.362, 17.359, 422.9, 422.9, 483.15, 483.15, 60.25, 998.727, 998.719, 998.714, 3118.71, 3117.13, 60.3894, 60.2194, 69.548, -0.281465, 21679, 0.00278562, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23), +(43, '2014-01-22 16:21:48', '2014-01-22 16:23:08', 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.2673, 17.274, 17.259, 17.3324, 17.329, 17.316, 17.3468, 17.355, 17.342, 483.2, 483.2, 543.45, 543.45, 60.25, 998.73, 998.719, 998.716, 3119.78, 3118.2, 60.3894, 60.2194, 69.524, -0.281453, 21679, 0.00278562, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23), +(44, '2014-01-22 16:23:19', '2014-01-22 16:24:39', 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.2602, 17.263, 17.254, 17.3006, 17.31, 17.297, 17.3294, 17.338, 17.324, 543.45, 543.45, 603.75, 603.75, 60.3, 998.731, 998.724, 998.719, 3121.43, 3117.26, 60.4392, 60.2194, 69.545, -0.363607, 21679, 0.00278791, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23), +(45, '2014-01-22 16:25:00', '2014-01-22 16:26:20', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.248, 17.253, 17.242, 17.288, 17.295, 17.275, 17.3215, 17.324, 17.313, 603.75, 603.75, 684.117, 684.117, 80.3667, 998.733, 998.726, 998.72, 4179.36, 4175.74, 80.5521, 80.2972, 69.226, -0.316373, 28907, 0.00278659, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24), +(46, '2014-01-22 16:26:31', '2014-01-22 16:27:51', 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.2481, 17.242, 17.243, 17.2722, 17.271, 17.275, 17.3024, 17.31, 17.3, 684.15, 684.15, 764.5, 764.5, 80.3499, 998.733, 998.729, 998.724, 4179.39, 4176.5, 80.535, 80.2944, 69.211, -0.298715, 28906, 0.0027861, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24), +(47, '2014-01-22 16:28:02', '2014-01-22 16:29:22', 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.2303, 17.236, 17.227, 17.2607, 17.271, 17.254, 17.2948, 17.3, 17.286, 764.55, 764.55, 844.9, 844.9, 80.3501, 998.737, 998.731, 998.725, 4175.18, 4172.28, 80.535, 80.2944, 69.281, -0.298743, 28906, 0.0027861, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24), +(48, '2014-01-22 16:29:33', '2014-01-22 16:30:53', 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.2214, 17.225, 17.218, 17.2451, 17.25, 17.238, 17.2773, 17.283, 17.273, 844.9, 844.9, 925.25, 925.25, 80.3499, 998.738, 998.734, 998.728, 4181.26, 4178.38, 80.5346, 80.2944, 69.18, -0.298233, 28906, 0.00278609, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24), +(49, '2014-01-22 16:31:04', '2014-01-22 16:32:24', 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.2209, 17.22, 17.221, 17.2358, 17.239, 17.236, 17.2663, 17.268, 17.263, 925.25, 925.25, 1005.62, 1005.62, 80.3667, 998.738, 998.736, 998.73, 4181.59, 4177.83, 80.5513, 80.2944, 69.189, -0.318895, 28906, 0.00278666, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24), +(50, '2014-01-22 16:32:44', '2014-01-22 16:34:07', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.2195, 17.226, 17.212, 17.2277, 17.23, 17.23, 17.2623, 17.265, 17.259, 1005.65, 1005.65, 1126.07, 1126.07, 120.417, 998.738, 998.737, 998.731, 6007.98, 6008.4, 120.693, 120.425, 72.154, -0.222163, 43353, 0.00278396, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25), +(51, '2014-01-22 16:34:18', '2014-01-22 16:35:40', 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.2095, 17.218, 17.203, 17.22, 17.22, 17.215, 17.2511, 17.255, 17.247, 1126.1, 1126.1, 1246.53, 1246.53, 120.433, 998.74, 998.738, 998.733, 6089.5, 6089.36, 120.71, 120.431, 71.198, -0.231234, 43355, 0.00278422, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25), +(52, '2014-01-22 16:35:51', '2014-01-22 16:37:13', 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.1967, 17.199, 17.193, 17.2102, 17.214, 17.204, 17.2379, 17.245, 17.234, 1246.55, 1246.55, 1366.97, 1366.97, 120.417, 998.742, 998.74, 998.735, 6087.88, 6088.59, 120.693, 120.431, 71.207, -0.217208, 43355, 0.00278382, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25), +(53, '2014-01-22 16:37:24', '2014-01-22 16:38:46', 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.1888, 17.19, 17.189, 17.2037, 17.201, 17.192, 17.2271, 17.228, 17.224, 1367, 1367, 1487.45, 1487.45, 120.45, 998.744, 998.741, 998.737, 6088.02, 6087.05, 120.726, 120.431, 71.225, -0.2446, 43355, 0.00278459, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25), +(54, '2014-01-22 16:38:58', '2014-01-22 16:40:19', 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.1873, 17.188, 17.188, 17.19, 17.192, 17.19, 17.2222, 17.224, 17.219, 1487.5, 1487.5, 1607.9, 1607.9, 120.4, 998.744, 998.744, 998.738, 6064.73, 6066.13, 120.676, 120.428, 71.469, -0.205397, 43354, 0.0027835, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25), +(55, '2014-01-22 17:02:12', '2014-01-22 17:03:08', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.0874, 17.097, 17.081, 17.0734, 17.085, 17.065, 17.1019, 17.109, 17.095, 15.1, 15.1, 216.233, 216.233, 201.133, 998.762, 998.764, 998.759, 16247, 16245.2, 201.59, 201.111, 44.567, -0.237371, 7240, 0.0278439, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26), +(56, '2014-01-22 17:57:43', '2014-01-22 17:58:40', 1, 21.81, 948.212, 29.9233, 0, 0, 0, 0, 0, 0, 17.1047, 17.122, 17.09, 17.0985, 17.122, 17.083, 17.1413, 17.185, 17.114, -17.05, -17.05, 184.1, 184.1, 201.15, 998.759, 998.76, 998.752, 15815.1, 15812.9, 201.607, 201.122, 45.788, -0.240582, 72404, 0.00278448, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(57, '2014-01-23 08:44:35', '2014-01-23 08:45:32', 1, 23.45, 950.68, 26.0282, 0, 0, 0, 0, 0, 0, 18.453, 19.041, 18.037, 19.1917, 20.404, 18.331, 20.0359, 21.914, 18.711, 0, 0, 189.483, 189.483, 189.483, 998.513, 998.37, 998.199, 14954, 15872.7, 189.988, 201.125, 45.616, 5.86181, 72405, 0.00262397, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(58, '2014-01-23 08:50:09', '2014-01-23 08:51:06', 2, 23.5362, 950.676, 26.7004, 0, 0, 0, 0, 0, 0, 17.6413, 17.64, 17.65, 17.6502, 17.655, 17.655, 17.6828, 17.695, 17.677, 0, 0, 186.75, 186.75, 186.75, 998.663, 998.662, 998.656, 14745.4, 15880.6, 187.193, 201.128, 45.594, 7.44413, 72406, 0.00258532, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(59, '2014-01-23 08:55:42', '2014-01-23 08:56:38', 3, 23.62, 950.554, 26.6455, 0, 0, 0, 0, 0, 0, 17.416, 17.47, 17.361, 17.4474, 17.493, 17.395, 17.4955, 17.54, 17.442, 0, 0, 186.75, 186.75, 186.75, 998.704, 998.698, 998.689, 14742.8, 15877.8, 187.186, 201.128, 45.602, 7.44806, 72406, 0.00258523, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(60, '2014-01-23 08:56:55', '2014-01-23 08:57:51', 4, 23.623, 950.795, 26.392, 0, 0, 0, 0, 0, 0, 17.2409, 17.284, 17.2, 17.2702, 17.312, 17.222, 17.3208, 17.373, 17.266, -22.55, -22.55, 178.6, 178.6, 201.15, 998.735, 998.73, 998.721, 15883.7, 15882, 201.613, 201.128, 45.59, -0.24084, 72406, 0.00278448, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(61, '2014-01-23 09:31:37', '2014-01-23 09:35:35', 1, 23.5322, 951.066, 27.0611, 0, 0, 0, 0, 0, 0, 17.1355, 17.562, 17.05, 17.1693, 17.66, 17.047, 17.2724, 17.93, 17.091, 0, 0, 989.017, 989.017, 989.017, 998.753, 998.747, 998.729, 15679.7, 15871.7, 991.277, 1001.12, 227.074, 0.993456, 360405, 0.00275045, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27), +(62, '2014-01-23 09:49:45', '2014-01-23 09:53:43', 1, 23.4289, 951.307, 27.749, 0, 0, 0, 0, 0, 0, 17.0658, 17.192, 17.039, 17.0687, 17.222, 17.031, 17.106, 17.246, 17.054, -0.3, -0.3, 1000.65, 1000.65, 1000.95, 998.765, 998.765, 998.758, 15872.4, 15875.2, 1003.22, 1001.13, 227.025, -0.208551, 360406, 0.00278358, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27), +(63, '2014-01-23 09:58:22', '2014-01-23 10:02:20', 1, 23.3655, 951.275, 27.6753, 0, 0, 0, 0, 0, 0, 17.0131, 17.017, 17.007, 17.0014, 17.006, 16.996, 17.0201, 17.025, 17.01, 34.1, 34.1, 1035.08, 1035.08, 1000.98, 998.775, 998.777, 998.773, 15872.3, 15874.6, 1003.24, 1001.12, 227.033, -0.210986, 360405, 0.00278365, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27), +(64, '2014-01-23 10:04:51', '2014-01-23 10:08:49', 2, 23.2715, 951.288, 27.3465, 0, 0, 0, 0, 0, 0, 16.996, 16.998, 16.995, 16.9819, 16.985, 16.981, 17.0011, 17.004, 17.002, 32.9, 32.9, 1034.05, 1034.05, 1001.15, 998.778, 998.78, 998.777, 15874.2, 15873.8, 1003.41, 1001.12, 227.044, -0.227527, 360404, 0.00278411, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27), +(65, '2014-01-23 10:11:24', '2014-01-23 10:15:22', 3, 23.1503, 951.305, 27.0103, 0, 0, 0, 0, 0, 0, 16.9938, 16.995, 16.993, 16.9781, 16.978, 16.98, 16.9963, 16.996, 16.996, 33.15, 33.15, 1034.13, 1034.13, 1000.98, 998.778, 998.781, 998.778, 15872.1, 15874.3, 1003.24, 1001.12, 227.036, -0.210841, 360404, 0.00278365, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27), +(66, '2014-01-23 10:17:57', '2014-01-23 10:21:55', 4, 23.0528, 951.479, 27.0146, 0, 0, 0, 0, 0, 0, 16.9936, 16.993, 16.994, 16.9767, 16.977, 16.977, 16.9958, 16.998, 16.997, 32.85, 32.85, 1033.85, 1033.85, 1001, 998.778, 998.781, 998.778, 15873.3, 15875.3, 1003.25, 1001.12, 227.023, -0.212212, 360405, 0.00278369, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27), +(67, '2014-01-23 10:32:46', '2014-01-23 10:36:44', 1, 22.836, 951.592, 27.534, 0, 0, 0, 0, 0, 0, 16.999, 17, 16.999, 16.9772, 16.978, 16.977, 16.9958, 16.998, 16.994, 33.3, 33.3, 1034.27, 1034.27, 1000.97, 998.777, 998.781, 998.778, 15872.1, 15874.6, 1003.22, 1001.12, 227.032, -0.20891, 360405, 0.00278359, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27), +(68, '2014-01-23 10:39:14', '2014-01-23 10:43:12', 2, 22.7173, 951.711, 27.5574, 0, 0, 0, 0, 0, 0, 17.0003, 16.999, 17.001, 16.9784, 16.977, 16.979, 16.9973, 16.996, 16.998, 32.95, 32.95, 1033.9, 1033.9, 1000.95, 998.777, 998.781, 998.777, 15871.2, 15874, 1003.2, 1001.12, 227.041, -0.207258, 360405, 0.00278355, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27), +(69, '2014-01-23 10:45:43', '2014-01-23 10:49:41', 3, 22.5937, 951.647, 27.4176, 0, 0, 0, 0, 0, 0, 17.0002, 17, 16.999, 16.9784, 16.978, 16.979, 16.9972, 16.997, 16.996, 33.05, 33.05, 1034.05, 1034.05, 1001, 998.777, 998.781, 998.777, 15869.6, 15871.6, 1003.25, 1001.12, 227.076, -0.212249, 360405, 0.00278369, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27), +(70, '2014-01-23 10:52:16', '2014-01-23 10:56:15', 4, 22.526, 951.594, 27.5806, 0, 0, 0, 0, 0, 0, 17.0014, 17.002, 17.003, 16.9788, 16.978, 16.979, 16.9989, 16.997, 16.998, 33, 33, 1033.98, 1033.98, 1000.98, 998.777, 998.781, 998.777, 15871.1, 15873.4, 1003.24, 1001.13, 227.051, -0.210299, 360406, 0.00278363, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27), +(71, '2014-01-23 10:58:49', '2014-01-23 11:02:47', 5, 22.4358, 951.725, 27.4002, 0, 0, 0, 0, 0, 0, 17.0043, 17.003, 17.004, 16.981, 16.979, 16.982, 16.9999, 16.997, 17, 33.15, 33.15, 1034.1, 1034.1, 1000.95, 998.776, 998.78, 998.777, 15873.3, 15876.1, 1003.2, 1001.13, 227.011, -0.207021, 360406, 0.00278354, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27), +(72, '2014-01-23 11:03:27', '2014-01-23 11:09:25', 1, 22.381, 951.688, 27.6094, 0, 0, 0, 0, 0, 0, 17.0359, 17.014, 17.041, 17.0425, 16.99, 17.078, 17.8152, 18.731, 17.476, -0.0136667, -0.0136667, 100.162, 100.162, 100.175, 998.771, 998.769, 998.632, 1035.88, 1034.83, 100.402, 100.073, 348.14, -0.327396, 240176, 0.000418035, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28), +(73, '2014-01-23 11:10:11', '2014-01-23 11:16:10', 2, 22.3575, 951.648, 27.5311, 0, 0, 0, 0, 0, 0, 17.0517, 17.046, 17.055, 17.1016, 17.084, 17.111, 17.4316, 17.448, 17.426, 5.42533, 5.42533, 105.64, 105.64, 100.215, 998.768, 998.759, 998.701, 1036.77, 1035.31, 100.443, 100.073, 347.978, -0.367552, 240176, 0.000418204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28), +(74, '2014-01-23 11:16:58', '2014-01-23 11:22:57', 3, 22.3472, 951.517, 27.2686, 0, 0, 0, 0, 0, 0, 17.0592, 17.054, 17.062, 17.125, 17.114, 17.13, 17.4365, 17.429, 17.444, 5.60667, 5.60667, 105.809, 105.809, 100.203, 998.767, 998.755, 998.7, 1036.63, 1035.29, 100.431, 100.073, 347.982, -0.356025, 240176, 0.000418155, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28), +(75, '2014-01-23 11:23:45', '2014-01-23 11:29:44', 4, 22.3489, 951.527, 27.0005, 0, 0, 0, 0, 0, 0, 17.0613, 17.058, 17.063, 17.1369, 17.133, 17.135, 17.4475, 17.442, 17.454, 5.24433, 5.24433, 105.465, 105.465, 100.221, 998.766, 998.753, 998.698, 1036.52, 1034.99, 100.449, 100.073, 348.083, -0.374469, 240176, 0.000418233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28), +(76, '2014-01-23 11:30:31', '2014-01-23 11:36:30', 5, 22.3677, 951.481, 26.8638, 0, 0, 0, 0, 0, 0, 17.0642, 17.061, 17.069, 17.142, 17.133, 17.15, 17.4536, 17.454, 17.452, 5.583, 5.583, 105.801, 105.801, 100.218, 998.766, 998.752, 998.697, 1036.55, 1035.06, 100.446, 100.073, 348.062, -0.371238, 240176, 0.000418219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28), +(77, '2014-01-23 14:36:43', '2014-01-23 14:37:40', 1, 22.1304, 950.107, 27.0682, 0, 0, 0, 0, 0, 0, 17.1687, 17.174, 17.16, 17.167, 17.175, 17.159, 17.2108, 17.23, 17.196, 33.1, 33.1, 234.25, 234.25, 201.15, 998.747, 998.748, 998.74, 15876.4, 15874.5, 201.61, 201.125, 45.611, -0.240383, 72405, 0.00278447, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(78, '2014-01-23 14:40:03', '2014-01-23 14:44:01', 1, 22.1172, 950.109, 27.9356, 0, 0, 0, 0, 0, 0, 17.1405, 17.13, 17.147, 17.1268, 17.119, 17.13, 17.1458, 17.145, 17.148, 33.5, 33.5, 1034.45, 1034.45, 1000.95, 998.752, 998.755, 998.751, 15870.6, 15873.4, 1003.23, 1001.12, 227.05, -0.209839, 360405, 0.00278362, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27), +(79, '2014-01-23 14:46:33', '2014-01-23 14:50:32', 2, 22.0557, 950.031, 27.9047, 0, 0, 0, 0, 0, 0, 17.0877, 17.134, 17.062, 17.0744, 17.123, 17.045, 17.0975, 17.145, 17.066, 32.7, 32.7, 1033.65, 1033.65, 1000.95, 998.762, 998.764, 998.76, 15870.6, 15873.4, 1003.22, 1001.12, 227.05, -0.208928, 360405, 0.00278359, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27), +(80, '2014-01-23 14:53:06', '2014-01-23 14:57:04', 3, 22.0006, 950.123, 27.87, 0, 0, 0, 0, 0, 0, 17.0567, 17.057, 17.05, 17.0369, 17.036, 17.031, 17.0565, 17.055, 17.051, 33.3, 33.3, 1034.4, 1034.4, 1001.1, 998.767, 998.77, 998.767, 15872.8, 15873.2, 1003.36, 1001.12, 227.053, -0.22323, 360405, 0.00278399, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27), +(81, '2014-01-23 14:59:35', '2014-01-23 15:03:33', 4, 21.9671, 950.105, 27.9426, 0, 0, 0, 0, 0, 0, 17.0501, 17.049, 17.051, 17.0276, 17.027, 17.029, 17.0484, 17.049, 17.048, 33, 33, 1033.9, 1033.9, 1000.9, 998.768, 998.772, 998.768, 15873.1, 15876.6, 1003.16, 1001.12, 227.003, -0.203403, 360404, 0.00278344, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27), +(82, '2014-01-23 15:06:08', '2014-01-23 15:10:06', 5, 21.9451, 950.152, 27.9535, 0, 0, 0, 0, 0, 0, 17.054, 17.051, 17.056, 17.0309, 17.029, 17.033, 17.0513, 17.05, 17.052, 32.9, 32.9, 1033.95, 1033.95, 1001.05, 998.768, 998.771, 998.768, 15872.7, 15873.9, 1003.31, 1001.12, 227.042, -0.218131, 360405, 0.00278385, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27), +(83, '2014-01-23 15:10:28', '2014-01-23 15:16:28', 1, 21.9423, 950.104, 28.1947, 0, 0, 0, 0, 0, 0, 17.0873, 17.059, 17.095, 17.0896, 17.038, 17.125, 17.8578, 19.567, 17.514, 0.236667, 0.236667, 100.459, 100.459, 100.223, 998.762, 998.761, 998.624, 1032.16, 1030.62, 100.45, 100.073, 349.559, -0.375704, 240175, 0.000418238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28), +(84, '2014-01-23 15:17:15', '2014-01-23 15:23:15', 2, 21.9366, 950.112, 28.259, 0, 0, 0, 0, 0, 0, 17.1022, 17.095, 17.109, 17.1503, 17.13, 17.167, 17.4923, 17.505, 17.492, 5.38167, 5.38167, 105.599, 105.599, 100.217, 998.759, 998.751, 998.69, 1032.51, 1031.03, 100.446, 100.073, 349.421, -0.371126, 240175, 0.000418219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28), +(85, '2014-01-23 15:24:03', '2014-01-23 15:30:04', 3, 21.9112, 950.105, 28.1581, 0, 0, 0, 0, 0, 0, 17.1102, 17.109, 17.115, 17.176, 17.173, 17.182, 17.4962, 17.494, 17.504, 5.20133, 5.20133, 105.405, 105.405, 100.203, 998.758, 998.746, 998.689, 1032.5, 1031.16, 100.432, 100.073, 349.376, -0.357995, 240175, 0.000418164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28), +(86, '2014-01-23 15:30:52', '2014-01-23 15:36:52', 4, 21.9089, 950.05, 27.8639, 0, 0, 0, 0, 0, 0, 17.1158, 17.116, 17.115, 17.1856, 17.182, 17.212, 17.5053, 17.509, 17.515, 5.57667, 5.57667, 105.799, 105.799, 100.222, 998.757, 998.744, 998.688, 1032.58, 1031.04, 100.451, 100.073, 349.416, -0.376725, 240175, 0.000418242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28), +(87, '2014-01-23 15:37:40', '2014-01-23 15:43:40', 5, 21.9101, 950.054, 27.8539, 0, 0, 0, 0, 0, 0, 17.117, 17.118, 17.121, 17.1896, 17.193, 17.191, 17.5014, 17.507, 17.499, 5.59267, 5.59267, 105.795, 105.795, 100.202, 998.756, 998.744, 998.688, 1032.52, 1031.19, 100.431, 100.073, 349.366, -0.356905, 240175, 0.000418159, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28), +(88, '2014-01-23 16:33:16', '2014-01-23 16:37:14', 1, 22.2809, 950.137, 29.0679, 0, 0, 0, 0, 0, 0, 17.1094, 17.109, 17.104, 17.0906, 17.089, 17.087, 17.1091, 17.107, 17.108, 1.15, 1.15, 1.15, 1.15, 0, 998.758, 998.761, 998.758, 0, 15850.1, 0, 1001.12, 227.383, 0.1, 360405, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27), +(89, '2014-01-23 16:50:04', '2014-01-23 16:51:00', 1, 22.2748, 950.052, 29.2155, 0, 0, 0, 0, 0, 0, 17.0772, 17.076, 17.077, 17.0559, 17.056, 17.056, 17.0756, 17.077, 17.075, 33.05, 33.05, 234.2, 234.2, 201.15, 998.763, 998.767, 998.764, 15905, 15903.3, 201.606, 201.128, 45.529, -0.237072, 72406, 0.00278438, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(90, '2014-01-23 16:53:00', '2014-01-23 16:53:57', 2, 22.28, 950.177, 29.1289, 0, 0, 0, 0, 0, 0, 17.077, 17.075, 17.079, 17.054, 17.053, 17.056, 17.0725, 17.073, 17.073, 33.5667, 33.5667, 234.7, 234.7, 201.133, 998.763, 998.767, 998.764, 15911, 15910.6, 201.589, 201.128, 45.508, -0.228773, 72406, 0.00278415, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(91, '2014-01-23 16:55:57', '2014-01-23 16:56:54', 3, 22.2762, 950.3, 29.1878, 0, 0, 0, 0, 0, 0, 17.0771, 17.077, 17.078, 17.0544, 17.053, 17.056, 17.072, 17.072, 17.072, 33, 33, 234.2, 234.2, 201.2, 998.763, 998.767, 998.764, 15910.4, 15904.4, 201.656, 201.125, 45.525, -0.263217, 72405, 0.00278511, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(92, '2014-01-23 16:58:54', '2014-01-23 16:59:50', 4, 22.2625, 950.295, 29.23, 0, 0, 0, 0, 0, 0, 17.0783, 17.078, 17.077, 17.054, 17.054, 17.054, 17.0734, 17.073, 17.074, 33.45, 33.45, 234.6, 234.6, 201.15, 998.763, 998.768, 998.764, 15904.3, 15902.6, 201.606, 201.128, 45.531, -0.23705, 72406, 0.00278438, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(93, '2014-01-23 17:01:50', '2014-01-23 17:02:47', 5, 22.25, 950.2, 29.2922, 0, 0, 0, 0, 0, 0, 17.0784, 17.078, 17.079, 17.0549, 17.054, 17.056, 17.0739, 17.073, 17.076, 32.9667, 32.9667, 234.117, 234.117, 201.15, 998.763, 998.767, 998.764, 15909.6, 15907.8, 201.606, 201.128, 45.516, -0.23705, 72406, 0.00278438, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(94, '2014-01-23 18:11:56', '2014-01-23 18:12:59', 1, 21.6157, 950.069, 29.512, 0, 0, 0, 0, 0, 0, 17.1888, 17.242, 17.155, 17.1899, 17.236, 17.157, 17.2798, 17.427, 17.206, -0.05, -0.05, 200.9, 200.9, 200.95, 998.744, 998.744, 998.728, 14034.5, 14037.6, 201.41, 200.994, 51.546, -0.206317, 72358, 0.00278352, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(95, '2014-01-24 09:49:41', '2014-01-24 09:50:40', 1, 22.6, 948.534, 27.64, 0, 0, 0, 0, 0, 0, 18.5668, 19.343, 18.13, 19.4426, 21.161, 18.427, 20.1827, 21.875, 18.962, 0, 0, 201.05, 201.05, 201.05, 998.491, 998.32, 998.168, 15121.3, 15123.2, 201.596, 201.075, 47.865, -0.258345, 72387, 0.00278497, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15), +(96, '2014-01-24 09:54:08', '2014-01-24 09:56:52', 1, 22.5919, 948.819, 29.9135, 0, 0, 0, 0, 0, 0, 17.7907, 17.86, 17.737, 17.8374, 17.969, 17.763, 17.9082, 18.042, 17.815, 302.75, 302.75, 903.683, 903.683, 600.933, 998.636, 998.628, 998.615, 14070.9, 14072.4, 602.379, 600.997, 153.747, -0.229386, 216359, 0.00278416, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29), +(97, '2014-01-24 09:57:48', '2014-01-24 10:01:47', 1, 22.5884, 948.599, 30.4115, 0, 0, 0, 0, 0, 0, 17.7214, 17.708, 17.735, 17.7629, 17.732, 17.776, 17.7996, 17.785, 17.816, 903.75, 903.75, 1104.1, 1104.1, 200.35, 998.649, 998.641, 998.634, 3157.6, 3155.59, 200.829, 200.222, 228.42, -0.302252, 72080, 0.0027862, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30), +(98, '2014-01-24 10:08:47', '2014-01-24 10:11:21', 1, 22.5246, 948.847, 30.101, 0, 0, 0, 0, 0, 0, 17.6874, 17.777, 17.624, 17.7124, 17.833, 17.631, 17.7955, 17.983, 17.687, 1104.15, 1104.15, 1705.03, 1705.03, 600.883, 998.655, 998.65, 998.635, 15090.3, 15094.9, 602.315, 601.067, 143.349, -0.207279, 216384, 0.00278355, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29), +(99, '2014-01-24 10:12:21', '2014-01-24 10:16:20', 1, 22.5002, 948.827, 31.126, 0, 0, 0, 0, 0, 0, 17.5736, 17.588, 17.548, 17.6089, 17.608, 17.593, 17.6488, 17.655, 17.637, 1705.1, 1705.1, 1905.42, 1905.42, 200.317, 998.675, 998.669, 998.662, 3151.86, 3150.38, 200.79, 200.222, 228.798, -0.282879, 72080, 0.00278566, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30), +(100, '2014-01-24 10:17:13', '2014-01-24 10:22:31', 1, 22.4694, 948.939, 31.3745, 0, 0, 0, 0, 0, 0, 17.5237, 17.546, 17.493, 17.6182, 17.601, 17.625, 18.0608, 18.404, 17.923, 5.674, 5.674, 105.906, 105.906, 100.232, 998.684, 998.667, 998.586, 1178.96, 1177.21, 100.469, 100.083, 306.062, -0.383661, 240200, 0.000418271, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31), +(101, '2014-01-24 10:24:03', '2014-01-24 10:26:19', 1, 22.4202, 949.037, 30.8028, 0, 0, 0, 0, 0, 0, 17.4585, 17.498, 17.435, 17.5486, 17.6, 17.496, 17.744, 17.816, 17.688, 5.60467, 5.60467, 105.998, 105.998, 100.394, 998.696, 998.68, 998.645, 2888.08, 2882.56, 100.63, 100.202, 125.141, -0.425557, 240484, 0.000418447, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32), +(102, '2014-01-24 11:27:34', '2014-01-24 11:30:09', 1, 22.2572, 949.084, 29.9756, 0, 0, 0, 0, 0, 0, 17.3901, 17.615, 17.313, 17.4633, 17.94, 17.316, 17.6353, 18.542, 17.388, 1905.45, 1905.45, 2506.23, 2506.23, 600.784, 998.708, 998.695, 998.664, 15064, 15071.2, 602.188, 601.069, 143.575, -0.185765, 216385, 0.00278295, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29), +(103, '2014-01-24 11:33:10', '2014-01-24 11:37:10', 1, 22.2358, 949.059, 30.417, 0, 0, 0, 0, 0, 0, 17.2012, 17.2, 17.197, 17.2137, 17.208, 17.216, 17.244, 17.239, 17.25, 23.4, 23.4, 223.8, 223.8, 200.4, 998.742, 998.74, 998.734, 3146.94, 3144.15, 200.86, 200.222, 229.251, -0.317324, 72080, 0.00278662, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30), +(104, '2014-01-24 11:38:48', '2014-01-24 11:44:38', 1, 22.2371, 949.064, 29.9864, 0, 0, 0, 0, 0, 0, 17.2171, 17.207, 17.227, 17.2649, 17.223, 17.296, 17.7839, 18.155, 17.642, 5.552, 5.552, 105.759, 105.759, 100.207, 998.739, 998.73, 998.637, 1065.44, 1064.03, 100.438, 100.075, 338.589, -0.361469, 240180, 0.000418178, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31), +(105, '2014-01-24 11:46:13', '2014-01-24 11:48:28', 1, 22.2581, 949.068, 28.5927, 0, 0, 0, 0, 0, 0, 17.2312, 17.252, 17.219, 17.2727, 17.301, 17.246, 17.4753, 17.517, 17.454, 5.552, 5.552, 105.959, 105.959, 100.407, 998.736, 998.729, 998.693, 2907.1, 2901.22, 100.639, 100.204, 124.339, -0.431722, 240490, 0.000418473, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32), +(106, '2014-01-24 12:02:16', '2014-01-24 12:04:50', 1, 22.5164, 949.085, 27.5738, 0, 0, 0, 0, 0, 0, 17.2041, 17.274, 17.172, 17.215, 17.334, 17.169, 17.3073, 17.613, 17.213, 223.8, 223.8, 824.8, 824.8, 601, 998.741, 998.739, 998.723, 15076.2, 15078, 602.378, 601.072, 143.511, -0.216843, 216386, 0.00278381, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29), +(107, '2014-01-24 12:05:51', '2014-01-24 12:09:51', 1, 22.5944, 949.109, 27.5323, 0, 0, 0, 0, 0, 0, 17.1726, 17.166, 17.171, 17.1775, 17.165, 17.175, 17.2016, 17.196, 17.208, 824.85, 824.85, 1025.23, 1025.23, 200.383, 998.747, 998.746, 998.742, 3141.05, 3138.53, 200.842, 200.222, 229.662, -0.308402, 72080, 0.00278637, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30), +(108, '2014-01-24 13:07:48', '2014-01-24 13:10:21', 1, 23.0909, 949.002, 26.2842, 0, 0, 0, 0, 0, 0, 17.2331, 17.429, 17.175, 17.2812, 17.719, 17.182, 17.4027, 18.026, 17.225, 1025.25, 1025.25, 1626.13, 1626.13, 600.883, 998.736, 998.728, 998.706, 15204.5, 15209.4, 602.268, 601.075, 142.272, -0.198164, 216387, 0.00278329, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29), +(109, '2014-01-24 13:11:21', '2014-01-24 13:15:19', 1, 23.1303, 948.951, 26.183, 0, 0, 0, 0, 0, 0, 17.1652, 17.161, 17.166, 17.177, 17.161, 17.179, 17.202, 17.195, 17.209, 1626.2, 1626.2, 1826.55, 1826.55, 200.35, 998.748, 998.746, 998.742, 3172.69, 3170.71, 200.809, 200.225, 227.334, -0.290581, 72081, 0.00278587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30), +(110, '2014-01-24 13:16:22', '2014-01-24 13:21:36', 1, 23.1949, 948.915, 26.1312, 0, 0, 0, 0, 0, 0, 17.1793, 17.175, 17.175, 17.2394, 17.196, 17.259, 17.883, 18.531, 17.64, 5.227, 5.227, 105.449, 105.449, 100.222, 998.746, 998.735, 998.619, 1190.55, 1188.91, 100.452, 100.084, 303.052, -0.366476, 240202, 0.000418199, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31), +(111, '2014-01-24 13:23:09', '2014-01-24 13:25:25', 1, 23.3193, 948.973, 26.3648, 0, 0, 0, 0, 0, 0, 17.1846, 17.197, 17.179, 17.226, 17.26, 17.202, 17.4636, 17.515, 17.43, 5.561, 5.561, 105.96, 105.96, 100.399, 998.745, 998.737, 998.695, 2916.87, 2911.32, 100.63, 100.208, 123.913, -0.418833, 240500, 0.000418419, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32), +(112, '2014-01-24 14:03:10', '2014-01-24 14:05:43', 1, 23.6351, 948.813, 26.7518, 155.811, 155.886, 155.911, 141.568, 141.71, 141.343, 10.5715, 10.6832, 10.5338, 10.621, 10.7674, 10.562, 10.6782, 10.7867, 10.6027, 196.25, 196.25, 796.983, 796.983, 600.733, 999.65, 999.645, 999.639, 15250, 15241.4, 601.566, 600.394, 141.812, -0.194703, 216142, 0.0027832, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29), +(113, '2014-01-24 14:55:04', '2014-01-24 14:57:37', 1, 24.3689, 948.904, 28.2572, 155.805, 155.828, 155.811, 141.454, 141.788, 141.235, 10.5344, 10.604, 10.4959, 10.5674, 10.6485, 10.5277, 10.6463, 10.8516, 10.563, 0, 0, 572.65, 572.65, 572.65, 999.653, 999.65, 999.642, 14534, 15238, 573.441, 600.392, 141.843, 4.6999, 216141, 0.00265309, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29), +(114, '2014-01-24 14:58:38', '2014-01-24 15:02:36', 1, 24.4131, 948.846, 28.5036, 155.913, 155.893, 155.986, 159.13, 158.947, 159.16, 10.5067, 10.4905, 10.5103, 10.5614, 10.5151, 10.589, 10.5935, 10.5522, 10.6172, 572.7, 572.7, 773, 773, 200.3, 999.656, 999.651, 999.647, 3171.19, 3167.67, 200.576, 200.078, 227.385, -0.248582, 72028, 0.0027847, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30), +(115, '2014-01-24 15:03:45', '2014-01-24 15:09:24', 1, 24.4372, 948.986, 28.6013, 155.93, 155.957, 155.975, 157.52, 157.461, 157.645, 10.5299, 10.5266, 10.532, 10.6805, 10.5908, 10.7206, 11.6102, 12.0364, 11.4289, 0.081, 0.081, 100.249, 100.249, 100.168, 999.654, 999.639, 999.543, 1100.24, 1098.97, 100.307, 100.052, 327.749, -0.254171, 240125, 0.000417728, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31), +(116, '2014-01-24 15:10:58', '2014-01-24 15:13:13', 1, 24.47, 948.983, 28.7628, 155.939, 155.975, 156.009, 155.564, 155.477, 155.056, 10.555, 10.5662, 10.532, 10.6734, 10.7188, 10.6341, 11.1051, 11.1928, 11.054, 5.425, 5.425, 105.682, 105.682, 100.257, 999.651, 999.64, 999.597, 2906.11, 2902.65, 100.396, 100.138, 124.195, -0.25757, 240330, 0.000417743, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32); + +-- -------------------------------------------------------- + +-- +-- Tabellenstruktur für Tabelle `user` +-- + +CREATE TABLE IF NOT EXISTS `user` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `Name` varchar(255) DEFAULT NULL, + `Password` varchar(255) DEFAULT NULL, + `Description` varchar(255) DEFAULT NULL, + `LastPwChange` datetime DEFAULT NULL, + PRIMARY KEY (`Id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=3 ; + +-- +-- Daten für Tabelle `user` +-- + +INSERT INTO `user` (`Id`, `Name`, `Password`, `Description`, `LastPwChange`) VALUES +(1, 'admin', 'af242843887f3bdcc52e485483356eaccd37ba67a35941530bd195a8310fc7d5aca8560576dfb62ad5a4bd2df789a5e8be068e62e7c976d6eeed8d63abbd9909', 'Application administrator', '2013-12-30 12:17:19'), +(2, 'tester', '', 'tester', '2013-12-30 12:17:19'); + +-- -------------------------------------------------------- + +-- +-- Tabellenstruktur für Tabelle `watermeter` +-- + +CREATE TABLE IF NOT EXISTS `watermeter` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `Serial` varchar(255) DEFAULT NULL, + `WMType_id` int(11) DEFAULT NULL, + PRIMARY KEY (`Id`), + KEY `WMType_id` (`WMType_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; + +-- -------------------------------------------------------- + +-- +-- Tabellenstruktur für Tabelle `wmtype` +-- + +CREATE TABLE IF NOT EXISTS `wmtype` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `CreateTime` datetime DEFAULT NULL, + `CreateUserName` varchar(255) DEFAULT NULL, + `CreateDescription` varchar(255) DEFAULT NULL, + `Name` varchar(255) DEFAULT NULL, + `PulseRate` float DEFAULT NULL, + PRIMARY KEY (`Id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; + +-- +-- Constraints der exportierten Tabellen +-- + +-- +-- Constraints der Tabelle `componentprocedure` +-- +ALTER TABLE `componentprocedure` + ADD CONSTRAINT `FKA4EE67E2C1B693F2` FOREIGN KEY (`Procedure_id`) REFERENCES `procedure` (`Id`); + +-- +-- Constraints der Tabelle `componenttest` +-- +ALTER TABLE `componenttest` + ADD CONSTRAINT `FK4933B35E048BC68` FOREIGN KEY (`Test_id`) REFERENCES `test` (`Id`); + +-- +-- Constraints der Tabelle `group` +-- +ALTER TABLE `group` + ADD CONSTRAINT `FKFBBA8E27F90D2266` FOREIGN KEY (`User_id`) REFERENCES `user` (`Id`); + +-- +-- Constraints der Tabelle `measurementcorrection` +-- +ALTER TABLE `measurementcorrection` + ADD CONSTRAINT `FK2E70F3322F02977E` FOREIGN KEY (`Component_id`) REFERENCES `component` (`Id`); + +-- +-- Constraints der Tabelle `metertestresult` +-- +ALTER TABLE `metertestresult` + ADD CONSTRAINT `FK1CE41B064BD6C9B6` FOREIGN KEY (`TestResult_id`) REFERENCES `testresult` (`Id`); + +-- +-- Constraints der Tabelle `purgeend` +-- +ALTER TABLE `purgeend` + ADD CONSTRAINT `FK14832B1AC1B693F2` FOREIGN KEY (`Procedure_id`) REFERENCES `procedure` (`Id`); + +-- +-- Constraints der Tabelle `purgestart` +-- +ALTER TABLE `purgestart` + ADD CONSTRAINT `FKDC8627F9C1B693F2` FOREIGN KEY (`Procedure_id`) REFERENCES `procedure` (`Id`); + +-- +-- Constraints der Tabelle `test` +-- +ALTER TABLE `test` + ADD CONSTRAINT `FKCC127866C1B693F2` FOREIGN KEY (`Procedure_id`) REFERENCES `procedure` (`Id`); + +-- +-- Constraints der Tabelle `testresult` +-- +ALTER TABLE `testresult` + ADD CONSTRAINT `FKAD39033FE048BC68` FOREIGN KEY (`Test_id`) REFERENCES `test` (`Id`); + +-- +-- Constraints der Tabelle `watermeter` +-- +ALTER TABLE `watermeter` + ADD CONSTRAINT `FKA968A8E699BF9B30` FOREIGN KEY (`WMType_id`) REFERENCES `wmtype` (`Id`); + +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; diff --git a/TestBenchFramework/SampleConfig/sensus.sql b/TestBenchFramework/SampleConfig/sensus.sql new file mode 100644 index 000000000..73c89d61f --- /dev/null +++ b/TestBenchFramework/SampleConfig/sensus.sql @@ -0,0 +1,1147 @@ +-- phpMyAdmin SQL Dump +-- version 4.0.4.1 +-- http://www.phpmyadmin.net +-- +-- Hostiteľ: 127.0.0.1 +-- Vygenerované: Ne 27.Júl 2014, 11:39 +-- Verzia serveru: 5.6.11 +-- Verzia PHP: 5.5.3 + +SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; +SET time_zone = "+00:00"; + + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; + +-- +-- Databáza: `sensus` +-- +CREATE DATABASE IF NOT EXISTS `sensus` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; +USE `sensus`; + +-- -------------------------------------------------------- + +-- +-- Štruktúra tabuľky pre tabuľku `benchpath` +-- + +CREATE TABLE IF NOT EXISTS `benchpath` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `ItemNr` int(11) DEFAULT NULL, + `Name` varchar(255) DEFAULT NULL, + `Qfrom` float DEFAULT NULL, + `Qto` float DEFAULT NULL, + `TempIn` varchar(255) DEFAULT NULL, + `TempOut` varchar(255) DEFAULT NULL, + `PressIn` varchar(255) DEFAULT NULL, + `PressOut` varchar(255) DEFAULT NULL, + `ValvesOpen` varchar(8000) DEFAULT NULL, + `ValvesClose` varchar(8000) DEFAULT NULL, + PRIMARY KEY (`Id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=3 ; + +-- +-- Sťahujem dáta pre tabuľku `benchpath` +-- + +INSERT INTO `benchpath` (`Id`, `ItemNr`, `Name`, `Qfrom`, `Qto`, `TempIn`, `TempOut`, `PressIn`, `PressOut`, `ValvesOpen`, `ValvesClose`) VALUES +(1, 1, 'PT1', 0, 250, 'T1', 'T2', 'P1', 'P2', 'K5', ''), +(2, 0, '', 0, 0, '---', '---', '---', '---', '', 'K5'); + +-- -------------------------------------------------------- + +-- +-- Štruktúra tabuľky pre tabuľku `component` +-- + +CREATE TABLE IF NOT EXISTS `component` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `Name` varchar(255) DEFAULT NULL, + `ClassName` varchar(255) DEFAULT NULL, + `ParentName` varchar(255) DEFAULT NULL, + `ItemNr` int(11) DEFAULT NULL, + `Mode` varchar(255) DEFAULT NULL, + `Logging` varchar(255) DEFAULT NULL, + `Parameters` varchar(8000) DEFAULT NULL, + PRIMARY KEY (`Id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=62 ; + +-- +-- Sťahujem dáta pre tabuľku `component` +-- + +INSERT INTO `component` (`Id`, `Name`, `ClassName`, `ParentName`, `ItemNr`, `Mode`, `Logging`, `Parameters`) VALUES +(1, 'CB', 'ControlBoard', NULL, 0, 'Normal', 'Off', '\r\n\r\n 1\r\n'), +(2, 'K5', 'Valve', 'CB', 1, 'Normal', 'Off', '\r\n\r\n 0\r\n \r\n false\r\n K5\r\n CB\r\n'), +(3, 'K7', 'Valve', 'CB', 2, 'Normal', 'Off', '\r\n\r\n 1\r\n \r\n false\r\n K7\r\n CB\r\n'), +(4, 'K10', 'Valve', 'CB', 3, 'Normal', 'Off', '\r\n\r\n 2\r\n \r\n false\r\n K10\r\n CB\r\n'), +(5, 'K13', 'Valve', 'CB', 4, 'Normal', 'Off', '\r\n\r\n 3\r\n \r\n false\r\n K13\r\n CB\r\n'), +(6, 'K16', 'Valve', 'CB', 5, 'Normal', 'Off', '\r\n\r\n 4\r\n \r\n false\r\n K16\r\n CB\r\n'), +(7, 'K2', 'Valve', 'CB', 6, 'Normal', 'Off', '\r\n\r\n 5\r\n \r\n false\r\n K2\r\n CB\r\n'), +(8, 'K4', 'Valve', 'CB', 7, 'Normal', 'Off', '\r\n\r\n 6\r\n \r\n false\r\n K4\r\n CB\r\n'), +(9, 'Pumpe1', 'Valve', 'CB', 8, 'Normal', 'Off', '\r\n\r\n 16\r\n \r\n false\r\n Pumpe1\r\n CB\r\n'), +(10, 'K19', 'Valve', 'CB', 9, 'Normal', 'Off', '\r\n\r\n 17\r\n \r\n false\r\n K19\r\n CB\r\n'), +(11, 'K20', 'Valve', 'CB', 10, 'Normal', 'Off', '\r\n\r\n 18\r\n \r\n false\r\n K20\r\n CB\r\n'), +(12, 'K21', 'Valve', 'CB', 11, 'Normal', 'Off', '\r\n\r\n 19\r\n \r\n false\r\n K21\r\n CB\r\n'), +(13, 'Pumpe2', 'Valve', 'CB', 12, 'Normal', 'Off', '\r\n\r\n 20\r\n \r\n false\r\n Pumpe2\r\n CB\r\n'), +(14, 'Vl5', 'Valve', 'CB', 13, 'Normal', 'Off', '\r\n\r\n 21\r\n \r\n false\r\n Vl5\r\n CB\r\n'), +(15, 'KL1', 'Diverter', 'CB', 14, 'Normal', 'Off', '\r\n\r\n 8\r\n KL1\r\n CB\r\n'), +(16, 'KL2', 'Diverter', 'CB', 15, 'Normal', 'Off', '\r\n\r\n 9\r\n KL2\r\n CB\r\n'), +(17, 'T1', 'TempMeter', 'CB', 16, 'Normal', 'Off', '\r\n\r\n 0\r\n -21.62223\r\n 0.001777413\r\n 4.39902E-09\r\n 1.357676E-15\r\n 0\r\n'), +(18, 'T2', 'TempMeter', 'CB', 17, 'Normal', 'Off', '\r\n\r\n 1\r\n -21.56429\r\n 0.001777858\r\n 4.61575E-09\r\n 1.18247E-15\r\n 0\r\n'), +(19, 'T3', 'TempMeter', 'CB', 18, 'Normal', 'Off', '\r\n\r\n 2\r\n -21.7311\r\n 0.001780699\r\n 3.371811E-09\r\n 2.692937E-15\r\n 0\r\n'), +(20, 'T4', 'TempMeter', 'CB', 19, 'Normal', 'Off', '\r\n\r\n 3\r\n -21.68512\r\n 0.001776832\r\n 3.822327E-09\r\n 1.940195E-15\r\n 0\r\n'), +(22, 'RV1', 'RegulationValve', 'CB', 20, 'Normal', 'Off', '\r\n\r\n 1\r\n 100\r\n 500\r\n 0\r\n true\r\n'), +(23, 'RV2', 'RegulationValve', 'CB', 21, 'Normal', 'Off', '\r\n\r\n 2\r\n 100\r\n 500\r\n 0\r\n true\r\n'), +(24, 'RV3', 'RegulationValve', 'CB', 22, 'Normal', 'Off', '\r\n\r\n 3\r\n 100\r\n 500\r\n 0\r\n true\r\n'), +(25, 'RV4', 'RegulationValve', 'CB', 23, 'Normal', 'Off', '\r\n\r\n 4\r\n 100\r\n 500\r\n 0\r\n true\r\n'), +(26, 'RV5', 'RegulationValve', 'CB', 24, 'Normal', 'Off', '\r\n\r\n 5\r\n 100\r\n 500\r\n 0\r\n true\r\n'), +(27, 'E1', 'FlowMeter', 'CB', 25, 'Normal', 'Off', '\r\n\r\n 1\r\n 0.3\r\n E1\r\n CB\r\n'), +(28, 'E2', 'FlowMeter', 'CB', 26, 'Normal', 'Off', '\r\n\r\n 2\r\n 2.5\r\n E2\r\n CB\r\n'), +(29, 'E3', 'FlowMeter', 'CB', 27, 'Normal', 'Off', '\r\n\r\n 3\r\n 25\r\n E3\r\n CB\r\n'), +(30, 'E4', 'FlowMeter', 'CB', 28, 'Normal', 'Off', '\r\n\r\n 4\r\n 250\r\n E4\r\n CB\r\n'), +(31, 'E5', 'FlowMeter', 'CB', 29, 'Normal', 'Off', '\r\n\r\n 5\r\n 0.2\r\n E5\r\n CB\r\n'), +(32, 'Sens1', 'RegisterReader', 'CB', 30, 'Normal', 'Off', '\r\n\r\n 1\r\n'), +(33, 'Sens2', 'RegisterReader', 'CB', 31, 'Normal', 'Off', '\r\n\r\n 2\r\n'), +(34, 'Sens3', 'RegisterReader', 'CB', 32, 'Normal', 'Off', '\r\n\r\n 3\r\n'), +(36, 'Waage1', 'MettlerToledo Balance', NULL, 34, 'Normal', 'Off', '\r\n\r\n 4\r\n 2400\r\n Even\r\n 7\r\n One\r\n XOnXOff\r\n 120\r\n'), +(37, 'Waage2', 'MettlerToledo Balance', NULL, 35, 'Normal', 'Off', '\r\n\r\n 3\r\n 2400\r\n Even\r\n 7\r\n One\r\n XOnXOff\r\n 3000\r\n'), +(40, 'P1', 'PressureMeter', 'CB', 37, 'Normal', 'Off', '\r\n\r\n 0\r\n 99\r\n P1\r\n CB\r\n'), +(41, 'P2', 'PressureMeter', 'CB', 38, 'Normal', 'Off', '\r\n\r\n 1\r\n 100\r\n P2\r\n CB\r\n'), +(42, 'FlyingStartCollection', 'Flying-Start-Collection', NULL, 37, 'Normal', 'Off', '\r\n'), +(43, 'CombinedMeters', 'CombinedMeters', NULL, 38, 'Normal', 'Off', '\r\n'), +(44, 'Idc1', 'IdcCamera', NULL, 39, 'Off', 'Off', '\r\n\r\n 5\r\n 57600\r\n 1\r\n'), +(45, 'Idc2', 'IdcCamera', NULL, 40, 'AutoDetect', 'Off', '\r\n\r\n 6\r\n 57600\r\n 1\r\n'), +(46, 'Idc3', 'IdcCamera', NULL, 41, 'Off', 'Off', '\r\n\r\n 23\r\n 57600\r\n 1\r\n'), +(47, 'DataEntryForm', 'DataEntryForm-Munich', NULL, 42, 'Normal', 'Off', '\r\n'), +(48, 'Printer4Munich', 'ResultsPrinter4Munich', NULL, 43, 'Normal', 'Off', '\r\n'), +(49, 'Printer', 'BasicResultsPrinter', NULL, 44, 'Normal', 'Off', '\r\n'), +(50, 'Results2Disk', 'BasicResultsWriter', NULL, 45, 'Normal', 'Off', '\r\n'), +(51, 'WaterMeter1', 'WaterMeter', NULL, 46, 'Normal', 'Off', '\r\n\r\n \r\n 2.5\r\n \r\n A\r\n'), +(52, 'WaterMeter2', 'WaterMeter', NULL, 47, 'Normal', 'Off', '\r\n\r\n \r\n 2.5\r\n \r\n A\r\n'), +(53, 'WaterMeter3', 'WaterMeter', NULL, 48, 'Normal', 'Off', '\r\n\r\n \r\n 2.5\r\n \r\n A\r\n'), +(54, 'Bench-ID', 'Bench-ID', NULL, 49, 'Normal', 'Off', '\r\n\r\n 1\r\n'), +(55, 'Idc1-Roi1', 'CameraROI', 'Idc1', 50, 'Off', 'Off', '\r\n\r\n 1\r\n'), +(56, 'Idc1-Roi2', 'CameraROI', 'Idc1', 51, 'Off', 'Off', '\r\n\r\n 2\r\n'), +(57, 'Idc2-Roi1', 'CameraROI', 'Idc2', 52, 'Inherit', 'Off', '\r\n\r\n 1\r\n'), +(58, 'Idc2-Roi2', 'CameraROI', 'Idc2', 53, 'Inherit', 'Off', '\r\n\r\n 2\r\n'), +(59, 'Idc3-Roi1', 'CameraROI', 'Idc3', 54, 'Off', 'Off', '\r\n\r\n 1\r\n'), +(60, 'Idc3-Roi2', 'CameraROI', 'Idc3', 55, 'Off', 'Off', '\r\n\r\n 2\r\n'), +(61, 'RoiDetection', 'ROI Detection', NULL, 56, 'Normal', 'Off', '\r\n'); + +-- -------------------------------------------------------- + +-- +-- Štruktúra tabuľky pre tabuľku `componentprocedure` +-- + +CREATE TABLE IF NOT EXISTS `componentprocedure` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `CmpntName` varchar(255) DEFAULT NULL, + `Parameters` varchar(8000) DEFAULT NULL, + `Procedure_id` int(11) DEFAULT NULL, + PRIMARY KEY (`Id`), + KEY `Procedure_id` (`Procedure_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=31 ; + +-- +-- Sťahujem dáta pre tabuľku `componentprocedure` +-- + +INSERT INTO `componentprocedure` (`Id`, `CmpntName`, `Parameters`, `Procedure_id`) VALUES +(1, 'Sens1', '\r\n\r\n 1\r\n', 1), +(2, 'Sens2', '\r\n\r\n 1\r\n', 1), +(3, 'Sens3', '\r\n\r\n 1\r\n', 1), +(4, 'Printer4Munich', '\r\n\r\n 4/13\r\n \r\n \r\n 2014\r\n', 1), +(5, 'WaterMeter1', '\r\n\r\n \r\n 2.5\r\n \r\n A\r\n', 1), +(6, 'WaterMeter2', '\r\n\r\n \r\n 2.5\r\n \r\n A\r\n', 1), +(7, 'WaterMeter3', '\r\n\r\n \r\n 2.5\r\n \r\n A\r\n', 1), +(8, 'WaterMeter1', '\r\n\r\n \r\n 2.5\r\n \r\n A\r\n', 2), +(9, 'WaterMeter2', '\r\n\r\n \r\n 2.5\r\n \r\n A\r\n', 2), +(10, 'WaterMeter3', '\r\n\r\n \r\n 2.5\r\n \r\n A\r\n', 2), +(11, 'Sens1', '\r\n\r\n 1\r\n', 2), +(12, 'Sens2', '\r\n\r\n 1\r\n', 2), +(13, 'Sens3', '\r\n\r\n 1\r\n', 2), +(14, 'WaterMeter1', '\r\n\r\n \r\n 2.5\r\n \r\n A\r\n', 3), +(15, 'WaterMeter2', '\r\n\r\n \r\n 2.5\r\n \r\n A\r\n', 3), +(16, 'WaterMeter3', '\r\n\r\n \r\n 2.5\r\n \r\n A\r\n', 3), +(17, 'Sens1', '\r\n\r\n 1\r\n', 3), +(18, 'Sens2', '\r\n\r\n 1\r\n', 3), +(19, 'Sens3', '\r\n\r\n 1\r\n', 3), +(20, 'Idc1-Roi1', '\r\n\r\n 60\r\n 1\r\n 520\r\n 478\r\n 40\r\n true\r\n 89\r\n 89\r\n 44\r\n 44\r\n 44\r\n 20\r\n 0\r\n 0\r\n 400\r\n 40\r\n 8\r\n 1\r\n 0\r\n 1\r\n', 3), +(21, 'Idc2-Roi1', '\r\n\r\n 60\r\n 1\r\n 520\r\n 478\r\n 40\r\n true\r\n 89\r\n 89\r\n 44\r\n 44\r\n 20\r\n 44\r\n 0\r\n 0\r\n 400\r\n 66.67\r\n 0\r\n 0\r\n 8\r\n 1\r\n 0\r\n 1\r\n', 3), +(22, 'Idc3-Roi1', '\r\n\r\n 60\r\n 1\r\n 520\r\n 478\r\n 40\r\n true\r\n 89\r\n 89\r\n 44\r\n 44\r\n 44\r\n 20\r\n 0\r\n 0\r\n 400\r\n 40\r\n 8\r\n 1\r\n 0\r\n 1\r\n', 3), +(23, 'Printer4Munich', NULL, 3), +(24, 'Idc1-Roi2', NULL, 3), +(25, 'Idc2-Roi2', NULL, 3), +(26, 'Idc3-Roi2', NULL, 3), +(27, 'Idc1-Roi1', NULL, 1), +(28, 'Idc1-Roi2', NULL, 1), +(29, 'Idc3-Roi1', NULL, 1), +(30, 'Idc3-Roi2', NULL, 1); + +-- -------------------------------------------------------- + +-- +-- Štruktúra tabuľky pre tabuľku `componenttest` +-- + +CREATE TABLE IF NOT EXISTS `componenttest` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `CmpntName` varchar(255) DEFAULT NULL, + `Parameters` varchar(8000) DEFAULT NULL, + `Test_id` int(11) DEFAULT NULL, + PRIMARY KEY (`Id`), + KEY `Test_id` (`Test_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ; + +-- +-- Sťahujem dáta pre tabuľku `componenttest` +-- + +INSERT INTO `componenttest` (`Id`, `CmpntName`, `Parameters`, `Test_id`) VALUES +(1, 'CombinedMeters', '\r\n\r\n 3.05\r\n 3.3\r\n -0.7\r\n -0.5\r\n 0.05\r\n 0.1\r\n', 1); + +-- -------------------------------------------------------- + +-- +-- Štruktúra tabuľky pre tabuľku `feedingpath` +-- + +CREATE TABLE IF NOT EXISTS `feedingpath` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `ItemNr` int(11) NOT NULL DEFAULT '0', + `Name` varchar(255) DEFAULT NULL, + `Qfrom` float DEFAULT NULL, + `Qto` float DEFAULT NULL, + `Pump` varchar(255) DEFAULT NULL, + `ValvesOpen` varchar(8000) DEFAULT NULL, + `ValvesClose` varchar(8000) DEFAULT NULL, + PRIMARY KEY (`Id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=5 ; + +-- +-- Sťahujem dáta pre tabuľku `feedingpath` +-- + +INSERT INTO `feedingpath` (`Id`, `ItemNr`, `Name`, `Qfrom`, `Qto`, `Pump`, `ValvesOpen`, `ValvesClose`) VALUES +(1, 1, 'PF1', 0, 250, '', 'K2', 'K4'), +(2, 2, 'PF2', 0, 10, 'Pumpe1', '', 'K2;K4'), +(3, 3, 'PF3', 10, 250, 'Pumpe2', 'K4', 'K2'), +(4, 0, '', 0, 0, '', '', 'K2;K4'); + +-- -------------------------------------------------------- + +-- +-- Štruktúra tabuľky pre tabuľku `group` +-- + +CREATE TABLE IF NOT EXISTS `group` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `Gid` int(11) DEFAULT NULL, + `Name` varchar(255) DEFAULT NULL, + `User_id` int(11) DEFAULT NULL, + PRIMARY KEY (`Id`), + KEY `User_id` (`User_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=8 ; + +-- +-- Sťahujem dáta pre tabuľku `group` +-- + +INSERT INTO `group` (`Id`, `Gid`, `Name`, `User_id`) VALUES +(1, 0, 'Testers', 2), +(2, 1, 'Testing Specialists', 1), +(3, 2, 'Head Of Lab', 1), +(4, 3, 'Maintenance Specialists', 1), +(5, 4, 'Metrologists', 1), +(6, 5, 'Calibration Specialists', 1), +(7, 6, 'Administrators', 1); + +-- -------------------------------------------------------- + +-- +-- Štruktúra tabuľky pre tabuľku `measurementcorrection` +-- + +CREATE TABLE IF NOT EXISTS `measurementcorrection` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `Measurement` float DEFAULT NULL, + `Correction` float DEFAULT NULL, + `Component_id` int(11) DEFAULT NULL, + PRIMARY KEY (`Id`), + KEY `Component_id` (`Component_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=7 ; + +-- +-- Sťahujem dáta pre tabuľku `measurementcorrection` +-- + +INSERT INTO `measurementcorrection` (`Id`, `Measurement`, `Correction`, `Component_id`) VALUES +(1, 10, 0, 36), +(2, 20, 0, 36), +(3, 50, 0, 36), +(4, 100, 0, 36), +(5, 250, 0, 36), +(6, 150, 0.0005, 36); + +-- -------------------------------------------------------- + +-- +-- Štruktúra tabuľky pre tabuľku `meterspath` +-- + +CREATE TABLE IF NOT EXISTS `meterspath` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `ItemNr` int(11) NOT NULL DEFAULT '0', + `Name` varchar(255) DEFAULT NULL, + `Qfrom` float DEFAULT NULL, + `Qto` float DEFAULT NULL, + `Sensor1` varchar(255) DEFAULT NULL, + `Sensor2` varchar(255) DEFAULT NULL, + `Sensor3` varchar(255) DEFAULT NULL, + PRIMARY KEY (`Id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=4 ; + +-- +-- Sťahujem dáta pre tabuľku `meterspath` +-- + +INSERT INTO `meterspath` (`Id`, `ItemNr`, `Name`, `Qfrom`, `Qto`, `Sensor1`, `Sensor2`, `Sensor3`) VALUES +(1, 0, 'PM1', 0, 250, 'Sens1', 'Sens2', 'Sens3'), +(2, 1, 'CamR1', 0, 250, 'Idc1-Roi1', 'Idc2-Roi1', 'Idc3-Roi1'), +(3, 2, 'CamR2', 0, 250, 'Idc1-Roi2', 'Idc2-Roi2', 'Idc3-Roi2'); + +-- -------------------------------------------------------- + +-- +-- Štruktúra tabuľky pre tabuľku `metertestresult` +-- + +CREATE TABLE IF NOT EXISTS `metertestresult` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `SerialNr` varchar(255) DEFAULT NULL, + `VolumeStart` float DEFAULT NULL, + `VolumeEnd` float DEFAULT NULL, + `VolumeMeter` float DEFAULT NULL, + `VolumeRef` float DEFAULT NULL, + `VolumeErrorPct` float DEFAULT NULL, + `PulsesMeter` float DEFAULT NULL, + `PulsesMaster` float DEFAULT NULL, + `Time` float DEFAULT NULL, + `TestResult_id` int(11) DEFAULT NULL, + PRIMARY KEY (`Id`), + KEY `TestResult_id` (`TestResult_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=319 ; + +-- +-- Sťahujem dáta pre tabuľku `metertestresult` +-- + +INSERT INTO `metertestresult` (`Id`, `SerialNr`, `VolumeStart`, `VolumeEnd`, `VolumeMeter`, `VolumeRef`, `VolumeErrorPct`, `PulsesMeter`, `PulsesMaster`, `Time`, `TestResult_id`) VALUES +(1, 'wm1', 0, 0, 0, -0.0000014201, -100, 0, 43368, 65.643, 12), +(2, 'wm2', 0, 0, 7.5, -0.00000136807, -548219000, 15, 41779, 65.643, 12), +(3, 'wm3', 0, 0, 0, 0, -100, 0, 0, 65.643, 12), +(4, 'wm4', 0, 0, 0, 0, -100, 0, 0, 65.643, 12), +(5, 'wm1', 0, 0, 0, -0.00000141785, -100, 0, 43368, 65.689, 13), +(6, 'wm2', 0, 0, 7, -0.00000128243, -545839000, 14, 39226, 65.689, 13), +(7, 'wm3', 0, 0, 0, 0, -100, 0, 0, 65.689, 13), +(8, 'wm4', 0, 0, 0, 0, -100, 0, 0, 65.689, 13), +(9, 'wm1', 0, 0, 0, -0.00000520273, -100, 0, 14465, 56.854, 14), +(10, 'wm2', 0, 0, 24.5, -0.00000504339, -485784000, 49, 14022, 56.854, 14), +(11, 'wm3', 0, 0, 0, 0, -100, 0, 0, 56.854, 14), +(12, 'wm4', 0, 0, 0, 0, -100, 0, 0, 56.854, 14), +(13, 'wm1', 0, 0, 0, -0.00000141865, -100, 0, 41862, 65.593, 15), +(14, 'wm2', 0, 0, 7.5, 0, -100, 15, 0, 65.593, 15), +(15, 'wm3', 0, 0, 0, 0, -100, 0, 0, 65.593, 15), +(16, 'wm1', 0, 0, 0, -0.00000140309, -100, 0, 41967, 65.605, 16), +(17, 'wm2', 0, 0, 7.5, 0, -100, 15, 0, 65.605, 16), +(18, 'wm3', 0, 0, 0, 0, -100, 0, 0, 65.605, 16), +(19, 'wm1', 0, 0, 0, -0.00000481652, -100, 0, 14324, 56.645, 17), +(20, 'wm2', 0, 0, 25, 0, -100, 50, 0, 56.645, 17), +(21, 'wm3', 0, 0, 0, 0, -100, 0, 0, 56.645, 17), +(22, 'wm1', 0, 0, 0, -0.00000143335, -100, 0, 39130, 65.835, 18), +(23, 'wm2', 0, 0, 7, 0, -100, 14, 0, 65.835, 18), +(24, 'wm3', 0, 0, 0, 0, -100, 0, 0, 65.835, 18), +(25, 'wm1', 0, 0, 7.5, -0.00000158789, -100, 15, 41910, 65.3, 19), +(26, 'wm2', 0, 0, 0, 0, -100, 0, 0, 65.3, 19), +(27, 'wm3', 0, 0, 0, 0, -100, 0, 0, 65.3, 19), +(28, 'wm1', 0, 0, 7, -0.00000146845, -100, 14, 39259, 65.434, 20), +(29, 'wm2', 0, 0, 0, 0, -100, 0, 0, 65.434, 20), +(30, 'wm3', 0, 0, 0, 0, -100, 0, 0, 65.434, 20), +(31, 'wm1', 0, 0, 24.5, -0.0000053534, -100, 49, 14064, 56.942, 21), +(32, 'wm2', 0, 0, 0, 0, -100, 0, 0, 56.942, 21), +(33, 'wm3', 0, 0, 0, 0, -100, 0, 0, 56.942, 21), +(34, 'wm1', 0, 0, 14, -0.0000017251, -100, 14, 39042, 65.181, 22), +(35, 'wm2', 0, 0, 0, 0, -100, 0, 0, 65.181, 22), +(36, 'wm3', 0, 0, 0, 0, -100, 0, 0, 65.181, 22), +(37, 'wm1', 0, 0, 15, -0.00000184669, -100, 15, 41903, 65.272, 23), +(38, 'wm2', 0, 0, 0, 0, -100, 0, 0, 65.272, 23), +(39, 'wm3', 0, 0, 0, 0, -100, 0, 0, 65.272, 23), +(40, 'wm1', 0, 0, 50, -0.00000632833, -100, 50, 14332, 57.218, 24), +(41, 'wm2', 0, 0, 0, 0, -100, 0, 0, 57.218, 24), +(42, 'wm3', 0, 0, 0, 0, -100, 0, 0, 57.218, 24), +(43, 'wm1', 0, 0, 19, -0.00000243629, -100, 19, 53128, 76.309, 25), +(44, 'wm2', 0, 0, 0, 0, -100, 0, 0, 76.309, 25), +(45, 'wm3', 0, 0, 0, 0, -100, 0, 0, 76.309, 25), +(46, 'wm1', 0, 0, 20, -0.00000255392, -100, 20, 55773, 76.156, 26), +(47, 'wm2', 0, 0, 0, 0, -100, 0, 0, 76.156, 26), +(48, 'wm3', 0, 0, 0, 0, -100, 0, 0, 76.156, 26), +(49, 'wm1', 0, 0, 20, -0.00000255049, -100, 20, 55783, 76.172, 27), +(50, 'wm2', 0, 0, 0, 0, -100, 0, 0, 76.172, 27), +(51, 'wm3', 0, 0, 0, 0, -100, 0, 0, 76.172, 27), +(52, 'wm1', 0, 0, 19, -0.00000242366, -100, 19, 53016, 76.181, 28), +(53, 'wm2', 0, 0, 0, 0, -100, 0, 0, 76.181, 28), +(54, 'wm3', 0, 0, 0, 0, -100, 0, 0, 76.181, 28), +(55, 'wm1', 0, 0, 20, -0.0000025397, -100, 20, 55712, 76.206, 29), +(56, 'wm2', 0, 0, 0, 0, -100, 0, 0, 76.206, 29), +(57, 'wm3', 0, 0, 0, 0, -100, 0, 0, 76.206, 29), +(58, 'wm1', 0, 0, 49, -0.00000643354, -100, 49, 14090, 42.913, 30), +(59, 'wm2', 0, 0, 0, 0, -100, 0, 0, 42.913, 30), +(60, 'wm3', 0, 0, 0, 0, -100, 0, 0, 42.913, 30), +(61, 'wm1', 0, 0, 49, -0.00000650082, -100, 49, 14107, 42.918, 31), +(62, 'wm2', 0, 0, 0, 0, -100, 0, 0, 42.918, 31), +(63, 'wm3', 0, 0, 0, 0, -100, 0, 0, 42.918, 31), +(64, 'wm1', 0, 0, 50, -0.00000668643, -100, 50, 14391, 42.91, 32), +(65, 'wm2', 0, 0, 0, 0, -100, 0, 0, 42.91, 32), +(66, 'wm3', 0, 0, 0, 0, -100, 0, 0, 42.91, 32), +(67, 'wm1', 0, 0, 50, -0.00000674168, -100, 50, 14415, 42.908, 33), +(68, 'wm2', 0, 0, 0, 0, -100, 0, 0, 42.908, 33), +(69, 'wm3', 0, 0, 0, 0, -100, 0, 0, 42.908, 33), +(70, 'wm1', 0, 0, 49, -0.00000662135, -100, 49, 14107, 42.927, 34), +(71, 'wm2', 0, 0, 0, 0, -100, 0, 0, 42.927, 34), +(72, 'wm3', 0, 0, 0, 0, -100, 0, 0, 42.927, 34), +(73, 'wm1', 0, 0, 14, 0.0134641, 103880, 14, 38794, 60.867, 35), +(74, 'wm2', 0, 0, 0, 0, -100, 0, 0, 60.867, 35), +(75, 'wm3', 0, 0, 0, 0, -100, 0, 0, 60.867, 35), +(76, 'wm1', 0, 0, 20, 0.0193145, 103449, 20, 55638, 78.562, 36), +(77, 'wm2', 0, 0, 0, 0, -100, 0, 0, 78.562, 36), +(78, 'wm3', 0, 0, 0, 0, -100, 0, 0, 78.562, 36), +(79, 'wm1', 0, 0, 20, 0.0193175, 103433, 20, 55640, 78.606, 37), +(80, 'wm2', 0, 0, 0, 0, -100, 0, 0, 78.606, 37), +(81, 'wm3', 0, 0, 0, 0, -100, 0, 0, 78.606, 37), +(82, 'wm1', 0, 0, 20, 0.0193201, 103419, 20, 55644, 78.652, 38), +(83, 'wm2', 0, 0, 0, 0, -100, 0, 0, 78.652, 38), +(84, 'wm3', 0, 0, 0, 0, -100, 0, 0, 78.652, 38), +(85, 'wm1', 0, 0, 20, 0.0193422, 103301, 20, 55713, 78.661, 39), +(86, 'wm2', 0, 0, 0, 0, -100, 0, 0, 78.661, 39), +(87, 'wm3', 0, 0, 0, 0, -100, 0, 0, 78.661, 39), +(88, 'wm1', 0, 0, 19, 0.0184151, 103076, 19, 53049, 78.694, 40), +(89, 'wm2', 0, 0, 0, 0, -100, 0, 0, 78.694, 40), +(90, 'wm3', 0, 0, 0, 0, -100, 0, 0, 78.694, 40), +(91, 'wm1', 0, 0, 50, 0.0496446, 100616, 50, 14324, 43.227, 41), +(92, 'wm2', 0, 0, 0, 0, -100, 0, 0, 43.227, 41), +(93, 'wm3', 0, 0, 0, 0, -100, 0, 0, 43.227, 41), +(94, 'wm1', 0, 0, 50, 0.0496703, 100564, 50, 14345, 43.175, 42), +(95, 'wm2', 0, 0, 0, 0, -100, 0, 0, 43.175, 42), +(96, 'wm3', 0, 0, 0, 0, -100, 0, 0, 43.175, 42), +(97, 'wm1', 0, 0, 50, 0.049618, 100670, 50, 14330, 43.161, 43), +(98, 'wm2', 0, 0, 0, 0, -100, 0, 0, 43.161, 43), +(99, 'wm3', 0, 0, 0, 0, -100, 0, 0, 43.161, 43), +(100, 'wm1', 0, 0, 49, 0.048745, 100423, 49, 14078, 43.114, 44), +(101, 'wm2', 0, 0, 0, 0, -100, 0, 0, 43.114, 44), +(102, 'wm3', 0, 0, 0, 0, -100, 0, 0, 43.114, 44), +(103, 'wm1', 0, 0, 49, 0.0488142, 100281, 49, 14084, 43.151, 45), +(104, 'wm2', 0, 0, 0, 0, -100, 0, 0, 43.151, 45), +(105, 'wm3', 0, 0, 0, 0, -100, 0, 0, 43.151, 45), +(106, 'wm1', 0, 0, 14, 0.0134812, 103748, 14, 38841, 65.647, 46), +(107, 'wm2', 0, 0, 0, 0, -100, 0, 0, 65.647, 46), +(108, 'wm3', 0, 0, 0, 0, -100, 0, 0, 65.647, 46), +(109, 'wm1', 0, 0, 15, 0.0144675, 103581, 15, 41676, 65.691, 47), +(110, 'wm2', 0, 0, 0, 0, -100, 0, 0, 65.691, 47), +(111, 'wm3', 0, 0, 0, 0, -100, 0, 0, 65.691, 47), +(112, 'wm1', 0, 0, 51, 49.1762, 3.70868, 51, 141729, 221.982, 48), +(113, 'wm2', 0, 0, 0, 0, -100, 0, 0, 221.982, 48), +(114, 'wm3', 0, 0, 0, 0, -100, 0, 0, 221.982, 48), +(115, 'wm1', 0, 0, 0, 0, -100, 0, 0, 227.928, 49), +(116, 'wm2', 0, 0, 0, 0, -100, 0, 0, 227.928, 49), +(117, 'wm3', 0, 0, 0, 0, -100, 0, 0, 227.928, 49), +(118, 'wm1', 0, 0, 0, 0, -100, 0, 0, 221.56, 50), +(119, 'wm2', 0, 0, 0, 0, -100, 0, 0, 221.56, 50), +(120, 'wm3', 0, 0, 0, 0, -100, 0, 0, 221.56, 50), +(121, 'wm1', 0, 0, 0, 0, -100, 0, 0, 225.102, 51), +(122, 'wm2', 0, 0, 0, 0, -100, 0, 0, 225.102, 51), +(123, 'wm3', 0, 0, 0, 0, -100, 0, 0, 225.102, 51), +(124, 'wm1', 0, 0, 0, 0, -100, 0, 0, 224.715, 52), +(125, 'wm2', 0, 0, 0, 0, -100, 0, 0, 224.715, 52), +(126, 'wm3', 0, 0, 0, 0, -100, 0, 0, 224.715, 52), +(127, 'wm1', 0, 0, 0, 0, -100, 0, 0, 224.588, 53), +(128, 'wm2', 0, 0, 0, 0, -100, 0, 0, 224.588, 53), +(129, 'wm3', 0, 0, 0, 0, -100, 0, 0, 224.588, 53), +(130, 'wm1', 0, 0, 0, 0, -100, 0, 0, 214.569, 54), +(131, 'wm2', 0, 0, 0, 0, -100, 0, 0, 214.569, 54), +(132, 'wm3', 0, 0, 0, 0, -100, 0, 0, 214.569, 54), +(133, 'wm1', 0, 0, 0, 0, -100, 0, 0, 223.989, 55), +(134, 'wm2', 0, 0, 0, 0, -100, 0, 0, 223.989, 55), +(135, 'wm3', 0, 0, 177.6, 49.7885, 256.709, 1776, 143594, 223.989, 55), +(136, 'wm1', 0, 0, 0, 0, -100, 0, 0, 223.628, 56), +(137, 'wm2', 0, 0, 0, 0, -100, 0, 0, 223.628, 56), +(138, 'wm3', 0, 0, 113.4, 46.0886, 146.048, 1134, 132892, 223.628, 56), +(139, 'wm1', 0, 0, 0, 0, -100, 0, 0, 223.655, 57), +(140, 'wm2', 0, 0, 0, 0, -100, 0, 0, 223.655, 57), +(141, 'wm3', 0, 0, 17.3, 39.5122, -56.2161, 173, 113938, 223.655, 57), +(142, 'wm1', 0, 0, 0, 0, -100, 0, 0, 223.463, 58), +(143, 'wm2', 0, 0, 0, 0, -100, 0, 0, 223.463, 58), +(144, 'wm3', 0, 0, 0, 5816.1, -100, 0, 16775400, 223.463, 58), +(145, 'wm1', 0, 0, 0, 0, -100, 0, 0, 56.945, 59), +(146, 'wm2', 0, 0, 0, 0, -100, 0, 0, 56.945, 59), +(147, 'wm3', 0, 0, 0, 58059.1, -100, 0, 16775400, 56.945, 59), +(148, 'wm1', 0, 0, 0, 0, -100, 0, 0, 57.148, 60), +(149, 'wm2', 0, 0, 0, 0, -100, 0, 0, 57.148, 60), +(150, 'wm3', 0, 0, 0, 58059.1, -100, 0, 16775400, 57.148, 60), +(151, 'wm1', 0, 0, 0, 0, -100, 0, 0, 222.742, 61), +(152, 'wm2', 0, 0, 0, 0, -100, 0, 0, 222.742, 61), +(153, 'wm3', 0, 0, 0, 5814.02, -100, 0, 16775400, 222.742, 61), +(154, 'wm1', 0, 0, 0, 0, -100, 0, 0, 57.164, 62), +(155, 'wm2', 0, 0, 0, 0, -100, 0, 0, 57.164, 62), +(156, 'wm3', 0, 0, 0, 58059.1, -100, 0, 16775400, 57.164, 62), +(157, 'wm1', 0, 0, 0, 0, -100, 0, 0, 215.445, 63), +(158, 'wm2', 0, 0, 0, 0, -100, 0, 0, 215.445, 63), +(159, 'wm3', 0, 0, 0, 0, -100, 0, 0, 215.445, 63), +(160, 'wm1', 0, 0, 0, 0, -100, 0, 0, 56.661, 64), +(161, 'wm2', 0, 0, 0, 0, -100, 0, 0, 56.661, 64), +(162, 'wm3', 0, 0, 4.8, 49.5899, -90.3206, 48, 14288, 56.661, 64), +(163, 'wm1', 0, 0, 0, 0, -100, 0, 0, 216.739, 65), +(164, 'wm2', 0, 0, 0, 0, -100, 0, 0, 216.739, 65), +(165, 'wm3', 0, 0, 0, 5816.55, -100, 0, 16777200, 216.739, 65), +(166, 'wm1', 0, 0, 0, 0, -100, 0, 0, 217.506, 66), +(167, 'wm2', 0, 0, 0, 0, -100, 0, 0, 217.506, 66), +(168, 'wm3', 0, 0, 0, 5817.48, -100, 0, 16777200, 217.506, 66), +(169, 'wm1', 0, 0, 0, 0, -100, 0, 0, 55.072, 67), +(170, 'wm2', 0, 0, 0, 0, -100, 0, 0, 55.072, 67), +(171, 'wm3', 0, 0, 47, 49.6764, -5.38774, 47, 14341, 55.072, 67), +(172, 'wm1', 0, 0, 0, 0, -100, 0, 0, 216.334, 68), +(173, 'wm2', 0, 0, 0, 0, -100, 0, 0, 216.334, 68), +(174, 'wm3', 0, 0, 0, 5815.24, -100, 0, 16777200, 216.334, 68), +(175, 'wm1', 0, 0, 0, 0, -100, 0, 0, 54.924, 69), +(176, 'wm2', 0, 0, 0, 0, -100, 0, 0, 54.924, 69), +(177, 'wm3', 0, 0, 46, 48.3776, -4.91467, 46, 13967, 54.924, 69), +(178, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 70), +(179, 'wm2', 0, 0, 0, 0, -100, 0, 0, 44.087, 70), +(180, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 70), +(181, 'wm1', 0, 0, 0, 0, -100, 0, 0, 173.4, 71), +(182, 'wm2', 0, 0, 0, 0, -100, 0, 0, 173.4, 71), +(183, 'wm3', 0, 0, 0, 0, -100, 0, 0, 173.4, 71), +(184, 'wm1', 0, 0, 0, 0, -100, 0, 0, 69.588, 72), +(185, 'wm2', 0, 0, 0, 0, -100, 0, 0, 69.588, 72), +(186, 'wm3', 0, 0, 0, 0, -100, 0, 0, 69.588, 72), +(187, 'wm1', 0, 0, 0, 0, -100, 0, 0, 87.774, 73), +(188, 'wm2', 0, 0, 0, 0, -100, 0, 0, 87.774, 73), +(189, 'wm3', 0, 0, 0, 0, -100, 0, 0, 87.774, 73), +(190, 'wm1', 0, 0, 0, 0, -100, 0, 0, 73.019, 74), +(191, 'wm2', 0, 0, 0, 0, -100, 0, 0, 73.019, 74), +(192, 'wm3', 0, 0, 0, 0, -100, 0, 0, 73.019, 74), +(193, 'wm1', 0, 0, 0, 0, -100, 0, 0, 89.881, 75), +(194, 'wm2', 0, 0, 0, 0, -100, 0, 0, 89.881, 75), +(195, 'wm3', 0, 0, 0, 0, -100, 0, 0, 89.881, 75), +(196, 'wm1', 0, 0, 0, 0, -100, 0, 0, 66.484, 76), +(197, 'wm2', 0, 0, 0, 0, -100, 0, 0, 66.484, 76), +(198, 'wm3', 0, 0, 0, 0, -100, 0, 0, 66.484, 76), +(199, 'wm1', 0, 0, 0, 0, -100, 0, 0, 66.335, 77), +(200, 'wm2', 0, 0, 0, 0, -100, 0, 0, 66.335, 77), +(201, 'wm3', 0, 0, 0, 0, -100, 0, 0, 66.335, 77), +(202, 'wm1', 0, 0, 0, 0, -100, 0, 0, 89.601, 78), +(203, 'wm2', 0, 0, 0, 0, -100, 0, 0, 89.601, 78), +(204, 'wm3', 0, 0, 0, 0, -100, 0, 0, 89.601, 78), +(205, 'wm1', 0, 0, 0, 0, -100, 0, 0, 66.414, 79), +(206, 'wm2', 0, 0, 0, 0, -100, 0, 0, 66.414, 79), +(207, 'wm3', 0, 0, 0, 0, -100, 0, 0, 66.414, 79), +(208, 'wm1', 0, 0, 0, 0, -100, 0, 0, 89.587, 80), +(209, 'wm2', 0, 0, 0, 0, -100, 0, 0, 89.587, 80), +(210, 'wm3', 0, 0, 0, 0, -100, 0, 0, 89.587, 80), +(211, 'wm1', 0, 0, 0, 0, -100, 0, 0, 67.821, 81), +(212, 'wm2', 0, 0, 0, 0, -100, 0, 0, 67.821, 81), +(213, 'wm3', 0, 0, 0, 0, -100, 0, 0, 67.821, 81), +(214, 'wm1', 0, 0, 0, 0, -100, 0, 0, 89.595, 82), +(215, 'wm2', 0, 0, 0, 0, -100, 0, 0, 89.595, 82), +(216, 'wm3', 0, 0, 0, 0, -100, 0, 0, 89.595, 82), +(217, 'wm1', 0, 0, 0, 0, -100, 0, 0, 66.883, 83), +(218, 'wm2', 0, 0, 0, 0, -100, 0, 0, 66.883, 83), +(219, 'wm3', 0, 0, 0, 0, -100, 0, 0, 66.883, 83), +(220, 'wm1', 0, 0, 0, 0, -100, 0, 0, 90.391, 84), +(221, 'wm2', 0, 0, 0, 0, -100, 0, 0, 90.391, 84), +(222, 'wm3', 0, 0, 0, 0, -100, 0, 0, 90.391, 84), +(223, 'wm1', 0, 0, 0, 0, -100, 0, 0, 66.953, 85), +(224, 'wm2', 0, 0, 0, 0, -100, 0, 0, 66.953, 85), +(225, 'wm3', 0, 0, 0, 0, -100, 0, 0, 66.953, 85), +(226, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 86), +(227, 'wm2', 0, 0, -0.5, 0, -100, -20, 0, 71.498, 86), +(228, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 86), +(229, 'wm1', 0, 0, 0, 0, -100, 0, 0, 67.139, 87), +(230, 'wm2', 0, 0, 0, 0, -100, 0, 0, 67.139, 87), +(231, 'wm3', 0, 0, 0, 0, -100, 0, 0, 67.139, 87), +(232, 'wm1', 0, 0, 0, 0, -100, 0, 0, 68.254, 88), +(233, 'wm2', 0, 0, 0, 0, -100, 0, 0, 68.254, 88), +(234, 'wm3', 0, 0, 0, 0, -100, 0, 0, 68.254, 88), +(235, 'wm1', 0, 0, 0, 0, -100, 0, 0, 68.379, 89), +(236, 'wm2', 0, 0, 0, 0, -100, 0, 0, 68.379, 89), +(237, 'wm3', 0, 0, 0, 0, -100, 0, 0, 68.379, 89), +(238, 'wm1', 0, 0, 0, 0, -100, 0, 0, 90.174, 90), +(239, 'wm2', 0, 0, 0, 0, -100, 0, 0, 90.174, 90), +(240, 'wm3', 0, 0, 0, 0, -100, 0, 0, 90.174, 90), +(241, 'wm1', 0, 0, 0, 0, -100, 0, 0, 67.109, 91), +(242, 'wm2', 0, 0, 0, 0, -100, 0, 0, 67.109, 91), +(243, 'wm3', 0, 0, 0, 0, -100, 0, 0, 67.109, 91), +(244, 'wm1', 0, 0, 0, 0, -100, 0, 0, 68.109, 92), +(245, 'wm2', 0, 0, 0, 0, -100, 0, 0, 68.109, 92), +(246, 'wm3', 0, 0, 0, 0, -100, 0, 0, 68.109, 92), +(247, 'wm1', 0, 0, 0, 0, -100, 0, 0, 88.966, 93), +(248, 'wm2', 0, 0, 0, 0, -100, 0, 0, 88.966, 93), +(249, 'wm3', 0, 0, 0, 0, -100, 0, 0, 88.966, 93), +(250, 'wm1', 0, 0, 0, 0, -100, 0, 0, 66.832, 94), +(251, 'wm2', 0, 0, 0, 0, -100, 0, 0, 66.832, 94), +(252, 'wm3', 0, 0, 0, 0, -100, 0, 0, 66.832, 94), +(253, 'wm1', 0, 0, 0, 0, -100, 0, 0, 90.071, 95), +(254, 'wm2', 0, 0, 0, 0, -100, 0, 0, 90.071, 95), +(255, 'wm3', 0, 0, 0, 0, -100, 0, 0, 90.071, 95), +(256, 'wm1', 0, 0, 0, 0, -100, 0, 0, 67.071, 96), +(257, 'wm2', 0, 0, 0, 0, -100, 0, 0, 67.071, 96), +(258, 'wm3', 0, 0, 0, 0, -100, 0, 0, 67.071, 96), +(259, 'wm1', 0, 0, 0, 0, -100, 0, 0, 90.5, 97), +(260, 'wm2', 0, 0, 0, 0, -100, 0, 0, 90.5, 97), +(261, 'wm3', 0, 0, 0, 0, -100, 0, 0, 90.5, 97), +(262, 'wm1', 0, 0, 0, 0, -100, 0, 0, 66.515, 98), +(263, 'wm2', 0, 0, 0, 0, -100, 0, 0, 66.515, 98), +(264, 'wm3', 0, 0, 0, 0, -100, 0, 0, 66.515, 98), +(265, 'wm1', 0, 0, 0, 0, -100, 0, 0, 73.818, 99), +(266, 'wm2', 0, 0, 0, 0, -100, 0, 0, 73.818, 99), +(267, 'wm3', 0, 0, 0, 0, -100, 0, 0, 73.818, 99), +(268, 'wm1', 0, 0, 0, 0, -100, 0, 0, 89.951, 100), +(269, 'wm2', 0, 0, 0, 0, -100, 0, 0, 89.951, 100), +(270, 'wm3', 0, 0, 0, 0, -100, 0, 0, 89.951, 100), +(271, 'wm1', 0, 0, 0, 0, -100, 0, 0, 224.321, 101), +(272, 'wm2', 0, 0, 0, 0, -100, 0, 0, 224.321, 101), +(273, 'wm3', 0, 0, 0, 0, -100, 0, 0, 224.321, 101), +(274, 'wm1', 0, 0, 0, 0, -100, 0, 0, 55.013, 102), +(275, 'wm2', 0, 0, 0, 0, -100, 0, 0, 55.013, 102), +(276, 'wm3', 0, 0, 0, 0, -100, 0, 0, 55.013, 102), +(277, 'wm1', 0, 0, 0, 0, -100, 0, 0, 66.765, 103), +(278, 'wm2', 0, 0, 0, 0, -100, 0, 0, 66.765, 103), +(279, 'wm3', 0, 0, 0, 0, -100, 0, 0, 66.765, 103), +(280, 'wm1', 0, 0, 0, 0, -100, 0, 0, 90.12, 104), +(281, 'wm2', 0, 0, 0, 0, -100, 0, 0, 90.12, 104), +(282, 'wm3', 0, 0, 0, 0, -100, 0, 0, 90.12, 104), +(283, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 105), +(284, 'wm2', 0, 0, -0.5, 0, -100, -20, 0, 71.567, 105), +(285, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 105), +(286, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 106), +(287, 'wm2', 0, 0, -0.5, 0, -100, -20, 0, 72.269, 106), +(288, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 106), +(289, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 107), +(290, 'wm2', 0, 0, 523.65, 0, -100, 20946, 0, 72.508, 107), +(291, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 107), +(292, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 108), +(293, 'wm2', 0, 0, -0.5, 0, -100, -20, 0, 72.255, 108), +(294, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 108), +(295, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 109), +(296, 'wm2', 0, 0, -0.5, 0, -100, -20, 0, 72.134, 109), +(297, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 109), +(298, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 110), +(299, 'wm2', 0, 0, 625.075, 0, -100, 25003, 0, 72.128, 110), +(300, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 110), +(301, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 111), +(302, 'wm2', 0, 0, -62, 0, -100, -2480, 0, 103.047, 111), +(303, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 111), +(304, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 112), +(305, 'wm2', 0, 0, 0, 0, -100, 0, 0, 110.424, 112), +(306, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 112), +(307, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 113), +(308, 'wm2', 0, 0, 0, 0, -100, 0, 0, 109.842, 113), +(309, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 113), +(310, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 114), +(311, 'wm2', 0, 0, -642.025, 0, -100, -25681, 0, 107.2, 114), +(312, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 114), +(313, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 115), +(314, 'wm2', 0, 0, -1522.07, 0, -100, -60883, 0, 35.92, 115), +(315, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 115), +(316, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 116), +(317, 'wm2', 0, 0, -3519.18, 0, -100, -140767, 0, 35.797, 116), +(318, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 116); + +-- -------------------------------------------------------- + +-- +-- Štruktúra tabuľky pre tabuľku `outputpath` +-- + +CREATE TABLE IF NOT EXISTS `outputpath` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `ItemNr` int(11) NOT NULL DEFAULT '0', + `Name` varchar(255) DEFAULT NULL, + `Qfrom` float DEFAULT NULL, + `Qto` float DEFAULT NULL, + `RegulValve` varchar(255) DEFAULT NULL, + `FlowMeter` varchar(255) DEFAULT NULL, + `Diverter` varchar(255) DEFAULT NULL, + `TempDiv` varchar(255) DEFAULT NULL, + `Balance` varchar(255) DEFAULT NULL, + `EmptyTankValve` varchar(255) DEFAULT NULL, + `ValvesOpen` varchar(8000) DEFAULT NULL, + `ValvesClose` varchar(8000) DEFAULT NULL, + PRIMARY KEY (`Id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=7 ; + +-- +-- Sťahujem dáta pre tabuľku `outputpath` +-- + +INSERT INTO `outputpath` (`Id`, `ItemNr`, `Name`, `Qfrom`, `Qto`, `RegulValve`, `FlowMeter`, `Diverter`, `TempDiv`, `Balance`, `EmptyTankValve`, `ValvesOpen`, `ValvesClose`) VALUES +(1, 1, 'PO1', 0.1, 0.3, 'RV1', 'E1', 'KL1', 'T3', 'Waage1', 'K19', 'K7', 'K10;K13;K16;Vl5'), +(2, 2, 'PO2', 0.2, 2.5, 'RV2', 'E2', 'KL1', 'T3', 'Waage1', 'K19', 'K10', 'K7;K13;K16;Vl5'), +(3, 3, 'PO3', 2, 25, 'RV3', 'E3', 'KL2', 'T4', 'Waage2', 'K20', 'K13', 'K7;K10;K16;Vl5'), +(4, 4, 'PO4', 20, 250, 'RV4', 'E4', 'KL2', 'T4', 'Waage2', 'K20', 'K16', 'K7;K10;K13;Vl5'), +(5, 5, 'PO5', 0, 0.2, 'RV5', 'E5', 'KL1', 'T3', 'Waage1', 'K19', 'Vl5', 'K7;K10;K13;K16'), +(6, 0, '', 0, 0, '---', '---', '---', '---', '---', '---', '', 'K7;K10;K13;K16;Vl5'); + +-- -------------------------------------------------------- + +-- +-- Štruktúra tabuľky pre tabuľku `procedure` +-- + +CREATE TABLE IF NOT EXISTS `procedure` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `ItemNr` int(11) DEFAULT NULL, + `Name` varchar(255) DEFAULT NULL, + `Description` varchar(255) DEFAULT NULL, + `CreationUser` varchar(255) DEFAULT NULL, + `CreationTime` datetime DEFAULT NULL, + `LastChgUser` varchar(255) DEFAULT NULL, + `LastChgTime` datetime DEFAULT NULL, + `LongDescription` varchar(255) DEFAULT NULL, + `Watermeters` varchar(255) DEFAULT NULL, + `DataEntry` varchar(255) DEFAULT NULL, + `ResultsPrinter` varchar(255) DEFAULT NULL, + `ResultsWriter` varchar(255) DEFAULT NULL, + `TransitionStart` varchar(255) DEFAULT NULL, + `TransitionEnd` varchar(255) DEFAULT NULL, + PRIMARY KEY (`Id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=4 ; + +-- +-- Sťahujem dáta pre tabuľku `procedure` +-- + +INSERT INTO `procedure` (`Id`, `ItemNr`, `Name`, `Description`, `CreationUser`, `CreationTime`, `LastChgUser`, `LastChgTime`, `LongDescription`, `Watermeters`, `DataEntry`, `ResultsPrinter`, `ResultsWriter`, `TransitionStart`, `TransitionEnd`) VALUES +(1, 0, 'Procedure1', '', 'admin', '2013-12-30 12:26:17', 'admin', '2014-07-26 15:39:40', '', '', 'DataEntryForm', 'Printer4Munich', '', 'Tr1', ''), +(2, 0, 'Procedure2', '', 'admin', '2014-01-12 17:10:26', 'admin', '2014-02-09 23:46:45', '', '', '', '', '', '', ''), +(3, 0, 'Procedure3', '', 'admin', '2014-01-16 19:16:14', 'admin', '2014-07-27 11:11:46', '', '', '', '', '', '', ''); + +-- -------------------------------------------------------- + +-- +-- Štruktúra tabuľky pre tabuľku `test` +-- + +CREATE TABLE IF NOT EXISTS `test` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `ItemNr` int(11) DEFAULT NULL, + `Name` varchar(255) DEFAULT NULL, + `Qfrom` float DEFAULT NULL, + `Qto` float DEFAULT NULL, + `Volume` float DEFAULT NULL, + `TstTime` float DEFAULT NULL, + `Repeats` int(11) DEFAULT NULL, + `Emptying` tinyint(1) DEFAULT NULL, + `Zeroing` tinyint(1) DEFAULT NULL, + `Method` varchar(255) DEFAULT NULL, + `ErrLimLo` float DEFAULT NULL, + `ErrLimHi` float DEFAULT NULL, + `TolerRed` double DEFAULT NULL, + `RedType` varchar(255) DEFAULT NULL, + `FeedingPath` varchar(255) DEFAULT NULL, + `BenchPath` varchar(255) DEFAULT NULL, + `OutputPath` varchar(255) DEFAULT NULL, + `MetersPath` varchar(255) DEFAULT NULL, + `TransitionStart` varchar(255) DEFAULT NULL, + `TransitionEnd` varchar(255) DEFAULT NULL, + `Procedure_id` int(11) DEFAULT NULL, + PRIMARY KEY (`Id`), + KEY `Procedure_id` (`Procedure_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=10 ; + +-- +-- Sťahujem dáta pre tabuľku `test` +-- + +INSERT INTO `test` (`Id`, `ItemNr`, `Name`, `Qfrom`, `Qto`, `Volume`, `TstTime`, `Repeats`, `Emptying`, `Zeroing`, `Method`, `ErrLimLo`, `ErrLimHi`, `TolerRed`, `RedType`, `FeedingPath`, `BenchPath`, `OutputPath`, `MetersPath`, `TransitionStart`, `TransitionEnd`, `Procedure_id`) VALUES +(1, 3, 'Q4', 3, 3.3, 50, 57.1429, 1, 0, 0, 'FlyingStartCollection', -2, 2, 0, 'Fix', 'PF1', 'PT1', 'PO3', 'PM1', '', '', 1), +(2, 2, 'Q3', 0.8, 0.85, 50, 218.182, 1, 0, 0, 'FlyingStartCollection', -2, 2, 0, 'Fix', 'PF1', 'PT1', 'PO2', 'PM1', '', '', 1), +(3, 0, 'Q1', 0.8, 0.85, 15, 65.4545, 2, 0, 0, 'FlyingStartCollection', -2, 2, 0, 'Fix', 'PF1', 'PT1', 'PO2', 'PM1', NULL, NULL, 2), +(4, 1, 'Q2', 3, 3.3, 50, 57.1429, 1, 0, 0, 'FlyingStartCollection', -2, 2, 0, 'Fix', 'PF1', 'PT1', 'PO3', 'PM1', NULL, NULL, 2), +(5, 0, 'Q1', 0.1, 0.11, 1, 34.2857, 1, 0, 0, 'RoiDetection', 0, 0, 0, 'Fix', 'PF1', 'PT1', 'PO1', 'CamR1', '', 'Empty', 3), +(6, 1, 'Q2', 0.1, 0.11, 1, 34.2857, 1, 0, 0, 'FlyingStartCollection', -5, 5, 0, 'Fix', 'PF1', 'PT1', 'PO1', 'CamR1', 'Empty', '', 3), +(7, 0, 'Q1', 0.1, 0.11, 2, 68.5714, 1, 0, 0, 'FlyingStartCollection', 0, 0, 0.20000000298023224, 'Fix', 'PF1', 'PT1', 'PO1', 'PM1', NULL, NULL, 1), +(9, 1, 'Q2', 0.2, 0.22, 5, 85.7143, 1, 0, 0, 'FlyingStartCollection', 0, 0, 0.20000000298023224, 'Fix', 'PF1', 'PT1', 'PO1', 'PM1', NULL, NULL, 1); + +-- -------------------------------------------------------- + +-- +-- Štruktúra tabuľky pre tabuľku `testresult` +-- + +CREATE TABLE IF NOT EXISTS `testresult` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `Name` varchar(255) NOT NULL, + `TestName` varchar(255) NOT NULL, + `Qfrom` float NOT NULL, + `Qto` float NOT NULL, + `Volume` float NOT NULL, + `TstTime` float NOT NULL, + `Repeats` int(11) NOT NULL, + `Emptying` tinyint(4) NOT NULL, + `Zeroing` tinyint(4) NOT NULL, + `Method` varchar(255) NOT NULL, + `ErrLimLo` float NOT NULL, + `ErrLimHi` float NOT NULL, + `FeedingPath` varchar(4000) NOT NULL, + `BenchPath` varchar(4000) NOT NULL, + `OutputPath` varchar(4000) NOT NULL, + `MetersPath` varchar(4000) NOT NULL, + `TimeStart` datetime DEFAULT NULL, + `TimeEnd` datetime DEFAULT NULL, + `RepetitionNr` int(11) DEFAULT NULL, + `AmbientTempAve` float DEFAULT NULL, + `AmbientPressAve` float DEFAULT NULL, + `AmbientHumiAve` float DEFAULT NULL, + `PressInAvrg` float DEFAULT NULL, + `PressInStart` float DEFAULT NULL, + `PressInEnd` float DEFAULT NULL, + `PressOutAvrg` float DEFAULT NULL, + `PressOutStart` float DEFAULT NULL, + `PressOutEnd` float DEFAULT NULL, + `TempInAvrg` float DEFAULT NULL, + `TempInStart` float DEFAULT NULL, + `TempInEnd` float DEFAULT NULL, + `TempOutAvrg` float DEFAULT NULL, + `TempOutStart` float DEFAULT NULL, + `TempOutEnd` float DEFAULT NULL, + `TempDivAvrg` float DEFAULT NULL, + `TempDivStart` float DEFAULT NULL, + `TempDivEnd` float DEFAULT NULL, + `MassStartRaw` float DEFAULT NULL, + `MassStart` float DEFAULT NULL, + `MassEndRaw` float DEFAULT NULL, + `MassEnd` float DEFAULT NULL, + `MassDiff` float DEFAULT NULL, + `DensityIn` float DEFAULT NULL, + `DensityOut` float DEFAULT NULL, + `DensityDiv` float DEFAULT NULL, + `FlowMass` float DEFAULT NULL, + `FlowVolume` float DEFAULT NULL, + `VolumeCTV` float DEFAULT NULL, + `VolumeMaster` float DEFAULT NULL, + `Time` float DEFAULT NULL, + `ErrorMaster` float DEFAULT NULL, + `PulsesMaster` float DEFAULT NULL, + `ConstMaster` float DEFAULT NULL, + `TimeDivStart0` float DEFAULT NULL, + `TimeDivStart1` float DEFAULT NULL, + `TimeDivStart2` float DEFAULT NULL, + `TimeDivStart3` float DEFAULT NULL, + `TimeDivStart4` float DEFAULT NULL, + `TimeDivStart5` float DEFAULT NULL, + `TimeDivEnd0` float DEFAULT NULL, + `TimeDivEnd1` float DEFAULT NULL, + `TimeDivEnd2` float DEFAULT NULL, + `TimeDivEnd3` float DEFAULT NULL, + `TimeDivEnd4` float DEFAULT NULL, + `TimeDivEnd5` float DEFAULT NULL, + `Test_id` int(11) DEFAULT NULL, + PRIMARY KEY (`Id`), + KEY `Test_id` (`Test_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=117 ; + +-- +-- Sťahujem dáta pre tabuľku `testresult` +-- + +INSERT INTO `testresult` (`Id`, `Name`, `TestName`, `Qfrom`, `Qto`, `Volume`, `TstTime`, `Repeats`, `Emptying`, `Zeroing`, `Method`, `ErrLimLo`, `ErrLimHi`, `FeedingPath`, `BenchPath`, `OutputPath`, `MetersPath`, `TimeStart`, `TimeEnd`, `RepetitionNr`, `AmbientTempAve`, `AmbientPressAve`, `AmbientHumiAve`, `PressInAvrg`, `PressInStart`, `PressInEnd`, `PressOutAvrg`, `PressOutStart`, `PressOutEnd`, `TempInAvrg`, `TempInStart`, `TempInEnd`, `TempOutAvrg`, `TempOutStart`, `TempOutEnd`, `TempDivAvrg`, `TempDivStart`, `TempDivEnd`, `MassStartRaw`, `MassStart`, `MassEndRaw`, `MassEnd`, `MassDiff`, `DensityIn`, `DensityOut`, `DensityDiv`, `FlowMass`, `FlowVolume`, `VolumeCTV`, `VolumeMaster`, `Time`, `ErrorMaster`, `PulsesMaster`, `ConstMaster`, `TimeDivStart0`, `TimeDivStart1`, `TimeDivStart2`, `TimeDivStart3`, `TimeDivStart4`, `TimeDivStart5`, `TimeDivEnd0`, `TimeDivEnd1`, `TimeDivEnd2`, `TimeDivEnd3`, `TimeDivEnd4`, `TimeDivEnd5`, `Test_id`) VALUES +(12, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-16 16:14:45', '2014-01-16 16:16:01', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20.6817, 20.707, 20.66, 20.6444, 20.64, 20.649, 21.0332, 21.476, 20.977, 15.004, 15.004, 30.0003, 30.0003, 14.9963, -10653400, -10560100, -11565500, 0.82243, 0.000825831, -0.0000014201, 0.0150583, 65.643, -1060470, 43368, -0.0000000000327453, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2), +(13, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-16 16:16:12', '2014-01-16 16:17:29', 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20.5147, 20.594, 20.434, 20.6606, 20.655, 20.665, 20.8344, 20.985, 20.671, 30.001, 30.001, 45.031, 45.031, 15.03, -10240700, -10600600, -11042300, 0.823699, 0.000825252, -0.00000141785, 0.0150583, 65.689, -1062160, 43368, -0.0000000000326934, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2), +(14, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-16 16:18:24', '2014-01-16 16:19:32', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19.9611, 20.087, 19.855, 20.253, 20.359, 20.162, 19.5097, 19.689, 19.392, -0.15, -0.15, 49.9, 49.9, 50.05, -8963330, -9619950, -8018890, 3.16917, 0.00318029, -0.00000520273, 0.0502257, 56.854, -965472, 14465, -0.000000000359677, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1), +(15, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-16 18:07:01', '2014-01-16 18:08:17', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21.1302, 21.238, 21.055, 20.5009, 20.49, 20.52, 21.1938, 22.347, 21.157, 45.0307, 45.0307, 60.032, 60.032, 15.0013, -11827900, -10207200, -12002400, 0.823332, 0.00082646, -0.00000146969, 0.0150583, 65.593, -1024690, 43368, -0.0000000000338887, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2), +(16, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-16 18:08:28', '2014-01-16 18:09:44', 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20.8347, 20.945, 20.74, 20.5656, 20.539, 20.586, 21.0495, 21.208, 20.886, 60.033, 60.033, 75.0617, 75.0617, 15.0287, -11043100, -10365100, -11609200, 0.824681, 0.000826309, -0.00000144993, 0.0150583, 65.605, -1038660, 43368, -0.0000000000334332, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2), +(17, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-16 18:09:57', '2014-01-16 18:11:05', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20.5572, 20.668, 20.437, 20.5237, 20.59, 20.427, 20.4795, 20.667, 20.07, 37.5333, 37.5333, 87.45, 87.45, 49.9167, -10344600, -10262600, -10155400, 3.17239, 0.00319203, -0.00000486393, 0.0502257, 56.645, -1032710, 14465, -0.000000000336255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1), +(18, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-16 18:11:58', '2014-01-16 18:13:15', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20.089, 20.18, 20.028, 20.1851, 20.23, 20.162, 19.7536, 20.562, 19.612, 75.064, 75.064, 90.0983, 90.0983, 15.0343, -9246400, -9463970, -8518710, 0.822109, 0.000823422, -0.00000158859, 0.0150583, 65.835, -948008, 43368, -0.0000000000366304, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2), +(19, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-16 18:58:11', '2014-01-16 18:59:28', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20.4796, 20.516, 20.472, 20.0509, 20.045, 20.06, 20.5582, 21.385, 20.513, 105.137, 105.137, 120.175, 120.175, 15.0382, -10155600, -9161340, -10347100, 0.829056, 0.000830188, -0.00000164317, 0.0150587, 65.3, -916540, 43369, -0.0000000000378881, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2), +(20, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-16 19:02:57', '2014-01-16 19:04:13', 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20.0879, 20.11, 20.067, 20.1025, 20.116, 20.088, 19.71, 19.767, 19.663, -0.015, -0.015, 15.018, 15.018, 15.033, -9243910, -9276700, -8427500, 0.827075, 0.000828488, -0.00000162218, 0.0150587, 65.434, -928399, 43369, -0.0000000000374041, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2), +(21, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-16 19:04:26', '2014-01-16 19:05:35', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20.009, 20.048, 19.945, 20.015, 20.073, 19.948, 20.0492, 20.382, 19.64, 62.2, 62.2, 112.15, 112.15, 49.95, -9068620, -9081830, -9157540, 3.15795, 0.00317516, -0.00000550566, 0.0502222, 56.942, -912293, 14464, -0.000000000380646, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1), +(22, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-16 19:12:23', '2014-01-16 19:13:39', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19.4851, 19.484, 19.495, 19.427, 19.423, 19.432, 19.3704, 20.249, 19.264, 15.019, 15.019, 30.0557, 30.0557, 15.0367, -7969830, -7854850, -7744200, 0.830487, 0.000831703, -0.00000191629, 0.0150587, 65.181, -785926, 43369, -0.0000000000441856, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2), +(23, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-16 19:13:50', '2014-01-16 19:15:06', 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19.516, 19.502, 19.53, 19.4375, 19.435, 19.44, 19.233, 19.243, 19.227, 30.0567, 30.0567, 45.094, 45.094, 15.0373, -8031570, -7875550, -7480540, 0.829367, 0.000830563, -0.00000191134, 0.015059, 65.272, -787979, 43370, -0.0000000000440705, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2), +(24, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-16 19:15:19', '2014-01-16 19:16:28', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19.5343, 19.539, 19.516, 19.4179, 19.439, 19.391, 19.1755, 19.149, 19.144, 99.45, 99.45, 149.45, 149.45, 50, -8068290, -7836940, -7372300, 3.14586, 0.00315984, -0.00000638661, 0.0502222, 57.218, -786467, 14464, -0.000000000441552, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1), +(25, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-16 19:21:22', '2014-01-16 19:22:49', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19.4173, 19.404, 19.432, 19.275, 19.268, 19.281, 19.2343, 19.514, 19.188, 45.096, 45.096, 65.112, 65.112, 20.016, -7835780, -7560240, -7482960, 0.944287, 0.00094671, -0.00000265026, 0.0200674, 76.309, -757284, 57794, -0.0000000000458571, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5), +(26, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-16 19:23:00', '2014-01-16 19:24:27', 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19.4584, 19.443, 19.468, 19.287, 19.284, 19.29, 19.1715, 19.181, 19.165, 65.113, 65.113, 85.1613, 85.1613, 20.0483, -7916720, -7583320, -7364810, 0.947713, 0.000948612, -0.00000264647, 0.0200674, 76.156, -758370, 57794, -0.0000000000457913, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5), +(27, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-16 19:24:38', '2014-01-16 19:26:05', 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19.4885, 19.478, 19.497, 19.2926, 19.29, 19.294, 19.158, 19.154, 19.157, 85.162, 85.162, 105.208, 105.208, 20.0457, -7976610, -7593900, -7339700, 0.94739, 0.000948413, -0.00000264243, 0.0200674, 76.172, -759527, 57794, -0.0000000000457216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5), +(28, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-16 19:26:16', '2014-01-16 19:27:44', 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19.5015, 19.499, 19.506, 19.2965, 19.295, 19.297, 19.1523, 19.153, 19.148, 105.209, 105.209, 125.272, 125.272, 20.0632, -8002540, -7601500, -7329090, 0.948104, 0.000948301, -0.00000264209, 0.0200674, 76.181, -759626, 57794, -0.0000000000457157, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5), +(29, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-16 19:31:21', '2014-01-16 19:32:48', 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19.5373, 19.531, 19.541, 19.3035, 19.303, 19.303, 19.1628, 19.162, 19.167, -0.0146667, -0.0146667, 20.0267, 20.0267, 20.0413, -8074350, -7614920, -7348710, 0.94676, 0.000947973, -0.00000263456, 0.020067, 76.206, -761783, 57793, -0.0000000000455862, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5), +(30, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-16 19:33:05', '2014-01-16 19:34:00', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19.5399, 19.547, 19.522, 19.2907, 19.303, 19.277, 19.2285, 19.281, 19.17, 135.35, 135.35, 185.5, 185.5, 50.15, -8079450, -7590320, -7472090, 4.20712, 0.00421929, -0.0000066139, 0.0502951, 42.913, -760546, 14485, -0.000000000456604, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6), +(31, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-16 19:34:11', '2014-01-16 19:35:05', 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19.4769, 19.499, 19.457, 19.25, 19.264, 19.24, 19.0993, 19.122, 19.082, 185.5, 185.5, 235.6, 235.6, 50.1, -7953420, -7512820, -7230970, 4.20243, 0.00421909, -0.00000667547, 0.0502986, 42.918, -753584, 14486, -0.000000000460822, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6), +(32, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-16 19:35:16', '2014-01-16 19:36:10', 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19.4244, 19.441, 19.409, 19.2175, 19.228, 19.206, 19.0555, 19.068, 19.043, 235.6, 235.6, 285.7, 285.7, 50.1, -7849770, -7451310, -7150720, 4.20322, 0.00421988, -0.00000673057, 0.0502986, 42.91, -747416, 14486, -0.000000000464626, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6), +(33, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-16 19:36:21', '2014-01-16 19:37:16', 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19.387, 19.397, 19.378, 19.1919, 19.197, 19.186, 19.0261, 19.032, 19.022, 285.7, 285.7, 335.8, 335.8, 50.1, -7776420, -7403080, -7097240, 4.20341, 0.00421978, -0.00000677442, 0.0502951, 42.908, -742528, 14485, -0.000000000467685, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6), +(34, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-16 19:37:27', '2014-01-16 19:38:21', 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19.3662, 19.371, 19.364, 19.1738, 19.176, 19.169, 19.0227, 19.018, 19.022, 335.85, 335.85, 385.9, 385.9, 50.05, -7735960, -7369200, -7090920, 4.19736, 0.00421792, -0.00000679877, 0.0502951, 42.927, -739868, 14485, -0.000000000469367, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6), +(35, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-16 20:00:50', '2014-01-16 20:02:02', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19.8612, 19.848, 19.899, 19.3546, 19.353, 19.363, 19.7422, 20.301, 19.717, 20.026, 20.026, 35.066, 35.066, 15.04, 999.835, 999.937, 999.859, 889.546, 0.890918, 0.0150564, 0.0150632, 60.867, 0.0448699, 43382, 0.000000347067, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2), +(36, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-16 20:12:46', '2014-01-16 20:14:15', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19.74, 19.768, 19.725, 19.5982, 19.595, 19.601, 19.5246, 19.636, 19.445, 35.068, 35.068, 55.1057, 55.1057, 20.0377, 999.859, 999.888, 999.903, 918.2, 0.919449, 0.0200605, 0.0200649, 78.562, 0.0218572, 57787, 0.000000347146, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5), +(37, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-16 20:14:26', '2014-01-16 20:15:55', 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19.7113, 19.715, 19.706, 19.5993, 19.601, 19.594, 19.3943, 19.42, 19.368, 55.106, 55.106, 75.146, 75.146, 20.04, 999.865, 999.888, 999.929, 917.793, 0.918934, 0.0200629, 0.0200649, 78.606, 0.0101567, 57787, 0.000000347187, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5), +(38, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-16 20:16:06', '2014-01-16 20:17:35', 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19.6979, 19.702, 19.693, 19.5842, 19.592, 19.574, 19.3313, 19.352, 19.316, 75.147, 75.147, 95.1887, 95.1887, 20.0417, 999.868, 999.891, 999.942, 917.332, 0.918413, 0.0200645, 0.0200653, 78.652, 0.00390826, 57788, 0.000000347209, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5), +(39, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-16 20:17:46', '2014-01-16 20:19:15', 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19.6841, 19.691, 19.679, 19.5638, 19.571, 19.556, 19.2957, 19.302, 19.283, 95.19, 95.19, 115.229, 115.229, 20.0395, 999.871, 999.895, 999.949, 917.127, 0.918292, 0.0200622, 0.0200649, 78.661, 0.0134901, 57787, 0.000000347175, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5), +(40, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-16 20:22:40', '2014-01-16 20:24:09', 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19.6572, 19.662, 19.654, 19.5088, 19.514, 19.503, 19.2485, 19.247, 19.243, -0.008, -0.008, 20.0293, 20.0293, 20.0373, 999.876, 999.906, 999.958, 916.644, 0.917907, 0.0200599, 0.0200649, 78.694, 0.0253307, 57787, 0.000000347134, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5), +(41, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-16 20:24:22', '2014-01-16 20:25:17', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19.6376, 19.647, 19.619, 19.4704, 19.498, 19.444, 19.5684, 19.723, 19.322, 321.3, 321.3, 371.45, 371.45, 50.1501, 999.88, 999.914, 999.894, 4176.56, 4.18893, 0.050206, 0.0502986, 43.227, 0.184409, 14486, 0.00000346583, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6), +(42, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-16 20:25:28', '2014-01-16 20:26:23', 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19.5563, 19.585, 19.534, 19.3967, 19.416, 19.375, 19.1705, 19.204, 19.142, 371.45, 371.45, 421.55, 421.55, 50.0999, 999.897, 999.929, 999.974, 4177.41, 4.19369, 0.0501551, 0.0502951, 43.175, 0.279231, 14485, 0.00000346255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6), +(43, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-16 20:26:34', '2014-01-16 20:27:29', 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19.4932, 19.508, 19.474, 19.3424, 19.355, 19.326, 19.1169, 19.123, 19.11, 421.55, 421.55, 471.65, 471.65, 50.1, 999.909, 999.94, 999.984, 4178.78, 4.19505, 0.0501547, 0.0502951, 43.161, 0.28008, 14485, 0.00000346252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6), +(44, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-16 20:27:40', '2014-01-16 20:28:35', 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19.4493, 19.463, 19.439, 19.3025, 19.314, 19.295, 19.0939, 19.104, 19.083, 471.65, 471.65, 521.75, 521.75, 50.1, 999.918, 999.948, 999.989, 4183.33, 4.19962, 0.0501542, 0.0502951, 43.114, 0.280944, 14485, 0.00000346249, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6), +(45, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-16 20:28:46', '2014-01-16 20:29:41', 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19.4219, 19.429, 19.418, 19.2712, 19.28, 19.263, 19.0808, 19.079, 19.082, 521.75, 521.75, 571.9, 571.9, 50.15, 999.924, 999.954, 999.991, 4183.91, 4.19602, 0.050204, 0.0502951, 43.151, 0.181545, 14485, 0.00000346593, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6), +(46, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-16 20:40:54', '2014-01-16 20:42:10', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19.5879, 19.565, 19.632, 19.266, 19.264, 19.269, 19.4481, 20.174, 19.391, 20.03, 20.03, 35.0663, 35.0663, 15.0363, 999.89, 999.955, 999.918, 824.574, 825.78, 0.0150525, 15.0583, 65.647, 99938.8, 43368, 0.000000347088, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2), +(47, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-16 20:42:21', '2014-01-16 20:43:38', 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19.6285, 19.633, 19.623, 19.2796, 19.27, 19.286, 19.3683, 19.376, 19.415, 35.067, 35.067, 50.1057, 50.1057, 15.0387, 999.882, 999.952, 999.934, 824.149, 825.227, 0.0150549, 15.0583, 65.691, 99923, 43368, 0.000000347143, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2), +(48, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-01-16 21:13:06', '2014-01-16 21:16:59', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19.7619, 19.772, 19.735, 19.5558, 19.549, 19.559, 19.5009, 19.92, 19.399, 65.114, 65.114, 115.079, 115.079, 49.9652, 999.855, 999.897, 999.908, 810.312, 811.811, 50.0218, 50.0576, 221.982, 0.0716774, 144166, 0.000346974, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2), +(49, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-02-09 16:26:51', '2014-02-09 16:30:50', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 20.0735, 20.92, 19.658, 20.7167, 20.932, 20.172, 20.8378, 21.172, 20.15, 0.01, 0.01, 49.9093, 49.9093, 49.8993, 998.191, 998.056, 998.03, 788.133, 790.606, 50.048, 50.0559, 227.928, 0.0157243, 144161, 0.000347168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2), +(50, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-02-09 16:31:58', '2014-02-09 16:35:50', 2, 20, 1, 40, 0, 0, 0, 0, 0, 0, 19.4366, 19.6, 19.234, 19.7194, 19.891, 19.556, 19.7971, 19.945, 19.648, 18.304, 18.304, 68.2543, 68.2543, 49.9503, 998.321, 998.264, 998.248, 811.614, 813.346, 50.0887, 50.0569, 221.56, -0.063486, 144164, 0.000347443, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2), +(51, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-02-09 18:14:07', '2014-02-09 18:18:04', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 22.6622, 22.933, 22.489, 23.1471, 23.138, 23.14, 23.0598, 23.464, 22.816, 0.008, 0.008, 49.845, 49.845, 49.837, 997.621, 997.506, 997.527, 797.031, 800.543, 50.0131, 50.0566, 225.102, 0.0870668, 144163, 0.00034692, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2), +(52, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-02-09 18:19:10', '2014-02-09 18:23:06', 2, 20, 1, 40, 0, 0, 0, 0, 0, 0, 21.2836, 22.028, 20.712, 23.0582, 23.115, 22.967, 22.1527, 22.736, 21.466, 18.1983, 18.1983, 68.0997, 68.0997, 49.9013, 997.933, 997.527, 997.738, 799.434, 801.921, 50.0766, 50.0566, 224.715, -0.039856, 144163, 0.000347361, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2), +(53, '', '', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', '', '2014-02-09 18:24:41', '2014-02-09 18:28:36', 3, 20, 1, 40, 0, 0, 0, 0, 0, 0, 20.2791, 20.433, 20.162, 22.6056, 22.818, 22.389, 20.7234, 20.996, 20.53, 18.1687, 18.1687, 68.0953, 68.0953, 49.9267, 998.148, 997.634, 998.054, 800.292, 802.38, 50.0966, 50.0569, 224.588, -0.0792307, 144164, 0.000347498, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2), +(54, 'Q1 (1/3)', 'Q1', 0.8, 0.85, 50, 218.182, 3, 0, 0, 'FlyingStartCollection', -2, 2, 'PF1', 'PT1', 'PO2', 'PM1', '2014-02-09 21:52:01', '2014-02-09 21:55:53', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68.0957, 68.0957, 117.959, 117.959, 49.8632, 999.843, 999.843, 999.843, 836.595, 839.305, 49.9224, 50.0247, 214.569, 0.204862, 144071, 0.000346512, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(55, 'Q1 (1/3)', 'Q1', 0.8, 0.85, 50, 218.182, 3, 0, 0, 'FlyingStartCollection', -2, 2, 'PF1', 'PT1', 'PO2', 'PM1', '2014-02-09 23:22:17', '2014-02-09 23:26:18', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18.28, 18.28, 68.1767, 68.1767, 49.8967, 999.843, 999.843, 999.843, 801.95, 804.041, 49.9559, 50.0267, 223.989, 0.141757, 144077, 0.000346731, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(56, 'Q1 (2/3)', 'Q1', 0.8, 0.85, 50, 218.182, 3, 0, 0, 'FlyingStartCollection', -2, 2, 'PF1', 'PT1', 'PO2', 'PM1', '2014-02-09 23:28:05', '2014-02-09 23:32:06', 2, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18.1723, 18.1723, 68.0773, 68.0773, 49.905, 999.843, 999.843, 999.843, 803.379, 805.283, 49.9643, 50.0233, 223.628, 0.118073, 144067, 0.000346813, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(57, 'Q1 (3/3)', 'Q1', 0.8, 0.85, 50, 218.182, 3, 0, 0, 'FlyingStartCollection', -2, 2, 'PF1', 'PT1', 'PO2', 'PM1', '2014-02-09 23:33:53', '2014-02-09 23:37:54', 3, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.8957, 17.8957, 67.797, 67.797, 49.9013, 999.843, 999.843, 999.843, 803.223, 805.185, 49.9606, 50.0233, 223.655, 0.12545, 144067, 0.000346787, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(58, 'Q1', 'Q1', 0.8, 0.85, 50, 218.182, 1, 0, 0, 'FlyingStartCollection', -2, 2, 'PF1', 'PT1', 'PO2', 'PM1', '2014-02-10 00:23:37', '2014-02-10 00:27:39', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.6677, 17.6677, 67.5567, 67.5567, 49.889, 999.843, 999.843, 999.843, 803.714, 805.872, 49.9483, 50.0229, 223.463, 0.149485, 144066, 0.000346704, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(59, 'Q2', 'Q2', 3, 3.3, 50, 57.1429, 1, 0, 0, 'FlyingStartCollection', -2, 2, 'PF1', 'PT1', 'PO3', 'PM1', '2014-02-10 00:28:01', '2014-02-10 00:29:16', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77.4, 77.4, 127.4, 127.4, 50, 999.843, 999.843, 999.843, 3160.94, 3174.99, 50.0594, 50.2222, 56.945, 0.325297, 14464, 0.00346096, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(60, 'Q2', 'Q2', 3, 3.3, 50, 57.1429, 1, 0, 0, 'FlyingStartCollection', -2, 2, 'PF1', 'PT1', 'PO3', 'PM1', '2014-02-10 00:44:43', '2014-02-10 00:45:59', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36.9, 36.9, 86.9, 86.9, 50, 999.843, 999.843, 999.843, 3149.72, 3163.72, 50.0594, 50.2222, 57.148, 0.325297, 14464, 0.00346096, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(61, 'Q1', 'Q1', 0.8, 0.85, 50, 218.182, 1, 0, 0, 'FlyingStartCollection', -2, 2, 'PF1', 'PT1', 'PO2', 'PM1', '2014-02-10 00:47:02', '2014-02-10 00:51:02', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10.26, 10.26, 60.1353, 60.1353, 49.8753, 999.843, 999.843, 999.843, 806.095, 808.548, 49.9346, 50.0271, 222.742, 0.185278, 144078, 0.00034658, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(62, 'Q2', 'Q2', 3, 3.3, 50, 57.1429, 1, 0, 0, 'FlyingStartCollection', -2, 2, 'PF1', 'PT1', 'PO3', 'PM1', '2014-02-10 01:00:54', '2014-02-10 01:02:10', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86.85, 86.85, 136.85, 136.85, 50, 999.843, 999.843, 999.843, 3148.84, 3162.83, 50.0594, 50.2222, 57.164, 0.325282, 14464, 0.00346096, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(63, 'Q1', 'Q1', 0.8, 0.85, 50, 218.182, 1, 0, 0, 'FlyingStartCollection', -2, 2, 'PF1', 'PT1', 'PO2', 'PM1', '2014-02-10 01:35:39', '2014-02-10 01:39:32', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 20.618, 20.938, 20.255, 22.3268, 22.327, 22.319, 21.924, 22.491, 21.371, 0.011, 0.011, 49.915, 49.915, 49.904, 998.077, 997.698, 997.79, 833.876, 836.466, 50.0706, 50.059, 215.445, -0.0231911, 144170, 0.000347303, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(64, 'Q2', 'Q2', 3, 3.3, 50, 57.1429, 1, 0, 0, 'FlyingStartCollection', -2, 2, 'PF1', 'PT1', 'PO3', 'PM1', '2014-02-10 01:49:10', '2014-02-10 01:50:26', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 19.694, 19.697, 19.686, 21.1796, 21.209, 21.152, 19.9144, 19.905, 19.874, 0.2, 0.2, 50.25, 50.25, 50.05, 998.269, 997.956, 998.224, 3179.97, 3191.13, 50.2042, 50.2257, 56.661, 0.0428624, 14465, 0.00347073, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(65, 'Q1', 'Q1', 0.8, 0.85, 50, 218.182, 1, 0, 0, 'FlyingStartCollection', -2, 2, 'PF1', 'PT1', 'PO2', 'PM1', '2014-02-10 02:03:10', '2014-02-10 02:07:04', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18.2937, 18.2937, 68.182, 68.182, 49.8883, 999.843, 999.843, 999.843, 828.637, 830.884, 49.9476, 50.0236, 216.739, 0.152221, 144068, 0.000346694, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(66, 'Q1', 'Q1', 0.8, 0.85, 50, 218.182, 1, 0, 0, 'FlyingStartCollection', -2, 2, 'PF1', 'PT1', 'PO2', 'PM1', '2014-02-10 02:16:08', '2014-02-10 02:20:04', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17.7903, 17.7903, 67.6867, 67.6867, 49.8963, 999.843, 999.843, 999.843, 825.847, 827.954, 49.9556, 50.0236, 217.506, 0.136191, 144068, 0.00034675, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(67, 'Q2', 'Q2', 3, 3.3, 50, 57.1429, 1, 0, 0, 'FlyingStartCollection', -2, 2, 'PF1', 'PT1', 'PO3', 'PM1', '2014-02-10 02:20:31', '2014-02-10 02:21:45', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95.05, 95.05, 145.1, 145.1, 50.05, 999.843, 999.843, 999.843, 3271.72, 3283.43, 50.1094, 50.2292, 55.072, 0.238948, 14466, 0.00346395, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(68, 'Q1', 'Q1', 0.8, 0.85, 50, 218.182, 1, 0, 0, 'FlyingStartCollection', -2, 2, 'PF1', 'PT1', 'PO2', 'PM1', '2014-02-10 02:59:06', '2014-02-10 03:03:00', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19.208, 19.208, 69.0857, 69.0857, 49.8777, 999.843, 999.843, 999.843, 830.011, 832.451, 49.9369, 50.0243, 216.334, 0.175041, 144070, 0.000346616, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(69, 'Q2', 'Q2', 3, 3.3, 50, 57.1429, 1, 0, 0, 'FlyingStartCollection', -2, 2, 'PF1', 'PT1', 'PO3', 'PM1', '2014-02-10 03:03:30', '2014-02-10 03:04:43', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145.05, 145.05, 195.1, 195.1, 50.05, 999.843, 999.843, 999.843, 3280.53, 3292.5, 50.1095, 50.2326, 54.924, 0.24583, 14467, 0.00346371, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(70, 'Q2', 'Q2', 4, 4.4, 50, 42.8571, 1, 0, 0, 'FlyingStartCollection', 0, 2, 'PF1', 'PT1', 'PO3', 'CamR1', '2014-02-10 08:20:28', '2014-02-10 08:21:30', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.1, 0.1, 50.2, 50.2, 50.1, 999.843, 999.843, 999.843, 4091, 4106.37, 50.1595, 50.2882, 44.087, 0.256574, 14483, 0.00346334, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(71, 'Q0', 'Q0', 0.1, 0.11, 5, 171.429, 1, 0, 0, 'FlyingStartCollection', 0, 0, 'PF1', 'PT1', 'PO1', 'PM1', '2014-07-26 10:17:23', '2014-07-26 10:20:25', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7.269, 7.269, 12.257, 12.257, 4.988, 999.843, 999.843, 999.843, 103.557, 103.867, 4.99392, 5.00292, 173.4, 0.180072, 120070, 0.0000415918, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(72, 'Q1', 'Q1', 0.1, 0.11, 2, 68.5714, 1, 0, 0, 'FlyingStartCollection', 0, 0, 'PF1', 'PT1', 'PO1', 'PM1', '2014-07-26 11:14:17', '2014-07-26 11:15:35', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12.256, 12.256, 14.2223, 14.2223, 1.96633, 999.843, 999.843, 999.843, 101.724, 103.617, 1.96867, 2.00292, 69.588, 1.73966, 48070, 0.0000409542, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(73, 'Q2', 'Q2', 0.2, 0.22, 5, 85.7143, 1, 0, 0, 'FlyingStartCollection', 0, 0, 'PF1', 'PT1', 'PO1', 'PM1', '2014-07-26 11:16:44', '2014-07-26 11:18:20', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14.225, 14.225, 19.1427, 19.1427, 4.91767, 999.843, 999.843, 999.843, 201.695, 205.317, 4.92351, 5.00596, 87.774, 1.67467, 120143, 0.0000409804, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(74, 'Q1', 'Q1', 0.1, 0.11, 2, 68.5714, 1, 0, 0, 'FlyingStartCollection', 0, 0, 'PF1', 'PT1', 'PO1', 'PM1', '2014-07-26 11:30:06', '2014-07-26 11:31:28', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19.145, 19.145, 21.1093, 21.1093, 1.96433, 999.843, 999.843, 999.843, 96.846, 98.7421, 1.96667, 2.00279, 73.019, 1.83694, 48067, 0.0000409151, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(75, 'Q2', 'Q2', 0.2, 0.22, 5, 85.7143, 1, 0, 0, 'FlyingStartCollection', 0, 0, 'PF1', 'PT1', 'PO1', 'PM1', '2014-07-26 11:33:12', '2014-07-26 11:34:50', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21.112, 21.112, 26.0257, 26.0257, 4.91367, 999.843, 999.843, 999.843, 196.807, 200.529, 4.9195, 5.00658, 89.881, 1.77015, 120158, 0.0000409419, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(76, 'Q1', 'Q1', 0.1, 0.11, 2, 68.5714, 1, 0, 0, 'FlyingStartCollection', 0, 0, 'PF1', 'PT1', 'PO1', 'PM1', '2014-07-26 11:44:38', '2014-07-26 11:45:53', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26.028, 26.028, 28.024, 28.024, 1.996, 999.843, 999.843, 999.843, 108.08, 108.489, 1.99837, 2.00354, 66.484, 0.258764, 48085, 0.0000415591, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(77, 'Q1', 'Q1', 0.1, 0.11, 2, 68.5714, 1, 0, 0, 'FlyingStartCollection', 0, 0, 'PF1', 'PT1', 'PO1', 'PM1', '2014-07-26 12:08:50', '2014-07-26 12:10:05', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28.025, 28.025, 29.992, 29.992, 1.967, 999.843, 999.843, 999.843, 106.749, 108.705, 1.96933, 2.00304, 66.335, 1.71158, 48073, 0.0000409655, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(78, 'Q2', 'Q2', 0.2, 0.22, 5, 85.7143, 1, 0, 0, 'FlyingStartCollection', 0, 0, 'PF1', 'PT1', 'PO1', 'PM1', '2014-07-26 12:11:09', '2014-07-26 12:12:47', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29.994, 29.994, 34.9147, 34.9147, 4.92067, 999.843, 999.843, 999.843, 197.703, 201.158, 4.92652, 5.00667, 89.601, 1.62695, 120160, 0.0000409996, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(79, 'Q1', 'Q1', 0.1, 0.11, 2, 68.5714, 1, 0, 0, 'FlyingStartCollection', 0, 0, 'PF1', 'PT1', 'PO1', 'PM1', '2014-07-26 12:13:40', '2014-07-26 12:14:55', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34.917, 34.917, 36.883, 36.883, 1.966, 999.843, 999.843, 999.843, 106.568, 108.58, 1.96833, 2.00313, 66.414, 1.76753, 48075, 0.000040943, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(80, 'Q2', 'Q2', 0.2, 0.22, 5, 85.7143, 1, 0, 0, 'FlyingStartCollection', 0, 0, 'PF1', 'PT1', 'PO1', 'PM1', '2014-07-26 12:17:31', '2014-07-26 12:19:09', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36.885, 36.885, 41.8103, 41.8103, 4.92533, 999.843, 999.843, 999.843, 197.922, 201.153, 4.93118, 5.00575, 89.587, 1.51213, 120138, 0.000041046, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(81, 'Q1', 'Q1', 0.1, 0.11, 2, 68.5714, 1, 0, 0, 'FlyingStartCollection', 0, 0, 'PF1', 'PT1', 'PO1', 'PM1', '2014-07-26 12:29:18', '2014-07-26 12:30:35', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41.813, 41.813, 43.7767, 43.7767, 1.96367, 999.843, 999.843, 999.843, 104.233, 106.345, 1.966, 2.00346, 67.821, 1.90527, 48083, 0.0000408876, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(82, 'Q2', 'Q2', 0.2, 0.22, 5, 85.7143, 1, 0, 0, 'FlyingStartCollection', 0, 0, 'PF1', 'PT1', 'PO1', 'PM1', '2014-07-26 12:31:45', '2014-07-26 12:33:24', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43.779, 43.779, 48.706, 48.706, 4.927, 999.843, 999.843, 999.843, 197.971, 201.135, 4.93285, 5.00575, 89.595, 1.47778, 120138, 0.0000410599, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(83, 'Q1', 'Q1', 0.1, 0.11, 2, 68.5714, 1, 0, 0, 'FlyingStartCollection', 0, 0, 'PF1', 'PT1', 'PO1', 'PM1', '2014-07-26 12:37:44', '2014-07-26 12:39:00', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48.708, 48.708, 50.6973, 50.6973, 1.98933, 999.843, 999.843, 999.843, 107.077, 108.059, 1.9917, 2.00758, 66.883, 0.797651, 48182, 0.0000413369, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(84, 'Q2', 'Q2', 0.2, 0.22, 5, 85.7143, 1, 0, 0, 'FlyingStartCollection', 0, 0, 'PF1', 'PT1', 'PO1', 'PM1', '2014-07-26 12:40:05', '2014-07-26 12:41:44', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50.699, 50.699, 55.6387, 55.6387, 4.93967, 999.843, 999.843, 999.843, 196.732, 199.696, 4.94553, 5.01408, 90.391, 1.38612, 120338, 0.000041097, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(85, 'Q1', 'Q1', 0.1, 0.11, 2, 68.5714, 1, 0, 0, 'FlyingStartCollection', 0, 0, 'PF1', 'PT1', 'PO1', 'PM1', '2014-07-26 12:58:37', '2014-07-26 12:59:52', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55.64, 55.64, 57.6257, 57.6257, 1.98567, 999.843, 999.843, 999.843, 106.768, 107.946, 1.98803, 2.00758, 66.953, 0.983745, 48182, 0.0000412608, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(86, 'Q2', 'Q2', 0.15, 0.17, 3, 67.5, 1, 0, 0, 'FlyingStartCollection', -5, 5, 'PF1', 'PT1', 'PO1', 'CamR1', '2014-07-26 13:26:50', '2014-07-26 13:28:10', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57.627, 57.627, 60.5873, 60.5873, 2.96034, 999.843, 999.843, 999.843, 149.056, 151.592, 2.96385, 3.01071, 71.498, 1.58086, 72257, 0.0000410182, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(87, 'Q1', 'Q1', 0.1, 0.11, 2, 68.5714, 1, 0, 0, 'FlyingStartCollection', 0, 0, 'PF1', 'PT1', 'PO1', 'PM1', '2014-07-26 14:19:00', '2014-07-26 14:20:16', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.534, 0.534, 2.505, 2.505, 1.971, 999.843, 999.843, 999.843, 105.685, 107.645, 1.97334, 2.00754, 67.139, 1.73315, 48181, 0.0000409568, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(88, 'Q1', 'Q1', 0.1, 0.11, 2, 68.5714, 1, 0, 0, 'FlyingStartCollection', 0, 0, 'PF1', 'PT1', 'PO1', 'PM1', '2014-07-26 14:22:17', '2014-07-26 14:23:34', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2.507, 2.507, 4.48033, 4.48033, 1.97333, 999.843, 999.843, 999.843, 104.082, 105.877, 1.97568, 2.00738, 68.254, 1.60444, 48177, 0.0000410087, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(89, 'Q1', 'Q1', 0.1, 0.11, 2, 68.5714, 1, 0, 0, 'FlyingStartCollection', 0, 0, 'PF1', 'PT1', 'PO1', 'PM1', '2014-07-26 14:30:05', '2014-07-26 14:31:22', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4.482, 4.482, 6.45633, 6.45633, 1.97433, 999.843, 999.843, 999.843, 103.944, 105.684, 1.97668, 2.00738, 68.379, 1.55298, 48177, 0.0000410295, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(90, 'Q2', 'Q2', 0.2, 0.22, 5, 85.7143, 1, 0, 0, 'FlyingStartCollection', 0, 0, 'PF1', 'PT1', 'PO1', 'PM1', '2014-07-26 14:41:57', '2014-07-26 14:43:36', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6.458, 6.458, 11.393, 11.393, 4.935, 999.843, 999.843, 999.843, 197.019, 200.178, 4.94086, 5.01413, 90.174, 1.48282, 120339, 0.0000410579, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(91, 'Q1', 'Q1', 0.1, 0.11, 2, 68.5714, 1, 0, 0, 'FlyingStartCollection', 0, 0, 'PF1', 'PT1', 'PO1', 'PM1', '2014-07-26 15:03:04', '2014-07-26 15:04:20', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11.394, 11.394, 13.3933, 13.3933, 1.99933, 999.843, 999.843, 999.843, 107.252, 107.695, 2.00171, 2.00758, 67.109, 0.293529, 48182, 0.0000415447, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(92, 'Q1', 'Q1', 0.1, 0.11, 2, 68.5714, 1, 0, 0, 'FlyingStartCollection', 0, 0, 'PF1', 'PT1', 'PO1', 'PM1', '2014-07-26 15:09:48', '2014-07-26 15:11:05', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13.394, 13.394, 15.3663, 15.3663, 1.97233, 999.843, 999.843, 999.843, 104.251, 106.107, 1.97468, 2.00746, 68.109, 1.66019, 48179, 0.0000409862, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(93, 'Q2', 'Q2', 0.2, 0.22, 5, 85.7143, 1, 0, 0, 'FlyingStartCollection', 0, 0, 'PF1', 'PT1', 'PO1', 'PM1', '2014-07-26 15:12:15', '2014-07-26 15:13:53', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15.368, 15.368, 20.2937, 20.2937, 4.92566, 999.843, 999.843, 999.843, 199.317, 202.901, 4.93151, 5.01425, 88.966, 1.6777, 120342, 0.0000409792, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(94, 'Q1', 'Q1', 0.1, 0.11, 2, 68.5714, 1, 0, 0, 'FlyingStartCollection', 0, 0, 'PF1', 'PT1', 'PO1', 'PM1', '2014-07-26 15:14:19', '2014-07-26 15:15:35', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20.295, 20.295, 22.2647, 22.2647, 1.96967, 999.843, 999.843, 999.843, 106.099, 108.141, 1.972, 2.00758, 66.832, 1.80419, 48182, 0.0000409282, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(95, 'Q2', 'Q2', 0.2, 0.22, 5, 85.7143, 1, 0, 0, 'FlyingStartCollection', 0, 0, 'PF1', 'PT1', 'PO1', 'PM1', '2014-07-26 15:16:05', '2014-07-26 15:17:44', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.266, 22.266, 27.203, 27.203, 4.937, 999.843, 999.843, 999.843, 197.324, 200.414, 4.94286, 5.01429, 90.071, 1.44517, 120343, 0.0000410731, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(96, 'Q1', 'Q1', 0.1, 0.11, 2, 68.5714, 1, 0, 0, 'FlyingStartCollection', 0, 0, 'PF1', 'PT1', 'PO1', 'PM1', '2014-07-26 15:25:44', '2014-07-26 15:27:00', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19.775, 19.775, 21.7583, 21.7583, 1.98333, 999.843, 999.843, 999.843, 106.454, 107.756, 1.98569, 2.00758, 67.071, 1.10261, 48182, 0.0000412123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(97, 'Q2', 'Q2', 0.2, 0.22, 5, 85.7143, 1, 0, 0, 'FlyingStartCollection', 0, 0, 'PF1', 'PT1', 'PO1', 'PM1', '2014-07-26 15:27:57', '2014-07-26 15:29:36', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21.759, 21.759, 26.696, 26.696, 4.937, 999.843, 999.843, 999.843, 196.389, 199.455, 4.94286, 5.01408, 90.5, 1.44091, 120338, 0.0000410748, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(98, 'Q1', 'Q1', 0.1, 0.11, 2, 68.5714, 1, 0, 0, 'FlyingStartCollection', 0, 0, 'PF1', 'PT1', 'PO1', 'PM1', '2014-07-26 15:30:04', '2014-07-26 15:31:19', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26.697, 26.697, 28.6853, 28.6853, 1.98833, 999.843, 999.843, 999.843, 107.615, 108.659, 1.99069, 2.00763, 66.515, 0.85051, 48183, 0.0000413153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(99, 'Q1', 'Q1', 0.1, 0.11, 2, 68.5714, 1, 0, 0, 'FlyingStartCollection', 0, 0, 'PF1', 'PT1', 'PO1', 'PM1', '2014-07-26 16:18:39', '2014-07-26 16:20:02', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28.685, 28.685, 30.6587, 30.6587, 1.97367, 999.843, 999.843, 999.843, 96.253, 97.8684, 1.97601, 2.00679, 73.818, 1.55772, 48163, 0.0000410276, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(100, 'Q2', 'Q2', 0.2, 0.22, 5, 85.7143, 1, 0, 0, 'FlyingStartCollection', 0, 0, 'PF1', 'PT1', 'PO1', 'PM1', '2014-07-26 16:20:47', '2014-07-26 16:22:26', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30.66, 30.66, 35.599, 35.599, 4.939, 999.843, 999.843, 999.843, 197.668, 200.678, 4.94487, 5.01421, 89.951, 1.40231, 120341, 0.0000410905, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(101, 'Q3', 'Q3', 0.8, 0.85, 50, 218.182, 1, 0, 0, 'FlyingStartCollection', -2, 2, 'PF1', 'PT1', 'PO2', 'PM1', '2014-07-26 16:23:16', '2014-07-26 16:27:09', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35.599, 35.599, 85.5213, 85.5213, 49.9223, 999.843, 999.843, 999.843, 801.175, 803.33, 49.9816, 50.0566, 224.321, 0.150003, 144163, 0.000346702, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(102, 'Q4', 'Q4', 3, 3.3, 50, 57.1429, 1, 0, 0, 'FlyingStartCollection', -2, 2, 'PF1', 'PT1', 'PO3', 'PM1', '2014-07-26 16:30:24', '2014-07-26 16:31:29', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.35, 0.35, 50.45, 50.45, 50.1, 999.843, 999.843, 999.843, 3278.5, 3287.18, 50.1595, 50.2326, 55.013, 0.145813, 14467, 0.00346717, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(103, 'Q1', 'Q1', 0.1, 0.11, 2, 68.5714, 1, 0, 0, 'FlyingStartCollection', 0, 0, 'PF1', 'PT1', 'PO1', 'PM1', '2014-07-26 17:15:25', '2014-07-26 17:16:40', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.722, 1.722, 3.695, 3.695, 1.973, 999.843, 999.843, 999.843, 106.385, 108.25, 1.97534, 2.00758, 66.765, 1.63214, 48182, 0.0000409975, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(104, 'Q2', 'Q2', 0.2, 0.22, 5, 85.7143, 1, 0, 0, 'FlyingStartCollection', 0, 0, 'PF1', 'PT1', 'PO1', 'PM1', '2014-07-26 17:23:26', '2014-07-26 17:25:05', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3.694, 3.694, 8.63, 8.63, 4.936, 999.843, 999.843, 999.843, 197.177, 200.296, 4.94186, 5.01408, 90.12, 1.46144, 120338, 0.0000410665, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(105, 'Q2', 'Q2', 0.15, 0.17, 3, 67.5, 1, 0, 0, 'FlyingStartCollection', -5, 5, 'PF1', 'PT1', 'PO1', 'CamR1', '2014-07-26 17:34:19', '2014-07-26 17:35:39', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8.631, 8.631, 11.555, 11.555, 2.924, 999.843, 999.843, 999.843, 147.085, 151.444, 2.92747, 3.01067, 71.567, 2.84183, 72256, 0.0000405153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(106, 'Q2', 'Q2', 0.15, 0.17, 3, 67.5, 1, 0, 0, 'FlyingStartCollection', -5, 5, 'PF1', 'PT1', 'PO1', 'CamR1', '2014-07-26 17:59:24', '2014-07-26 18:00:45', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12.154, 12.154, 15.117, 15.117, 2.963, 999.843, 999.843, 999.843, 147.599, 149.967, 2.96652, 3.01054, 72.269, 1.48402, 72253, 0.0000410574, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(107, 'Q2', 'Q2', 0.15, 0.17, 3, 67.5, 1, 0, 0, 'FlyingStartCollection', -5, 5, 'PF1', 'PT1', 'PO1', 'CamR1', '2014-07-26 18:19:22', '2014-07-26 18:20:43', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15.119, 15.119, 18.0793, 18.0793, 2.96033, 999.843, 999.843, 999.843, 146.98, 149.47, 2.96385, 3.0105, 72.508, 1.57406, 72252, 0.000041021, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(108, 'Q2', 'Q2', 0.15, 0.17, 3, 67.5, 1, 0, 0, 'FlyingStartCollection', -5, 5, 'PF1', 'PT1', 'PO1', 'CamR1', '2014-07-26 18:41:58', '2014-07-26 18:43:19', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18.08, 18.08, 21.0407, 21.0407, 2.96067, 999.843, 999.843, 999.843, 147.511, 149.996, 2.96418, 3.01054, 72.255, 1.56398, 72253, 0.000041025, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(109, 'Q2', 'Q2', 0.15, 0.17, 3, 67.5, 1, 0, 0, 'FlyingStartCollection', -5, 5, 'PF1', 'PT1', 'PO1', 'CamR1', '2014-07-26 18:55:08', '2014-07-26 18:56:29', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21.042, 21.042, 24.004, 24.004, 2.962, 999.843, 999.843, 999.843, 147.825, 150.247, 2.96552, 3.01054, 72.134, 1.51826, 72253, 0.0000410435, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(110, 'Q2', 'Q2', 0.15, 0.17, 3, 67.5, 1, 0, 0, 'FlyingStartCollection', -5, 5, 'PF1', 'PT1', 'PO1', 'CamR1', '2014-07-26 19:18:36', '2014-07-26 19:19:57', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24.005, 24.005, 26.9677, 26.9677, 2.96267, 999.843, 999.843, 999.843, 147.87, 150.26, 2.96619, 3.01054, 72.128, 1.49539, 72253, 0.0000410528, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(111, 'Q2', 'Q2', 0.1, 0.11, 3, 102.857, 1, 0, 0, 'FlyingStartCollection', -5, 5, 'PF1', 'PT1', 'PO1', 'CamR1', '2014-07-26 19:47:10', '2014-07-26 19:49:02', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26.969, 26.969, 29.9237, 29.9237, 2.95467, 999.843, 999.843, 999.843, 103.223, 105.064, 2.95817, 3.00738, 103.047, 1.6632, 72177, 0.000040985, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(112, 'Q2', 'Q2', 0.1, 0.11, 3, 102.857, 1, 0, 0, 'FlyingStartCollection', -5, 5, 'PF1', 'PT1', 'PO1', 'CamR1', '2014-07-27 10:30:09', '2014-07-27 10:32:08', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.011, 0.011, 2.96033, 2.96033, 2.94933, 999.843, 999.843, 999.843, 96.153, 98.029, 2.95284, 3.00688, 110.424, 1.83007, 72165, 0.0000409178, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(113, 'Q2', 'Q2', 0.1, 0.11, 3, 102.857, 1, 0, 0, 'FlyingStartCollection', -5, 5, 'PF1', 'PT1', 'PO1', 'CamR1', '2014-07-27 10:36:50', '2014-07-27 10:38:49', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2.962, 2.962, 5.91533, 5.91533, 2.95333, 999.843, 999.843, 999.843, 96.7936, 98.547, 2.95684, 3.00683, 109.842, 1.69075, 72164, 0.0000409739, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(114, 'Q2', 'Q2', 0.1, 0.11, 3, 102.857, 1, 0, 0, 'FlyingStartCollection', -5, 5, 'PF1', 'PT1', 'PO1', 'CamR1', '2014-07-27 11:01:45', '2014-07-27 11:03:41', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5.916, 5.916, 8.87, 8.87, 2.954, 999.843, 999.843, 999.843, 99.2015, 100.984, 2.95751, 3.00708, 107.2, 1.67626, 72170, 0.0000409797, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(115, 'Q2', 'Q2', 0.1, 0.11, 1, 34.2857, 1, 0, 0, 'FlyingStartCollection', -5, 5, 'PF1', 'PT1', 'PO1', 'CamR1', '2014-07-27 11:13:59', '2014-07-27 11:14:44', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10.623, 10.623, 11.611, 11.611, 0.988, 999.843, 999.843, 999.843, 99.02, 100.937, 0.989173, 1.00713, 35.92, 1.81483, 24171, 0.000040924, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL), +(116, 'Q2', 'Q2', 0.1, 0.11, 1, 34.2857, 1, 0, 0, 'FlyingStartCollection', -5, 5, 'PF1', 'PT1', 'PO1', 'CamR1', '2014-07-27 11:26:19', '2014-07-27 11:27:04', 1, 20, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12.603, 12.603, 13.5893, 13.5893, 0.986333, 999.843, 999.843, 999.843, 99.1926, 101.284, 0.987504, 1.00713, 35.797, 1.98691, 24171, 0.0000408549, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL); + +-- -------------------------------------------------------- + +-- +-- Štruktúra tabuľky pre tabuľku `transitionsequence` +-- + +CREATE TABLE IF NOT EXISTS `transitionsequence` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `ItemNr` int(11) DEFAULT NULL, + `Name` varchar(255) DEFAULT NULL, + `Description` varchar(255) DEFAULT NULL, + PRIMARY KEY (`Id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=4 ; + +-- +-- Sťahujem dáta pre tabuľku `transitionsequence` +-- + +INSERT INTO `transitionsequence` (`Id`, `ItemNr`, `Name`, `Description`) VALUES +(1, 0, 'Tr1', NULL), +(2, 1, 'Tr0', NULL), +(3, 2, 'Empty', NULL); + +-- -------------------------------------------------------- + +-- +-- Štruktúra tabuľky pre tabuľku `transitionstep` +-- + +CREATE TABLE IF NOT EXISTS `transitionstep` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `ItemNr` int(11) DEFAULT NULL, + `Duration` int(11) DEFAULT NULL, + `ValvesOpen` varchar(8000) DEFAULT NULL, + `ValvesClose` varchar(8000) DEFAULT NULL, + `RegulValvesPct` varchar(255) DEFAULT NULL, + `TransitionSequence_id` int(11) DEFAULT NULL, + PRIMARY KEY (`Id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=6 ; + +-- +-- Sťahujem dáta pre tabuľku `transitionstep` +-- + +INSERT INTO `transitionstep` (`Id`, `ItemNr`, `Duration`, `ValvesOpen`, `ValvesClose`, `RegulValvesPct`, `TransitionSequence_id`) VALUES +(1, 0, 15, 'K5;K7;K2', '', '30;---;---;---;---', 1), +(2, 1, 15, 'K10', '', '20;30;---;---;---', 1), +(3, 2, 15, 'K13', '', '10;20;30;---;---', 1), +(4, 3, 15, 'K5', 'K7;K10;K13;K2', '0;0;0;---;---', 1), +(5, 0, 1, '', '', '---;---;---;---;---', 2); + +-- -------------------------------------------------------- + +-- +-- Štruktúra tabuľky pre tabuľku `user` +-- + +CREATE TABLE IF NOT EXISTS `user` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `Name` varchar(255) DEFAULT NULL, + `Password` varchar(255) DEFAULT NULL, + `Description` varchar(255) DEFAULT NULL, + `LastPwChange` datetime DEFAULT NULL, + PRIMARY KEY (`Id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=3 ; + +-- +-- Sťahujem dáta pre tabuľku `user` +-- + +INSERT INTO `user` (`Id`, `Name`, `Password`, `Description`, `LastPwChange`) VALUES +(1, 'admin', 'af242843887f3bdcc52e485483356eaccd37ba67a35941530bd195a8310fc7d5aca8560576dfb62ad5a4bd2df789a5e8be068e62e7c976d6eeed8d63abbd9909', 'Application administrator', '2013-12-30 12:17:19'), +(2, 'tester', '', 'tester', '2013-12-30 12:17:19'); + +-- -------------------------------------------------------- + +-- +-- Štruktúra tabuľky pre tabuľku `watermeter` +-- + +CREATE TABLE IF NOT EXISTS `watermeter` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `Serial` varchar(255) DEFAULT NULL, + `WMType_id` int(11) DEFAULT NULL, + PRIMARY KEY (`Id`), + KEY `WMType_id` (`WMType_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=3 ; + +-- +-- Sťahujem dáta pre tabuľku `watermeter` +-- + +INSERT INTO `watermeter` (`Id`, `Serial`, `WMType_id`) VALUES +(1, '1234', 1), +(2, '4321', 2); + +-- -------------------------------------------------------- + +-- +-- Štruktúra tabuľky pre tabuľku `wmtype` +-- + +CREATE TABLE IF NOT EXISTS `wmtype` ( + `Id` int(11) NOT NULL AUTO_INCREMENT, + `CreateTime` datetime DEFAULT NULL, + `CreateUserName` varchar(255) DEFAULT NULL, + `CreateDescription` varchar(255) DEFAULT NULL, + `Name` varchar(255) DEFAULT NULL, + `PulseRate` float DEFAULT NULL, + PRIMARY KEY (`Id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=3 ; + +-- +-- Sťahujem dáta pre tabuľku `wmtype` +-- + +INSERT INTO `wmtype` (`Id`, `CreateTime`, `CreateUserName`, `CreateDescription`, `Name`, `PulseRate`) VALUES +(1, '0001-01-01 00:00:00', NULL, NULL, 'defaultmetertype', 1000), +(2, '0001-01-01 00:00:00', NULL, NULL, 'secondtype', 2000); + +-- +-- Obmedzenie pre exportované tabuľky +-- + +-- +-- Obmedzenie pre tabuľku `componentprocedure` +-- +ALTER TABLE `componentprocedure` + ADD CONSTRAINT `FKA4EE67E2C1B693F2` FOREIGN KEY (`Procedure_id`) REFERENCES `procedure` (`Id`), + ADD CONSTRAINT `FKF52C29EE2B6C2FF0` FOREIGN KEY (`Procedure_id`) REFERENCES `procedure` (`Id`); + +-- +-- Obmedzenie pre tabuľku `componenttest` +-- +ALTER TABLE `componenttest` + ADD CONSTRAINT `FK191C57B82582AD8D` FOREIGN KEY (`Test_id`) REFERENCES `test` (`Id`), + ADD CONSTRAINT `FK4933B35E048BC68` FOREIGN KEY (`Test_id`) REFERENCES `test` (`Id`); + +-- +-- Obmedzenie pre tabuľku `group` +-- +ALTER TABLE `group` + ADD CONSTRAINT `FKBA21C18EF68B56E6` FOREIGN KEY (`User_id`) REFERENCES `user` (`Id`); + +-- +-- Obmedzenie pre tabuľku `measurementcorrection` +-- +ALTER TABLE `measurementcorrection` + ADD CONSTRAINT `FK2E70F3322F02977E` FOREIGN KEY (`Component_id`) REFERENCES `component` (`Id`), + ADD CONSTRAINT `FKD31F9EED177796BA` FOREIGN KEY (`Component_id`) REFERENCES `component` (`Id`); + +-- +-- Obmedzenie pre tabuľku `metertestresult` +-- +ALTER TABLE `metertestresult` + ADD CONSTRAINT `FK70D262D7BB966EEE` FOREIGN KEY (`TestResult_id`) REFERENCES `testresult` (`Id`); + +-- +-- Obmedzenie pre tabuľku `test` +-- +ALTER TABLE `test` + ADD CONSTRAINT `FKCC127866C1B693F2` FOREIGN KEY (`Procedure_id`) REFERENCES `procedure` (`Id`), + ADD CONSTRAINT `FKEAE38E972B6C2FF0` FOREIGN KEY (`Procedure_id`) REFERENCES `procedure` (`Id`); + +-- +-- Obmedzenie pre tabuľku `testresult` +-- +ALTER TABLE `testresult` + ADD CONSTRAINT `FK420D31612582AD8D` FOREIGN KEY (`Test_id`) REFERENCES `test` (`Id`); + +-- +-- Obmedzenie pre tabuľku `watermeter` +-- +ALTER TABLE `watermeter` + ADD CONSTRAINT `FK7FD3784077883960` FOREIGN KEY (`WMType_id`) REFERENCES `wmtype` (`Id`); + +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; diff --git a/TestBenchFramework/Screens/LogsTabPageCtrl.Designer.cs b/TestBenchFramework/Screens/LogsTabPageCtrl.Designer.cs new file mode 100644 index 000000000..f9b01e17a --- /dev/null +++ b/TestBenchFramework/Screens/LogsTabPageCtrl.Designer.cs @@ -0,0 +1,100 @@ +namespace TBF.Screens +{ + partial class LogsTabPageCtrl + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(LogsTabPageCtrl)); + this.logTextBox = new System.Windows.Forms.TextBox(); + this.clearButton = new System.Windows.Forms.Button(); + this.splitContainer = new System.Windows.Forms.SplitContainer(); + this.logsTextBox = new System.Windows.Forms.TextBox(); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).BeginInit(); + this.splitContainer.Panel1.SuspendLayout(); + this.splitContainer.Panel2.SuspendLayout(); + this.splitContainer.SuspendLayout(); + this.SuspendLayout(); + // + // logTextBox + // + resources.ApplyResources(this.logTextBox, "logTextBox"); + this.logTextBox.Name = "logTextBox"; + // + // clearButton + // + resources.ApplyResources(this.clearButton, "clearButton"); + this.clearButton.Name = "clearButton"; + this.clearButton.UseVisualStyleBackColor = true; + this.clearButton.Click += new System.EventHandler(this.clearButton_Click); + // + // splitContainer + // + resources.ApplyResources(this.splitContainer, "splitContainer"); + this.splitContainer.FixedPanel = System.Windows.Forms.FixedPanel.Panel1; + this.splitContainer.Name = "splitContainer"; + // + // splitContainer.Panel1 + // + this.splitContainer.Panel1.BackColor = System.Drawing.SystemColors.Control; + this.splitContainer.Panel1.Controls.Add(this.clearButton); + // + // splitContainer.Panel2 + // + this.splitContainer.Panel2.Controls.Add(this.logsTextBox); + // + // logsTextBox + // + this.logsTextBox.BackColor = System.Drawing.SystemColors.Control; + resources.ApplyResources(this.logsTextBox, "logsTextBox"); + this.logsTextBox.Name = "logsTextBox"; + // + // LogsTabPageCtrl + // + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.BackColor = System.Drawing.Color.Silver; + this.Controls.Add(this.splitContainer); + this.Controls.Add(this.logTextBox); + this.Name = "LogsTabPageCtrl"; + this.splitContainer.Panel1.ResumeLayout(false); + this.splitContainer.Panel2.ResumeLayout(false); + this.splitContainer.Panel2.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).EndInit(); + this.splitContainer.ResumeLayout(false); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TextBox logTextBox; + private System.Windows.Forms.Button clearButton; + private System.Windows.Forms.SplitContainer splitContainer; + private System.Windows.Forms.TextBox logsTextBox; + } +} diff --git a/TestBenchFramework/Screens/LogsTabPageCtrl.cs b/TestBenchFramework/Screens/LogsTabPageCtrl.cs new file mode 100644 index 000000000..63049a589 --- /dev/null +++ b/TestBenchFramework/Screens/LogsTabPageCtrl.cs @@ -0,0 +1,35 @@ +using System; +using System.Windows.Forms; +using TBF.Resources; +using TBF.UiBridge; + +namespace TBF.Screens +{ + public partial class LogsTabPageCtrl : UserControl + { + public LogsTabPageCtrl() + { + InitializeComponent(); + clearButton.Text = Strings.ClearBtnText; + + Bridge.LogHandler += delegate(object sender, LogEventArgs args) + { + if (InvokeRequired) + { + Invoke(new EventHandler(OnLog), sender, args); + } + else OnLog(sender, args); + }; + } + + private void clearButton_Click(object sender, EventArgs e) + { + logsTextBox.Clear(); + } + + void OnLog(object sender, LogEventArgs args) + { + logsTextBox.AppendText(args.LogMessage); + } + } +} diff --git a/TestBenchFramework/Screens/LogsTabPageCtrl.resx b/TestBenchFramework/Screens/LogsTabPageCtrl.resx new file mode 100644 index 000000000..968ca4f69 --- /dev/null +++ b/TestBenchFramework/Screens/LogsTabPageCtrl.resx @@ -0,0 +1,291 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 98, 249 + + + + 2, 2, 2, 2 + + + + True + + + Both + + + 644, 420 + + + 0 + + + logTextBox + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 1 + + + Microsoft Sans Serif, 8.25pt + + + NoControl + + + 20, 10 + + + 2, 2, 2, 2 + + + 100, 30 + + + 1 + + + &Clear + + + clearButton + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + splitContainer.Panel1 + + + 0 + + + Fill + + + True + + + 0, 0 + + + Horizontal + + + splitContainer.Panel1 + + + System.Windows.Forms.SplitterPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + splitContainer + + + 0 + + + Fill + + + 0, 0 + + + True + + + Vertical + + + 965, 643 + + + 0 + + + logsTextBox + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + splitContainer.Panel2 + + + 0 + + + splitContainer.Panel2 + + + System.Windows.Forms.SplitterPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + splitContainer + + + 1 + + + 965, 689 + + + 42 + + + 2 + + + splitContainer + + + System.Windows.Forms.SplitContainer, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 0 + + + True + + + 6, 13 + + + Microsoft Sans Serif, 8.25pt + + + 965, 689 + + + LogsTabPageCtrl + + + System.Windows.Forms.UserControl, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/Screens/MeasurementTabPageCtrl.Designer.cs b/TestBenchFramework/Screens/MeasurementTabPageCtrl.Designer.cs new file mode 100644 index 000000000..6013a73f9 --- /dev/null +++ b/TestBenchFramework/Screens/MeasurementTabPageCtrl.Designer.cs @@ -0,0 +1,205 @@ +namespace TBF.Screens +{ + partial class MeasurementTabPageCtrl + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.measurementLabel5 = new System.Windows.Forms.Label(); + this.measurementLabel4 = new System.Windows.Forms.Label(); + this.measurementLabel3 = new System.Windows.Forms.Label(); + this.measurementLabel2 = new System.Windows.Forms.Label(); + this.measurementLabel = new System.Windows.Forms.Label(); + this.measurementTableLayoutPanel4 = new System.Windows.Forms.TableLayoutPanel(); + this.measurementTableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel(); + this.measurementTableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel(); + this.measurementTableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); + this.SuspendLayout(); + // + // measurementLabel5 + // + this.measurementLabel5.AutoSize = true; + this.measurementLabel5.Font = new System.Drawing.Font("Verdana", 11.25F); + this.measurementLabel5.ImeMode = System.Windows.Forms.ImeMode.NoControl; + this.measurementLabel5.Location = new System.Drawing.Point(471, 136); + this.measurementLabel5.Name = "measurementLabel5"; + this.measurementLabel5.Size = new System.Drawing.Size(74, 18); + this.measurementLabel5.TabIndex = 17; + this.measurementLabel5.Text = "Time Bar"; + // + // measurementLabel4 + // + this.measurementLabel4.AutoSize = true; + this.measurementLabel4.Font = new System.Drawing.Font("Verdana", 11.25F); + this.measurementLabel4.ImeMode = System.Windows.Forms.ImeMode.NoControl; + this.measurementLabel4.Location = new System.Drawing.Point(328, 136); + this.measurementLabel4.Name = "measurementLabel4"; + this.measurementLabel4.Size = new System.Drawing.Size(74, 18); + this.measurementLabel4.TabIndex = 16; + this.measurementLabel4.Text = "Time Bar"; + // + // measurementLabel3 + // + this.measurementLabel3.AutoSize = true; + this.measurementLabel3.Font = new System.Drawing.Font("Verdana", 11.25F); + this.measurementLabel3.ImeMode = System.Windows.Forms.ImeMode.NoControl; + this.measurementLabel3.Location = new System.Drawing.Point(484, 164); + this.measurementLabel3.Name = "measurementLabel3"; + this.measurementLabel3.Size = new System.Drawing.Size(45, 18); + this.measurementLabel3.TabIndex = 15; + this.measurementLabel3.Text = "Total"; + // + // measurementLabel2 + // + this.measurementLabel2.AutoSize = true; + this.measurementLabel2.Font = new System.Drawing.Font("Verdana", 11.25F); + this.measurementLabel2.ImeMode = System.Windows.Forms.ImeMode.NoControl; + this.measurementLabel2.Location = new System.Drawing.Point(323, 164); + this.measurementLabel2.Name = "measurementLabel2"; + this.measurementLabel2.Size = new System.Drawing.Size(87, 18); + this.measurementLabel2.TabIndex = 14; + this.measurementLabel2.Text = "Actual test"; + // + // measurementLabel + // + this.measurementLabel.AutoSize = true; + this.measurementLabel.Font = new System.Drawing.Font("Verdana", 11.25F); + this.measurementLabel.ImeMode = System.Windows.Forms.ImeMode.NoControl; + this.measurementLabel.Location = new System.Drawing.Point(639, 514); + this.measurementLabel.Name = "measurementLabel"; + this.measurementLabel.Size = new System.Drawing.Size(108, 18); + this.measurementLabel.TabIndex = 13; + this.measurementLabel.Text = "Target values"; + // + // measurementTableLayoutPanel4 + // + this.measurementTableLayoutPanel4.ColumnCount = 3; + this.measurementTableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F)); + this.measurementTableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 30F)); + this.measurementTableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 20F)); + this.measurementTableLayoutPanel4.Location = new System.Drawing.Point(642, 544); + this.measurementTableLayoutPanel4.Name = "measurementTableLayoutPanel4"; + this.measurementTableLayoutPanel4.RowCount = 4; + this.measurementTableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 25F)); + this.measurementTableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 25F)); + this.measurementTableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 25F)); + this.measurementTableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 25F)); + this.measurementTableLayoutPanel4.Size = new System.Drawing.Size(216, 101); + this.measurementTableLayoutPanel4.TabIndex = 12; + // + // measurementTableLayoutPanel3 + // + this.measurementTableLayoutPanel3.ColumnCount = 3; + this.measurementTableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33F)); + this.measurementTableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33F)); + this.measurementTableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 34F)); + this.measurementTableLayoutPanel3.Location = new System.Drawing.Point(521, 11); + this.measurementTableLayoutPanel3.Name = "measurementTableLayoutPanel3"; + this.measurementTableLayoutPanel3.RowCount = 2; + this.measurementTableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F)); + this.measurementTableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F)); + this.measurementTableLayoutPanel3.Size = new System.Drawing.Size(348, 55); + this.measurementTableLayoutPanel3.TabIndex = 11; + // + // measurementTableLayoutPanel2 + // + this.measurementTableLayoutPanel2.ColumnCount = 2; + this.measurementTableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F)); + this.measurementTableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F)); + this.measurementTableLayoutPanel2.Location = new System.Drawing.Point(11, 245); + this.measurementTableLayoutPanel2.Name = "measurementTableLayoutPanel2"; + this.measurementTableLayoutPanel2.RowCount = 12; + this.measurementTableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.measurementTableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25F)); + this.measurementTableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25F)); + this.measurementTableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25F)); + this.measurementTableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25F)); + this.measurementTableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25F)); + this.measurementTableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25F)); + this.measurementTableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25F)); + this.measurementTableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25F)); + this.measurementTableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25F)); + this.measurementTableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25F)); + this.measurementTableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25F)); + this.measurementTableLayoutPanel2.Size = new System.Drawing.Size(177, 303); + this.measurementTableLayoutPanel2.TabIndex = 10; + // + // measurementTableLayoutPanel1 + // + this.measurementTableLayoutPanel1.ColumnCount = 3; + this.measurementTableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 30F)); + this.measurementTableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 35F)); + this.measurementTableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 35F)); + this.measurementTableLayoutPanel1.Location = new System.Drawing.Point(11, 21); + this.measurementTableLayoutPanel1.Name = "measurementTableLayoutPanel1"; + this.measurementTableLayoutPanel1.RowCount = 7; + this.measurementTableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.measurementTableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25F)); + this.measurementTableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25F)); + this.measurementTableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25F)); + this.measurementTableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25F)); + this.measurementTableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25F)); + this.measurementTableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25F)); + this.measurementTableLayoutPanel1.Size = new System.Drawing.Size(283, 183); + this.measurementTableLayoutPanel1.TabIndex = 9; + // + // MeasurementTabPageCtrl + // + this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 18F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(150)))), ((int)(((byte)(180)))), ((int)(((byte)(200))))); + this.Controls.Add(this.measurementLabel5); + this.Controls.Add(this.measurementLabel4); + this.Controls.Add(this.measurementLabel3); + this.Controls.Add(this.measurementLabel2); + this.Controls.Add(this.measurementLabel); + this.Controls.Add(this.measurementTableLayoutPanel4); + this.Controls.Add(this.measurementTableLayoutPanel3); + this.Controls.Add(this.measurementTableLayoutPanel2); + this.Controls.Add(this.measurementTableLayoutPanel1); + this.Font = new System.Drawing.Font("Verdana", 11.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238))); + this.Margin = new System.Windows.Forms.Padding(4); + this.Name = "MeasurementTabPageCtrl"; + this.Size = new System.Drawing.Size(900, 689); + this.Paint += new System.Windows.Forms.PaintEventHandler(this.measurement_Paint); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label measurementLabel5; + private System.Windows.Forms.Label measurementLabel4; + private System.Windows.Forms.Label measurementLabel3; + private System.Windows.Forms.Label measurementLabel2; + private System.Windows.Forms.Label measurementLabel; + private System.Windows.Forms.TableLayoutPanel measurementTableLayoutPanel4; + private System.Windows.Forms.TableLayoutPanel measurementTableLayoutPanel3; + private System.Windows.Forms.TableLayoutPanel measurementTableLayoutPanel2; + private System.Windows.Forms.TableLayoutPanel measurementTableLayoutPanel1; + } +} diff --git a/TestBenchFramework/Screens/MeasurementTabPageCtrl.cs b/TestBenchFramework/Screens/MeasurementTabPageCtrl.cs new file mode 100644 index 000000000..603a28c97 --- /dev/null +++ b/TestBenchFramework/Screens/MeasurementTabPageCtrl.cs @@ -0,0 +1,178 @@ +using System; +using System.Drawing; +using System.Windows.Forms; +using log4net; +using TBF.UiBridge; + +namespace TBF.Screens +{ + public partial class MeasurementTabPageCtrl : UserControl + { + static readonly ILog log = LogManager.GetLogger(typeof(MeasurementTabPageCtrl)); + + AttachedTextBoxes measurementTbl1Row1; /// Table 1 + AttachedTextBoxes measurementTbl1Col1; + AttachedTextBoxes measurementTbl1Col2; + AttachedTextBoxes measurementTbl1Col3; + AttachedTextBoxes measurementTbl2Row1; /// Table 2 + AttachedTextBoxes measurementTbl2Col1; + AttachedTextBoxes measurementTbl2Col2; + AttachedTextBoxes measurementTbl3Row1; /// Table 3 + AttachedTextBoxes measurementTbl3Row2; + AttachedTextBoxes measurementTbl4Col1; + AttachedTextBoxes measurementTbl4Col2; + AttachedTextBoxes measurementTbl4Col3; + + BarGraph measurementBar1; + BarGraph measurementBar2; + + public MeasurementTabPageCtrl() + { + InitializeComponent(); + + Bridge.TestSelectedHandler += delegate(object sender, TestSelectedEventArgs args) + { + if (InvokeRequired) + { + Invoke(new EventHandler(OnTestSelected), sender, args); + } + else OnTestSelected(sender, args); + }; + Bridge.TestProgressHandler += delegate(object sender, TestProgressEventArgs args) + { + if (InvokeRequired) + { + Invoke(new EventHandler(OnTestProgress), sender, args); + } + else OnTestProgress(sender, args); + }; + Bridge.TestCompletedHandler += delegate(object sender, TestCompletedEventArgs args) + { + if (InvokeRequired) + { + Invoke(new EventHandler(OnTestCompleted), sender, args); + } + else OnTestCompleted(sender, args); + }; + + Init(); + } + + private void Init() + { + measurementTbl1Row1 = new AttachedTextBoxes(measurementTableLayoutPanel1, Arrangement.RowOfStrings, 1, 0, 2); + measurementTbl1Col1 = new AttachedTextBoxes(measurementTableLayoutPanel1, Arrangement.ColumnOfStrings, 0, 1, 6); + measurementTbl1Col2 = new AttachedTextBoxes(measurementTableLayoutPanel1, Arrangement.ColumnOfDoubles, 1, 1, 6); + measurementTbl1Col3 = new AttachedTextBoxes(measurementTableLayoutPanel1, Arrangement.ColumnOfDoubles, 2, 1, 6); + measurementTbl2Row1 = new AttachedTextBoxes(measurementTableLayoutPanel2, Arrangement.RowOfStrings, 1, 0, 1); + measurementTbl2Col1 = new AttachedTextBoxes(measurementTableLayoutPanel2, Arrangement.ColumnOfStrings, 0, 1, 11); + measurementTbl2Col2 = new AttachedTextBoxes(measurementTableLayoutPanel2, Arrangement.ColumnOfDoubles, 1, 1, 11); + measurementTbl3Row1 = new AttachedTextBoxes(measurementTableLayoutPanel3, Arrangement.RowOfStrings, 0, 0, 3); + measurementTbl3Row2 = new AttachedTextBoxes(measurementTableLayoutPanel3, Arrangement.RowOfDoubles, 0, 1, 3); + measurementTbl4Col1 = new AttachedTextBoxes(measurementTableLayoutPanel4, Arrangement.ColumnOfStrings, 0, 0, 4); + measurementTbl4Col2 = new AttachedTextBoxes(measurementTableLayoutPanel4, Arrangement.ColumnOfDoubles, 1, 0, 4); + measurementTbl4Col3 = new AttachedTextBoxes(measurementTableLayoutPanel4, Arrangement.ColumnOfStrings, 2, 0, 4); + + CustomStyle.Apply(1, measurementTbl1Row1); + CustomStyle.Apply(1, measurementTbl1Col1); + CustomStyle.Apply(1, measurementTbl1Col2); + CustomStyle.Apply(1, measurementTbl1Col3); + CustomStyle.Apply(1, measurementTbl2Row1); + CustomStyle.Apply(1, measurementTbl2Col1); + CustomStyle.Apply(1, measurementTbl2Col2); + CustomStyle.Apply(1, measurementTbl3Row1); + CustomStyle.Apply(1, measurementTbl3Row2); + CustomStyle.Apply(1, measurementTbl4Col1); + CustomStyle.Apply(1, measurementTbl4Col2); + CustomStyle.Apply(1, measurementTbl4Col3); + + measurementTbl1Row1.SetData(0, "Vmer"); + measurementTbl1Row1.SetData(1, "Emer"); + for (int i = 0; i < Program.WMsCount; i++) measurementTbl1Col1.SetData(i, "Meter" + (i + 1).ToString()); + + measurementTbl2Row1.SetData(0, "Ergebnise"); + measurementTbl2Col1.SetData(0, "IMP"); + measurementTbl2Col1.SetData(1, "Zeit"); + measurementTbl2Col1.SetData(2, "V_etn"); + measurementTbl2Col1.SetData(3, "Temp up"); + measurementTbl2Col1.SetData(4, "Temp dn"); + measurementTbl2Col1.SetData(5, "T Kl"); + measurementTbl2Col1.SetData(6, "Druck up"); + measurementTbl2Col1.SetData(7, "Druck dn"); + measurementTbl2Col1.SetData(8, "Durchfl. act"); + measurementTbl2Col1.SetData(9, "Zeit Kl in"); + measurementTbl2Col1.SetData(10, "Zeit Kl out"); + + measurementTbl3Row1.SetData(0, "Temp. Luft"); + measurementTbl3Row1.SetData(1, "Druck Luft"); + measurementTbl3Row1.SetData(2, "Humi. Luft"); + + measurementTbl4Col1.SetData(0, "Durchfl. Tar Min"); + measurementTbl4Col1.SetData(1, "Durchfl. Tar Max"); + measurementTbl4Col1.SetData(2, "Volumen Tar"); + measurementTbl4Col1.SetData(3, "Dauer"); + + //measurementTbl4Col2.SetData(0, 1.5); + //measurementTbl4Col2.SetData(1, 1.65); + //measurementTbl4Col2.SetData(2, 50); + //measurementTbl4Col2.SetData(3, 114.29); + + measurementTbl4Col3.SetData(0, "m3/h"); + measurementTbl4Col3.SetData(1, "m3/h"); + measurementTbl4Col3.SetData(2, "l"); + measurementTbl4Col3.SetData(3, "s"); + + measurementBar1 = new BarGraph(this, 320, 200, 100, 400, Color.DarkBlue, Color.WhiteSmoke); + measurementBar2 = new BarGraph(this, 470, 200, 100, 400, Color.DarkBlue, Color.WhiteSmoke); + } + + private void measurement_Paint(object sender, PaintEventArgs e) + { + Graphics g = e.Graphics; + if (measurementBar1 != null) measurementBar1.Paint(g); + if (measurementBar2 != null) measurementBar2.Paint(g); + g.DrawRectangle(new Pen(Color.Black, 2.0F), 500, -2, 402, 80); + g.DrawRectangle(new Pen(Color.Black, 2.0F), 620, 500, 282, 250); + } + + + public void OnTestSelected(object sender, TestSelectedEventArgs data) + { + measurementTbl4Col2.SetData(0, data.Test.Qfrom.ToString("F2")); + measurementTbl4Col2.SetData(1, data.Test.Qto.ToString("F2")); + measurementTbl4Col2.SetData(2, data.Test.Volume.ToString("F1")); + measurementTbl4Col2.SetData(3, data.Test.TstTime.ToString("F1")); + } + + public void OnTestProgress(object sender, TestProgressEventArgs data) + { + if (data.WmVolume != null) + { + for (int i = 0; i < Program.WMsCount; i++) + { + measurementTbl1Col2.SetData(i, data.WmVolume[i].ToString("F1")); + measurementTbl1Col3.SetData(i, data.WmErrPct[i].ToString("F1")); + } + } + measurementTbl2Col2.SetData(0, data.RefPulses); + measurementTbl2Col2.SetData(1, data.Time.ToString("F1")); + + measurementTbl2Col2.SetData(3, data.Tin.ToString("F2")); + measurementTbl2Col2.SetData(4, data.Tout.ToString("F2")); + measurementTbl2Col2.SetData(5, data.Tdiv.ToString("F2")); + measurementTbl2Col2.SetData(6, data.Pin); + measurementTbl2Col2.SetData(7, data.Pout); + measurementTbl2Col2.SetData(8, data.Flow.ToString("F3")); + + measurementTbl3Row2.SetData(0, data.AmbientTemp); + measurementTbl3Row2.SetData(1, data.AmbientPressure); + measurementTbl3Row2.SetData(2, data.AmbientHumidity); + + //measurementBar1.FValue = data.Progress; + } + + public void OnTestCompleted(object sender, TestCompletedEventArgs data) + { + } + } +} diff --git a/TestBenchFramework/Screens/MeasurementTabPageCtrl.resx b/TestBenchFramework/Screens/MeasurementTabPageCtrl.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/TestBenchFramework/Screens/MeasurementTabPageCtrl.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/Screens/PicturesTabPageCtrl.Designer.cs b/TestBenchFramework/Screens/PicturesTabPageCtrl.Designer.cs new file mode 100644 index 000000000..ee6062e67 --- /dev/null +++ b/TestBenchFramework/Screens/PicturesTabPageCtrl.Designer.cs @@ -0,0 +1,174 @@ +namespace TBF.Screens +{ + partial class PicturesTabPageCtrl + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(PicturesTabPageCtrl)); + this.logTextBox = new System.Windows.Forms.TextBox(); + this.splitContainer = new System.Windows.Forms.SplitContainer(); + this.configureButton = new System.Windows.Forms.Button(); + this.cameraPictureCtrl6 = new TBF.UiControls.CameraPictureCtrl(); + this.cameraPictureCtrl5 = new TBF.UiControls.CameraPictureCtrl(); + this.cameraPictureCtrl4 = new TBF.UiControls.CameraPictureCtrl(); + this.cameraPictureCtrl3 = new TBF.UiControls.CameraPictureCtrl(); + this.cameraPictureCtrl2 = new TBF.UiControls.CameraPictureCtrl(); + this.cameraPictureCtrl1 = new TBF.UiControls.CameraPictureCtrl(); + this.grabButton = new System.Windows.Forms.Button(); + this.liveButton = new System.Windows.Forms.Button(); + this.focusButton = new System.Windows.Forms.Button(); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).BeginInit(); + this.splitContainer.Panel1.SuspendLayout(); + this.splitContainer.Panel2.SuspendLayout(); + this.splitContainer.SuspendLayout(); + this.SuspendLayout(); + // + // logTextBox + // + resources.ApplyResources(this.logTextBox, "logTextBox"); + this.logTextBox.Name = "logTextBox"; + // + // splitContainer + // + resources.ApplyResources(this.splitContainer, "splitContainer"); + this.splitContainer.FixedPanel = System.Windows.Forms.FixedPanel.Panel1; + this.splitContainer.Name = "splitContainer"; + // + // splitContainer.Panel1 + // + this.splitContainer.Panel1.BackColor = System.Drawing.SystemColors.Control; + this.splitContainer.Panel1.Controls.Add(this.focusButton); + this.splitContainer.Panel1.Controls.Add(this.liveButton); + this.splitContainer.Panel1.Controls.Add(this.grabButton); + this.splitContainer.Panel1.Controls.Add(this.configureButton); + // + // splitContainer.Panel2 + // + this.splitContainer.Panel2.Controls.Add(this.cameraPictureCtrl6); + this.splitContainer.Panel2.Controls.Add(this.cameraPictureCtrl5); + this.splitContainer.Panel2.Controls.Add(this.cameraPictureCtrl4); + this.splitContainer.Panel2.Controls.Add(this.cameraPictureCtrl3); + this.splitContainer.Panel2.Controls.Add(this.cameraPictureCtrl2); + this.splitContainer.Panel2.Controls.Add(this.cameraPictureCtrl1); + // + // configureButton + // + resources.ApplyResources(this.configureButton, "configureButton"); + this.configureButton.Name = "configureButton"; + this.configureButton.UseVisualStyleBackColor = true; + this.configureButton.Click += new System.EventHandler(this.configureButton_Click); + // + // cameraPictureCtrl6 + // + this.cameraPictureCtrl6.BackColor = System.Drawing.SystemColors.ButtonShadow; + resources.ApplyResources(this.cameraPictureCtrl6, "cameraPictureCtrl6"); + this.cameraPictureCtrl6.Name = "cameraPictureCtrl6"; + // + // cameraPictureCtrl5 + // + this.cameraPictureCtrl5.BackColor = System.Drawing.SystemColors.ButtonShadow; + resources.ApplyResources(this.cameraPictureCtrl5, "cameraPictureCtrl5"); + this.cameraPictureCtrl5.Name = "cameraPictureCtrl5"; + // + // cameraPictureCtrl4 + // + this.cameraPictureCtrl4.BackColor = System.Drawing.SystemColors.ButtonShadow; + resources.ApplyResources(this.cameraPictureCtrl4, "cameraPictureCtrl4"); + this.cameraPictureCtrl4.Name = "cameraPictureCtrl4"; + // + // cameraPictureCtrl3 + // + this.cameraPictureCtrl3.BackColor = System.Drawing.SystemColors.ButtonShadow; + resources.ApplyResources(this.cameraPictureCtrl3, "cameraPictureCtrl3"); + this.cameraPictureCtrl3.Name = "cameraPictureCtrl3"; + // + // cameraPictureCtrl2 + // + this.cameraPictureCtrl2.BackColor = System.Drawing.SystemColors.ButtonShadow; + resources.ApplyResources(this.cameraPictureCtrl2, "cameraPictureCtrl2"); + this.cameraPictureCtrl2.Name = "cameraPictureCtrl2"; + // + // cameraPictureCtrl1 + // + this.cameraPictureCtrl1.BackColor = System.Drawing.SystemColors.ButtonShadow; + resources.ApplyResources(this.cameraPictureCtrl1, "cameraPictureCtrl1"); + this.cameraPictureCtrl1.Name = "cameraPictureCtrl1"; + // + // grabButton + // + resources.ApplyResources(this.grabButton, "grabButton"); + this.grabButton.Name = "grabButton"; + this.grabButton.UseVisualStyleBackColor = true; + this.grabButton.Click += new System.EventHandler(this.grabButton_Click); + // + // liveButton + // + resources.ApplyResources(this.liveButton, "liveButton"); + this.liveButton.Name = "liveButton"; + this.liveButton.UseVisualStyleBackColor = true; + this.liveButton.Click += new System.EventHandler(this.liveButton_Click); + // + // focusButton + // + resources.ApplyResources(this.focusButton, "focusButton"); + this.focusButton.Name = "focusButton"; + this.focusButton.UseVisualStyleBackColor = true; + this.focusButton.Click += new System.EventHandler(this.focusButton_Click); + // + // PicturesTabPageCtrl + // + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.BackColor = System.Drawing.Color.Silver; + this.Controls.Add(this.splitContainer); + this.Controls.Add(this.logTextBox); + this.Name = "PicturesTabPageCtrl"; + this.splitContainer.Panel1.ResumeLayout(false); + this.splitContainer.Panel2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).EndInit(); + this.splitContainer.ResumeLayout(false); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TextBox logTextBox; + private System.Windows.Forms.SplitContainer splitContainer; + private System.Windows.Forms.Button configureButton; + private UiControls.CameraPictureCtrl cameraPictureCtrl6; + private UiControls.CameraPictureCtrl cameraPictureCtrl5; + private UiControls.CameraPictureCtrl cameraPictureCtrl4; + private UiControls.CameraPictureCtrl cameraPictureCtrl3; + private UiControls.CameraPictureCtrl cameraPictureCtrl2; + private UiControls.CameraPictureCtrl cameraPictureCtrl1; + private System.Windows.Forms.Button focusButton; + private System.Windows.Forms.Button liveButton; + private System.Windows.Forms.Button grabButton; + } +} diff --git a/TestBenchFramework/Screens/PicturesTabPageCtrl.cs b/TestBenchFramework/Screens/PicturesTabPageCtrl.cs new file mode 100644 index 000000000..a99e133e9 --- /dev/null +++ b/TestBenchFramework/Screens/PicturesTabPageCtrl.cs @@ -0,0 +1,82 @@ +using System; +using System.Windows.Forms; +using TBF.Resources; +using TBF.UiBridge; + +namespace TBF.Screens +{ + public partial class PicturesTabPageCtrl : UserControl + { + public PicturesTabPageCtrl() + { + InitializeComponent(); + configureButton.Text = Strings.Configure; + + Bridge.CameraStateChangedHandler += delegate(object sender, CameraStateChangedEventArgs args) + { + if (InvokeRequired) + { + Invoke(new EventHandler(OnCameraStateChanged), sender, args); + } + else OnCameraStateChanged(sender, args); + }; + + Bridge.ImageUpdatedHandler += delegate(object sender, ImageUpdatedEventArgs args) + { + if (InvokeRequired) + { + Invoke(new EventHandler(OnImageUpdated), sender, args); + } + else OnImageUpdated(sender, args); + }; + } + + void OnCameraStateChanged(object sender, CameraStateChangedEventArgs args) + { + switch (args.CameraIdx) + { + case 0: cameraPictureCtrl1.CameraState = args.State; break; + case 1: cameraPictureCtrl2.CameraState = args.State; break; + case 2: cameraPictureCtrl3.CameraState = args.State; break; + case 3: cameraPictureCtrl4.CameraState = args.State; break; + case 4: cameraPictureCtrl5.CameraState = args.State; break; + case 5: cameraPictureCtrl6.CameraState = args.State; break; + default: break; + } + } + + void OnImageUpdated(object sender, ImageUpdatedEventArgs args) + { + switch (args.CameraIdx) + { + case 0: cameraPictureCtrl1.PictureBox.ImageLocation = args.ImageLocation; break; + case 1: cameraPictureCtrl2.PictureBox.ImageLocation = args.ImageLocation; break; + case 2: cameraPictureCtrl3.PictureBox.ImageLocation = args.ImageLocation; break; + case 3: cameraPictureCtrl4.PictureBox.ImageLocation = args.ImageLocation; break; + case 4: cameraPictureCtrl5.PictureBox.ImageLocation = args.ImageLocation; break; + case 5: cameraPictureCtrl6.PictureBox.ImageLocation = args.ImageLocation; break; + default: break; + } + } + + private void configureButton_Click(object sender, EventArgs e) + { + + } + + private void grabButton_Click(object sender, EventArgs e) + { + + } + + private void liveButton_Click(object sender, EventArgs e) + { + + } + + private void focusButton_Click(object sender, EventArgs e) + { + + } + } +} diff --git a/TestBenchFramework/Screens/PicturesTabPageCtrl.resx b/TestBenchFramework/Screens/PicturesTabPageCtrl.resx new file mode 100644 index 000000000..00e84dd5f --- /dev/null +++ b/TestBenchFramework/Screens/PicturesTabPageCtrl.resx @@ -0,0 +1,462 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 98, 249 + + + + 2, 2, 2, 2 + + + + True + + + Both + + + 644, 420 + + + 0 + + + logTextBox + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 1 + + + Fill + + + True + + + 0, 0 + + + Horizontal + + + NoControl + + + 386, 7 + + + 100, 30 + + + 5 + + + Focus + + + focusButton + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + splitContainer.Panel1 + + + 0 + + + NoControl + + + 280, 7 + + + 100, 30 + + + 4 + + + Live + + + liveButton + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + splitContainer.Panel1 + + + 1 + + + 174, 7 + + + 100, 30 + + + 3 + + + Grab + + + grabButton + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + splitContainer.Panel1 + + + 2 + + + False + + + 20, 7 + + + 100, 30 + + + 2 + + + Configure + + + False + + + configureButton + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + splitContainer.Panel1 + + + 3 + + + splitContainer.Panel1 + + + System.Windows.Forms.SplitterPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + splitContainer + + + 0 + + + 673, 323 + + + 334, 320 + + + 5 + + + cameraPictureCtrl6 + + + TBF.UiControls.CameraPictureCtrl, TBF, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + + splitContainer.Panel2 + + + 0 + + + 338, 323 + + + 334, 320 + + + 4 + + + cameraPictureCtrl5 + + + TBF.UiControls.CameraPictureCtrl, TBF, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + + splitContainer.Panel2 + + + 1 + + + 3, 323 + + + 334, 320 + + + 3 + + + cameraPictureCtrl4 + + + TBF.UiControls.CameraPictureCtrl, TBF, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + + splitContainer.Panel2 + + + 2 + + + 673, 3 + + + 334, 320 + + + 2 + + + cameraPictureCtrl3 + + + TBF.UiControls.CameraPictureCtrl, TBF, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + + splitContainer.Panel2 + + + 3 + + + 338, 3 + + + 334, 320 + + + 1 + + + cameraPictureCtrl2 + + + TBF.UiControls.CameraPictureCtrl, TBF, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + + splitContainer.Panel2 + + + 4 + + + 3, 3 + + + 334, 320 + + + 0 + + + cameraPictureCtrl1 + + + TBF.UiControls.CameraPictureCtrl, TBF, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + + splitContainer.Panel2 + + + 5 + + + splitContainer.Panel2 + + + System.Windows.Forms.SplitterPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + splitContainer + + + 1 + + + 965, 689 + + + 42 + + + 2 + + + splitContainer + + + System.Windows.Forms.SplitContainer, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 0 + + + True + + + 6, 13 + + + Microsoft Sans Serif, 8.25pt + + + 965, 689 + + + PicturesTabPageCtrl + + + System.Windows.Forms.UserControl, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/Screens/ProcessTabPageCtrl.Designer.cs b/TestBenchFramework/Screens/ProcessTabPageCtrl.Designer.cs new file mode 100644 index 000000000..7f1a12772 --- /dev/null +++ b/TestBenchFramework/Screens/ProcessTabPageCtrl.Designer.cs @@ -0,0 +1,1081 @@ +namespace TBF.Screens +{ + partial class ProcessTabPageCtrl + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.sensor1Label = new System.Windows.Forms.Label(); + this.pulses1Label = new System.Windows.Forms.Label(); + this.refPulses1Label = new System.Windows.Forms.Label(); + this.label1 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.label3 = new System.Windows.Forms.Label(); + this.volume1Label = new System.Windows.Forms.Label(); + this.label4 = new System.Windows.Forms.Label(); + this.error1Label = new System.Windows.Forms.Label(); + this.passed1Label = new System.Windows.Forms.Label(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.passed2Label = new System.Windows.Forms.Label(); + this.error2Label = new System.Windows.Forms.Label(); + this.label8 = new System.Windows.Forms.Label(); + this.volume2Label = 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.refPulses2Label = new System.Windows.Forms.Label(); + this.pulses2Label = new System.Windows.Forms.Label(); + this.sensor2Label = new System.Windows.Forms.Label(); + this.groupBox3 = new System.Windows.Forms.GroupBox(); + this.passed3Label = new System.Windows.Forms.Label(); + this.error3Label = new System.Windows.Forms.Label(); + this.label12 = new System.Windows.Forms.Label(); + this.volume3Label = new System.Windows.Forms.Label(); + this.label11 = new System.Windows.Forms.Label(); + this.label10 = new System.Windows.Forms.Label(); + this.label9 = new System.Windows.Forms.Label(); + this.refPulses3Label = new System.Windows.Forms.Label(); + this.pulses3Label = new System.Windows.Forms.Label(); + this.sensor3Label = new System.Windows.Forms.Label(); + this.label13 = new System.Windows.Forms.Label(); + this.label14 = new System.Windows.Forms.Label(); + this.tInLabel = new System.Windows.Forms.Label(); + this.prInLabel = new System.Windows.Forms.Label(); + this.prOutLabel = new System.Windows.Forms.Label(); + this.tOutLabel = new System.Windows.Forms.Label(); + this.label17 = new System.Windows.Forms.Label(); + this.label18 = new System.Windows.Forms.Label(); + this.label15 = new System.Windows.Forms.Label(); + this.tInCmpntLabel = new System.Windows.Forms.Label(); + this.tOutCmpntLabel = new System.Windows.Forms.Label(); + this.prOutCmpntLabel = new System.Windows.Forms.Label(); + this.prInCmpntLabel = new System.Windows.Forms.Label(); + this.refFlowLabel = new System.Windows.Forms.Label(); + this.label16 = new System.Windows.Forms.Label(); + this.refFreqLabel = new System.Windows.Forms.Label(); + this.label19 = new System.Windows.Forms.Label(); + this.refPulsesLabel = new System.Windows.Forms.Label(); + this.refFlowCmpntLabel = new System.Windows.Forms.Label(); + this.regValveCmpntLabel = new System.Windows.Forms.Label(); + this.regValvePosLabel = new System.Windows.Forms.Label(); + this.label21 = new System.Windows.Forms.Label(); + this.tDivCmpntLabel = new System.Windows.Forms.Label(); + this.tDivLabel = new System.Windows.Forms.Label(); + this.label24 = new System.Windows.Forms.Label(); + this.scaleCmpntLabel = new System.Windows.Forms.Label(); + this.label22 = new System.Windows.Forms.Label(); + this.massLabel = new System.Windows.Forms.Label(); + this.label23 = new System.Windows.Forms.Label(); + this.massDiffLabel = new System.Windows.Forms.Label(); + this.label25 = new System.Windows.Forms.Label(); + this.refVolumeLabel = new System.Windows.Forms.Label(); + this.label26 = new System.Windows.Forms.Label(); + this.volumeCtvLabel = new System.Windows.Forms.Label(); + this.label27 = new System.Windows.Forms.Label(); + this.refErrorLabel = new System.Windows.Forms.Label(); + this.label28 = new System.Windows.Forms.Label(); + this.label29 = new System.Windows.Forms.Label(); + this.label20 = new System.Windows.Forms.Label(); + this.label30 = new System.Windows.Forms.Label(); + this.targetFlowLowLabel = new System.Windows.Forms.Label(); + this.targetFlowHighLabel = new System.Windows.Forms.Label(); + this.targetVolumeLabel = new System.Windows.Forms.Label(); + this.label31 = new System.Windows.Forms.Label(); + this.targetRefCountLabel = new System.Windows.Forms.Label(); + this.estmtdTimeLabel = new System.Windows.Forms.Label(); + this.label32 = new System.Windows.Forms.Label(); + this.label33 = new System.Windows.Forms.Label(); + this.label34 = new System.Windows.Forms.Label(); + this.airTempLabel = new System.Windows.Forms.Label(); + this.airPressLabel = new System.Windows.Forms.Label(); + this.airHumiLabel = new System.Windows.Forms.Label(); + this.groupBox1.SuspendLayout(); + this.groupBox2.SuspendLayout(); + this.groupBox3.SuspendLayout(); + this.SuspendLayout(); + // + // sensor1Label + // + this.sensor1Label.AutoSize = true; + this.sensor1Label.Location = new System.Drawing.Point(74, 16); + this.sensor1Label.Name = "sensor1Label"; + this.sensor1Label.Size = new System.Drawing.Size(44, 13); + this.sensor1Label.TabIndex = 0; + this.sensor1Label.Text = "sensor1"; + // + // pulses1Label + // + this.pulses1Label.AutoSize = true; + this.pulses1Label.Location = new System.Drawing.Point(74, 36); + this.pulses1Label.Name = "pulses1Label"; + this.pulses1Label.Size = new System.Drawing.Size(43, 13); + this.pulses1Label.TabIndex = 1; + this.pulses1Label.Text = "pulses1"; + // + // refPulses1Label + // + this.refPulses1Label.AutoSize = true; + this.refPulses1Label.Location = new System.Drawing.Point(74, 57); + this.refPulses1Label.Name = "refPulses1Label"; + this.refPulses1Label.Size = new System.Drawing.Size(56, 13); + this.refPulses1Label.TabIndex = 2; + this.refPulses1Label.Text = "refPulses1"; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(30, 36); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(38, 13); + this.label1.TabIndex = 3; + this.label1.Text = "Count:"; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(8, 57); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(60, 13); + this.label2.TabIndex = 4; + this.label2.Text = "Ref. count:"; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(23, 77); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(45, 13); + this.label3.TabIndex = 5; + this.label3.Text = "Volume:"; + // + // volume1Label + // + this.volume1Label.AutoSize = true; + this.volume1Label.Location = new System.Drawing.Point(74, 77); + this.volume1Label.Name = "volume1Label"; + this.volume1Label.Size = new System.Drawing.Size(47, 13); + this.volume1Label.TabIndex = 6; + this.volume1Label.Text = "volume1"; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(19, 98); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(49, 13); + this.label4.TabIndex = 7; + this.label4.Text = "Error [%]:"; + // + // error1Label + // + this.error1Label.AutoSize = true; + this.error1Label.Location = new System.Drawing.Point(74, 98); + this.error1Label.Name = "error1Label"; + this.error1Label.Size = new System.Drawing.Size(34, 13); + this.error1Label.TabIndex = 8; + this.error1Label.Text = "error1"; + // + // passed1Label + // + this.passed1Label.AutoSize = true; + this.passed1Label.Location = new System.Drawing.Point(74, 118); + this.passed1Label.Name = "passed1Label"; + this.passed1Label.Size = new System.Drawing.Size(47, 13); + this.passed1Label.TabIndex = 9; + this.passed1Label.Text = "passed1"; + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.passed1Label); + this.groupBox1.Controls.Add(this.error1Label); + this.groupBox1.Controls.Add(this.label4); + this.groupBox1.Controls.Add(this.volume1Label); + this.groupBox1.Controls.Add(this.label3); + this.groupBox1.Controls.Add(this.label2); + this.groupBox1.Controls.Add(this.label1); + this.groupBox1.Controls.Add(this.refPulses1Label); + this.groupBox1.Controls.Add(this.pulses1Label); + this.groupBox1.Controls.Add(this.sensor1Label); + this.groupBox1.Location = new System.Drawing.Point(134, 181); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(139, 144); + this.groupBox1.TabIndex = 10; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Meter 1"; + // + // groupBox2 + // + this.groupBox2.Controls.Add(this.passed2Label); + this.groupBox2.Controls.Add(this.error2Label); + this.groupBox2.Controls.Add(this.label8); + this.groupBox2.Controls.Add(this.volume2Label); + this.groupBox2.Controls.Add(this.label7); + this.groupBox2.Controls.Add(this.label6); + this.groupBox2.Controls.Add(this.label5); + this.groupBox2.Controls.Add(this.refPulses2Label); + this.groupBox2.Controls.Add(this.pulses2Label); + this.groupBox2.Controls.Add(this.sensor2Label); + this.groupBox2.Location = new System.Drawing.Point(279, 181); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size(139, 144); + this.groupBox2.TabIndex = 11; + this.groupBox2.TabStop = false; + this.groupBox2.Text = "Meter 2"; + // + // passed2Label + // + this.passed2Label.AutoSize = true; + this.passed2Label.Location = new System.Drawing.Point(74, 118); + this.passed2Label.Name = "passed2Label"; + this.passed2Label.Size = new System.Drawing.Size(47, 13); + this.passed2Label.TabIndex = 9; + this.passed2Label.Text = "passed2"; + // + // error2Label + // + this.error2Label.AutoSize = true; + this.error2Label.Location = new System.Drawing.Point(74, 98); + this.error2Label.Name = "error2Label"; + this.error2Label.Size = new System.Drawing.Size(34, 13); + this.error2Label.TabIndex = 8; + this.error2Label.Text = "error2"; + // + // label8 + // + this.label8.AutoSize = true; + this.label8.Location = new System.Drawing.Point(19, 98); + this.label8.Name = "label8"; + this.label8.Size = new System.Drawing.Size(49, 13); + this.label8.TabIndex = 7; + this.label8.Text = "Error [%]:"; + // + // volume2Label + // + this.volume2Label.AutoSize = true; + this.volume2Label.Location = new System.Drawing.Point(74, 77); + this.volume2Label.Name = "volume2Label"; + this.volume2Label.Size = new System.Drawing.Size(47, 13); + this.volume2Label.TabIndex = 6; + this.volume2Label.Text = "volume2"; + // + // label7 + // + this.label7.AutoSize = true; + this.label7.Location = new System.Drawing.Point(23, 77); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size(45, 13); + this.label7.TabIndex = 5; + this.label7.Text = "Volume:"; + // + // label6 + // + this.label6.AutoSize = true; + this.label6.Location = new System.Drawing.Point(8, 57); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(60, 13); + this.label6.TabIndex = 4; + this.label6.Text = "Ref. count:"; + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point(30, 36); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(38, 13); + this.label5.TabIndex = 3; + this.label5.Text = "Count:"; + // + // refPulses2Label + // + this.refPulses2Label.AutoSize = true; + this.refPulses2Label.Location = new System.Drawing.Point(74, 57); + this.refPulses2Label.Name = "refPulses2Label"; + this.refPulses2Label.Size = new System.Drawing.Size(56, 13); + this.refPulses2Label.TabIndex = 2; + this.refPulses2Label.Text = "refPulses2"; + // + // pulses2Label + // + this.pulses2Label.AutoSize = true; + this.pulses2Label.Location = new System.Drawing.Point(74, 36); + this.pulses2Label.Name = "pulses2Label"; + this.pulses2Label.Size = new System.Drawing.Size(43, 13); + this.pulses2Label.TabIndex = 1; + this.pulses2Label.Text = "pulses2"; + // + // sensor2Label + // + this.sensor2Label.AutoSize = true; + this.sensor2Label.Location = new System.Drawing.Point(74, 16); + this.sensor2Label.Name = "sensor2Label"; + this.sensor2Label.Size = new System.Drawing.Size(44, 13); + this.sensor2Label.TabIndex = 0; + this.sensor2Label.Text = "sensor2"; + // + // groupBox3 + // + this.groupBox3.Controls.Add(this.passed3Label); + this.groupBox3.Controls.Add(this.error3Label); + this.groupBox3.Controls.Add(this.label12); + this.groupBox3.Controls.Add(this.volume3Label); + this.groupBox3.Controls.Add(this.label11); + this.groupBox3.Controls.Add(this.label10); + this.groupBox3.Controls.Add(this.label9); + this.groupBox3.Controls.Add(this.refPulses3Label); + this.groupBox3.Controls.Add(this.pulses3Label); + this.groupBox3.Controls.Add(this.sensor3Label); + this.groupBox3.Location = new System.Drawing.Point(424, 181); + this.groupBox3.Name = "groupBox3"; + this.groupBox3.Size = new System.Drawing.Size(139, 144); + this.groupBox3.TabIndex = 12; + this.groupBox3.TabStop = false; + this.groupBox3.Text = "Meter 3"; + // + // passed3Label + // + this.passed3Label.AutoSize = true; + this.passed3Label.Location = new System.Drawing.Point(74, 118); + this.passed3Label.Name = "passed3Label"; + this.passed3Label.Size = new System.Drawing.Size(47, 13); + this.passed3Label.TabIndex = 9; + this.passed3Label.Text = "passed3"; + // + // error3Label + // + this.error3Label.AutoSize = true; + this.error3Label.Location = new System.Drawing.Point(74, 98); + this.error3Label.Name = "error3Label"; + this.error3Label.Size = new System.Drawing.Size(34, 13); + this.error3Label.TabIndex = 8; + this.error3Label.Text = "error3"; + // + // label12 + // + this.label12.AutoSize = true; + this.label12.Location = new System.Drawing.Point(19, 98); + this.label12.Name = "label12"; + this.label12.Size = new System.Drawing.Size(49, 13); + this.label12.TabIndex = 7; + this.label12.Text = "Error [%]:"; + // + // volume3Label + // + this.volume3Label.AutoSize = true; + this.volume3Label.Location = new System.Drawing.Point(74, 77); + this.volume3Label.Name = "volume3Label"; + this.volume3Label.Size = new System.Drawing.Size(47, 13); + this.volume3Label.TabIndex = 6; + this.volume3Label.Text = "volume3"; + // + // label11 + // + this.label11.AutoSize = true; + this.label11.Location = new System.Drawing.Point(23, 77); + this.label11.Name = "label11"; + this.label11.Size = new System.Drawing.Size(45, 13); + this.label11.TabIndex = 5; + this.label11.Text = "Volume:"; + // + // label10 + // + this.label10.AutoSize = true; + this.label10.Location = new System.Drawing.Point(8, 57); + this.label10.Name = "label10"; + this.label10.Size = new System.Drawing.Size(60, 13); + this.label10.TabIndex = 4; + this.label10.Text = "Ref. count:"; + // + // label9 + // + this.label9.AutoSize = true; + this.label9.Location = new System.Drawing.Point(30, 36); + this.label9.Name = "label9"; + this.label9.Size = new System.Drawing.Size(38, 13); + this.label9.TabIndex = 3; + this.label9.Text = "Count:"; + // + // refPulses3Label + // + this.refPulses3Label.AutoSize = true; + this.refPulses3Label.Location = new System.Drawing.Point(74, 57); + this.refPulses3Label.Name = "refPulses3Label"; + this.refPulses3Label.Size = new System.Drawing.Size(56, 13); + this.refPulses3Label.TabIndex = 2; + this.refPulses3Label.Text = "refPulses3"; + // + // pulses3Label + // + this.pulses3Label.AutoSize = true; + this.pulses3Label.Location = new System.Drawing.Point(74, 36); + this.pulses3Label.Name = "pulses3Label"; + this.pulses3Label.Size = new System.Drawing.Size(43, 13); + this.pulses3Label.TabIndex = 1; + this.pulses3Label.Text = "pulses3"; + // + // sensor3Label + // + this.sensor3Label.AutoSize = true; + this.sensor3Label.Location = new System.Drawing.Point(74, 16); + this.sensor3Label.Name = "sensor3Label"; + this.sensor3Label.Size = new System.Drawing.Size(44, 13); + this.sensor3Label.TabIndex = 0; + this.sensor3Label.Text = "sensor3"; + // + // label13 + // + this.label13.AutoSize = true; + this.label13.Location = new System.Drawing.Point(22, 242); + this.label13.Name = "label13"; + this.label13.Size = new System.Drawing.Size(52, 13); + this.label13.TabIndex = 13; + this.label13.Text = "T up [°C]:"; + // + // label14 + // + this.label14.AutoSize = true; + this.label14.Location = new System.Drawing.Point(6, 291); + this.label14.Name = "label14"; + this.label14.Size = new System.Drawing.Size(68, 13); + this.label14.TabIndex = 14; + this.label14.Text = "Pr up [mBar]:"; + // + // tInLabel + // + this.tInLabel.AutoSize = true; + this.tInLabel.Location = new System.Drawing.Point(80, 242); + this.tInLabel.Name = "tInLabel"; + this.tInLabel.Size = new System.Drawing.Size(19, 13); + this.tInLabel.TabIndex = 15; + this.tInLabel.Text = "tIn"; + // + // prInLabel + // + this.prInLabel.AutoSize = true; + this.prInLabel.Location = new System.Drawing.Point(80, 291); + this.prInLabel.Name = "prInLabel"; + this.prInLabel.Size = new System.Drawing.Size(25, 13); + this.prInLabel.TabIndex = 16; + this.prInLabel.Text = "prIn"; + // + // prOutLabel + // + this.prOutLabel.AutoSize = true; + this.prOutLabel.Location = new System.Drawing.Point(654, 291); + this.prOutLabel.Name = "prOutLabel"; + this.prOutLabel.Size = new System.Drawing.Size(33, 13); + this.prOutLabel.TabIndex = 20; + this.prOutLabel.Text = "prOut"; + // + // tOutLabel + // + this.tOutLabel.AutoSize = true; + this.tOutLabel.Location = new System.Drawing.Point(654, 242); + this.tOutLabel.Name = "tOutLabel"; + this.tOutLabel.Size = new System.Drawing.Size(27, 13); + this.tOutLabel.TabIndex = 19; + this.tOutLabel.Text = "tOut"; + // + // label17 + // + this.label17.AutoSize = true; + this.label17.Location = new System.Drawing.Point(568, 291); + this.label17.Name = "label17"; + this.label17.Size = new System.Drawing.Size(82, 13); + this.label17.TabIndex = 18; + this.label17.Text = "Pr down [mBar]:"; + // + // label18 + // + this.label18.AutoSize = true; + this.label18.Location = new System.Drawing.Point(584, 242); + this.label18.Name = "label18"; + this.label18.Size = new System.Drawing.Size(66, 13); + this.label18.TabIndex = 17; + this.label18.Text = "T down [°C]:"; + // + // label15 + // + this.label15.AutoSize = true; + this.label15.Location = new System.Drawing.Point(564, 119); + this.label15.Name = "label15"; + this.label15.Size = new System.Drawing.Size(86, 13); + this.label15.TabIndex = 21; + this.label15.Text = "Ref. flow [m3/h]:"; + // + // tInCmpntLabel + // + this.tInCmpntLabel.AutoSize = true; + this.tInCmpntLabel.Location = new System.Drawing.Point(80, 222); + this.tInCmpntLabel.Name = "tInCmpntLabel"; + this.tInCmpntLabel.Size = new System.Drawing.Size(49, 13); + this.tInCmpntLabel.TabIndex = 22; + this.tInCmpntLabel.Text = "tInCmpnt"; + // + // tOutCmpntLabel + // + this.tOutCmpntLabel.AutoSize = true; + this.tOutCmpntLabel.Location = new System.Drawing.Point(654, 222); + this.tOutCmpntLabel.Name = "tOutCmpntLabel"; + this.tOutCmpntLabel.Size = new System.Drawing.Size(57, 13); + this.tOutCmpntLabel.TabIndex = 23; + this.tOutCmpntLabel.Text = "tOutCmpnt"; + // + // prOutCmpntLabel + // + this.prOutCmpntLabel.AutoSize = true; + this.prOutCmpntLabel.Location = new System.Drawing.Point(654, 272); + this.prOutCmpntLabel.Name = "prOutCmpntLabel"; + this.prOutCmpntLabel.Size = new System.Drawing.Size(63, 13); + this.prOutCmpntLabel.TabIndex = 24; + this.prOutCmpntLabel.Text = "prOutCmpnt"; + // + // prInCmpntLabel + // + this.prInCmpntLabel.AutoSize = true; + this.prInCmpntLabel.Location = new System.Drawing.Point(80, 272); + this.prInCmpntLabel.Name = "prInCmpntLabel"; + this.prInCmpntLabel.Size = new System.Drawing.Size(55, 13); + this.prInCmpntLabel.TabIndex = 25; + this.prInCmpntLabel.Text = "prInCmpnt"; + // + // refFlowLabel + // + this.refFlowLabel.AutoSize = true; + this.refFlowLabel.Location = new System.Drawing.Point(654, 119); + this.refFlowLabel.Name = "refFlowLabel"; + this.refFlowLabel.Size = new System.Drawing.Size(41, 13); + this.refFlowLabel.TabIndex = 26; + this.refFlowLabel.Text = "refFlow"; + // + // label16 + // + this.label16.AutoSize = true; + this.label16.Location = new System.Drawing.Point(574, 98); + this.label16.Name = "label16"; + this.label16.Size = new System.Drawing.Size(76, 13); + this.label16.TabIndex = 27; + this.label16.Text = "Ref. freq. [Hz]:"; + // + // refFreqLabel + // + this.refFreqLabel.AutoSize = true; + this.refFreqLabel.Location = new System.Drawing.Point(654, 98); + this.refFreqLabel.Name = "refFreqLabel"; + this.refFreqLabel.Size = new System.Drawing.Size(40, 13); + this.refFreqLabel.TabIndex = 28; + this.refFreqLabel.Text = "refFreq"; + // + // label19 + // + this.label19.AutoSize = true; + this.label19.Location = new System.Drawing.Point(590, 78); + this.label19.Name = "label19"; + this.label19.Size = new System.Drawing.Size(60, 13); + this.label19.TabIndex = 29; + this.label19.Text = "Ref. count:"; + // + // refPulsesLabel + // + this.refPulsesLabel.AutoSize = true; + this.refPulsesLabel.Location = new System.Drawing.Point(654, 78); + this.refPulsesLabel.Name = "refPulsesLabel"; + this.refPulsesLabel.Size = new System.Drawing.Size(50, 13); + this.refPulsesLabel.TabIndex = 30; + this.refPulsesLabel.Text = "refPulses"; + // + // refFlowCmpntLabel + // + this.refFlowCmpntLabel.AutoSize = true; + this.refFlowCmpntLabel.Location = new System.Drawing.Point(654, 58); + this.refFlowCmpntLabel.Name = "refFlowCmpntLabel"; + this.refFlowCmpntLabel.Size = new System.Drawing.Size(71, 13); + this.refFlowCmpntLabel.TabIndex = 31; + this.refFlowCmpntLabel.Text = "refFlowCmpnt"; + // + // regValveCmpntLabel + // + this.regValveCmpntLabel.AutoSize = true; + this.regValveCmpntLabel.Location = new System.Drawing.Point(875, 58); + this.regValveCmpntLabel.Name = "regValveCmpntLabel"; + this.regValveCmpntLabel.Size = new System.Drawing.Size(79, 13); + this.regValveCmpntLabel.TabIndex = 34; + this.regValveCmpntLabel.Text = "regValveCmpnt"; + // + // regValvePosLabel + // + this.regValvePosLabel.AutoSize = true; + this.regValvePosLabel.Location = new System.Drawing.Point(875, 78); + this.regValvePosLabel.Name = "regValvePosLabel"; + this.regValvePosLabel.Size = new System.Drawing.Size(67, 13); + this.regValvePosLabel.TabIndex = 35; + this.regValvePosLabel.Text = "regValvePos"; + // + // label21 + // + this.label21.AutoSize = true; + this.label21.Location = new System.Drawing.Point(786, 78); + this.label21.Name = "label21"; + this.label21.Size = new System.Drawing.Size(85, 13); + this.label21.TabIndex = 36; + this.label21.Text = "Reg. valve pos.:"; + // + // tDivCmpntLabel + // + this.tDivCmpntLabel.AutoSize = true; + this.tDivCmpntLabel.Location = new System.Drawing.Point(875, 129); + this.tDivCmpntLabel.Name = "tDivCmpntLabel"; + this.tDivCmpntLabel.Size = new System.Drawing.Size(56, 13); + this.tDivCmpntLabel.TabIndex = 39; + this.tDivCmpntLabel.Text = "tDivCmpnt"; + // + // tDivLabel + // + this.tDivLabel.AutoSize = true; + this.tDivLabel.Location = new System.Drawing.Point(875, 148); + this.tDivLabel.Name = "tDivLabel"; + this.tDivLabel.Size = new System.Drawing.Size(26, 13); + this.tDivLabel.TabIndex = 38; + this.tDivLabel.Text = "tDiv"; + // + // label24 + // + this.label24.AutoSize = true; + this.label24.Location = new System.Drawing.Point(817, 148); + this.label24.Name = "label24"; + this.label24.Size = new System.Drawing.Size(54, 13); + this.label24.TabIndex = 37; + this.label24.Text = "T div [°C]:"; + // + // scaleCmpntLabel + // + this.scaleCmpntLabel.AutoSize = true; + this.scaleCmpntLabel.Location = new System.Drawing.Point(875, 209); + this.scaleCmpntLabel.Name = "scaleCmpntLabel"; + this.scaleCmpntLabel.Size = new System.Drawing.Size(62, 13); + this.scaleCmpntLabel.TabIndex = 40; + this.scaleCmpntLabel.Text = "scaleCmpnt"; + // + // label22 + // + this.label22.AutoSize = true; + this.label22.Location = new System.Drawing.Point(815, 230); + this.label22.Name = "label22"; + this.label22.Size = new System.Drawing.Size(56, 13); + this.label22.TabIndex = 41; + this.label22.Text = "Mass [kg]:"; + // + // massLabel + // + this.massLabel.AutoSize = true; + this.massLabel.Location = new System.Drawing.Point(875, 230); + this.massLabel.Name = "massLabel"; + this.massLabel.Size = new System.Drawing.Size(31, 13); + this.massLabel.TabIndex = 42; + this.massLabel.Text = "mass"; + // + // label23 + // + this.label23.AutoSize = true; + this.label23.Location = new System.Drawing.Point(795, 250); + this.label23.Name = "label23"; + this.label23.Size = new System.Drawing.Size(76, 13); + this.label23.TabIndex = 43; + this.label23.Text = "Mass diff. [kg]:"; + // + // massDiffLabel + // + this.massDiffLabel.AutoSize = true; + this.massDiffLabel.Location = new System.Drawing.Point(875, 250); + this.massDiffLabel.Name = "massDiffLabel"; + this.massDiffLabel.Size = new System.Drawing.Size(47, 13); + this.massDiffLabel.TabIndex = 44; + this.massDiffLabel.Text = "massDiff"; + // + // label25 + // + this.label25.AutoSize = true; + this.label25.Location = new System.Drawing.Point(576, 140); + this.label25.Name = "label25"; + this.label25.Size = new System.Drawing.Size(78, 13); + this.label25.TabIndex = 45; + this.label25.Text = "Ref. volume [l]:"; + // + // refVolumeLabel + // + this.refVolumeLabel.AutoSize = true; + this.refVolumeLabel.Location = new System.Drawing.Point(654, 140); + this.refVolumeLabel.Name = "refVolumeLabel"; + this.refVolumeLabel.Size = new System.Drawing.Size(54, 13); + this.refVolumeLabel.TabIndex = 46; + this.refVolumeLabel.Text = "refVolume"; + // + // label26 + // + this.label26.AutoSize = true; + this.label26.Location = new System.Drawing.Point(815, 271); + this.label26.Name = "label26"; + this.label26.Size = new System.Drawing.Size(56, 13); + this.label26.TabIndex = 47; + this.label26.Text = "Volume [l]:"; + // + // volumeCtvLabel + // + this.volumeCtvLabel.AutoSize = true; + this.volumeCtvLabel.Location = new System.Drawing.Point(875, 271); + this.volumeCtvLabel.Name = "volumeCtvLabel"; + this.volumeCtvLabel.Size = new System.Drawing.Size(57, 13); + this.volumeCtvLabel.TabIndex = 48; + this.volumeCtvLabel.Text = "volumeCtv"; + // + // label27 + // + this.label27.AutoSize = true; + this.label27.Location = new System.Drawing.Point(800, 293); + this.label27.Name = "label27"; + this.label27.Size = new System.Drawing.Size(71, 13); + this.label27.TabIndex = 49; + this.label27.Text = "Ref. error [%]:"; + // + // refErrorLabel + // + this.refErrorLabel.AutoSize = true; + this.refErrorLabel.Location = new System.Drawing.Point(875, 293); + this.refErrorLabel.Name = "refErrorLabel"; + this.refErrorLabel.Size = new System.Drawing.Size(41, 13); + this.refErrorLabel.TabIndex = 50; + this.refErrorLabel.Text = "refError"; + // + // label28 + // + this.label28.AutoSize = true; + this.label28.Location = new System.Drawing.Point(291, 58); + this.label28.Name = "label28"; + this.label28.Size = new System.Drawing.Size(116, 13); + this.label28.TabIndex = 51; + this.label28.Text = "Target flow low [m3/h]:"; + // + // label29 + // + this.label29.AutoSize = true; + this.label29.Location = new System.Drawing.Point(287, 78); + this.label29.Name = "label29"; + this.label29.Size = new System.Drawing.Size(120, 13); + this.label29.TabIndex = 52; + this.label29.Text = "Target flow high [m3/h]:"; + // + // label20 + // + this.label20.AutoSize = true; + this.label20.Location = new System.Drawing.Point(318, 98); + this.label20.Name = "label20"; + this.label20.Size = new System.Drawing.Size(89, 13); + this.label20.TabIndex = 53; + this.label20.Text = "Target volume [l]:"; + // + // label30 + // + this.label30.AutoSize = true; + this.label30.Location = new System.Drawing.Point(315, 140); + this.label30.Name = "label30"; + this.label30.Size = new System.Drawing.Size(92, 13); + this.label30.TabIndex = 54; + this.label30.Text = "Estimated time [s]:"; + // + // targetFlowLowLabel + // + this.targetFlowLowLabel.AutoSize = true; + this.targetFlowLowLabel.Location = new System.Drawing.Point(410, 58); + this.targetFlowLowLabel.Name = "targetFlowLowLabel"; + this.targetFlowLowLabel.Size = new System.Drawing.Size(76, 13); + this.targetFlowLowLabel.TabIndex = 55; + this.targetFlowLowLabel.Text = "targetFlowLow"; + // + // targetFlowHighLabel + // + this.targetFlowHighLabel.AutoSize = true; + this.targetFlowHighLabel.Location = new System.Drawing.Point(410, 78); + this.targetFlowHighLabel.Name = "targetFlowHighLabel"; + this.targetFlowHighLabel.Size = new System.Drawing.Size(78, 13); + this.targetFlowHighLabel.TabIndex = 56; + this.targetFlowHighLabel.Text = "targetFlowHigh"; + // + // targetVolumeLabel + // + this.targetVolumeLabel.AutoSize = true; + this.targetVolumeLabel.Location = new System.Drawing.Point(410, 98); + this.targetVolumeLabel.Name = "targetVolumeLabel"; + this.targetVolumeLabel.Size = new System.Drawing.Size(69, 13); + this.targetVolumeLabel.TabIndex = 57; + this.targetVolumeLabel.Text = "targetVolume"; + // + // label31 + // + this.label31.AutoSize = true; + this.label31.Location = new System.Drawing.Point(318, 119); + this.label31.Name = "label31"; + this.label31.Size = new System.Drawing.Size(89, 13); + this.label31.TabIndex = 58; + this.label31.Text = "Target ref. count:"; + // + // targetRefCountLabel + // + this.targetRefCountLabel.AutoSize = true; + this.targetRefCountLabel.Location = new System.Drawing.Point(410, 119); + this.targetRefCountLabel.Name = "targetRefCountLabel"; + this.targetRefCountLabel.Size = new System.Drawing.Size(79, 13); + this.targetRefCountLabel.TabIndex = 59; + this.targetRefCountLabel.Text = "targetRefCount"; + // + // estmtdTimeLabel + // + this.estmtdTimeLabel.AutoSize = true; + this.estmtdTimeLabel.Location = new System.Drawing.Point(410, 140); + this.estmtdTimeLabel.Name = "estmtdTimeLabel"; + this.estmtdTimeLabel.Size = new System.Drawing.Size(61, 13); + this.estmtdTimeLabel.TabIndex = 60; + this.estmtdTimeLabel.Text = "estmtdTime"; + // + // label32 + // + this.label32.AutoSize = true; + this.label32.Location = new System.Drawing.Point(66, 58); + this.label32.Name = "label32"; + this.label32.Size = new System.Drawing.Size(101, 13); + this.label32.TabIndex = 61; + this.label32.Text = "Air temperature [°C]:"; + // + // label33 + // + this.label33.AutoSize = true; + this.label33.Location = new System.Drawing.Point(69, 78); + this.label33.Name = "label33"; + this.label33.Size = new System.Drawing.Size(98, 13); + this.label33.TabIndex = 62; + this.label33.Text = "Air pressure [mBar]:"; + // + // label34 + // + this.label34.AutoSize = true; + this.label34.Location = new System.Drawing.Point(87, 98); + this.label34.Name = "label34"; + this.label34.Size = new System.Drawing.Size(80, 13); + this.label34.TabIndex = 63; + this.label34.Text = "Air humidity [%]:"; + // + // airTempLabel + // + this.airTempLabel.AutoSize = true; + this.airTempLabel.Location = new System.Drawing.Point(169, 58); + this.airTempLabel.Name = "airTempLabel"; + this.airTempLabel.Size = new System.Drawing.Size(45, 13); + this.airTempLabel.TabIndex = 64; + this.airTempLabel.Text = "airTemp"; + // + // airPressLabel + // + this.airPressLabel.AutoSize = true; + this.airPressLabel.Location = new System.Drawing.Point(169, 78); + this.airPressLabel.Name = "airPressLabel"; + this.airPressLabel.Size = new System.Drawing.Size(44, 13); + this.airPressLabel.TabIndex = 65; + this.airPressLabel.Text = "airPress"; + // + // airHumiLabel + // + this.airHumiLabel.AutoSize = true; + this.airHumiLabel.Location = new System.Drawing.Point(169, 98); + this.airHumiLabel.Name = "airHumiLabel"; + this.airHumiLabel.Size = new System.Drawing.Size(42, 13); + this.airHumiLabel.TabIndex = 66; + this.airHumiLabel.Text = "airHumi"; + // + // ProcessTabPageCtrl + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.BackColor = System.Drawing.SystemColors.Control; + this.Controls.Add(this.airHumiLabel); + this.Controls.Add(this.airPressLabel); + this.Controls.Add(this.airTempLabel); + this.Controls.Add(this.label34); + this.Controls.Add(this.label33); + this.Controls.Add(this.label32); + this.Controls.Add(this.estmtdTimeLabel); + this.Controls.Add(this.targetRefCountLabel); + this.Controls.Add(this.label31); + this.Controls.Add(this.targetVolumeLabel); + this.Controls.Add(this.targetFlowHighLabel); + this.Controls.Add(this.targetFlowLowLabel); + this.Controls.Add(this.label30); + this.Controls.Add(this.label20); + this.Controls.Add(this.label29); + this.Controls.Add(this.label28); + this.Controls.Add(this.refErrorLabel); + this.Controls.Add(this.label27); + this.Controls.Add(this.volumeCtvLabel); + this.Controls.Add(this.label26); + this.Controls.Add(this.refVolumeLabel); + this.Controls.Add(this.label25); + this.Controls.Add(this.massDiffLabel); + this.Controls.Add(this.label23); + this.Controls.Add(this.massLabel); + this.Controls.Add(this.label22); + this.Controls.Add(this.scaleCmpntLabel); + this.Controls.Add(this.tDivCmpntLabel); + this.Controls.Add(this.tDivLabel); + this.Controls.Add(this.label24); + this.Controls.Add(this.label21); + this.Controls.Add(this.regValvePosLabel); + this.Controls.Add(this.regValveCmpntLabel); + this.Controls.Add(this.refFlowCmpntLabel); + this.Controls.Add(this.refPulsesLabel); + this.Controls.Add(this.label19); + this.Controls.Add(this.refFreqLabel); + this.Controls.Add(this.label16); + this.Controls.Add(this.refFlowLabel); + this.Controls.Add(this.prInCmpntLabel); + this.Controls.Add(this.prOutCmpntLabel); + this.Controls.Add(this.tOutCmpntLabel); + this.Controls.Add(this.tInCmpntLabel); + this.Controls.Add(this.label15); + this.Controls.Add(this.prOutLabel); + this.Controls.Add(this.tOutLabel); + this.Controls.Add(this.label17); + this.Controls.Add(this.label18); + this.Controls.Add(this.prInLabel); + this.Controls.Add(this.tInLabel); + this.Controls.Add(this.label14); + this.Controls.Add(this.label13); + this.Controls.Add(this.groupBox3); + this.Controls.Add(this.groupBox2); + this.Controls.Add(this.groupBox1); + this.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238))); + this.Name = "ProcessTabPageCtrl"; + this.Size = new System.Drawing.Size(984, 498); + this.Load += new System.EventHandler(this.ProcessTabPageCtrl_Load); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.groupBox2.ResumeLayout(false); + this.groupBox2.PerformLayout(); + this.groupBox3.ResumeLayout(false); + this.groupBox3.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label sensor1Label; + private System.Windows.Forms.Label pulses1Label; + private System.Windows.Forms.Label refPulses1Label; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.Label volume1Label; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.Label error1Label; + private System.Windows.Forms.Label passed1Label; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.GroupBox groupBox2; + private System.Windows.Forms.Label passed2Label; + private System.Windows.Forms.Label error2Label; + private System.Windows.Forms.Label label8; + private System.Windows.Forms.Label volume2Label; + private System.Windows.Forms.Label label7; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.Label refPulses2Label; + private System.Windows.Forms.Label pulses2Label; + private System.Windows.Forms.Label sensor2Label; + private System.Windows.Forms.GroupBox groupBox3; + private System.Windows.Forms.Label passed3Label; + private System.Windows.Forms.Label error3Label; + private System.Windows.Forms.Label label12; + private System.Windows.Forms.Label volume3Label; + private System.Windows.Forms.Label label11; + private System.Windows.Forms.Label label10; + private System.Windows.Forms.Label label9; + private System.Windows.Forms.Label refPulses3Label; + private System.Windows.Forms.Label pulses3Label; + private System.Windows.Forms.Label sensor3Label; + private System.Windows.Forms.Label label13; + private System.Windows.Forms.Label label14; + private System.Windows.Forms.Label tInLabel; + private System.Windows.Forms.Label prInLabel; + private System.Windows.Forms.Label prOutLabel; + private System.Windows.Forms.Label tOutLabel; + private System.Windows.Forms.Label label17; + private System.Windows.Forms.Label label18; + private System.Windows.Forms.Label label15; + private System.Windows.Forms.Label tInCmpntLabel; + private System.Windows.Forms.Label tOutCmpntLabel; + private System.Windows.Forms.Label prOutCmpntLabel; + private System.Windows.Forms.Label prInCmpntLabel; + private System.Windows.Forms.Label refFlowLabel; + private System.Windows.Forms.Label label16; + private System.Windows.Forms.Label refFreqLabel; + private System.Windows.Forms.Label label19; + private System.Windows.Forms.Label refPulsesLabel; + private System.Windows.Forms.Label refFlowCmpntLabel; + private System.Windows.Forms.Label regValveCmpntLabel; + private System.Windows.Forms.Label regValvePosLabel; + private System.Windows.Forms.Label label21; + private System.Windows.Forms.Label tDivCmpntLabel; + private System.Windows.Forms.Label tDivLabel; + private System.Windows.Forms.Label label24; + private System.Windows.Forms.Label scaleCmpntLabel; + private System.Windows.Forms.Label label22; + private System.Windows.Forms.Label massLabel; + private System.Windows.Forms.Label label23; + private System.Windows.Forms.Label massDiffLabel; + private System.Windows.Forms.Label label25; + private System.Windows.Forms.Label refVolumeLabel; + private System.Windows.Forms.Label label26; + private System.Windows.Forms.Label volumeCtvLabel; + private System.Windows.Forms.Label label27; + private System.Windows.Forms.Label refErrorLabel; + private System.Windows.Forms.Label label28; + private System.Windows.Forms.Label label29; + private System.Windows.Forms.Label label20; + private System.Windows.Forms.Label label30; + private System.Windows.Forms.Label targetFlowLowLabel; + private System.Windows.Forms.Label targetFlowHighLabel; + private System.Windows.Forms.Label targetVolumeLabel; + private System.Windows.Forms.Label label31; + private System.Windows.Forms.Label targetRefCountLabel; + private System.Windows.Forms.Label estmtdTimeLabel; + private System.Windows.Forms.Label label32; + private System.Windows.Forms.Label label33; + private System.Windows.Forms.Label label34; + private System.Windows.Forms.Label airTempLabel; + private System.Windows.Forms.Label airPressLabel; + private System.Windows.Forms.Label airHumiLabel; + + + } +} diff --git a/TestBenchFramework/Screens/ProcessTabPageCtrl.cs b/TestBenchFramework/Screens/ProcessTabPageCtrl.cs new file mode 100644 index 000000000..21f5653cc --- /dev/null +++ b/TestBenchFramework/Screens/ProcessTabPageCtrl.cs @@ -0,0 +1,280 @@ +using System; +using System.Windows.Forms; +using log4net; +using TBF.UiBridge; + +namespace TBF.Screens +{ + public partial class ProcessTabPageCtrl : UserControl + { + static readonly ILog log = LogManager.GetLogger(typeof(ProcessTabPageCtrl)); + + public ProcessTabPageCtrl() + { + InitializeComponent(); + + Bridge.ProcedureSelectedHandler += delegate(object sender, ProcedureSelectedEventArgs args) + { + if (InvokeRequired) + { + Invoke(new EventHandler(OnProcedureSelected), sender, args); + } + else OnProcedureSelected(sender, args); + }; + Bridge.TestSelectedHandler += delegate(object sender, TestSelectedEventArgs args) + { + if (InvokeRequired) + { + Invoke(new EventHandler(OnTestSelected), sender, args); + } + else OnTestSelected(sender, args); + }; + Bridge.TestProgressHandler += delegate(object sender, TestProgressEventArgs args) + { + if (InvokeRequired) + { + Invoke(new EventHandler(OnTestProgress), sender, args); + } + else OnTestProgress(sender, args); + }; + Bridge.TestCompletedHandler += delegate(object sender, TestCompletedEventArgs args) + { + if (InvokeRequired) + { + Invoke(new EventHandler(OnTestCompleted), sender, args); + } + else OnTestCompleted(sender, args); + }; + Bridge.ProcedureCompletedHandler += delegate(object sender, ProcedureCompletedEventArgs args) + { + if (InvokeRequired) + { + Invoke(new EventHandler(OnProcedureCompleted), sender, args); + } + else OnProcedureCompleted(sender, args); + }; + } + + private void ProcessTabPageCtrl_Load(object sender, EventArgs e) + { + Once(); + Reset(); + } + + void Once() + { + + } + + void Reset() + { + prInCmpntLabel.Text = "---"; + prOutCmpntLabel.Text = "---"; + tInCmpntLabel.Text = "---"; + tOutCmpntLabel.Text = "---"; + tDivCmpntLabel.Text = "---"; + refFlowCmpntLabel.Text = "---"; + regValveCmpntLabel.Text = "---"; + scaleCmpntLabel.Text = "---"; + sensor1Label.Text = "---"; + sensor2Label.Text = "---"; + sensor3Label.Text = "---"; + + targetFlowLowLabel.Text = "---"; + targetFlowHighLabel.Text= "---"; + targetVolumeLabel.Text = "---"; + targetRefCountLabel.Text= "---"; + estmtdTimeLabel.Text = "---"; + + pulses1Label.Text = "---"; + pulses2Label.Text = "---"; + pulses3Label.Text = "---"; + refPulses1Label.Text = "---"; + refPulses2Label.Text = "---"; + refPulses3Label.Text = "---"; + volume1Label.Text = "---"; + volume2Label.Text = "---"; + volume3Label.Text = "---"; + error1Label.Text = "---"; + error2Label.Text = "---"; + error3Label.Text = "---"; + tInLabel.Text = "---"; + tOutLabel.Text = "---"; + tDivLabel.Text = "---"; + prInLabel.Text = "---"; + prOutLabel.Text = "---"; + airTempLabel.Text = "---"; + airPressLabel.Text = "---"; + airHumiLabel.Text = "---"; + + refPulsesLabel.Text = "---"; + //refFreqLabel.Text = "---"; + refFlowLabel.Text = "---"; + refVolumeLabel.Text = "---"; + //regValvePosLabel.Text = "---"; + //massLabel.Text = "---"; + } + + void OnProcedureSelected(object sender, ProcedureSelectedEventArgs args) + { + Reset(); + } + + void OnTestSelected(object sender, TestSelectedEventArgs args) + { + /// Names of virtual bench components + prInCmpntLabel.Text = args.BenchPath.PressIn.Cfg.Name; + prOutCmpntLabel.Text = args.BenchPath.PressOut.Cfg.Name; + tInCmpntLabel.Text = args.BenchPath.TempIn.Cfg.Name; + tOutCmpntLabel.Text = args.BenchPath.TempOut.Cfg.Name; + tDivCmpntLabel.Text = args.OutputPath.TempDiv.Cfg.Name; + refFlowCmpntLabel.Text = args.OutputPath.FlowMeter.Cfg.Name; + regValveCmpntLabel.Text = args.OutputPath.RegulValve.Cfg.Name; + scaleCmpntLabel.Text = args.OutputPath.Balance.Cfg.Name; + sensor1Label.Text = (args.MetersPath.RegisterReaders[0] == null) ? "" : args.MetersPath.RegisterReaders[0].Cfg.Name; + sensor2Label.Text = (args.MetersPath.RegisterReaders[1] == null) ? "" : args.MetersPath.RegisterReaders[1].Cfg.Name; + sensor3Label.Text = (args.MetersPath.RegisterReaders[2] == null) ? "" : args.MetersPath.RegisterReaders[2].Cfg.Name; + + /// Target values + targetFlowLowLabel.Text = args.Test.Qfrom.ToString("F3"); + targetFlowHighLabel.Text = args.Test.Qto.ToString("F3"); + targetVolumeLabel.Text = args.Test.Volume.ToString("F1"); + targetRefCountLabel.Text = args.TotalPulses.ToString(); + estmtdTimeLabel.Text = args.Test.TstTime.ToString("F1"); + + /// Invalidate other values + pulses1Label.Text = "---"; + pulses2Label.Text = "---"; + pulses3Label.Text = "---"; + refPulses1Label.Text = "---"; + refPulses2Label.Text = "---"; + refPulses3Label.Text = "---"; + volume1Label.Text = "---"; + volume2Label.Text = "---"; + volume3Label.Text = "---"; + error1Label.Text = "---"; + error2Label.Text = "---"; + error3Label.Text = "---"; + tInLabel.Text = "---"; + tOutLabel.Text = "---"; + tDivLabel.Text = "---"; + prInLabel.Text = "---"; + prOutLabel.Text = "---"; + airTempLabel.Text = "---"; + airPressLabel.Text = "---"; + airHumiLabel.Text = "---"; + + refPulsesLabel.Text = "---"; + //refFreqLabel.Text = "---"; + refFlowLabel.Text = "---"; + refVolumeLabel.Text = "---"; + //regValvePosLabel.Text = "---"; + //massLabel.Text = "---"; + } + + void OnTestProgress(object sender, TestProgressEventArgs args) + { + targetFlowLowLabel.Text = args.TestResult.Qfrom.ToString("F3"); + targetFlowHighLabel.Text = args.TestResult.Qto.ToString("F3"); + estmtdTimeLabel.Text = args.TestResult.TstTime.ToString("F1"); + + pulses1Label.Text = args.WmPulses[0].ToString(); + pulses2Label.Text = args.WmPulses[1].ToString(); + pulses3Label.Text = args.WmPulses[2].ToString(); + refPulses1Label.Text = args.WmRefPulses[0].ToString(); + refPulses2Label.Text = args.WmRefPulses[1].ToString(); + refPulses3Label.Text = args.WmRefPulses[2].ToString(); + volume1Label.Text = args.WmVolume[0].ToString("F2"); + volume2Label.Text = args.WmVolume[1].ToString("F2"); + volume3Label.Text = args.WmVolume[2].ToString("F2"); + error1Label.Text = args.WmErrPct[0].ToString("F2"); + error2Label.Text = args.WmErrPct[1].ToString("F2"); + error3Label.Text = args.WmErrPct[2].ToString("F2"); + tInLabel.Text = args.Tin.ToString("F2"); + tOutLabel.Text = args.Tout.ToString("F2"); + tDivLabel.Text = args.Tdiv.ToString("F2"); + prInLabel.Text = args.Pin.ToString("F1"); + prOutLabel.Text = args.Pout.ToString("F1"); + airTempLabel.Text = args.AmbientTemp.ToString("F1"); + airPressLabel.Text = args.AmbientPressure.ToString("F1"); + airHumiLabel.Text = args.AmbientHumidity.ToString("F1"); + + refPulsesLabel.Text = args.RefPulses.ToString(); + //refFreqLabel.Text = args. + refFlowLabel.Text = args.Flow.ToString("F2"); + refVolumeLabel.Text = args.Volume.ToString("F2"); + //regValvePosLabel.Text = args. + //massLabel.Text = args. + } + + void OnTestCompleted(object sender, TestCompletedEventArgs args) + { + Entities.TestResult tRes = args.TestResult; + + if (tRes.MetersKind == Entities.MetersKind.Single) + { + pulses1Label.Text = tRes.Meters[0].PulsesMeter.ToString("F0"); + pulses2Label.Text = tRes.Meters[1].PulsesMeter.ToString("F0"); + pulses3Label.Text = tRes.Meters[2].PulsesMeter.ToString("F0"); + refPulses1Label.Text = tRes.Meters[0].PulsesMaster.ToString("F0"); + refPulses2Label.Text = tRes.Meters[1].PulsesMaster.ToString("F0"); + refPulses3Label.Text = tRes.Meters[2].PulsesMaster.ToString("F0"); + volume1Label.Text = tRes.Meters[0].VolumeMeter.ToString("F2"); + volume2Label.Text = tRes.Meters[1].VolumeMeter.ToString("F2"); + volume3Label.Text = tRes.Meters[2].VolumeMeter.ToString("F2"); + error1Label.Text = tRes.Meters[0].VolumeErrorPct.ToString("F2"); + error2Label.Text = tRes.Meters[1].VolumeErrorPct.ToString("F2"); + error3Label.Text = tRes.Meters[2].VolumeErrorPct.ToString("F2"); + tInLabel.Text = tRes.TempInAvrg.ToString("F2"); + tOutLabel.Text = tRes.TempOutAvrg.ToString("F2"); + tDivLabel.Text = tRes.TempDivAvrg.ToString("F2"); + prInLabel.Text = tRes.PressInAvrg.ToString("F1"); + prOutLabel.Text = tRes.PressOutAvrg.ToString("F1"); + airTempLabel.Text = tRes.AmbientTempAve.ToString("F1"); + airPressLabel.Text = tRes.AmbientPressAve.ToString("F1"); + airHumiLabel.Text = tRes.AmbientHumiAve.ToString("F1"); + + refPulsesLabel.Text = tRes.PulsesMaster.ToString("F0"); + //refFreqLabel.Text = tstRslt. + refFlowLabel.Text = tRes.FlowMass.ToString("F2"); + refVolumeLabel.Text = tRes.VolumeCTV.ToString("F2"); + //regValvePosLabel.Text = tstRslt. + //massLabel.Text = tstRslt. + } + else if (tRes.MetersKind == Entities.MetersKind.Combined) + { + pulses1Label.Text = tRes.Meters[0].PulsesMeter.ToString("F0"); + pulses2Label.Text = tRes.Meters[1].PulsesMeter.ToString("F0"); + pulses3Label.Text = tRes.CombinedMeters[0].PulsesMeter.ToString("F0"); + refPulses1Label.Text = tRes.Meters[0].PulsesMaster.ToString("F0"); + refPulses2Label.Text = tRes.Meters[1].PulsesMaster.ToString("F0"); + refPulses3Label.Text = tRes.CombinedMeters[0].PulsesMaster.ToString("F0"); + volume1Label.Text = tRes.Meters[0].VolumeMeter.ToString("F2"); + volume2Label.Text = tRes.Meters[1].VolumeMeter.ToString("F2"); + volume3Label.Text = tRes.CombinedMeters[0].VolumeMeter.ToString("F2"); + error1Label.Text = tRes.Meters[0].VolumeErrorPct.ToString("F2"); + error2Label.Text = tRes.Meters[1].VolumeErrorPct.ToString("F2"); + error3Label.Text = tRes.CombinedMeters[0].VolumeErrorPct.ToString("F2"); + tInLabel.Text = tRes.TempInAvrg.ToString("F2"); + tOutLabel.Text = tRes.TempOutAvrg.ToString("F2"); + tDivLabel.Text = tRes.TempDivAvrg.ToString("F2"); + prInLabel.Text = tRes.PressInAvrg.ToString("F1"); + prOutLabel.Text = tRes.PressOutAvrg.ToString("F1"); + airTempLabel.Text = tRes.AmbientTempAve.ToString("F1"); + airPressLabel.Text = tRes.AmbientPressAve.ToString("F1"); + airHumiLabel.Text = tRes.AmbientHumiAve.ToString("F1"); + + refPulsesLabel.Text = tRes.PulsesMaster.ToString("F0"); + //refFreqLabel.Text = tstRslt. + refFlowLabel.Text = tRes.FlowMass.ToString("F2"); + refVolumeLabel.Text = tRes.VolumeCTV.ToString("F2"); + //regValvePosLabel.Text = tstRslt. + //massLabel.Text = tstRslt. + } + } + + void OnProcedureCompleted(object sender, ProcedureCompletedEventArgs args) + { + } + } +} diff --git a/TestBenchFramework/Screens/ProcessTabPageCtrl.resx b/TestBenchFramework/Screens/ProcessTabPageCtrl.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/TestBenchFramework/Screens/ProcessTabPageCtrl.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/Screens/ResultsTabPageCtrl.Designer.cs b/TestBenchFramework/Screens/ResultsTabPageCtrl.Designer.cs new file mode 100644 index 000000000..e09e542ef --- /dev/null +++ b/TestBenchFramework/Screens/ResultsTabPageCtrl.Designer.cs @@ -0,0 +1,118 @@ +namespace TBF.Screens +{ + partial class ResultsTabPageCtrl + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.splitContainer = new System.Windows.Forms.SplitContainer(); + this.clearResultsButton = new System.Windows.Forms.Button(); + this.configureButton = new System.Windows.Forms.Button(); + this.flowLayoutPanel = new System.Windows.Forms.FlowLayoutPanel(); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).BeginInit(); + this.splitContainer.Panel1.SuspendLayout(); + this.splitContainer.Panel2.SuspendLayout(); + this.splitContainer.SuspendLayout(); + this.SuspendLayout(); + // + // splitContainer + // + this.splitContainer.Dock = System.Windows.Forms.DockStyle.Fill; + this.splitContainer.FixedPanel = System.Windows.Forms.FixedPanel.Panel1; + this.splitContainer.IsSplitterFixed = true; + this.splitContainer.Location = new System.Drawing.Point(0, 0); + this.splitContainer.Name = "splitContainer"; + this.splitContainer.Orientation = System.Windows.Forms.Orientation.Horizontal; + // + // splitContainer.Panel1 + // + this.splitContainer.Panel1.BackColor = System.Drawing.SystemColors.Control; + this.splitContainer.Panel1.Controls.Add(this.clearResultsButton); + this.splitContainer.Panel1.Controls.Add(this.configureButton); + // + // splitContainer.Panel2 + // + this.splitContainer.Panel2.Controls.Add(this.flowLayoutPanel); + this.splitContainer.Size = new System.Drawing.Size(1057, 706); + this.splitContainer.SplitterDistance = 42; + this.splitContainer.TabIndex = 0; + // + // clearResultsButton + // + this.clearResultsButton.Location = new System.Drawing.Point(126, 10); + this.clearResultsButton.Name = "clearResultsButton"; + this.clearResultsButton.Size = new System.Drawing.Size(100, 30); + this.clearResultsButton.TabIndex = 1; + this.clearResultsButton.Text = "Clear results"; + this.clearResultsButton.UseVisualStyleBackColor = true; + this.clearResultsButton.Click += new System.EventHandler(this.clearResultsButton_Click); + // + // configureButton + // + this.configureButton.Location = new System.Drawing.Point(20, 10); + this.configureButton.Name = "configureButton"; + this.configureButton.Size = new System.Drawing.Size(100, 30); + this.configureButton.TabIndex = 0; + this.configureButton.Text = "Configure"; + this.configureButton.UseVisualStyleBackColor = true; + this.configureButton.Click += new System.EventHandler(this.configureButton_Click); + // + // flowLayoutPanel + // + this.flowLayoutPanel.AutoScroll = true; + this.flowLayoutPanel.BackColor = System.Drawing.SystemColors.Control; + this.flowLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill; + this.flowLayoutPanel.Location = new System.Drawing.Point(0, 0); + this.flowLayoutPanel.Name = "flowLayoutPanel"; + this.flowLayoutPanel.Size = new System.Drawing.Size(1057, 660); + this.flowLayoutPanel.TabIndex = 0; + // + // ResultsTabPageCtrl + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.BackColor = System.Drawing.Color.Silver; + this.Controls.Add(this.splitContainer); + this.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238))); + this.Name = "ResultsTabPageCtrl"; + this.Size = new System.Drawing.Size(1057, 706); + this.Load += new System.EventHandler(this.ResultsTabPageCtrl_Load); + this.splitContainer.Panel1.ResumeLayout(false); + this.splitContainer.Panel2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).EndInit(); + this.splitContainer.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.SplitContainer splitContainer; + private System.Windows.Forms.Button clearResultsButton; + private System.Windows.Forms.Button configureButton; + private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel; + } +} diff --git a/TestBenchFramework/Screens/ResultsTabPageCtrl.cs b/TestBenchFramework/Screens/ResultsTabPageCtrl.cs new file mode 100644 index 000000000..c4e3fddd8 --- /dev/null +++ b/TestBenchFramework/Screens/ResultsTabPageCtrl.cs @@ -0,0 +1,421 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Windows.Forms; +using log4net; +using TBF.Resources; +using TBF.UiBridge; + +namespace TBF.Screens +{ + public partial class ResultsTabPageCtrl : UserControl + { + static readonly ILog log = LogManager.GetLogger(typeof(ResultsTabPageCtrl)); + + public TBF.Forms.ResultsConfig.Meters MetersArrangement; + public TBF.Forms.ResultsConfig.TestsAre TestsArrangement; + + IList tests; + IList testResults; + + int lvWidth; + int lvHeight; + + /// + /// Constructor + /// + public ResultsTabPageCtrl() + { + InitializeComponent(); + + Bridge.ProcedureSelectedHandler += delegate(object sender, ProcedureSelectedEventArgs args) + { + if (InvokeRequired) + { + Invoke(new EventHandler(OnProcedureSelected), sender, args); + } + else OnProcedureSelected(sender, args); + }; + Bridge.TestCompletedHandler += delegate(object sender, TestCompletedEventArgs args) + { + if (InvokeRequired) + { + Invoke(new EventHandler(OnTestCompleted), sender, args); + } + else OnTestCompleted(sender, args); + }; + } + + private void ResultsTabPageCtrl_Load(object sender, EventArgs e) + { + // Localization + configureButton.Text = Strings.Configure; + clearResultsButton.Text = Strings.Clear_results; + + MetersArrangement = Program.LocalSettings.ResultsConfigMeters; + TestsArrangement = Program.LocalSettings.ResultsConfigTests; + + RedrawAll(); + } + + /// + /// Invoke a configuration dialog + /// + private void configureButton_Click(object sender, EventArgs e) + { + TBF.Forms.ResultsConfig dlg = new TBF.Forms.ResultsConfig(); + dlg.TestsArrangement = TestsArrangement; + dlg.MetersArrangement = MetersArrangement; + if (DialogResult.OK == dlg.ShowDialog()) + { + MetersArrangement = dlg.MetersArrangement; + TestsArrangement = dlg.TestsArrangement; + + Program.LocalSettings.ResultsConfigMeters = MetersArrangement; + Program.LocalSettings.ResultsConfigTests = TestsArrangement; + Program.LocalSettings.Save(); + } + RedrawAll(); + } + + /// + /// Clear the results + /// + private void clearResultsButton_Click(object sender, EventArgs e) + { + } + + #region Redraw + + /// + /// Re-draw the results. Apply new settings if they changed. + /// + void RedrawAll() + { + this.SuspendLayout(); + lvWidth = flowLayoutPanel.Width - 10; + lvHeight = flowLayoutPanel.Height - 10; + + if (MetersArrangement == Forms.ResultsConfig.Meters.Horizontally) + { + flowLayoutPanel.FlowDirection = FlowDirection.LeftToRight; + lvWidth = (lvWidth + 5) / Program.WMsCount - 5; + } + else + { + flowLayoutPanel.FlowDirection = FlowDirection.TopDown; + lvHeight = (lvHeight + 5) / Program.WMsCount - 5; + } + flowLayoutPanel.Controls.Clear(); + flowLayoutPanel.WrapContents = false; + flowLayoutPanel.AutoScroll = true; + + /// + /// Determine whether combined meter results are displayed + /// + bool combined = ((testResults != null) && + (testResults.Count > 0) && + (testResults[0].MetersKind == Entities.MetersKind.Combined)); + + for (int mtr = 0; mtr < (combined ? Program.WMsCount / 2 : Program.WMsCount); mtr++) + { + if (TestsArrangement == Forms.ResultsConfig.TestsAre.Rows) + { + ListView lview = GetResultsTestsAreRows(mtr, combined); + if (lview != null) flowLayoutPanel.Controls.Add(lview); + } + else + { + ListView lview = GetResultsTestsAreColumns(mtr, combined); + if (lview != null) flowLayoutPanel.Controls.Add(lview); + } + } + this.ResumeLayout(false); + } + + /// + /// Get an empty ListView control with appropriate parameters. + /// + /// ListView control + ListView GetListView() + { + ListView lview = new ListView(); + lview.AllowColumnReorder = false; + lview.Dock = System.Windows.Forms.DockStyle.None; + lview.FullRowSelect = true; + lview.GridLines = true; + lview.Location = new System.Drawing.Point(0, 0); + lview.Size = new System.Drawing.Size(lvWidth, lvHeight); + lview.TabIndex = 0; + lview.UseCompatibleStateImageBehavior = false; + lview.View = System.Windows.Forms.View.Details; + return lview; + } + + /// + /// Pre-fetch the test results corresponding to the columns or rows in the ListView + /// + /// Ordered list of test results containing null-s for missing results + IList GetCurrentTestResults() + { + IList rslts = new List(); + + foreach (var test in tests) + { + for (int rpt = 1; rpt <= test.Repeats; rpt++) + { + bool added = false; + if (testResults != null) + { + foreach (var testRslt in testResults) + { + if (testRslt.TestName.Equals(test.Name) && (testRslt.RepetitionNr == rpt) && !testRslt.DoNotPublish) + { + rslts.Add(testRslt); + added = true; + break; + } + } + } + if (!added) rslts.Add(null); + } + } + return rslts; + } + + IList GetAllDecoratedTestNames() + { + IList rslt = new List(); + foreach (var test in tests) + { + if (test.Repeats == 1) + { + rslt.Add(test.Name); + continue; + } + for (int rpt = 1; rpt <= test.Repeats; rpt++) + { + rslt.Add(test.Name + string.Format(" ({0}/{1})", rpt, test.Repeats)); + } + } + return rslt; + } + + IList GetAllResultNames(bool combined) + { + IList rslt = new List(); + if (combined) + { + rslt.Add("Q [l/h]"); + rslt.Add("Ref.volume [l]"); + rslt.Add("WM1 volume [l]"); + rslt.Add("WM2 volume [l]"); + rslt.Add("WM volume [l]"); + rslt.Add("Error [%]"); + rslt.Add("Result"); + } + else + { + rslt.Add("Q [l/h]"); + rslt.Add("Ref.volume [l]"); + rslt.Add("WM volume [l]"); + rslt.Add("Error [%]"); + rslt.Add("Result"); + } + return rslt; + } + + /// + /// Get a ListView control filled with results of the meter 'mtr' + /// + /// Water meter number: 0..Program.WMsCount + /// ListView object + ListView GetResultsTestsAreRows(int mtr, bool combined) + { + if (tests == null) return null; + + ListView lview = GetListView(); + + // Header + lview.Columns.Add((mtr + 1).ToString()); + foreach (var str in GetAllResultNames(combined)) lview.Columns.Add(str); + + IList testNames = GetAllDecoratedTestNames(); + int ix = 0; + foreach (var testRslt in GetCurrentTestResults()) + { + ListViewItem lvi = new ListViewItem(testNames[ix++]); + if (testRslt != null) + { + if (combined) + { + lvi.SubItems.Add(testRslt.FlowMass.ToString("F1")); + lvi.SubItems.Add(testRslt.VolumeCTV.ToString("F2")); + lvi.SubItems.Add(testRslt.Meters[2 * mtr].VolumeMeter.ToString("F2")); + lvi.SubItems.Add(testRslt.Meters[2 * mtr + 1].VolumeMeter.ToString("F2")); + lvi.SubItems.Add(testRslt.CombinedMeters[mtr].VolumeMeter.ToString("F2")); + lvi.SubItems.Add(testRslt.CombinedMeters[mtr].VolumeErrorPct.ToString("F2")); + lvi.SubItems.Add(testRslt.CombinedMeters[mtr].Passed ? Strings.Passed : Strings.Failed); + lvi.UseItemStyleForSubItems = false; + lvi.SubItems[7].BackColor = (testRslt.CombinedMeters[mtr].Passed ? Color.Green : Color.Red); + } + else + { + lvi.SubItems.Add(testRslt.FlowMass.ToString("F1")); + lvi.SubItems.Add(testRslt.VolumeCTV.ToString("F2")); + lvi.SubItems.Add(testRslt.Meters[mtr].VolumeMeter.ToString("F2")); + lvi.SubItems.Add(testRslt.Meters[mtr].VolumeErrorPct.ToString("F2")); + lvi.SubItems.Add(testRslt.Meters[mtr].Passed ? Strings.Passed : Strings.Failed); + lvi.UseItemStyleForSubItems = false; + lvi.SubItems[5].BackColor = (testRslt.Meters[mtr].Passed ? Color.Green : Color.Red); + } + } + lview.Items.Add(lvi); + } + + return lview; + } + + /// + /// Get a ListView control filled with results of the meter 'mtr' + /// + /// Water meter number: 0..Program.WMsCount + /// ListView object + ListView GetResultsTestsAreColumns(int mtr, bool combined) + { + if (tests == null) return null; + + ListView lview = GetListView(); + + // Header + lview.Columns.Add((mtr + 1).ToString()); + foreach (var str in GetAllDecoratedTestNames()) lview.Columns.Add(str); + + IList trs = GetCurrentTestResults(); + + int rsltId = 0; + foreach (var rsltName in GetAllResultNames(combined)) + { + ListViewItem lvi = new ListViewItem(rsltName); + if (combined) + { + switch (rsltId++) + { + case 0: + foreach (var tr in trs) lvi.SubItems.Add((tr != null) ? tr.FlowMass.ToString("F1") : string.Empty); + break; + case 1: + foreach (var tr in trs) lvi.SubItems.Add((tr != null) ? tr.VolumeCTV.ToString("F2") : string.Empty); + break; + case 2: + foreach (var tr in trs) lvi.SubItems.Add((tr != null) ? tr.Meters[2 * mtr].VolumeMeter.ToString("F2") : string.Empty); + break; + case 3: + foreach (var tr in trs) lvi.SubItems.Add((tr != null) ? tr.Meters[2 * mtr + 1].VolumeMeter.ToString("F2") : string.Empty); + break; + case 4: + foreach (var tr in trs) lvi.SubItems.Add((tr != null) ? tr.CombinedMeters[mtr].VolumeMeter.ToString("F2") : string.Empty); + break; + case 5: + foreach (var tr in trs) lvi.SubItems.Add((tr != null) ? tr.CombinedMeters[mtr].VolumeErrorPct.ToString("F2") : string.Empty); + break; + case 6: + int i = 1; + lvi.UseItemStyleForSubItems = false; + foreach (var tr in trs) + { + if (tr == null) + { + lvi.SubItems.Add(string.Empty); + } + else if (tr.CombinedMeters[mtr].Passed) + { + lvi.SubItems.Add(Strings.Passed); + lvi.SubItems[i].BackColor = Color.Green; + } + else + { + lvi.SubItems.Add(Strings.Failed); + lvi.SubItems[i].BackColor = Color.Red; + } + i++; + } + break; + } + } + else + { + switch (rsltId++) + { + case 0: + foreach (var tr in trs) lvi.SubItems.Add((tr != null) ? tr.FlowMass.ToString("F1") : string.Empty); + break; + case 1: + foreach (var tr in trs) lvi.SubItems.Add((tr != null) ? tr.VolumeCTV.ToString("F2") : string.Empty); + break; + case 2: + foreach (var tr in trs) lvi.SubItems.Add((tr != null) ? tr.Meters[mtr].VolumeMeter.ToString("F2") : string.Empty); + break; + case 3: + foreach (var tr in trs) lvi.SubItems.Add((tr != null) ? tr.Meters[mtr].VolumeErrorPct.ToString("F2") : string.Empty); + break; + case 4: + int i = 1; + lvi.UseItemStyleForSubItems = false; + foreach (var tr in trs) + { + if (tr == null) + { + lvi.SubItems.Add(string.Empty); + } + else if (tr.Meters[mtr].Passed) + { + lvi.SubItems.Add(Strings.Passed); + lvi.SubItems[i].BackColor = Color.Green; + } + else + { + lvi.SubItems.Add(Strings.Failed); + lvi.SubItems[i].BackColor = Color.Red; + } + i++; + } + break; + } + } + lview.Items.Add(lvi); + } + + return lview; + } + + #endregion + + void OnProcedureSelected(object sender, ProcedureSelectedEventArgs args) + { + tests = args.Procedure.Tests; + testResults = new List(); + RedrawAll(); + } + + void OnTestCompleted(object sender, TestCompletedEventArgs args) + { + if (args.TestResult != null) + { + /// Delete an existing testResults with the same test name and repetition number + try + { + Entities.TestResult tr = testResults + .First(x => x.Name.Equals(args.TestResult.Name)); + testResults.Remove(tr); + } + catch { }; + + /// Add the new test results + testResults.Add(args.TestResult); + RedrawAll(); + } + } + } +} diff --git a/TestBenchFramework/Screens/ResultsTabPageCtrl.resx b/TestBenchFramework/Screens/ResultsTabPageCtrl.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/TestBenchFramework/Screens/ResultsTabPageCtrl.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/SelectComponentClassDlg.Designer.cs b/TestBenchFramework/SelectComponentClassDlg.Designer.cs new file mode 100644 index 000000000..a8efa674e --- /dev/null +++ b/TestBenchFramework/SelectComponentClassDlg.Designer.cs @@ -0,0 +1,95 @@ +namespace TBF +{ + partial class SelectComponentClassDlg + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(SelectComponentClassDlg)); + this.availCmpntsLstBox = new System.Windows.Forms.ListBox(); + this.label1 = new System.Windows.Forms.Label(); + this.cancelButton = new System.Windows.Forms.Button(); + this.okButton = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // availCmpntsLstBox + // + resources.ApplyResources(this.availCmpntsLstBox, "availCmpntsLstBox"); + this.availCmpntsLstBox.FormattingEnabled = true; + this.availCmpntsLstBox.Name = "availCmpntsLstBox"; + this.availCmpntsLstBox.DoubleClick += new System.EventHandler(this.availCmpntsLstBox_DoubleClick); + // + // label1 + // + resources.ApplyResources(this.label1, "label1"); + this.label1.ImageKey = global::TBF.Resources.Strings.String1; + this.label1.Name = "label1"; + // + // cancelButton + // + resources.ApplyResources(this.cancelButton, "cancelButton"); + this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.cancelButton.ImageKey = global::TBF.Resources.Strings.String1; + this.cancelButton.Name = "cancelButton"; + this.cancelButton.UseVisualStyleBackColor = true; + this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click); + // + // okButton + // + resources.ApplyResources(this.okButton, "okButton"); + this.okButton.ImageKey = global::TBF.Resources.Strings.String1; + this.okButton.Name = "okButton"; + this.okButton.UseVisualStyleBackColor = true; + this.okButton.Click += new System.EventHandler(this.okButton_Click); + // + // ComponentAddDlg + // + this.AcceptButton = this.okButton; + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.cancelButton; + this.Controls.Add(this.cancelButton); + this.Controls.Add(this.okButton); + this.Controls.Add(this.label1); + this.Controls.Add(this.availCmpntsLstBox); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "ComponentAddDlg"; + this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide; + this.Load += new System.EventHandler(this.AddComponentDlg_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.ListBox availCmpntsLstBox; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Button cancelButton; + private System.Windows.Forms.Button okButton; + } +} \ No newline at end of file diff --git a/TestBenchFramework/SelectComponentClassDlg.cs b/TestBenchFramework/SelectComponentClassDlg.cs new file mode 100644 index 000000000..661eb15ed --- /dev/null +++ b/TestBenchFramework/SelectComponentClassDlg.cs @@ -0,0 +1,63 @@ +using System; +using System.Windows.Forms; +using TBF.BenchControl.Generic; + +namespace TBF +{ + public partial class SelectComponentClassDlg : Form + { + /// This is the main result of this dialog + public IComponentFactory SlctdCmpntFactory = null; + + int selectedIndex = -1; + + /// Constructor + public SelectComponentClassDlg() + { + InitializeComponent(); + + foreach (var componentFactory in BenchControl.TbfComponents.Factories) + { + availCmpntsLstBox.Items.Add(componentFactory.ClassName); + } + } + + /// Load components from BenchControl.SupportedComponents + private void AddComponentDlg_Load(object sender, EventArgs e) + { + if (selectedIndex >= 0 && selectedIndex < BenchControl.TbfComponents.Factories.Count) + { + availCmpntsLstBox.SelectedIndex = selectedIndex; + } + } + + /// Double click - Add the clicked component + private void availCmpntsLstBox_DoubleClick(object sender, EventArgs e) + { + okButton_Click(sender, e); + } + + /// OK - Add the selected component + private void okButton_Click(object sender, EventArgs e) + { + int ix = availCmpntsLstBox.SelectedIndex; + if (ix >= 0 && ix < BenchControl.TbfComponents.Factories.Count) + { + selectedIndex = ix; + SlctdCmpntFactory = BenchControl.TbfComponents.Factories[ix]; + DialogResult = DialogResult.OK; + Close(); + return; + } + } + + /// Cancel - Do nothing + private void cancelButton_Click(object sender, EventArgs e) + { + SlctdCmpntFactory = null; + DialogResult = DialogResult.Cancel; + Close(); + return; + } + } +} diff --git a/TestBenchFramework/SelectComponentClassDlg.de.resx b/TestBenchFramework/SelectComponentClassDlg.de.resx new file mode 100644 index 000000000..d3dae13f3 --- /dev/null +++ b/TestBenchFramework/SelectComponentClassDlg.de.resx @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 128, 13 + + + Verfügbare Komponenten + + + &Abbrechen + + + Komponenten Auswahl + + \ No newline at end of file diff --git a/TestBenchFramework/SelectComponentClassDlg.resx b/TestBenchFramework/SelectComponentClassDlg.resx new file mode 100644 index 000000000..c6763ee4b --- /dev/null +++ b/TestBenchFramework/SelectComponentClassDlg.resx @@ -0,0 +1,240 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 1 + + + cancelButton + + + + 6, 13 + + + 1 + + + 99, 25 + + + 12, 34 + + + System.Windows.Forms.Form, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Available Components: + + + 0 + + + 8 + + + availCmpntsLstBox + + + 0 + + + ComponentAddDlg + + + 200, 310 + + + 311, 347 + + + System.Windows.Forms.ListBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 2 + + + + CenterParent + + + label1 + + + &Cancel + + + $this + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + okButton + + + 95, 310 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + True + + + &OK + + + 288, 264 + + + 115, 13 + + + 9, 9 + + + 7 + + + 99, 25 + + + $this + + + $this + + + 3 + + + Select Component + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + True + + \ No newline at end of file diff --git a/TestBenchFramework/TBF.csproj b/TestBenchFramework/TBF.csproj new file mode 100644 index 000000000..5225b6a28 --- /dev/null +++ b/TestBenchFramework/TBF.csproj @@ -0,0 +1,1176 @@ + + + + Debug + AnyCPU + 8.0.50727 + 2.0 + {8648FD92-CDA1-4C3A-B5F9-FE547CE1FA48} + WinExe + Properties + TBF + TBF + v4.0 + + + 2.0 + + + false + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + true + true + + + true + full + false + bin\Debug\ + TRACE;DEBUG;DN100 + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE;DN100 + prompt + 4 + AnyCPU + + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + prompt + MinimumRecommendedRules.ruleset + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + prompt + MinimumRecommendedRules.ruleset + + + TBF.Program + + + + ..\packages\ControlBoard\ControlCom2VB.dll + + + ..\packages\FluentNHibernate.1.3.0.733\lib\FluentNHibernate.dll + + + ..\packages\Iesi.Collections.3.2.0.4000\lib\Net35\Iesi.Collections.dll + + + False + ..\packages\log4net.2.0.2\lib\net40-full\log4net.dll + + + True + + + True + ..\packages\MySql.Data.6.6.5\lib\net20\MySql.Data.dll + + + ..\packages\NHibernate.3.3.3.4001\lib\Net35\NHibernate.dll + + + + + ..\packages\System.Data.SQLite.1.0.90.0\lib\net40\System.Data.SQLite.dll + + + ..\packages\System.Data.SQLite.1.0.90.0\lib\net40\System.Data.SQLite.Linq.dll + + + + + + + + + + + UserControl + + + ComponentCfgCtrl.cs + + + + + + UserControl + + + CameraRoiCfgCtrl.cs + + + + + + + + + + + + + + + + UserControl + + + IdcCameraCfgCtrl.cs + + + + + + + + + + + + + + + Form + + + CycleBeginningForm.cs + + + Form + + + CycleEndForm.cs + + + + + UserControl + + + EntryFormCfgCtrl.cs + + + + + + + UserControl + + + PumpCfgCtrl.cs + + + + + + + + + + + UserControl + + + DiverterCfgCtrl.cs + + + UserControl + + + FlowMeterCfgCtrl.cs + + + + + + + + UserControl + + + PressureMeterCfgCtrl.cs + + + + + + + UserControl + + + PumpCfgCtrl.cs + + + + + + UserControl + + + RegisterReaderCfgCtrl.cs + + + + UserControl + + + RegulValveCfgCtrl.cs + + + UserControl + + + TempMeterCfgCtrl.cs + + + + + + + + + + + + + + + + + + + + + UserControl + + + AmbientCfgCtrl.cs + + + UserControl + + + ValveCfgCtrl.cs + + + UserControl + + + BalanceCfgCtrl.cs + + + + + + Form + + + AskYesNoForm.cs + + + + + + + + + + + + + + UserControl + + + PrinterCfgCtrl.cs + + + + Component + + + Component + + + + + UserControl + + + PrinterCfgCtrl.cs + + + + + + + UserControl + + + WriterCfgCtrl.cs + + + + + + + + UserControl + + + + + + + UserControl + + + + + + + + + UserControl + + + TestMethodCfgCtrl.cs + + + + + + + UserControl + + + + + + + + + UserControl + + + WaterMeterCfgCtrl.cs + + + + + + + Form + + + ClosingProgram.cs + + + Form + + + EmergencyStopForm.cs + + + Form + + + ResultsConfig.cs + + + Form + + + TabNameDlg.cs + + + + + UserControl + + + PicturesTabPageCtrl.cs + + + Form + + + SelectComponentClassDlg.cs + + + + + UserControl + + + ControlBoardCfgCtrl.cs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Form + + + ComponentParametersDlg.cs + + + Form + + + ComponentsManagerDlg.cs + + + + + + + + + + + + + + + Form + + + AboutDlg.cs + + + + + + + + + + + + + + + + + + Form + + + BenchesDlg.cs + + + Form + + + DatabaseSettingsDlg.cs + + + + + + + + + + Form + + + EditUsers.cs + + + Form + + + EditSelectedUser.cs + + + Form + + + ErrorDlg.cs + + + Form + + + NoBenchOrDatabaseDlg.cs + + + Form + + + EnterPasswordDlg.cs + + + + + + + + + + + + + Form + + + MetrologyDlg.cs + + + Form + + + PathsDlg.cs + + + + + + + + + + + + + Form + + + LoginDlgWithBenchSelection.cs + + + Form + + + PreferencesDlg.cs + + + + Form + + + LoginDlg.cs + + + Form + + + MainWnd.cs + + + Form + + + ProcedureDlg.cs + + + Form + + + ProceduresDlg.cs + + + + + + + + + + + True + True + Strings.de.resx + + + True + True + Strings.resx + + + UserControl + + + ProcessTabPageCtrl.cs + + + UserControl + + + LogsTabPageCtrl.cs + + + UserControl + + + MeasurementTabPageCtrl.cs + + + UserControl + + + ResultsTabPageCtrl.cs + + + + Form + + + FlowSelection.cs + + + Form + + + MethodSelection.cs + + + Form + + + SensorsSelection.cs + + + Form + + + VolumeAndErrorSelection.cs + + + + + + Form + + + TransitionsDlg.cs + + + + + + + + + + + + + + + + + Component + + + UserControl + + + BenchControlPanel.cs + + + UserControl + + + CameraPictureCtrl.cs + + + + + + UserControl + + + MetrologyDlgFlowMeterTab.cs + + + UserControl + + + MetrologyDlgBalanceTab.cs + + + UserControl + + + MetrologyDlgPressMeterTab.cs + + + Component + + + Component + + + Component + + + Component + + + Component + + + UserControl + + + ProcedureParamsCtrl.cs + + + Component + + + UserControl + + + SharedButtons.cs + + + UserControl + + + TestParamsCtrl.cs + + + UserControl + + + TestProgressCtrl.cs + + + Component + + + + ComponentCfgCtrl.cs + + + CameraRoiCfgCtrl.cs + + + IdcCameraCfgCtrl.cs + + + CycleBeginningForm.cs + + + CycleEndForm.cs + + + EntryFormCfgCtrl.cs + + + DiverterCfgCtrl.cs + + + FlowMeterCfgCtrl.cs + + + PressureMeterCfgCtrl.cs + + + PumpCfgCtrl.cs + + + PumpCfgCtrl.cs + + + RegisterReaderCfgCtrl.cs + + + RegulValveCfgCtrl.cs + + + TempMeterCfgCtrl.cs + + + AmbientCfgCtrl.cs + + + ValveCfgCtrl.cs + + + BalanceCfgCtrl.cs + + + AskYesNoForm.cs + + + PrinterCfgCtrl.cs + + + PrinterCfgCtrl.cs + + + WriterCfgCtrl.cs + + + RoiDetectionCfgCtrl.cs + + + + TestMethodCfgCtrl.cs + + + + WaterMeterCfgCtrl.cs + + + ClosingProgram.cs + + + EmergencyStopForm.cs + + + ResultsConfig.cs + + + TabNameDlg.cs + + + PicturesTabPageCtrl.cs + + + SelectComponentClassDlg.cs + + + SelectComponentClassDlg.cs + + + ControlBoardCfgCtrl.cs + + + ComponentParametersDlg.cs + + + ComponentParametersDlg.cs + + + ComponentsManagerDlg.cs + + + BenchesDlg.cs + + + AboutDlg.cs + + + Designer + AboutDlg.cs + + + Designer + BenchesDlg.cs + + + Designer + DatabaseSettingsDlg.cs + + + EditSelectedUser.cs + + + EditUsers.cs + + + EditUsers.cs + + + EditSelectedUser.cs + + + ErrorDlg.cs + + + ErrorDlg.cs + + + NoBenchOrDatabaseDlg.cs + + + EnterPasswordDlg.cs + + + LoginDlg.cs + + + LoginDlg.cs + Designer + + + LoginDlgWithBenchSelection.cs + + + LoginDlgWithBenchSelection.cs + + + LoginDlgWithBenchSelection.cs + + + MainWnd.cs + Designer + + + MainWnd.cs + Designer + + + MetrologyDlg.cs + + + PathsDlg.cs + + + PathsDlg.cs + + + PreferencesDlg.cs + + + Designer + PreferencesDlg.cs + + + ProcedureDlg.cs + + + ProcedureDlg.cs + + + ProceduresDlg.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + ResXFileCodeGenerator + Strings.de.Designer.cs + Designer + + + ResXFileCodeGenerator + Strings.Designer.cs + + + + ProcessTabPageCtrl.cs + + + LogsTabPageCtrl.cs + + + MeasurementTabPageCtrl.cs + + + ResultsTabPageCtrl.cs + + + FlowSelection.cs + + + MethodSelection.cs + + + SensorsSelection.cs + + + VolumeAndErrorSelection.cs + + + TransitionsDlg.cs + + + TransitionsDlg.cs + + + BenchControlPanel.cs + + + BenchControlPanel.cs + + + CameraPictureCtrl.cs + + + MetrologyDlgFlowMeterTab.cs + + + MetrologyDlgBalanceTab.cs + + + MetrologyDlgPressMeterTab.cs + + + ListViewEx.cs + + + ProcedureParamsCtrl.cs + + + SharedButtons.cs + + + TestParamsCtrl.cs + + + TestProgressCtrl.cs + + + + + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + Always + + + + + + + + False + Microsoft .NET Framework 4 %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + false + + + False + Windows Installer 4.5 + true + + + + + + + + + + + + Always + + + Always + + + + Always + + + Always + + + + + + \ No newline at end of file diff --git a/TestBenchFramework/TestProgressControls.cs b/TestBenchFramework/TestProgressControls.cs new file mode 100644 index 000000000..b1247bee1 --- /dev/null +++ b/TestBenchFramework/TestProgressControls.cs @@ -0,0 +1,136 @@ +using System; +using System.Collections.Generic; +using System.Windows.Forms; +using TBF.UiBridge; + +namespace TBF +{ + public class TestProgressControls + { + System.Windows.Forms.Control parent; /// parent is progressFlowLayoutPanel of the only MainWnd instance + IList progresses; + UiControls.TestProgressCtrl currentProgress; + + public TestProgressControls(Control parent) + { + this.parent = parent; + progresses = null; + currentProgress = null; + + Bridge.ProcedureSelectedHandler += delegate(object sender, ProcedureSelectedEventArgs args) + { + if (Program.MainWnd.InvokeRequired) + { + Program.MainWnd.Invoke(new EventHandler(OnProcedureSelected), sender, args); + } + else OnProcedureSelected(sender, args); + }; + Bridge.TestSelectedHandler += delegate(object sender, TestSelectedEventArgs args) + { + if (Program.MainWnd.InvokeRequired) + { + Program.MainWnd.Invoke(new EventHandler(OnTestSelected), sender, args); + } + else OnTestSelected(sender, args); + }; + Bridge.TestProgressHandler += delegate(object sender, TestProgressEventArgs args) + { + if (Program.MainWnd.InvokeRequired) + { + Program.MainWnd.Invoke(new EventHandler(OnTestProgress), sender, args); + } + else OnTestProgress(sender, args); + }; + Bridge.TestCompletedHandler += delegate(object sender, TestCompletedEventArgs args) + { + if (Program.MainWnd.InvokeRequired) + { + Program.MainWnd.Invoke(new EventHandler(OnTestCompleted), sender, args); + } + else OnTestCompleted(sender, args); + }; + Bridge.ProcedureCompletedHandler += delegate(object sender, ProcedureCompletedEventArgs args) + { + if (Program.MainWnd.InvokeRequired) + { + Program.MainWnd.Invoke(new EventHandler(OnProcedureCompleted), sender, args); + } + else OnProcedureCompleted(sender, args); + }; + } + + public void ProcedureSelectedInUI(object sender, ProcedureSelectedEventArgs args) + { + OnProcedureSelected(sender, args); + } + + void OnProcedureSelected(object sender, ProcedureSelectedEventArgs args) + { + currentProgress = null; + parent.Controls.Clear(); + progresses = new List(); + foreach (var test in args.Procedure.Tests) + { + /// Single test + if (test.Repeats == 1) + { + UiControls.TestProgressCtrl prgrs = new UiControls.TestProgressCtrl(test.Name); + progresses.Add(prgrs); + parent.Controls.Add(prgrs); + continue; + } + /// More test repetitions + for (int i = 1; i <= test.Repeats; i++) + { + UiControls.TestProgressCtrl prgrs = new UiControls.TestProgressCtrl(test.Name, i, test.Repeats); + progresses.Add(prgrs); + parent.Controls.Add(prgrs); + } + } + } + + void OnTestSelected(object sender, TestSelectedEventArgs args) + { + if (progresses != null) + { + foreach (var prgrs in progresses) + { + if (prgrs.TestName.Equals(args.Test.Name) && prgrs.RepetitionNr == args.RepetitionNr) + { + currentProgress = prgrs; + currentProgress.Progress = 0; + currentProgress.TestResult = UiControls.TestProgressCtrl.Result.NotDone; + return; + } + } + } + currentProgress = null; + } + + void OnTestProgress(object sender, TestProgressEventArgs args) + { + if (currentProgress != null) currentProgress.Progress = args.Progress; + } + + void OnTestCompleted(object sender, TestCompletedEventArgs args) + { + if (currentProgress != null) + { + // Test is 'failed' if any meter failed + foreach (var meterTestResult in args.TestResult.Meters) + { + if (!meterTestResult.Passed) + { + currentProgress.TestResult = UiControls.TestProgressCtrl.Result.Failed; + return; + } + } + currentProgress.TestResult = UiControls.TestProgressCtrl.Result.Failed; + } + } + + void OnProcedureCompleted(object sender, ProcedureCompletedEventArgs args) + { + } + } +} diff --git a/TestBenchFramework/TestWizard/FlowSelection.Designer.cs b/TestBenchFramework/TestWizard/FlowSelection.Designer.cs new file mode 100644 index 000000000..85d28c68f --- /dev/null +++ b/TestBenchFramework/TestWizard/FlowSelection.Designer.cs @@ -0,0 +1,192 @@ +namespace TBF.TestWizard +{ + partial class FlowSelection + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.horizSplitContainer = new System.Windows.Forms.SplitContainer(); + this.qToTextBox = new System.Windows.Forms.TextBox(); + this.qFromTextBox = new System.Windows.Forms.TextBox(); + this.testNameTextBox = new System.Windows.Forms.TextBox(); + this.qToLabel = new System.Windows.Forms.Label(); + this.qFromLabel = new System.Windows.Forms.Label(); + this.testNameLabel = new System.Windows.Forms.Label(); + this.cancelButton = new System.Windows.Forms.Button(); + this.nextButton = new System.Windows.Forms.Button(); + this.backButton = new System.Windows.Forms.Button(); + ((System.ComponentModel.ISupportInitialize)(this.horizSplitContainer)).BeginInit(); + this.horizSplitContainer.Panel1.SuspendLayout(); + this.horizSplitContainer.Panel2.SuspendLayout(); + this.horizSplitContainer.SuspendLayout(); + this.SuspendLayout(); + // + // horizSplitContainer + // + this.horizSplitContainer.Dock = System.Windows.Forms.DockStyle.Fill; + this.horizSplitContainer.FixedPanel = System.Windows.Forms.FixedPanel.Panel2; + this.horizSplitContainer.Location = new System.Drawing.Point(0, 0); + this.horizSplitContainer.Name = "horizSplitContainer"; + this.horizSplitContainer.Orientation = System.Windows.Forms.Orientation.Horizontal; + // + // horizSplitContainer.Panel1 + // + this.horizSplitContainer.Panel1.Controls.Add(this.qToTextBox); + this.horizSplitContainer.Panel1.Controls.Add(this.qFromTextBox); + this.horizSplitContainer.Panel1.Controls.Add(this.testNameTextBox); + this.horizSplitContainer.Panel1.Controls.Add(this.qToLabel); + this.horizSplitContainer.Panel1.Controls.Add(this.qFromLabel); + this.horizSplitContainer.Panel1.Controls.Add(this.testNameLabel); + // + // horizSplitContainer.Panel2 + // + this.horizSplitContainer.Panel2.Controls.Add(this.cancelButton); + this.horizSplitContainer.Panel2.Controls.Add(this.nextButton); + this.horizSplitContainer.Panel2.Controls.Add(this.backButton); + this.horizSplitContainer.Size = new System.Drawing.Size(284, 262); + this.horizSplitContainer.SplitterDistance = 182; + this.horizSplitContainer.TabIndex = 1; + // + // qToTextBox + // + this.qToTextBox.Location = new System.Drawing.Point(126, 86); + this.qToTextBox.Name = "qToTextBox"; + this.qToTextBox.Size = new System.Drawing.Size(97, 20); + this.qToTextBox.TabIndex = 5; + this.qToTextBox.TextChanged += new System.EventHandler(this.anyTextBox_TextChanged); + // + // qFromTextBox + // + this.qFromTextBox.Location = new System.Drawing.Point(126, 56); + this.qFromTextBox.Name = "qFromTextBox"; + this.qFromTextBox.Size = new System.Drawing.Size(97, 20); + this.qFromTextBox.TabIndex = 4; + this.qFromTextBox.TextChanged += new System.EventHandler(this.anyTextBox_TextChanged); + // + // testNameTextBox + // + this.testNameTextBox.Location = new System.Drawing.Point(126, 26); + this.testNameTextBox.Name = "testNameTextBox"; + this.testNameTextBox.Size = new System.Drawing.Size(97, 20); + this.testNameTextBox.TabIndex = 3; + this.testNameTextBox.TextChanged += new System.EventHandler(this.anyTextBox_TextChanged); + // + // qToLabel + // + this.qToLabel.AutoSize = true; + this.qToLabel.Location = new System.Drawing.Point(24, 89); + this.qToLabel.Name = "qToLabel"; + this.qToLabel.Size = new System.Drawing.Size(61, 13); + this.qToLabel.TabIndex = 2; + this.qToLabel.Text = "Q to [m3/h]"; + // + // qFromLabel + // + this.qFromLabel.AutoSize = true; + this.qFromLabel.Location = new System.Drawing.Point(24, 59); + this.qFromLabel.Name = "qFromLabel"; + this.qFromLabel.Size = new System.Drawing.Size(72, 13); + this.qFromLabel.TabIndex = 1; + this.qFromLabel.Text = "Q from [m3/h]"; + // + // testNameLabel + // + this.testNameLabel.AutoSize = true; + this.testNameLabel.Location = new System.Drawing.Point(24, 29); + this.testNameLabel.Name = "testNameLabel"; + this.testNameLabel.Size = new System.Drawing.Size(57, 13); + this.testNameLabel.TabIndex = 0; + this.testNameLabel.Text = "Test name"; + // + // cancelButton + // + this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.cancelButton.Location = new System.Drawing.Point(186, 17); + this.cancelButton.Name = "cancelButton"; + this.cancelButton.Size = new System.Drawing.Size(75, 42); + this.cancelButton.TabIndex = 27; + this.cancelButton.Text = "&Cancel"; + this.cancelButton.UseVisualStyleBackColor = true; + this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click); + // + // nextButton + // + this.nextButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.nextButton.Location = new System.Drawing.Point(105, 17); + this.nextButton.Name = "nextButton"; + this.nextButton.Size = new System.Drawing.Size(75, 42); + this.nextButton.TabIndex = 26; + this.nextButton.Text = "&Next >"; + this.nextButton.UseVisualStyleBackColor = true; + this.nextButton.Click += new System.EventHandler(this.nextButton_Click); + // + // backButton + // + this.backButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.backButton.DialogResult = System.Windows.Forms.DialogResult.Retry; + this.backButton.Location = new System.Drawing.Point(24, 17); + this.backButton.Name = "backButton"; + this.backButton.Size = new System.Drawing.Size(75, 42); + this.backButton.TabIndex = 25; + this.backButton.Text = "< &Back"; + this.backButton.UseVisualStyleBackColor = true; + this.backButton.Click += new System.EventHandler(this.backButton_Click); + // + // FlowSelection + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(284, 262); + this.Controls.Add(this.horizSplitContainer); + this.Name = "FlowSelection"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "FlowSelection"; + this.Load += new System.EventHandler(this.FlowSelection_Load); + this.horizSplitContainer.Panel1.ResumeLayout(false); + this.horizSplitContainer.Panel1.PerformLayout(); + this.horizSplitContainer.Panel2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.horizSplitContainer)).EndInit(); + this.horizSplitContainer.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.SplitContainer horizSplitContainer; + private System.Windows.Forms.Button cancelButton; + private System.Windows.Forms.Button nextButton; + private System.Windows.Forms.Button backButton; + private System.Windows.Forms.TextBox qToTextBox; + private System.Windows.Forms.TextBox qFromTextBox; + private System.Windows.Forms.TextBox testNameTextBox; + private System.Windows.Forms.Label qToLabel; + private System.Windows.Forms.Label qFromLabel; + private System.Windows.Forms.Label testNameLabel; + + } +} \ No newline at end of file diff --git a/TestBenchFramework/TestWizard/FlowSelection.cs b/TestBenchFramework/TestWizard/FlowSelection.cs new file mode 100644 index 000000000..f0e238df4 --- /dev/null +++ b/TestBenchFramework/TestWizard/FlowSelection.cs @@ -0,0 +1,98 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Windows.Forms; +using TBF.Resources; + +namespace TBF.TestWizard +{ + public partial class FlowSelection : Form + { + Entities.Test test; + + public FlowSelection() + { + InitializeComponent(); + } + + public FlowSelection(Entities.Test test) + : this() + { + this.test = test; + } + + private void FlowSelection_Load(object sender, EventArgs e) + { + if (test == null) return; + + backButton.Visible = false; + + Text = Strings.Flow_selection; + testNameLabel.Text = Strings.Test_name; + qFromLabel.Text = Strings.Q_from_m3h; + qToLabel.Text = Strings.Q_to_m3h; + backButton.Text = Strings.BackBtnText; + nextButton.Text = Strings.NextBtnText; + cancelButton.Text = Strings.CancelBtnText; + + RefreshWizardPage(); + } + + void RefreshWizardPage() + { + testNameTextBox.Text = test.Name; + qFromTextBox.Text = test.Qfrom.ToString(); + qToTextBox.Text = test.Qto.ToString(); + nextButton.Enabled = IsFormValid(); + } + + void UpdateTest() + { + test.Name = testNameTextBox.Text; + test.Qfrom = Utils.ParseUFloat(qFromTextBox.Text); + test.Qto = Utils.ParseUFloat(qToTextBox.Text); + } + + bool IsFormValid() + { + float dummy; + return Utils.TryParseUFloat(qFromTextBox.Text, out dummy) && + Utils.TryParseUFloat(qToTextBox.Text, out dummy); + } + + private void backButton_Click(object sender, EventArgs e) + { + DialogResult = DialogResult.Retry; + Close(); + } + + private void nextButton_Click(object sender, EventArgs e) + { + if (test != null && IsFormValid()) + { + UpdateTest(); + DialogResult = DialogResult.OK; + Close(); + } + else + { + DialogResult = DialogResult.None; + } + } + + private void cancelButton_Click(object sender, EventArgs e) + { + DialogResult = DialogResult.Cancel; + Close(); + } + + private void anyTextBox_TextChanged(object sender, EventArgs e) + { + nextButton.Enabled = IsFormValid(); + } + } +} diff --git a/TestBenchFramework/TestWizard/FlowSelection.resx b/TestBenchFramework/TestWizard/FlowSelection.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/TestBenchFramework/TestWizard/FlowSelection.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/TestWizard/MethodSelection.Designer.cs b/TestBenchFramework/TestWizard/MethodSelection.Designer.cs new file mode 100644 index 000000000..649afd3c4 --- /dev/null +++ b/TestBenchFramework/TestWizard/MethodSelection.Designer.cs @@ -0,0 +1,170 @@ +namespace TBF.TestWizard +{ + partial class MethodSelection + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.horizSplitContainer = new System.Windows.Forms.SplitContainer(); + this.sensorsComboBox = new System.Windows.Forms.ComboBox(); + this.sensorsLabel = new System.Windows.Forms.Label(); + this.testMethodComboBox = new System.Windows.Forms.ComboBox(); + this.testMethodLabel = new System.Windows.Forms.Label(); + this.cancelButton = new System.Windows.Forms.Button(); + this.nextButton = new System.Windows.Forms.Button(); + this.backButton = new System.Windows.Forms.Button(); + ((System.ComponentModel.ISupportInitialize)(this.horizSplitContainer)).BeginInit(); + this.horizSplitContainer.Panel1.SuspendLayout(); + this.horizSplitContainer.Panel2.SuspendLayout(); + this.horizSplitContainer.SuspendLayout(); + this.SuspendLayout(); + // + // horizSplitContainer + // + this.horizSplitContainer.Dock = System.Windows.Forms.DockStyle.Fill; + this.horizSplitContainer.FixedPanel = System.Windows.Forms.FixedPanel.Panel2; + this.horizSplitContainer.Location = new System.Drawing.Point(0, 0); + this.horizSplitContainer.Name = "horizSplitContainer"; + this.horizSplitContainer.Orientation = System.Windows.Forms.Orientation.Horizontal; + // + // horizSplitContainer.Panel1 + // + this.horizSplitContainer.Panel1.Controls.Add(this.sensorsComboBox); + this.horizSplitContainer.Panel1.Controls.Add(this.sensorsLabel); + this.horizSplitContainer.Panel1.Controls.Add(this.testMethodComboBox); + this.horizSplitContainer.Panel1.Controls.Add(this.testMethodLabel); + // + // horizSplitContainer.Panel2 + // + this.horizSplitContainer.Panel2.Controls.Add(this.cancelButton); + this.horizSplitContainer.Panel2.Controls.Add(this.nextButton); + this.horizSplitContainer.Panel2.Controls.Add(this.backButton); + this.horizSplitContainer.Size = new System.Drawing.Size(284, 262); + this.horizSplitContainer.SplitterDistance = 182; + this.horizSplitContainer.TabIndex = 0; + // + // sensorsComboBox + // + this.sensorsComboBox.FormattingEnabled = true; + this.sensorsComboBox.Location = new System.Drawing.Point(96, 84); + this.sensorsComboBox.Name = "sensorsComboBox"; + this.sensorsComboBox.Size = new System.Drawing.Size(165, 21); + this.sensorsComboBox.TabIndex = 3; + this.sensorsComboBox.TextChanged += new System.EventHandler(this.sensorsComboBox_TextChanged); + // + // sensorsLabel + // + this.sensorsLabel.AutoSize = true; + this.sensorsLabel.Location = new System.Drawing.Point(12, 87); + this.sensorsLabel.Name = "sensorsLabel"; + this.sensorsLabel.Size = new System.Drawing.Size(45, 13); + this.sensorsLabel.TabIndex = 2; + this.sensorsLabel.Text = "Sensors"; + // + // testMethodComboBox + // + this.testMethodComboBox.FormattingEnabled = true; + this.testMethodComboBox.Location = new System.Drawing.Point(96, 48); + this.testMethodComboBox.Name = "testMethodComboBox"; + this.testMethodComboBox.Size = new System.Drawing.Size(165, 21); + this.testMethodComboBox.TabIndex = 1; + this.testMethodComboBox.TextChanged += new System.EventHandler(this.testMethodComboBox_TextChanged); + // + // testMethodLabel + // + this.testMethodLabel.AutoSize = true; + this.testMethodLabel.Location = new System.Drawing.Point(12, 51); + this.testMethodLabel.Name = "testMethodLabel"; + this.testMethodLabel.Size = new System.Drawing.Size(66, 13); + this.testMethodLabel.TabIndex = 0; + this.testMethodLabel.Text = "Test method"; + // + // cancelButton + // + this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.cancelButton.Location = new System.Drawing.Point(186, 17); + this.cancelButton.Name = "cancelButton"; + this.cancelButton.Size = new System.Drawing.Size(75, 42); + this.cancelButton.TabIndex = 27; + this.cancelButton.Text = "&Cancel"; + this.cancelButton.UseVisualStyleBackColor = true; + this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click); + // + // nextButton + // + this.nextButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.nextButton.Location = new System.Drawing.Point(105, 17); + this.nextButton.Name = "nextButton"; + this.nextButton.Size = new System.Drawing.Size(75, 42); + this.nextButton.TabIndex = 26; + this.nextButton.Text = "&Next >"; + this.nextButton.UseVisualStyleBackColor = true; + this.nextButton.Click += new System.EventHandler(this.nextButton_Click); + // + // backButton + // + this.backButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.backButton.DialogResult = System.Windows.Forms.DialogResult.Retry; + this.backButton.Location = new System.Drawing.Point(24, 17); + this.backButton.Name = "backButton"; + this.backButton.Size = new System.Drawing.Size(75, 42); + this.backButton.TabIndex = 25; + this.backButton.Text = "< &Back"; + this.backButton.UseVisualStyleBackColor = true; + this.backButton.Click += new System.EventHandler(this.backButton_Click); + // + // MethodSelection + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(284, 262); + this.Controls.Add(this.horizSplitContainer); + this.Name = "MethodSelection"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "MethodSelection"; + this.Load += new System.EventHandler(this.MethodSelection_Load); + this.horizSplitContainer.Panel1.ResumeLayout(false); + this.horizSplitContainer.Panel1.PerformLayout(); + this.horizSplitContainer.Panel2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.horizSplitContainer)).EndInit(); + this.horizSplitContainer.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.SplitContainer horizSplitContainer; + private System.Windows.Forms.Button cancelButton; + private System.Windows.Forms.Button nextButton; + private System.Windows.Forms.Button backButton; + private System.Windows.Forms.ComboBox testMethodComboBox; + private System.Windows.Forms.Label testMethodLabel; + private System.Windows.Forms.ComboBox sensorsComboBox; + private System.Windows.Forms.Label sensorsLabel; + } +} \ No newline at end of file diff --git a/TestBenchFramework/TestWizard/MethodSelection.cs b/TestBenchFramework/TestWizard/MethodSelection.cs new file mode 100644 index 000000000..99c3faa4d --- /dev/null +++ b/TestBenchFramework/TestWizard/MethodSelection.cs @@ -0,0 +1,111 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Windows.Forms; +using TBF.Resources; + +namespace TBF.TestWizard +{ + public partial class MethodSelection : Form + { + Entities.Test test; + IList methods; + IList sensorPaths; + + public MethodSelection() + { + InitializeComponent(); + } + + public MethodSelection(Entities.Test test, + IList methods, + IList sensorPaths) + : this() + { + this.test = test; + this.methods = methods; + this.sensorPaths = sensorPaths; + } + + private void MethodSelection_Load(object sender, EventArgs e) + { + if (test == null) return; + + Text = Strings.Method_selection; + testMethodLabel.Text = Strings.Test_method; + sensorsLabel.Text = Strings.Sensors; + backButton.Text = Strings.BackBtnText; + nextButton.Text = Strings.NextBtnText; + cancelButton.Text = Strings.CancelBtnText; + + foreach (var method in methods) testMethodComboBox.Items.Add(method.Cfg.Name); + foreach (var path in sensorPaths) sensorsComboBox.Items.Add(path.Name); + + RefreshWizardPage(); + } + + void RefreshWizardPage() + { + nextButton.Enabled = IsFormValid(); + } + + void UpdateTest() + { + if (testMethodComboBox.Items.Contains(testMethodComboBox.Text)) + { + test.Method = testMethodComboBox.Text; + } + if (sensorsComboBox.Items.Contains(sensorsComboBox.Text)) + { + test.MetersPath = sensorsComboBox.Text; + } + } + + bool IsFormValid() + { + return testMethodComboBox.Items.Contains(testMethodComboBox.Text) && + sensorsComboBox.Items.Contains(sensorsComboBox.Text); + } + + private void backButton_Click(object sender, EventArgs e) + { + if (test != null && IsFormValid()) UpdateTest(); + DialogResult = DialogResult.Retry; + Close(); + } + + private void nextButton_Click(object sender, EventArgs e) + { + if (test != null && IsFormValid()) + { + UpdateTest(); + DialogResult = DialogResult.OK; + Close(); + } + else + { + DialogResult = DialogResult.None; + } + } + + private void cancelButton_Click(object sender, EventArgs e) + { + DialogResult = DialogResult.Cancel; + Close(); + } + + private void testMethodComboBox_TextChanged(object sender, EventArgs e) + { + nextButton.Enabled = IsFormValid(); + } + + private void sensorsComboBox_TextChanged(object sender, EventArgs e) + { + nextButton.Enabled = IsFormValid(); + } + } +} diff --git a/TestBenchFramework/TestWizard/MethodSelection.resx b/TestBenchFramework/TestWizard/MethodSelection.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/TestBenchFramework/TestWizard/MethodSelection.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/TestWizard/SensorsSelection.Designer.cs b/TestBenchFramework/TestWizard/SensorsSelection.Designer.cs new file mode 100644 index 000000000..c1998bc98 --- /dev/null +++ b/TestBenchFramework/TestWizard/SensorsSelection.Designer.cs @@ -0,0 +1,116 @@ +namespace TBF.TestWizard +{ + partial class SensorsSelection + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.horizSplitContainer = new System.Windows.Forms.SplitContainer(); + this.cancelButton = new System.Windows.Forms.Button(); + this.nextButton = new System.Windows.Forms.Button(); + this.backButton = new System.Windows.Forms.Button(); + ((System.ComponentModel.ISupportInitialize)(this.horizSplitContainer)).BeginInit(); + this.horizSplitContainer.Panel2.SuspendLayout(); + this.horizSplitContainer.SuspendLayout(); + this.SuspendLayout(); + // + // horizSplitContainer + // + this.horizSplitContainer.Dock = System.Windows.Forms.DockStyle.Fill; + this.horizSplitContainer.FixedPanel = System.Windows.Forms.FixedPanel.Panel2; + this.horizSplitContainer.Location = new System.Drawing.Point(0, 0); + this.horizSplitContainer.Name = "horizSplitContainer"; + this.horizSplitContainer.Orientation = System.Windows.Forms.Orientation.Horizontal; + // + // horizSplitContainer.Panel2 + // + this.horizSplitContainer.Panel2.Controls.Add(this.cancelButton); + this.horizSplitContainer.Panel2.Controls.Add(this.nextButton); + this.horizSplitContainer.Panel2.Controls.Add(this.backButton); + this.horizSplitContainer.Size = new System.Drawing.Size(284, 262); + this.horizSplitContainer.SplitterDistance = 182; + this.horizSplitContainer.TabIndex = 1; + // + // cancelButton + // + this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.cancelButton.Location = new System.Drawing.Point(186, 17); + this.cancelButton.Name = "cancelButton"; + this.cancelButton.Size = new System.Drawing.Size(75, 42); + this.cancelButton.TabIndex = 27; + this.cancelButton.Text = "&Cancel"; + this.cancelButton.UseVisualStyleBackColor = true; + this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click); + // + // nextButton + // + this.nextButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.nextButton.Location = new System.Drawing.Point(105, 17); + this.nextButton.Name = "nextButton"; + this.nextButton.Size = new System.Drawing.Size(75, 42); + this.nextButton.TabIndex = 26; + this.nextButton.Text = "&Next >"; + this.nextButton.UseVisualStyleBackColor = true; + this.nextButton.Click += new System.EventHandler(this.nextButton_Click); + // + // backButton + // + this.backButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.backButton.DialogResult = System.Windows.Forms.DialogResult.Retry; + this.backButton.Location = new System.Drawing.Point(24, 17); + this.backButton.Name = "backButton"; + this.backButton.Size = new System.Drawing.Size(75, 42); + this.backButton.TabIndex = 25; + this.backButton.Text = "< &Back"; + this.backButton.UseVisualStyleBackColor = true; + this.backButton.Click += new System.EventHandler(this.backButton_Click); + // + // SensorsSelection + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(284, 262); + this.Controls.Add(this.horizSplitContainer); + this.Name = "SensorsSelection"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "SensorsSelection"; + this.Load += new System.EventHandler(this.SensorsSelection_Load); + this.horizSplitContainer.Panel2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.horizSplitContainer)).EndInit(); + this.horizSplitContainer.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.SplitContainer horizSplitContainer; + private System.Windows.Forms.Button cancelButton; + private System.Windows.Forms.Button nextButton; + private System.Windows.Forms.Button backButton; + } +} \ No newline at end of file diff --git a/TestBenchFramework/TestWizard/SensorsSelection.cs b/TestBenchFramework/TestWizard/SensorsSelection.cs new file mode 100644 index 000000000..a7af5899c --- /dev/null +++ b/TestBenchFramework/TestWizard/SensorsSelection.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Windows.Forms; +using TBF.Resources; + +namespace TBF.TestWizard +{ + public partial class SensorsSelection : Form + { + Entities.Test test; + + public SensorsSelection() + { + InitializeComponent(); + } + + public SensorsSelection(Entities.Test test) + : this() + { + this.test = test; + } + + private void SensorsSelection_Load(object sender, EventArgs e) + { + if (test == null) return; + + backButton.Text = Strings.BackBtnText; + nextButton.Text = Strings.NextBtnText; + cancelButton.Text = Strings.CancelBtnText; + + RefreshWizardPage(); + } + + void RefreshWizardPage() + { + nextButton.Enabled = IsFormValid(); + } + + void UpdateTest() + { + } + + bool IsFormValid() + { + return true; + } + + private void backButton_Click(object sender, EventArgs e) + { + if (test != null && IsFormValid()) UpdateTest(); + DialogResult = DialogResult.Retry; + Close(); + } + + private void nextButton_Click(object sender, EventArgs e) + { + if (test != null && IsFormValid()) + { + UpdateTest(); + DialogResult = DialogResult.OK; + Close(); + } + else + { + DialogResult = DialogResult.None; + } + } + + private void cancelButton_Click(object sender, EventArgs e) + { + DialogResult = DialogResult.Cancel; + Close(); + } + } +} diff --git a/TestBenchFramework/TestWizard/SensorsSelection.resx b/TestBenchFramework/TestWizard/SensorsSelection.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/TestBenchFramework/TestWizard/SensorsSelection.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/TestWizard/VolumeAndErrorSelection.Designer.cs b/TestBenchFramework/TestWizard/VolumeAndErrorSelection.Designer.cs new file mode 100644 index 000000000..c498f4937 --- /dev/null +++ b/TestBenchFramework/TestWizard/VolumeAndErrorSelection.Designer.cs @@ -0,0 +1,214 @@ +namespace TBF.TestWizard +{ + partial class VolumeAndErrorSelection + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.horizSplitContainer = new System.Windows.Forms.SplitContainer(); + this.errLoPctTextBox = new System.Windows.Forms.TextBox(); + this.errHiPctTextBox = new System.Windows.Forms.TextBox(); + this.durationTextBox = new System.Windows.Forms.TextBox(); + this.volumeTextBox = new System.Windows.Forms.TextBox(); + this.errHiPctLabel = new System.Windows.Forms.Label(); + this.errLoPctLabel = new System.Windows.Forms.Label(); + this.durationLabel = new System.Windows.Forms.Label(); + this.volumeLabel = new System.Windows.Forms.Label(); + this.cancelButton = new System.Windows.Forms.Button(); + this.nextButton = new System.Windows.Forms.Button(); + this.backButton = new System.Windows.Forms.Button(); + ((System.ComponentModel.ISupportInitialize)(this.horizSplitContainer)).BeginInit(); + this.horizSplitContainer.Panel1.SuspendLayout(); + this.horizSplitContainer.Panel2.SuspendLayout(); + this.horizSplitContainer.SuspendLayout(); + this.SuspendLayout(); + // + // horizSplitContainer + // + this.horizSplitContainer.Dock = System.Windows.Forms.DockStyle.Fill; + this.horizSplitContainer.FixedPanel = System.Windows.Forms.FixedPanel.Panel2; + this.horizSplitContainer.Location = new System.Drawing.Point(0, 0); + this.horizSplitContainer.Name = "horizSplitContainer"; + this.horizSplitContainer.Orientation = System.Windows.Forms.Orientation.Horizontal; + // + // horizSplitContainer.Panel1 + // + this.horizSplitContainer.Panel1.Controls.Add(this.errLoPctTextBox); + this.horizSplitContainer.Panel1.Controls.Add(this.errHiPctTextBox); + this.horizSplitContainer.Panel1.Controls.Add(this.durationTextBox); + this.horizSplitContainer.Panel1.Controls.Add(this.volumeTextBox); + this.horizSplitContainer.Panel1.Controls.Add(this.errHiPctLabel); + this.horizSplitContainer.Panel1.Controls.Add(this.errLoPctLabel); + this.horizSplitContainer.Panel1.Controls.Add(this.durationLabel); + this.horizSplitContainer.Panel1.Controls.Add(this.volumeLabel); + // + // horizSplitContainer.Panel2 + // + this.horizSplitContainer.Panel2.Controls.Add(this.cancelButton); + this.horizSplitContainer.Panel2.Controls.Add(this.nextButton); + this.horizSplitContainer.Panel2.Controls.Add(this.backButton); + this.horizSplitContainer.Size = new System.Drawing.Size(284, 262); + this.horizSplitContainer.SplitterDistance = 182; + this.horizSplitContainer.TabIndex = 1; + // + // errLoPctTextBox + // + this.errLoPctTextBox.Location = new System.Drawing.Point(150, 85); + this.errLoPctTextBox.Name = "errLoPctTextBox"; + this.errLoPctTextBox.Size = new System.Drawing.Size(86, 20); + this.errLoPctTextBox.TabIndex = 7; + this.errLoPctTextBox.TextChanged += new System.EventHandler(this.anyTextBox_TextChanged); + // + // errHiPctTextBox + // + this.errHiPctTextBox.Location = new System.Drawing.Point(150, 117); + this.errHiPctTextBox.Name = "errHiPctTextBox"; + this.errHiPctTextBox.Size = new System.Drawing.Size(86, 20); + this.errHiPctTextBox.TabIndex = 6; + this.errHiPctTextBox.TextChanged += new System.EventHandler(this.anyTextBox_TextChanged); + // + // durationTextBox + // + this.durationTextBox.Location = new System.Drawing.Point(150, 53); + this.durationTextBox.Name = "durationTextBox"; + this.durationTextBox.Size = new System.Drawing.Size(86, 20); + this.durationTextBox.TabIndex = 5; + this.durationTextBox.TextChanged += new System.EventHandler(this.durationTextBox_TextChanged); + // + // volumeTextBox + // + this.volumeTextBox.Location = new System.Drawing.Point(150, 24); + this.volumeTextBox.Name = "volumeTextBox"; + this.volumeTextBox.Size = new System.Drawing.Size(86, 20); + this.volumeTextBox.TabIndex = 4; + this.volumeTextBox.TextChanged += new System.EventHandler(this.volumeTextBox_TextChanged); + // + // errHiPctLabel + // + this.errHiPctLabel.AutoSize = true; + this.errHiPctLabel.Location = new System.Drawing.Point(35, 117); + this.errHiPctLabel.Name = "errHiPctLabel"; + this.errHiPctLabel.Size = new System.Drawing.Size(89, 13); + this.errHiPctLabel.TabIndex = 3; + this.errHiPctLabel.Text = "Error high limit [%]"; + // + // errLoPctLabel + // + this.errLoPctLabel.AutoSize = true; + this.errLoPctLabel.Location = new System.Drawing.Point(35, 88); + this.errLoPctLabel.Name = "errLoPctLabel"; + this.errLoPctLabel.Size = new System.Drawing.Size(85, 13); + this.errLoPctLabel.TabIndex = 2; + this.errLoPctLabel.Text = "Error low limit [%]"; + // + // timeLabel + // + this.durationLabel.AutoSize = true; + this.durationLabel.Location = new System.Drawing.Point(35, 56); + this.durationLabel.Name = "timeLabel"; + this.durationLabel.Size = new System.Drawing.Size(83, 13); + this.durationLabel.TabIndex = 1; + this.durationLabel.Text = "Test duration [s]"; + // + // volumeLabel + // + this.volumeLabel.AutoSize = true; + this.volumeLabel.Location = new System.Drawing.Point(35, 27); + this.volumeLabel.Name = "volumeLabel"; + this.volumeLabel.Size = new System.Drawing.Size(53, 13); + this.volumeLabel.TabIndex = 0; + this.volumeLabel.Text = "Volume [l]"; + // + // cancelButton + // + this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.cancelButton.Location = new System.Drawing.Point(186, 17); + this.cancelButton.Name = "cancelButton"; + this.cancelButton.Size = new System.Drawing.Size(75, 42); + this.cancelButton.TabIndex = 27; + this.cancelButton.Text = "&Cancel"; + this.cancelButton.UseVisualStyleBackColor = true; + this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click); + // + // nextButton + // + this.nextButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.nextButton.Location = new System.Drawing.Point(105, 17); + this.nextButton.Name = "nextButton"; + this.nextButton.Size = new System.Drawing.Size(75, 42); + this.nextButton.TabIndex = 26; + this.nextButton.Text = "&Next >"; + this.nextButton.UseVisualStyleBackColor = true; + this.nextButton.Click += new System.EventHandler(this.nextButton_Click); + // + // backButton + // + this.backButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.backButton.DialogResult = System.Windows.Forms.DialogResult.Retry; + this.backButton.Location = new System.Drawing.Point(24, 17); + this.backButton.Name = "backButton"; + this.backButton.Size = new System.Drawing.Size(75, 42); + this.backButton.TabIndex = 25; + this.backButton.Text = "< &Back"; + this.backButton.UseVisualStyleBackColor = true; + this.backButton.Click += new System.EventHandler(this.backButton_Click); + // + // VolumeAndErrorSelection + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(284, 262); + this.Controls.Add(this.horizSplitContainer); + this.Name = "VolumeAndErrorSelection"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "VolumeAndErrorSelection"; + this.Load += new System.EventHandler(this.VolumeAndErrorSelection_Load); + this.horizSplitContainer.Panel1.ResumeLayout(false); + this.horizSplitContainer.Panel1.PerformLayout(); + this.horizSplitContainer.Panel2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.horizSplitContainer)).EndInit(); + this.horizSplitContainer.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.SplitContainer horizSplitContainer; + private System.Windows.Forms.Button cancelButton; + private System.Windows.Forms.Button nextButton; + private System.Windows.Forms.Button backButton; + private System.Windows.Forms.TextBox errLoPctTextBox; + private System.Windows.Forms.TextBox errHiPctTextBox; + private System.Windows.Forms.TextBox durationTextBox; + private System.Windows.Forms.TextBox volumeTextBox; + private System.Windows.Forms.Label errHiPctLabel; + private System.Windows.Forms.Label errLoPctLabel; + private System.Windows.Forms.Label durationLabel; + private System.Windows.Forms.Label volumeLabel; + } +} \ No newline at end of file diff --git a/TestBenchFramework/TestWizard/VolumeAndErrorSelection.cs b/TestBenchFramework/TestWizard/VolumeAndErrorSelection.cs new file mode 100644 index 000000000..680937240 --- /dev/null +++ b/TestBenchFramework/TestWizard/VolumeAndErrorSelection.cs @@ -0,0 +1,129 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Windows.Forms; +using TBF.Resources; + +namespace TBF.TestWizard +{ + public partial class VolumeAndErrorSelection : Form + { + Entities.Test test; + + public VolumeAndErrorSelection() + { + InitializeComponent(); + } + + public VolumeAndErrorSelection(Entities.Test test) + : this() + { + this.test = test; + } + + private void VolumeAndErrorSelection_Load(object sender, EventArgs e) + { + if (test == null) return; + + Text = Strings.Volume_and_error_selection; + volumeLabel.Text = Strings.Volume_ltr_chdr; + durationLabel.Text = Strings.Duration_s; + errLoPctLabel.Text = Strings.Err_limit_neg_pct_chdr; + errHiPctLabel.Text = Strings.Err_limit_pos_pct_chdr; + backButton.Text = Strings.BackBtnText; + nextButton.Text = Strings.FinishBtnText; + cancelButton.Text = Strings.CancelBtnText; + + RefreshWizardPage(); + } + + void RefreshWizardPage() + { + volumeTextBox.Text = test.Volume.ToString(); + durationTextBox.Text = test.TstTime.ToString(); + errLoPctTextBox.Text = test.ErrLimLo.ToString(); + errHiPctTextBox.Text = test.ErrLimHi.ToString(); + + nextButton.Enabled = IsFormValid(); + } + + bool IsFormValid() + { + float dummy; + return Utils.TryParseUFloat(volumeTextBox.Text, out dummy) && + Utils.TryParseUFloat(durationTextBox.Text, out dummy) && + Utils.TryParseSFloat(errLoPctTextBox.Text, out dummy) && + Utils.TryParseSFloat(errHiPctTextBox.Text, out dummy); + } + + void UpdateTest() + { + test.Volume = Utils.ParseUFloat(volumeTextBox.Text); + test.TstTime = Utils.ParseUFloat(durationTextBox.Text); + test.ErrLimLo = Utils.ParseSFloat(errLoPctTextBox.Text); + test.ErrLimHi = Utils.ParseSFloat(errHiPctTextBox.Text); + } + + private void backButton_Click(object sender, EventArgs e) + { + if (test != null && IsFormValid()) UpdateTest(); + DialogResult = DialogResult.Retry; + Close(); + } + + private void nextButton_Click(object sender, EventArgs e) + { + if (test != null && IsFormValid()) + { + UpdateTest(); + DialogResult = DialogResult.OK; + Close(); + } + else + { + DialogResult = DialogResult.None; + } + } + + private void cancelButton_Click(object sender, EventArgs e) + { + DialogResult = DialogResult.Cancel; + Close(); + } + + private void anyTextBox_TextChanged(object sender, EventArgs e) + { + nextButton.Enabled = IsFormValid(); + } + + private void volumeTextBox_TextChanged(object sender, EventArgs e) + { + float Qave_lps = (test.Qfrom + test.Qto) / 7.2f; + float volume; + if (Utils.TryParseUFloat(volumeTextBox.Text, out volume)) + { + durationTextBox.TextChanged -= new System.EventHandler(this.durationTextBox_TextChanged); + durationTextBox.Text = (volume / Qave_lps).ToString(); + durationTextBox.TextChanged += new System.EventHandler(this.durationTextBox_TextChanged); + } + anyTextBox_TextChanged(sender, e); + } + + private void durationTextBox_TextChanged(object sender, EventArgs e) + { + float Qave_lps = (test.Qfrom + test.Qto) / 7.2f; + float testTime; + if (Utils.TryParseUFloat(durationTextBox.Text, out testTime)) + { + volumeTextBox.TextChanged -= new System.EventHandler(this.volumeTextBox_TextChanged); + volumeTextBox.Text = (testTime * Qave_lps).ToString(); + volumeTextBox.TextChanged += new System.EventHandler(this.volumeTextBox_TextChanged); + } + anyTextBox_TextChanged(sender, e); + } + } +} diff --git a/TestBenchFramework/TestWizard/VolumeAndErrorSelection.resx b/TestBenchFramework/TestWizard/VolumeAndErrorSelection.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/TestBenchFramework/TestWizard/VolumeAndErrorSelection.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/Tools/ByteFormatter.cs b/TestBenchFramework/Tools/ByteFormatter.cs new file mode 100644 index 000000000..361834027 --- /dev/null +++ b/TestBenchFramework/Tools/ByteFormatter.cs @@ -0,0 +1,59 @@ +using System; +using System.Globalization; + +namespace TBF.Tools +{ + public class ByteFormatter : IFormatProvider, ICustomFormatter + { + public ByteFormatter() + { + } + + public object GetFormat(Type formatType) + { + if (formatType == typeof(ICustomFormatter)) + return this; + else + return null; + } + + public string Format(string fmt, object arg, IFormatProvider formatProvider) + { + if (arg.GetType() != typeof(byte)) + { + try + { + return HandleOtherFormats(fmt, arg); + } + catch (FormatException e) + { + throw new FormatException(String.Format("The format of '{0}' is invalid.", fmt), e); + } + } + + /// + /// Convert one byte to string + /// + byte b = (byte)arg; + if ((32 <= b) && (b <= 127)) return "'" + ((char)b).ToString() + "'"; + if ((char)b == '\r') return "'\\r'"; + if ((char)b == '\n') return "'\\n'"; + if ((char)b == '\t') return "'\\t'"; + if (b == 17) return "XON"; + if (b == 19) return "XOFF"; + if (b == 26) return "Ctrl-Z"; + return b.ToString(); + } + + + private string HandleOtherFormats(string format, object arg) + { + if (arg is IFormattable) + return ((IFormattable)arg).ToString(format, CultureInfo.CurrentCulture); + else if (arg != null) + return arg.ToString(); + else + return String.Empty; + } + } +} diff --git a/TestBenchFramework/Tools/IniUtil.cs b/TestBenchFramework/Tools/IniUtil.cs new file mode 100644 index 000000000..9b81fdae5 --- /dev/null +++ b/TestBenchFramework/Tools/IniUtil.cs @@ -0,0 +1,105 @@ +using System; +using System.Text; +using System.Runtime.InteropServices; +using System.Collections.Specialized; + +namespace TBF.Tools +{ + /// + /// The class use the WinApi GetPrivateProfileSectionNames, + /// GetPrivateProfileSection, GetPrivateProfileString, WritePrivateProfileString + /// and present easy methods to work from a NET point of view. + /// Usage: + /// IniUtil ini = new IniUtil(@"C:\program files (x86)\myapp\myapp.ini"); + /// string country = ini.GetValue("Carrier","Country","NoCountry"); + /// + public class IniUtil + { + [DllImport("kernel32.dll")] + private static extern int GetPrivateProfileSectionNames(byte[] lpszReturnBuffer, int nSize, string lpFileName); + [DllImport("kernel32.dll")] + private static extern int GetPrivateProfileSection(string lpAppName, byte[] lpReturnedString, int nSize, string lpFileName); + [DllImport("kernel32.dll")] + private static extern int GetPrivateProfileString(string lpApplicationName, string lpKeyName, string lpDefault, byte[] lpReturnedString, int nSize, string lpFileName); + [DllImport("kernel32.dll")] + private static extern bool WritePrivateProfileString(string lpApplicationName, string lpKeyName, string lpString, string lpFileName); + + private const int VALUE_BUFFER = 511; + private const int SECTION_BUFFER = (1024 * 16); + private string m_sIniFile; + + /// + /// .ctor with INI file name + /// + /// Fullpath to the INI file + public IniUtil(string fileName) + { + m_sIniFile = fileName; + } + + /// + /// Set the value for a specific key in a section + /// + /// Section containing the key to write to + /// Key to insert/update + /// Value for the key + /// True if OK + public bool SetValue(string section, string key, string keyvalue) + { + return WritePrivateProfileString(section, key, keyvalue, m_sIniFile); + } + + /// + /// Gets the value of the specidied key in the specified section, + /// If the key doesn't exists returns the default value + /// + /// Section containing the key to read from + /// Required key + /// Value to return in case the key is missing + /// string value of the key or missing value + public string GetValue(string section, string key, string ifMissing) + { + byte[] by = new byte[VALUE_BUFFER]; + int n = GetPrivateProfileString(section, key, ifMissing, by, VALUE_BUFFER, m_sIniFile); + string s = Encoding.ASCII.GetString(by); + return s.Substring(0, n); + } + + /// + /// Returns the NameValueCollection for every key in the section + /// + /// Section name + /// NameValueCollection with nake=Key and value=value + public NameValueCollection GetSectionKeysvalues(string section) + { + NameValueCollection n = new NameValueCollection(); + if(section.Length > 0) + { + byte[] by = new byte[SECTION_BUFFER]; + int x = GetPrivateProfileSection(section, by, SECTION_BUFFER, m_sIniFile); + if(x > 0) x--; + string keysvalues = Encoding.ASCII.GetString(by, 0, x); + string[] temp = keysvalues.Split('\0'); + foreach(string s in temp) + { + string[] t = s.Split('='); + n.Add(t[0], t[1]); + } + } + return n; + } + + /// + /// Get the names of all sections in .INI + /// + /// string array with all the key names + public string[] GetSectionNames() + { + byte[] by = new byte[SECTION_BUFFER]; + int x = GetPrivateProfileSectionNames(by, SECTION_BUFFER, m_sIniFile); + if(x > 0) x--; + string keys = Encoding.ASCII.GetString(by, 0, x); + return keys.Split('\0'); + } + } +} diff --git a/TestBenchFramework/Tools/XmlTools.cs b/TestBenchFramework/Tools/XmlTools.cs new file mode 100644 index 000000000..99ed51328 --- /dev/null +++ b/TestBenchFramework/Tools/XmlTools.cs @@ -0,0 +1,27 @@ +using System.IO; +using System.Xml.Serialization; + +namespace TBF.Tools +{ + public static class XmlTools + { + public static string ToXmlString(this T input) + { + using (var writer = new StringWriter()) + { + input.ToXml(writer); + return writer.ToString(); + } + } + + public static void ToXml(this T objectToSerialize, Stream stream) + { + new XmlSerializer(typeof(T)).Serialize(stream, objectToSerialize); + } + + public static void ToXml(this T objectToSerialize, StringWriter writer) + { + new XmlSerializer(typeof(T)).Serialize(writer, objectToSerialize); + } + } +} diff --git a/TestBenchFramework/TransitionsDlg.Designer.cs b/TestBenchFramework/TransitionsDlg.Designer.cs new file mode 100644 index 000000000..b0e2095fa --- /dev/null +++ b/TestBenchFramework/TransitionsDlg.Designer.cs @@ -0,0 +1,88 @@ +namespace TBF +{ + partial class TransitionsDlg + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(TransitionsDlg)); + this.mainSplitContainer = new System.Windows.Forms.SplitContainer(); + this.tabControl = new System.Windows.Forms.TabControl(); + this.sharedButtons = new TBF.UiControls.SharedButtons(); + ((System.ComponentModel.ISupportInitialize)(this.mainSplitContainer)).BeginInit(); + this.mainSplitContainer.Panel1.SuspendLayout(); + this.mainSplitContainer.Panel2.SuspendLayout(); + this.mainSplitContainer.SuspendLayout(); + this.SuspendLayout(); + // + // mainSplitContainer + // + resources.ApplyResources(this.mainSplitContainer, "mainSplitContainer"); + this.mainSplitContainer.FixedPanel = System.Windows.Forms.FixedPanel.Panel2; + this.mainSplitContainer.Name = "mainSplitContainer"; + // + // mainSplitContainer.Panel1 + // + this.mainSplitContainer.Panel1.Controls.Add(this.tabControl); + // + // mainSplitContainer.Panel2 + // + this.mainSplitContainer.Panel2.Controls.Add(this.sharedButtons); + // + // tabControl + // + resources.ApplyResources(this.tabControl, "tabControl"); + this.tabControl.Name = "tabControl"; + this.tabControl.SelectedIndex = 0; + this.tabControl.SelectedIndexChanged += new System.EventHandler(this.tabControl_SelectedIndexChanged); + // + // sharedButtons + // + resources.ApplyResources(this.sharedButtons, "sharedButtons"); + this.sharedButtons.Name = "sharedButtons"; + // + // TransitionsDlg + // + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.mainSplitContainer); + this.Name = "TransitionsDlg"; + this.Load += new System.EventHandler(this.ProcedureDlg_Load); + this.mainSplitContainer.Panel1.ResumeLayout(false); + this.mainSplitContainer.Panel2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.mainSplitContainer)).EndInit(); + this.mainSplitContainer.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.SplitContainer mainSplitContainer; + private System.Windows.Forms.TabControl tabControl; + private UiControls.SharedButtons sharedButtons; + } +} \ No newline at end of file diff --git a/TestBenchFramework/TransitionsDlg.cs b/TestBenchFramework/TransitionsDlg.cs new file mode 100644 index 000000000..5f37c1938 --- /dev/null +++ b/TestBenchFramework/TransitionsDlg.cs @@ -0,0 +1,276 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows.Forms; +using log4net; +using NHibernate; + +using TBF.BenchControl.Generic; +using TBF.BenchControl.GenericDevices; +using TBF.Entities; +using TBF.Resources; +using TBF.UiControls; + +namespace TBF +{ + public partial class TransitionsDlg : Form, IParentOfListViewEx + { + static readonly ILog log = LogManager.GetLogger(typeof(TransitionsDlg)); + + /// Used when re-scaling the dialog: 100% = 96dpi, 125% = 120dpi, 150% = 144dpi + public readonly int Dpi; + public const int Dpi100pct = 96; + + /// + /// Fluent-NHibernate database session + /// + public ISession Session; + + /// + /// Procedure to be updated by this dialog. + /// Set by the constructor or updated by the parent after creation and before loading. + /// + public IList LoadedSequences; + + /// + /// A list of tests to be deleted after closing this dialog + /// + public IList ToBeDeletedSteps; + + + /// Auxiliary public lists used also by user controls in tab pages + public IList TbfComponents; + public IList Valves; + public IList RegulValves; + + + IList transStepsCtrls; + + bool unlocked; + + public TransitionsDlg() + { + /// Detect display setting: 100% = 96dpi, 125% = 120dpi, 150% = 144dpi. + Dpi = (int)this.CreateGraphics().DpiX; + + InitializeComponent(); + + /// SharedDlgButtons configuration + sharedButtons.RequiredGroupMembership = Grp.GID.Metrologists; + sharedButtons.OptionalButtons = SharedButtons.Buttons.Add | SharedButtons.Buttons.Remove | + SharedButtons.Buttons.Up | SharedButtons.Buttons.Down | + SharedButtons.Buttons.NewTab | SharedButtons.Buttons.RenameTab | + SharedButtons.Buttons.RemoveTab; + sharedButtons.Unlocked += Unlocked; + sharedButtons.OKClicked += okButton_Click; + sharedButtons.CancelClicked += cancelButton_Click; + sharedButtons.AddClicked += addButton_Click; + sharedButtons.RemoveClicked += removeButton_Click; + sharedButtons.UpClicked += upButton_Click; + sharedButtons.DownClicked += downButton_Click; + sharedButtons.NewTabClicked += newTabButton_Click; + sharedButtons.RenameTabClicked += renameTabButton_Click; + sharedButtons.RemoveTabClicked += removeTabButton_Click; + + transStepsCtrls = new List(); + ToBeDeletedSteps = new List(); + } + + void Localize() + { + Text = Strings.Transitions; + } + + private void ProcedureDlg_Load(object sender, EventArgs e) + { + /// Load the procedures + Session = FluentCommon.CreateSession(Database.Procedures); + LoadedSequences = Session.CreateQuery("FROM TransitionSequence ORDER BY ItemNr") + .List(); + + /// Prepare a list of components and a list of all valves in the test bench + TbfComponents = BenchControl.TbfComponents.LoadComponentsFromDB(Session); + Valves = BenchControl.GenericDevices.ValveBase.MasterValves(TbfComponents); + RegulValves = new List(); + foreach (var cmpnt in TbfComponents) + { + if (cmpnt is IRegulValve) RegulValves.Add(cmpnt as IRegulValve); + } + + /// Create a tab with a TestParamsCtrl control for each used test method + foreach (var sequence in LoadedSequences) AddTab(sequence); + + /// Now refresh the content of the dialog + RefreshAllTabs(); + } + + void AddTab(TransitionSequence sequence) + { + TabPage nwTab = new TabPage(sequence.Name); + TransitionStepsCtrl newCtrl = new TransitionStepsCtrl(); + transStepsCtrls.Add(newCtrl); + nwTab.Controls.Add(newCtrl); + this.tabControl.TabPages.Add(nwTab); + newCtrl.Initialize(sequence, this, this.tabControl.TabPages[this.tabControl.TabPages.Count - 1]); + } + + void RefreshAllTabs() + { + foreach (var ctrl in transStepsCtrls) ctrl.Refresh(); + } + + private void Unlocked(object sender, EventArgs e) + { + unlocked = true; + foreach (var ctrl in transStepsCtrls) ctrl.Unlock(); + } + + private void newTabButton_Click(object sender, EventArgs e) + { + int tabId = LoadedSequences.Count; + Forms.TabNameDlg dlg = new Forms.TabNameDlg(); + dlg.TabNameLabel = Strings.New_transition_name; + dlg.TabName = "Tr1"; + dlg.ShowDialog(); + TransitionSequence sequence = new TransitionSequence(dlg.TabName, tabId); + LoadedSequences.Add(sequence); + AddTab(sequence); + transStepsCtrls[tabId].Unlock(); + tabControl.SelectTab(tabId); + } + + private void renameTabButton_Click(object sender, EventArgs e) + { + } + + private void removeTabButton_Click(object sender, EventArgs e) + { + } + + private void okButton_Click(object sender, EventArgs e) + { + if (transStepsCtrls.Count > slctdTab) transStepsCtrls[slctdTab].OkBtnClicked(); + + using (var transaction = Session.BeginTransaction()) + { + foreach (var sequence in LoadedSequences) + { + Session.SaveOrUpdate(sequence); + } + try { transaction.Commit(); } + catch { } + } + + DialogResult = DialogResult.OK; + Close(); + return; + } + + private void cancelButton_Click(object sender, EventArgs e) + { + DialogResult = DialogResult.Cancel; + Close(); + return; + } + + int slctdTab; + + private void tabControl_SelectedIndexChanged(object sender, EventArgs e) + { + if (transStepsCtrls.Count > slctdTab) + { + transStepsCtrls[slctdTab].OkBtnClicked(); + } + slctdTab = tabControl.SelectedIndex; + sharedButtons.SetEnabled(SharedButtons.Buttons.Add, true); + sharedButtons.DisableButtons(SharedButtons.Buttons.Remove); + RefreshAllTabs(); + } + + private void addButton_Click(object sender, EventArgs e) + { + if (transStepsCtrls.Count > slctdTab) transStepsCtrls[slctdTab].AddOne(); + } + + private void removeButton_Click(object sender, EventArgs e) + { + if (transStepsCtrls.Count > slctdTab) transStepsCtrls[slctdTab].RemoveSelected(); + } + + private void upButton_Click(object sender, EventArgs e) + { + if (transStepsCtrls.Count > slctdTab) transStepsCtrls[slctdTab].MoveUpSelected(); + } + + private void downButton_Click(object sender, EventArgs e) + { + if (transStepsCtrls.Count > slctdTab) transStepsCtrls[slctdTab].MoveDownSelected(); + } + + public void UpdateButtonStates(SharedButtons.SelectedItemPos selectedItemPos) + { + if (selectedItemPos == SharedButtons.SelectedItemPos.None) + { + sharedButtons.DisableButtons(SharedButtons.Buttons.Remove | SharedButtons.Buttons.Up | SharedButtons.Buttons.Down); + } + else if (selectedItemPos == SharedButtons.SelectedItemPos.First) + { + sharedButtons.EnableButtons(SharedButtons.Buttons.Remove | SharedButtons.Buttons.Down); + sharedButtons.DisableButtons(SharedButtons.Buttons.Up); + } + else if (selectedItemPos == SharedButtons.SelectedItemPos.Last) + { + sharedButtons.EnableButtons(SharedButtons.Buttons.Remove | SharedButtons.Buttons.Up); + sharedButtons.DisableButtons(SharedButtons.Buttons.Down); + } + else if (selectedItemPos == SharedButtons.SelectedItemPos.FirstAndLast) + { + sharedButtons.EnableButtons(SharedButtons.Buttons.Remove); + sharedButtons.DisableButtons(SharedButtons.Buttons.Up | SharedButtons.Buttons.Down); + } + else + { + sharedButtons.EnableButtons(SharedButtons.Buttons.Remove | SharedButtons.Buttons.Up | SharedButtons.Buttons.Down); + } + } + + private void purgeStartCtrl_SelectedIndexChanged(object sender, EventArgs e) + { + SelectedIndexChanged(sender, e); + } + + private void purgeEndCtrl_SelectedIndexChanged(object sender, EventArgs e) + { + SelectedIndexChanged(sender, e); + } + + /// + /// Common part for three xxxListViewEx_SelectedIndexChanged event handlers + /// + /// + void SelectedIndexChanged(object sender, EventArgs e) + { + ListViewEx listViewEx = sender as ListViewEx; + if (listViewEx.SelectedItems.Count != 1) + { + UpdateButtonStates(SharedButtons.SelectedItemPos.None); + } + else if (listViewEx.Items.Count == 1) + { + UpdateButtonStates(SharedButtons.SelectedItemPos.FirstAndLast); + } + else if (listViewEx.SelectedIndices[0] == 0) + { + UpdateButtonStates(SharedButtons.SelectedItemPos.First); + } + else if (listViewEx.SelectedIndices[0] == (listViewEx.Items.Count - 1)) + { + UpdateButtonStates(SharedButtons.SelectedItemPos.Last); + } + else + { + UpdateButtonStates(SharedButtons.SelectedItemPos.Middle); + } + } + } +} diff --git a/TestBenchFramework/TransitionsDlg.de.resx b/TestBenchFramework/TransitionsDlg.de.resx new file mode 100644 index 000000000..97779cd88 --- /dev/null +++ b/TestBenchFramework/TransitionsDlg.de.resx @@ -0,0 +1,321 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 139, 269 + + + 139, 237 + + + 139, 203 + + + 24, 272 + + + 24, 240 + + + 24, 206 + + + 348, 205 + + + 281, 208 + + + 61, 13 + + + Bemerkung + + + 139, 162 + + + 526, 20 + + + 24, 165 + + + 348, 120 + + + 291, 123 + + + 38, 13 + + + Datum + + + 140, 121 + + + 24, 123 + + + 102, 13 + + + letzte Änderung von + + + 348, 87 + + + 291, 90 + + + 38, 13 + + + Datum + + + 139, 87 + + + 24, 90 + + + 62, 13 + + + Errstellt von + + + 139, 53 + + + 526, 20 + + + 24, 56 + + + 92, 13 + + + Kurzbeschreibung + + + 75, 13 + + + Prüfungsname + + + 814, 406 + + + Allgemein + + + Benutzername + + + Datum + + + Kurzbeschreibung + + + 808, 400 + + + 814, 406 + + + Änderungen + + + 808, 400 + + + 814, 406 + + + Metrologie I. + + + 808, 400 + + + 814, 406 + + + Metrologie II. + + + 808, 400 + + + 814, 406 + + + Prozess + + + 3, 3 + + + 808, 400 + + + + 3, 3, 3, 3 + + + 814, 406 + + + Spülung - Start + + + 814, 406 + + + 814, 406 + + + Spülung - Ende + + + 822, 444 + + + 925, 444 + + + + 822 + + + 925, 444 + + + Prüfung + + \ No newline at end of file diff --git a/TestBenchFramework/TransitionsDlg.resx b/TestBenchFramework/TransitionsDlg.resx new file mode 100644 index 000000000..f2190cf21 --- /dev/null +++ b/TestBenchFramework/TransitionsDlg.resx @@ -0,0 +1,249 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + Fill + + + + True + + + + 0, 0 + + + Fill + + + 58, 30 + + + 0, 0 + + + 760, 366 + + + 1 + + + tabControl + + + System.Windows.Forms.TabControl, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + mainSplitContainer.Panel1 + + + 0 + + + mainSplitContainer.Panel1 + + + System.Windows.Forms.SplitterPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + mainSplitContainer + + + 0 + + + -1, 0 + + + 100, 636 + + + 0 + + + sharedButtons + + + TBF.UiControls.SharedButtons, TBF, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + + mainSplitContainer.Panel2 + + + 0 + + + mainSplitContainer.Panel2 + + + System.Windows.Forms.SplitterPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + mainSplitContainer + + + 1 + + + 863, 366 + + + 760 + + + 1 + + + mainSplitContainer + + + System.Windows.Forms.SplitContainer, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 0 + + + True + + + 6, 13 + + + 863, 366 + + + NoControl + + + CenterParent + + + Transitions + + + TransitionsDlg + + + System.Windows.Forms.Form, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/UiBridge/ActivityEventArgs.cs b/TestBenchFramework/UiBridge/ActivityEventArgs.cs new file mode 100644 index 000000000..bfa8c855d --- /dev/null +++ b/TestBenchFramework/UiBridge/ActivityEventArgs.cs @@ -0,0 +1,14 @@ +using System; + +namespace TBF.UiBridge +{ + public class ActivityEventArgs : EventArgs + { + public string Activity; + + public ActivityEventArgs(string activity) + { + Activity = activity; + } + } +} diff --git a/TestBenchFramework/UiBridge/Bridge.cs b/TestBenchFramework/UiBridge/Bridge.cs new file mode 100644 index 000000000..d832c96f5 --- /dev/null +++ b/TestBenchFramework/UiBridge/Bridge.cs @@ -0,0 +1,188 @@ +using System; +using System.Collections.Generic; +using log4net; + +namespace TBF.UiBridge +{ + /// + /// Provides separation of the UI and the state machine. + /// + static class Bridge + { + static readonly ILog log = LogManager.GetLogger(typeof(Bridge)); + + static Queue ui2machineQueue; + public static Queue Ui2MachineQueue { get { return ui2machineQueue; } } + + public static string SelectedProcedureName + { + get { return Program.MainWnd.ProcedureName; } + } + + public static string SelectedTestName + { + get { return Program.MainWnd.BenchControlPanel.TestName; } + } + + + static Bridge() + { + ui2machineQueue = new Queue(); + } + + /// + /// This function should be called from the UI + /// + /// + public static void Ui2Bench(UI2BenchCmd cmd) + { + lock (Ui2MachineQueue) + { + ui2machineQueue.Enqueue(cmd); + } + } + + /// + /// This function should be called from state machine operations + /// + public static void Bench2UI(ButtonsEtc flags) + { + if (ButtonsEtcHandler == null) return; + try { ButtonsEtcHandler(null, new ButtonsEtcEventArgs(flags)); } + catch (Exception e) { log.Error("UiEventHandler(...) failed", e); } + } + public static event EventHandler ButtonsEtcHandler; + + + /// + /// Called from the state machine when a procedure is selected and UI needs to be updated. + /// + public static void OnProcedureSelected(object sender, ProcedureSelectedEventArgs data) + { + if (ProcedureSelectedHandler == null) return; + try { ProcedureSelectedHandler(sender, data); } + catch (Exception e) { log.Error("ProcedureSelectedHandler(...) failed", e); } + } + public static event EventHandler ProcedureSelectedHandler; + + + /// + /// Called from the state machine when a test is selected and UI needs to be updated. + /// + public static void OnTestSelected(object sender, TestSelectedEventArgs data) + { + if (TestSelectedHandler == null) return; + try { TestSelectedHandler(sender, data); } + catch (Exception e) { log.Error("TestSelectedHandler(...) failed", e); } + } + public static event EventHandler TestSelectedHandler; + + + /// + /// Called from the state machine when test process data change and UI needs to be updated. + /// + public static void OnTestProgress(object sender, TestProgressEventArgs data) + { + if (TestProgressHandler == null) return; + try { TestProgressHandler(sender, data); } + catch (Exception e) { log.Error("TestProgressHandler(...) failed", e); } + } + public static event EventHandler TestProgressHandler; + + + /// + /// Called from the state machine when the test is completed and UI needs to be updated. + /// + public static void OnTestCompleted(object sender, TestCompletedEventArgs data) + { + if (TestCompletedHandler == null) return; + try { TestCompletedHandler(sender, data); } + catch (Exception e) { log.Error("TestCompletedHandler(...) failed", e); } + } + public static event EventHandler TestCompletedHandler; + + + /// + /// Called from the state machine when the procedure is completed and UI needs to be updated. + /// + public static void OnProcedureCompleted(object sender, ProcedureCompletedEventArgs data) + { + if (ProcedureCompletedHandler == null) return; + try { ProcedureCompletedHandler(sender, data); } + catch (Exception e) { log.Error("ProcedureCompletedHandler(...) failed", e); } + } + public static event EventHandler ProcedureCompletedHandler; + + + /// + /// Called from the state machine when the procedure is completed and UI needs to be updated. + /// + public static void OnCameraStateChanged(object sender, CameraStateChangedEventArgs data) + { + if (CameraStateChangedHandler == null) return; + try { CameraStateChangedHandler(sender, data); } + catch (Exception e) { log.Error("CameraStateChangedHandler(...) failed", e); } + } + public static event EventHandler CameraStateChangedHandler; + + + /// + /// Called from the state machine when the procedure is completed and UI needs to be updated. + /// + public static void OnImageUpdated(object sender, ImageUpdatedEventArgs data) + { + if (ImageUpdatedHandler == null) return; + try { ImageUpdatedHandler(sender, data); } + catch (Exception e) { log.Error("ImageUpdatedHandler(...) failed", e); } + } + public static event EventHandler ImageUpdatedHandler; + + + /// + /// Called from the state machine when there is and information to be logged. + /// + public static void OnLog(object sender, string message) + { + if (LogHandler == null) return; + try { LogHandler(sender, new LogEventArgs(message)); } + catch (Exception e) { log.Error("LogHandler(...) failed", e); } + } + public static event EventHandler LogHandler; + + + /// + /// Called from the state machine when 'Activity' information changes. + /// + public static void OnActivity(object sender, string activity) + { + if (ActivityHandler == null) return; + try { ActivityHandler(sender, new ActivityEventArgs(activity)); } + catch (Exception e) { log.Error("ActivityHandler(...) failed", e); } + } + public static event EventHandler ActivityHandler; + + + /// + /// 'State machine state has changed' event handler + /// + public static void OnStateChanged(object sender, string stateChangedMsg) + { + if (StateChangedHandler == null) return; + try { StateChangedHandler(sender, new StateChangedEventArgs(stateChangedMsg)); } + catch (Exception e) { string s = e.ToString(); } + } + public static event EventHandler StateChangedHandler; + + + /// + /// Called from the state machine when 'Activity' information changes. + /// + public static void OnEmergencyStopChanged(object sender, EmergencyStopEventArgs.State state) + { + if (EmergencyStopChangedHandler == null) return; + try { EmergencyStopChangedHandler(sender, new EmergencyStopEventArgs(state)); } + catch (Exception e) { log.Error("EmergencyStopHandler(...) failed", e); } + } + public static event EventHandler EmergencyStopChangedHandler; + } +} diff --git a/TestBenchFramework/UiBridge/ButtonsEtcEventArgs.cs b/TestBenchFramework/UiBridge/ButtonsEtcEventArgs.cs new file mode 100644 index 000000000..3dfa0753e --- /dev/null +++ b/TestBenchFramework/UiBridge/ButtonsEtcEventArgs.cs @@ -0,0 +1,17 @@ +using System; + +namespace TBF.UiBridge +{ + /// + /// Argument of UiBridgeEventHandler. + /// + public class ButtonsEtcEventArgs : EventArgs + { + public ButtonsEtc Flags; /// Flags to be passed to the UI. + + public ButtonsEtcEventArgs(ButtonsEtc flags) + { + this.Flags = flags; + } + } +} diff --git a/TestBenchFramework/UiBridge/CameraStateChangedEventArgs.cs b/TestBenchFramework/UiBridge/CameraStateChangedEventArgs.cs new file mode 100644 index 000000000..63c18b3d5 --- /dev/null +++ b/TestBenchFramework/UiBridge/CameraStateChangedEventArgs.cs @@ -0,0 +1,17 @@ +using System; +using TBF.BenchControl; + +namespace TBF.UiBridge +{ + class CameraStateChangedEventArgs : EventArgs + { + public int CameraIdx; + public BenchControl.Cameras.IdcCamera.IdcState State; + + public CameraStateChangedEventArgs(int cameraIdx, BenchControl.Cameras.IdcCamera.IdcState state) + { + CameraIdx = cameraIdx; + State = state; + } + } +} diff --git a/TestBenchFramework/UiBridge/EmergencyStopEventArgs.cs b/TestBenchFramework/UiBridge/EmergencyStopEventArgs.cs new file mode 100644 index 000000000..bde79a31e --- /dev/null +++ b/TestBenchFramework/UiBridge/EmergencyStopEventArgs.cs @@ -0,0 +1,22 @@ +using System; + +namespace TBF.UiBridge +{ + public class EmergencyStopEventArgs : EventArgs + { + public enum State + { + Unknown, + Inactive, + Active, + CloseForm, + } + + public State EmergencyStopState; + + public EmergencyStopEventArgs(State emergencyStopState) + { + this.EmergencyStopState = emergencyStopState; + } + } +} diff --git a/TestBenchFramework/UiBridge/Enums.cs b/TestBenchFramework/UiBridge/Enums.cs new file mode 100644 index 000000000..bf00f7897 --- /dev/null +++ b/TestBenchFramework/UiBridge/Enums.cs @@ -0,0 +1,52 @@ + +namespace TBF.UiBridge +{ + /// UI command ID-s used by UiBridge + public enum UI2BenchCmd + { + None = 0, + StartTest, + StartQ1, + StartQ2, + StartQ3, + StartCycle, + Stop, + PurgeBegin, + PurgeEnd, + EmptyTank1, + EmptyTank2, + TryOpticalHeads, + ResetResults, + AcceptResults, + Calibration, + SensitivityTest, + CameraTest, + B1, + B2, + B3, + Next, /// Used for debugging + } + + public enum ButtonsEtc + { + None = 0, + ProcedureCmbBoxEn = 0x1, + TestCmbBoxEn = 0x2, + StopBtnEn = 0x4, + StartTestBtnsEn = 0x8, + StartCycleBtnEn = 0x10, + PurgeBeginBtnEn = 0x20, + PurgeEndBtnEn = 0x40, + EmptyTankBtnsEn = 0x80, + TryOpticalHeadsBtnEn = 0x100, + ResetResultsBtnEn = 0x200, + AcceptResultsBtnEn = 0x300, + CalibrationBtnEn = 0x800, + SensitivityTestBtnEn = 0x1000, + + /// If one of the following flags is set, flags 0x1 through 0x1000 are ignored + /// + ShowBenchEmpty = 0x2000, + ShowBenchFilled = 0x4000, + } +} diff --git a/TestBenchFramework/UiBridge/ImageUpdatedEventArgs.cs b/TestBenchFramework/UiBridge/ImageUpdatedEventArgs.cs new file mode 100644 index 000000000..19bd5c9dc --- /dev/null +++ b/TestBenchFramework/UiBridge/ImageUpdatedEventArgs.cs @@ -0,0 +1,17 @@ +using System; +using TBF.BenchControl; + +namespace TBF.UiBridge +{ + public class ImageUpdatedEventArgs : EventArgs + { + public int CameraIdx; + public string ImageLocation; + + public ImageUpdatedEventArgs(int cameraIdx, string imageLocation) + { + CameraIdx = cameraIdx; + ImageLocation = imageLocation; + } + } +} diff --git a/TestBenchFramework/UiBridge/LogEventArgs.cs b/TestBenchFramework/UiBridge/LogEventArgs.cs new file mode 100644 index 000000000..5f6d61912 --- /dev/null +++ b/TestBenchFramework/UiBridge/LogEventArgs.cs @@ -0,0 +1,14 @@ +using System; + +namespace TBF.UiBridge +{ + public class LogEventArgs : EventArgs + { + public string LogMessage; + + public LogEventArgs(string logMessage) + { + this.LogMessage = logMessage; + } + } +} diff --git a/TestBenchFramework/UiBridge/ProcedureCompletedEventArgs.cs b/TestBenchFramework/UiBridge/ProcedureCompletedEventArgs.cs new file mode 100644 index 000000000..547488bf6 --- /dev/null +++ b/TestBenchFramework/UiBridge/ProcedureCompletedEventArgs.cs @@ -0,0 +1,15 @@ +using System; +using TBF.BenchControl; + +namespace TBF.UiBridge +{ + public class ProcedureCompletedEventArgs : EventArgs + { + public Entities.Procedure Procedure; + + public ProcedureCompletedEventArgs(Entities.Procedure procedure) + { + Procedure = procedure; + } + } +} diff --git a/TestBenchFramework/UiBridge/ProcedureSelectedEventArgs.cs b/TestBenchFramework/UiBridge/ProcedureSelectedEventArgs.cs new file mode 100644 index 000000000..20fa5ded0 --- /dev/null +++ b/TestBenchFramework/UiBridge/ProcedureSelectedEventArgs.cs @@ -0,0 +1,15 @@ +using System; +using TBF.BenchControl; + +namespace TBF.UiBridge +{ + public class ProcedureSelectedEventArgs : EventArgs + { + public Entities.Procedure Procedure; + + public ProcedureSelectedEventArgs(Entities.Procedure procedure) + { + this.Procedure = procedure; + } + } +} diff --git a/TestBenchFramework/UiBridge/StateChangedEventArgs.cs b/TestBenchFramework/UiBridge/StateChangedEventArgs.cs new file mode 100644 index 000000000..1c277273d --- /dev/null +++ b/TestBenchFramework/UiBridge/StateChangedEventArgs.cs @@ -0,0 +1,14 @@ +using System; + +namespace TBF.UiBridge +{ + public class StateChangedEventArgs : EventArgs + { + public string StateChangedMsg; + + public StateChangedEventArgs(string stateChangedMsg) + { + StateChangedMsg = stateChangedMsg; + } + } +} diff --git a/TestBenchFramework/UiBridge/TestCompletedEventArgs.cs b/TestBenchFramework/UiBridge/TestCompletedEventArgs.cs new file mode 100644 index 000000000..89fac7f52 --- /dev/null +++ b/TestBenchFramework/UiBridge/TestCompletedEventArgs.cs @@ -0,0 +1,14 @@ +using System; + +namespace TBF.UiBridge +{ + public class TestCompletedEventArgs : EventArgs + { + public Entities.TestResult TestResult; + + public TestCompletedEventArgs(Entities.TestResult testResult) + { + this.TestResult = testResult; + } + } +} diff --git a/TestBenchFramework/UiBridge/TestProgressEventArgs.cs b/TestBenchFramework/UiBridge/TestProgressEventArgs.cs new file mode 100644 index 000000000..b16717bb0 --- /dev/null +++ b/TestBenchFramework/UiBridge/TestProgressEventArgs.cs @@ -0,0 +1,30 @@ +using System; + +namespace TBF.UiBridge +{ + public class TestProgressEventArgs : EventArgs + { + public int RefPulses; + public float Flow; + public float Volume; + public float Time; + public float Progress; + public float OveralProgress; + + public float Tin; + public float Tout; + public float Tdiv; + public float Pin; + public float Pout; + public float AmbientTemp; + public float AmbientPressure; + public float AmbientHumidity; + + public int[] WmPulses = new int[Program.WMsCount]; + public int[] WmRefPulses = new int[Program.WMsCount]; + public float[] WmVolume = new float[Program.WMsCount]; + public float[] WmErrPct = new float[Program.WMsCount]; + + public Entities.TestResult TestResult; + } +} diff --git a/TestBenchFramework/UiBridge/TestSelectedEventArgs.cs b/TestBenchFramework/UiBridge/TestSelectedEventArgs.cs new file mode 100644 index 000000000..8d620caa6 --- /dev/null +++ b/TestBenchFramework/UiBridge/TestSelectedEventArgs.cs @@ -0,0 +1,27 @@ +using System; +using TBF.BenchControl; + +namespace TBF.UiBridge +{ + public class TestSelectedEventArgs : EventArgs + { + public Entities.Test Test; + public int RepetitionNr; + public FeedingPath FeedingPath; + public BenchPath BenchPath; + public OutputPath OutputPath; + public MetersPath MetersPath; + public int TotalPulses; + + public TestSelectedEventArgs(Entities.Test test, int repetitionNr, FeedingPath f, BenchPath b, OutputPath o, MetersPath m, int tp) + { + Test = test; + RepetitionNr = repetitionNr; + FeedingPath = f; + BenchPath = b; + OutputPath = o; + MetersPath = m; + TotalPulses = tp; + } + } +} diff --git a/TestBenchFramework/UiControls/BaseWithListViewEx.cs b/TestBenchFramework/UiControls/BaseWithListViewEx.cs new file mode 100644 index 000000000..b3692a14b --- /dev/null +++ b/TestBenchFramework/UiControls/BaseWithListViewEx.cs @@ -0,0 +1,203 @@ +using System; +using System.Collections.Generic; +using System.Windows.Forms; + +namespace TBF.UiControls +{ + public class BaseWithListViewEx : ListViewEx + { + /// + /// List of items to be edited + /// + public IList MyItems; + + /// + /// Number of items/rows with lowest ItemNr = 0,... + /// that cannot be deleted, moved down, renamed, etc. + /// + public int FixedRowsCount; + + /// + /// List of removed items that have to be removed from the database + /// when completed with OK. + /// + public IList ToBeRemovedItems; + + /// + /// true = editing was unlocked + /// + public bool Unlocked { get { return unlocked; } } /// read only + bool unlocked; + + public BaseWithListViewEx() + : base() + { + ToBeRemovedItems = new List(); + + /// Initialize the base (ListViewEx) + this.SuspendLayout(); + AllowColumnReorder = false; + Dock = System.Windows.Forms.DockStyle.Fill; + DoubleClickActivation = false; + FullRowSelect = true; + GridLines = true; + Location = new System.Drawing.Point(0, 0); + Name = "baseWithListViewEx"; + Size = new System.Drawing.Size(150, 150); + TabIndex = 0; + UseCompatibleStateImageBehavior = false; + View = System.Windows.Forms.View.Details; + ResumeLayout(false); + } + + public void Unlock() + { + unlocked = true; + + if (base.SelectedItems.Count == 1) + { + int ix = SelectedIndices[0]; + Focus(); + Items[ix].Selected = true; + Items[ix].EnsureVisible(); + } + } + + protected void RedrawAll() + { + Items.Clear(); + foreach (var myItem in MyItems) + { + DrawOne(myItem); + } + } + + public virtual void DrawOne(object myItem) + { + } + + void UpdateAll() + { + if (MyItems == null || (MyItems.Count != Items.Count)) return; + + foreach (ListViewItem lvi in Items) + { + UpdateOne(lvi, (MyItem)lvi.Tag); + } + } + + public virtual void UpdateOne(ListViewItem lvi, object myItem) + { + } + + public void OkBtnClicked() + { + UpdateAll(); + } + + public void CancelBtnClicked() + { + } + + public void AddOne(MyItem myItem) + { + MyItems.Add(myItem); + DrawOne(myItem); + + Focus(); + SelectedItems.Clear(); + Items[Items.Count - 1].Selected = true; + Items[Items.Count - 1].EnsureVisible(); + } + + /// + /// Called when 'Remove' button was clicked. + /// + /// true when the last item was removed and 'Remove' button should be disabled + public bool RemoveSelected() + { + if (SelectedItems.Count != 1) return false; + + UpdateAll(); + + int removeItemNr = SelectedIndices[0]; + if (removeItemNr < FixedRowsCount) return false; + + MyItem selectedItem = (MyItem)SelectedItems[0].Tag; + + if ((selectedItem as Entities.IHasItemNr).Id != 0) ToBeRemovedItems.Add(selectedItem); + MyItems.RemoveAt(removeItemNr); + if (selectedItem is Entities.IHasItemNr) + { + for (int i = removeItemNr; i < MyItems.Count; i++) + { + (MyItems[i] as Entities.IHasItemNr).ItemNr--; + } + } + + RedrawAll(); + + if (removeItemNr < base.Items.Count) + { + Focus(); + Items[removeItemNr].Selected = true; + Items[removeItemNr].EnsureVisible(); + return false; + } + else + { + return true; + } + } + + public void MoveUpSelected() + { + if (SelectedItems.Count != 1) + { + return; + } + int ix = base.SelectedIndices[0]; + if (ix <= FixedRowsCount || ix >= MyItems.Count) return; + + UpdateAll(); + + MyItem item1 = (MyItem)(Items[ix - 1].Tag); + MyItem item2 = (MyItem)(Items[ix].Tag); + (item1 as Entities.IHasItemNr).ItemNr++; + (item2 as Entities.IHasItemNr).ItemNr--; + MyItems.RemoveAt(ix); + MyItems.Insert(ix - 1, item2); + + RedrawAll(); + + Focus(); + Items[ix - 1].Selected = true; + Items[ix - 1].EnsureVisible(); + } + + public void MoveDownSelected() + { + if (base.SelectedItems.Count != 1) + { + return; + } + int ix = base.SelectedIndices[0]; + if (ix < FixedRowsCount || ix >= MyItems.Count - 1) return; + + UpdateAll(); + + MyItem item1 = (MyItem)(Items[ix].Tag); + MyItem item2 = (MyItem)(Items[ix + 1].Tag); + (item1 as Entities.IHasItemNr).ItemNr++; + (item2 as Entities.IHasItemNr).ItemNr--; + MyItems.RemoveAt(ix + 1); + MyItems.Insert(ix, item2); + + RedrawAll(); + + Focus(); + Items[ix + 1].Selected = true; + Items[ix + 1].EnsureVisible(); + } + } +} diff --git a/TestBenchFramework/UiControls/BenchControlPanel.Designer.cs b/TestBenchFramework/UiControls/BenchControlPanel.Designer.cs new file mode 100644 index 000000000..6db3b2eda --- /dev/null +++ b/TestBenchFramework/UiControls/BenchControlPanel.Designer.cs @@ -0,0 +1,289 @@ +namespace TBF.UiControls +{ + partial class BenchControlPanel + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(BenchControlPanel)); + this.stopBtn = new System.Windows.Forms.Button(); + this.startTestBtn = new System.Windows.Forms.Button(); + this.startCycleBtn = new System.Windows.Forms.Button(); + this.purgeBeginBtn = new System.Windows.Forms.Button(); + this.purgeEndBtn = new System.Windows.Forms.Button(); + this.tryHeadsBtn = new System.Windows.Forms.Button(); + this.resetResultsBtn = new System.Windows.Forms.Button(); + this.calibrationBtn = new System.Windows.Forms.Button(); + this.emptyTank1Btn = new System.Windows.Forms.Button(); + this.sensitivityTestBtn = new System.Windows.Forms.Button(); + this.emptyTank2Btn = new System.Windows.Forms.Button(); + this.testGroupBox = new System.Windows.Forms.GroupBox(); + this.startQ3Btn = new System.Windows.Forms.Button(); + this.startQ2Btn = new System.Windows.Forms.Button(); + this.startQ1Btn = new System.Windows.Forms.Button(); + this.testComboBox = new System.Windows.Forms.ComboBox(); + this.purgeGroupBox = new System.Windows.Forms.GroupBox(); + this.emptyGroupBox = new System.Windows.Forms.GroupBox(); + this.otherGroupBox = new System.Windows.Forms.GroupBox(); + this.nextButton = new System.Windows.Forms.Button(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.acceptResultsBtn = new System.Windows.Forms.Button(); + this.testGroupBox.SuspendLayout(); + this.purgeGroupBox.SuspendLayout(); + this.emptyGroupBox.SuspendLayout(); + this.otherGroupBox.SuspendLayout(); + this.groupBox1.SuspendLayout(); + this.SuspendLayout(); + // + // stopBtn + // + this.stopBtn.BackColor = System.Drawing.Color.Tomato; + resources.ApplyResources(this.stopBtn, "stopBtn"); + this.stopBtn.Name = "stopBtn"; + this.stopBtn.UseVisualStyleBackColor = false; + this.stopBtn.Click += new System.EventHandler(this.stopBtn_Click); + // + // startTestBtn + // + this.startTestBtn.BackColor = System.Drawing.Color.DarkSeaGreen; + resources.ApplyResources(this.startTestBtn, "startTestBtn"); + this.startTestBtn.Name = "startTestBtn"; + this.startTestBtn.UseVisualStyleBackColor = false; + this.startTestBtn.Click += new System.EventHandler(this.startTestBtn_Click); + // + // startCycleBtn + // + this.startCycleBtn.BackColor = System.Drawing.Color.LightSeaGreen; + resources.ApplyResources(this.startCycleBtn, "startCycleBtn"); + this.startCycleBtn.Name = "startCycleBtn"; + this.startCycleBtn.UseVisualStyleBackColor = false; + this.startCycleBtn.Click += new System.EventHandler(this.startCycleBtn_Click); + // + // purgeBeginBtn + // + this.purgeBeginBtn.BackColor = System.Drawing.Color.LightSteelBlue; + resources.ApplyResources(this.purgeBeginBtn, "purgeBeginBtn"); + this.purgeBeginBtn.Name = "purgeBeginBtn"; + this.purgeBeginBtn.UseVisualStyleBackColor = false; + this.purgeBeginBtn.Click += new System.EventHandler(this.purgeBeginBtn_Click); + // + // purgeEndBtn + // + this.purgeEndBtn.BackColor = System.Drawing.Color.LightSteelBlue; + resources.ApplyResources(this.purgeEndBtn, "purgeEndBtn"); + this.purgeEndBtn.Name = "purgeEndBtn"; + this.purgeEndBtn.UseVisualStyleBackColor = false; + this.purgeEndBtn.Click += new System.EventHandler(this.purgeEndBtn_Click); + // + // tryHeadsBtn + // + this.tryHeadsBtn.BackColor = System.Drawing.Color.DarkGray; + resources.ApplyResources(this.tryHeadsBtn, "tryHeadsBtn"); + this.tryHeadsBtn.Name = "tryHeadsBtn"; + this.tryHeadsBtn.UseVisualStyleBackColor = false; + this.tryHeadsBtn.Click += new System.EventHandler(this.tryHeadsBtn_Click); + // + // resetResultsBtn + // + this.resetResultsBtn.BackColor = System.Drawing.Color.Tomato; + resources.ApplyResources(this.resetResultsBtn, "resetResultsBtn"); + this.resetResultsBtn.Name = "resetResultsBtn"; + this.resetResultsBtn.UseVisualStyleBackColor = false; + this.resetResultsBtn.Click += new System.EventHandler(this.resetResultsBtn_Click); + // + // calibrationBtn + // + this.calibrationBtn.BackColor = System.Drawing.Color.DarkGray; + resources.ApplyResources(this.calibrationBtn, "calibrationBtn"); + this.calibrationBtn.Name = "calibrationBtn"; + this.calibrationBtn.UseVisualStyleBackColor = false; + this.calibrationBtn.Click += new System.EventHandler(this.calibrationBtn_Click); + // + // emptyTank1Btn + // + this.emptyTank1Btn.BackColor = System.Drawing.Color.LightSteelBlue; + resources.ApplyResources(this.emptyTank1Btn, "emptyTank1Btn"); + this.emptyTank1Btn.Name = "emptyTank1Btn"; + this.emptyTank1Btn.UseVisualStyleBackColor = false; + this.emptyTank1Btn.Click += new System.EventHandler(this.emptyTank1Btn_Click); + // + // sensitivityTestBtn + // + this.sensitivityTestBtn.BackColor = System.Drawing.Color.DarkGray; + resources.ApplyResources(this.sensitivityTestBtn, "sensitivityTestBtn"); + this.sensitivityTestBtn.Name = "sensitivityTestBtn"; + this.sensitivityTestBtn.UseVisualStyleBackColor = false; + this.sensitivityTestBtn.Click += new System.EventHandler(this.sensitivityTestBtn_Click); + // + // emptyTank2Btn + // + this.emptyTank2Btn.BackColor = System.Drawing.Color.LightSteelBlue; + resources.ApplyResources(this.emptyTank2Btn, "emptyTank2Btn"); + this.emptyTank2Btn.Name = "emptyTank2Btn"; + this.emptyTank2Btn.UseVisualStyleBackColor = false; + this.emptyTank2Btn.Click += new System.EventHandler(this.emptyTank2Btn_Click); + // + // testGroupBox + // + this.testGroupBox.Controls.Add(this.startQ3Btn); + this.testGroupBox.Controls.Add(this.startQ2Btn); + this.testGroupBox.Controls.Add(this.startQ1Btn); + this.testGroupBox.Controls.Add(this.testComboBox); + this.testGroupBox.Controls.Add(this.startTestBtn); + this.testGroupBox.Controls.Add(this.startCycleBtn); + this.testGroupBox.Controls.Add(this.stopBtn); + resources.ApplyResources(this.testGroupBox, "testGroupBox"); + this.testGroupBox.Name = "testGroupBox"; + this.testGroupBox.TabStop = false; + // + // startQ3Btn + // + this.startQ3Btn.BackColor = System.Drawing.Color.DarkSeaGreen; + resources.ApplyResources(this.startQ3Btn, "startQ3Btn"); + this.startQ3Btn.Name = "startQ3Btn"; + this.startQ3Btn.UseVisualStyleBackColor = false; + this.startQ3Btn.Click += new System.EventHandler(this.startQ3Btn_Click); + // + // startQ2Btn + // + this.startQ2Btn.BackColor = System.Drawing.Color.DarkSeaGreen; + resources.ApplyResources(this.startQ2Btn, "startQ2Btn"); + this.startQ2Btn.Name = "startQ2Btn"; + this.startQ2Btn.UseVisualStyleBackColor = false; + this.startQ2Btn.Click += new System.EventHandler(this.startQ2Btn_Click); + // + // startQ1Btn + // + this.startQ1Btn.BackColor = System.Drawing.Color.DarkSeaGreen; + resources.ApplyResources(this.startQ1Btn, "startQ1Btn"); + this.startQ1Btn.Name = "startQ1Btn"; + this.startQ1Btn.UseVisualStyleBackColor = false; + this.startQ1Btn.Click += new System.EventHandler(this.startQ1Btn_Click); + // + // testComboBox + // + resources.ApplyResources(this.testComboBox, "testComboBox"); + this.testComboBox.FormattingEnabled = true; + this.testComboBox.Name = "testComboBox"; + this.testComboBox.SelectedIndexChanged += new System.EventHandler(this.testComboBox_SelectedIndexChanged); + // + // purgeGroupBox + // + this.purgeGroupBox.BackColor = System.Drawing.SystemColors.Control; + this.purgeGroupBox.Controls.Add(this.purgeEndBtn); + this.purgeGroupBox.Controls.Add(this.purgeBeginBtn); + resources.ApplyResources(this.purgeGroupBox, "purgeGroupBox"); + this.purgeGroupBox.Name = "purgeGroupBox"; + this.purgeGroupBox.TabStop = false; + // + // emptyGroupBox + // + this.emptyGroupBox.Controls.Add(this.emptyTank1Btn); + this.emptyGroupBox.Controls.Add(this.emptyTank2Btn); + resources.ApplyResources(this.emptyGroupBox, "emptyGroupBox"); + this.emptyGroupBox.Name = "emptyGroupBox"; + this.emptyGroupBox.TabStop = false; + // + // otherGroupBox + // + this.otherGroupBox.Controls.Add(this.sensitivityTestBtn); + this.otherGroupBox.Controls.Add(this.nextButton); + this.otherGroupBox.Controls.Add(this.calibrationBtn); + this.otherGroupBox.Controls.Add(this.tryHeadsBtn); + resources.ApplyResources(this.otherGroupBox, "otherGroupBox"); + this.otherGroupBox.Name = "otherGroupBox"; + this.otherGroupBox.TabStop = false; + // + // nextButton + // + resources.ApplyResources(this.nextButton, "nextButton"); + this.nextButton.Name = "nextButton"; + this.nextButton.UseVisualStyleBackColor = true; + this.nextButton.Click += new System.EventHandler(this.nextButton_Click); + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.acceptResultsBtn); + this.groupBox1.Controls.Add(this.resetResultsBtn); + resources.ApplyResources(this.groupBox1, "groupBox1"); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.TabStop = false; + // + // acceptResultsBtn + // + this.acceptResultsBtn.BackColor = System.Drawing.Color.ForestGreen; + resources.ApplyResources(this.acceptResultsBtn, "acceptResultsBtn"); + this.acceptResultsBtn.Name = "acceptResultsBtn"; + this.acceptResultsBtn.UseVisualStyleBackColor = false; + this.acceptResultsBtn.Click += new System.EventHandler(this.acceptResultsBtn_Click); + // + // BenchControlPanel + // + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.BackColor = System.Drawing.SystemColors.Control; + this.Controls.Add(this.groupBox1); + this.Controls.Add(this.otherGroupBox); + this.Controls.Add(this.emptyGroupBox); + this.Controls.Add(this.purgeGroupBox); + this.Controls.Add(this.testGroupBox); + this.Name = "BenchControlPanel"; + this.Load += new System.EventHandler(this.BenchControlPanel_Load); + this.testGroupBox.ResumeLayout(false); + this.purgeGroupBox.ResumeLayout(false); + this.emptyGroupBox.ResumeLayout(false); + this.otherGroupBox.ResumeLayout(false); + this.groupBox1.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Button stopBtn; + private System.Windows.Forms.Button startTestBtn; + private System.Windows.Forms.Button startCycleBtn; + private System.Windows.Forms.Button purgeBeginBtn; + private System.Windows.Forms.Button purgeEndBtn; + private System.Windows.Forms.Button tryHeadsBtn; + private System.Windows.Forms.Button resetResultsBtn; + private System.Windows.Forms.Button calibrationBtn; + private System.Windows.Forms.Button emptyTank1Btn; + private System.Windows.Forms.Button sensitivityTestBtn; + private System.Windows.Forms.Button emptyTank2Btn; + private System.Windows.Forms.GroupBox testGroupBox; + private System.Windows.Forms.ComboBox testComboBox; + private System.Windows.Forms.Button startQ1Btn; + private System.Windows.Forms.Button startQ3Btn; + private System.Windows.Forms.Button startQ2Btn; + private System.Windows.Forms.GroupBox purgeGroupBox; + private System.Windows.Forms.GroupBox emptyGroupBox; + private System.Windows.Forms.GroupBox otherGroupBox; + private System.Windows.Forms.Button nextButton; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.Button acceptResultsBtn; + } +} diff --git a/TestBenchFramework/UiControls/BenchControlPanel.cs b/TestBenchFramework/UiControls/BenchControlPanel.cs new file mode 100644 index 000000000..fedd0fabe --- /dev/null +++ b/TestBenchFramework/UiControls/BenchControlPanel.cs @@ -0,0 +1,271 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Windows.Forms; +using NHibernate; +using log4net; +using TBF.Entities; +using TBF.UiBridge; + +namespace TBF.UiControls +{ + public partial class BenchControlPanel : UserControl + { + static readonly ILog log = LogManager.GetLogger(typeof(BenchControlPanel)); + + public string TestName; + + // Original (enabled) colors of buttons and empty bench + Color colorStopEn; + Color colorTestsEn; + Color colorCycleEn; + Color colorPurgeEn; + Color colorAcceptEn; + Color colorEmptyEn; + Color colorOtherEn; + + Color colorBenchEmpty; + + // Colors of disabled buttons + Color colorStopDis; + Color colorTestsDis; + Color colorCycleDis; + Color colorPurgeDis; + Color colorAcceptDis; + Color colorEmptyDis; + Color colorOtherDis; + + public BenchControlPanel() + { + InitializeComponent(); + + Bridge.ButtonsEtcHandler += delegate(object sender, ButtonsEtcEventArgs args) + { + if (InvokeRequired) + { + Invoke(new EventHandler(OnButtonsEtc), sender, args); + } + else OnButtonsEtc(sender, args); + }; + + Bridge.ProcedureSelectedHandler += delegate(object sender, ProcedureSelectedEventArgs args) + { + if (InvokeRequired) + { + Invoke(new EventHandler(OnProcedureSelected), sender, args); + } + else OnProcedureSelected(sender, args); + }; + + Bridge.TestSelectedHandler += delegate(object sender, TestSelectedEventArgs args) + { + if (InvokeRequired) + { + Invoke(new EventHandler(OnTestSelected), sender, args); + } + else OnTestSelected(sender, args); + }; + +#if DEBUG + nextButton.Visible = true; + nextButton.Enabled = true; +#endif + } + + int Lghtr(int component) + { + return 255 - (255 - component) / 2; + } + + private void BenchControlPanel_Load(object sender, EventArgs e) + { + // Original (enabled) colors of buttons + colorStopEn = stopBtn.BackColor; + colorTestsEn = startTestBtn.BackColor; + colorCycleEn = startCycleBtn.BackColor; + colorPurgeEn = purgeBeginBtn.BackColor; + colorAcceptEn = acceptResultsBtn.BackColor; + colorEmptyEn = emptyTank1Btn.BackColor; + colorOtherEn = tryHeadsBtn.BackColor; + colorBenchEmpty = emptyGroupBox.BackColor; + + // Colors of disabled buttons + colorStopDis = Color.FromArgb(Lghtr(colorStopEn.R), Lghtr(colorStopEn.G), Lghtr(colorStopEn.B)); + colorTestsDis = Color.FromArgb(Lghtr(colorTestsEn.R), Lghtr(colorTestsEn.G), Lghtr(colorTestsEn.B)); + colorCycleDis = Color.FromArgb(Lghtr(colorCycleEn.R), Lghtr(colorCycleEn.G), Lghtr(colorCycleEn.B)); + colorPurgeDis = Color.FromArgb(Lghtr(colorPurgeEn.R), Lghtr(colorPurgeEn.G), Lghtr(colorPurgeEn.B)); + colorAcceptDis = Color.FromArgb(Lghtr(colorAcceptEn.R), Lghtr(colorAcceptEn.G), Lghtr(colorAcceptEn.B)); + colorEmptyDis = Color.FromArgb(Lghtr(colorEmptyEn.R), Lghtr(colorEmptyEn.G), Lghtr(colorEmptyEn.B)); + colorOtherDis = Color.FromArgb(Lghtr(colorOtherEn.R), Lghtr(colorOtherEn.G), Lghtr(colorOtherEn.B)); + } + + + /// + /// Read the database and re-initialize testComboBox items. + /// Try to preserve the original selection. + /// + public void ReloadTests() + { + if (Program.MainWnd.ProcedureName == null) return; + + string oriTestName = testComboBox.Text; + + IList procedures = FluentCommon.CreateSession(Database.Procedures) + .CreateQuery("FROM Procedure WHERE Name = :name") + .SetParameter("name", Program.MainWnd.ProcedureName) + .List(); + + if (procedures.Count != 1) + { + testComboBox.Text = string.Empty; + TestName = null; + Program.MainWnd.CurrentProcedure = null; + return; + } + + Program.MainWnd.CurrentProcedure = procedures[0]; + + testComboBox.Items.Clear(); + foreach (var test in procedures[0].Tests) testComboBox.Items.Add(test.Name); + + if (testComboBox.Items.Contains(oriTestName)) + { + testComboBox.Text = oriTestName; + TestName = oriTestName; + } + else if (procedures[0].Tests.Count > 0) + { + testComboBox.Text = procedures[0].Tests[0].Name; + TestName = procedures[0].Tests[0].Name; + } + else + { + testComboBox.Text = string.Empty; + TestName = null; + } + } + + private void testComboBox_SelectedIndexChanged(object sender, EventArgs e) + { + TestName = testComboBox.Text; + startTestBtn.Select(); + } + + + private void startTestBtn_Click(object sender, EventArgs e) { Bridge.Ui2Bench(UI2BenchCmd.StartTest); } + private void startQ1Btn_Click(object sender, EventArgs e) { Bridge.Ui2Bench(UI2BenchCmd.StartQ1); } + private void startQ2Btn_Click(object sender, EventArgs e) { Bridge.Ui2Bench(UI2BenchCmd.StartQ2); } + private void startQ3Btn_Click(object sender, EventArgs e) { Bridge.Ui2Bench(UI2BenchCmd.StartQ3); } + private void startCycleBtn_Click(object sender, EventArgs e) { Bridge.Ui2Bench(UI2BenchCmd.StartCycle); } + private void stopBtn_Click(object sender, EventArgs e) { Bridge.Ui2Bench(UI2BenchCmd.Stop); } + private void purgeBeginBtn_Click(object sender, EventArgs e) { Bridge.Ui2Bench(UI2BenchCmd.PurgeBegin); } + private void purgeEndBtn_Click(object sender, EventArgs e) { Bridge.Ui2Bench(UI2BenchCmd.PurgeEnd); } + private void emptyTank1Btn_Click(object sender, EventArgs e) { Bridge.Ui2Bench(UI2BenchCmd.EmptyTank1); } + private void emptyTank2Btn_Click(object sender, EventArgs e) { Bridge.Ui2Bench(UI2BenchCmd.EmptyTank2); } + private void tryHeadsBtn_Click(object sender, EventArgs e) { Bridge.Ui2Bench(UI2BenchCmd.TryOpticalHeads); } + private void resetResultsBtn_Click(object sender, EventArgs e) { Bridge.Ui2Bench(UI2BenchCmd.ResetResults); } + private void acceptResultsBtn_Click(object sender, EventArgs e) { Bridge.Ui2Bench(UI2BenchCmd.AcceptResults); } + private void calibrationBtn_Click(object sender, EventArgs e) { Bridge.Ui2Bench(UI2BenchCmd.CameraTest); } + private void sensitivityTestBtn_Click(object sender, EventArgs e){ Bridge.Ui2Bench(UI2BenchCmd.SensitivityTest); } + private void button1_Click(object sender, EventArgs e) { Bridge.Ui2Bench(UI2BenchCmd.B1); } + private void button2_Click(object sender, EventArgs e) { Bridge.Ui2Bench(UI2BenchCmd.B2); } + private void nextButton_Click(object sender, EventArgs e) { Bridge.Ui2Bench(UI2BenchCmd.Next); } + + /// + /// Processes a pressed keys. + /// + /// key (char) + /// true when the key is handled, otherwise false + public bool ProcessKey(char key) + { + switch (key) + { + case '0': if (stopBtn.Enabled) { Bridge.Ui2Bench(UI2BenchCmd.Stop); } return true; + case '1': if (startQ1Btn.Enabled) { Bridge.Ui2Bench(UI2BenchCmd.StartQ1); } return true; + case '2': if (startQ2Btn.Enabled) { Bridge.Ui2Bench(UI2BenchCmd.StartQ2); } return true; + case '3': if (startQ3Btn.Enabled) { Bridge.Ui2Bench(UI2BenchCmd.StartQ3); } return true; + case '4': if (startTestBtn.Enabled) { Bridge.Ui2Bench(UI2BenchCmd.StartTest); } return true; + case '5': if (startCycleBtn.Enabled) { Bridge.Ui2Bench(UI2BenchCmd.StartCycle); } return true; + case '6': if (purgeBeginBtn.Enabled) { Bridge.Ui2Bench(UI2BenchCmd.PurgeBegin); } return true; + case '7': if (purgeEndBtn.Enabled) { Bridge.Ui2Bench(UI2BenchCmd.PurgeEnd); } return true; + case '8': if (emptyTank1Btn.Enabled) { Bridge.Ui2Bench(UI2BenchCmd.EmptyTank1); } return true; + case '9': if (emptyTank2Btn.Enabled) { Bridge.Ui2Bench(UI2BenchCmd.EmptyTank2); } return true; + default: + return false; + } + } + + + public void OnProcedureSelected(object sender, ProcedureSelectedEventArgs args) + { + ReloadTests(); + } + + public void OnTestSelected(object sender, TestSelectedEventArgs args) + { + testComboBox.Text = args.Test.Name; + } + + + public void OnButtonsEtc(object sender, ButtonsEtcEventArgs args) + { + if ((args.Flags & ButtonsEtc.ShowBenchEmpty) != 0) + { + purgeGroupBox.BackColor = colorBenchEmpty; + return; + } + else if ((args.Flags & ButtonsEtc.ShowBenchFilled) != 0) + { + purgeGroupBox.BackColor = Color.RoyalBlue; + return; + } + + testComboBox.Enabled = ((args.Flags & ButtonsEtc.TestCmbBoxEn) != 0); + + stopBtn.Enabled = ((args.Flags & ButtonsEtc.StopBtnEn) != 0); + stopBtn.BackColor = stopBtn.Enabled ? colorStopEn : colorStopDis; + + startTestBtn.Enabled = ((args.Flags & ButtonsEtc.StartTestBtnsEn) != 0); + startTestBtn.BackColor = startTestBtn.Enabled ? colorTestsEn : colorTestsDis; + + startQ1Btn.Enabled = ((args.Flags & ButtonsEtc.StartTestBtnsEn) != 0); + startQ1Btn.BackColor = startQ1Btn.Enabled ? colorTestsEn : colorTestsDis; + + startQ2Btn.Enabled = ((args.Flags & ButtonsEtc.StartTestBtnsEn) != 0); + startQ2Btn.BackColor = startQ2Btn.Enabled ? colorTestsEn : colorTestsDis; + + startQ3Btn.Enabled = ((args.Flags & ButtonsEtc.StartTestBtnsEn) != 0); + startQ3Btn.BackColor = startQ3Btn.Enabled ? colorTestsEn : colorTestsDis; + + startCycleBtn.Enabled = ((args.Flags & ButtonsEtc.StartCycleBtnEn) != 0); + startCycleBtn.BackColor = startCycleBtn.Enabled ? colorCycleEn : colorCycleDis; + + purgeBeginBtn.Enabled = ((args.Flags & ButtonsEtc.PurgeBeginBtnEn) != 0); + purgeBeginBtn.BackColor = purgeBeginBtn.Enabled ? colorPurgeEn : colorPurgeDis; + + purgeEndBtn.Enabled = ((args.Flags & ButtonsEtc.PurgeEndBtnEn) != 0); + purgeEndBtn.BackColor = purgeEndBtn.Enabled ? colorPurgeEn : colorPurgeDis; + + emptyTank1Btn.Enabled = ((args.Flags & ButtonsEtc.EmptyTankBtnsEn) != 0); + emptyTank1Btn.BackColor = emptyTank1Btn.Enabled ? colorEmptyEn : colorEmptyDis; + + emptyTank2Btn.Enabled = ((args.Flags & ButtonsEtc.EmptyTankBtnsEn) != 0); + emptyTank2Btn.BackColor = emptyTank2Btn.Enabled ? colorEmptyEn : colorEmptyDis; + + resetResultsBtn.Enabled = ((args.Flags & ButtonsEtc.ResetResultsBtnEn) != 0); + resetResultsBtn.BackColor = resetResultsBtn.Enabled ? colorStopEn : colorStopDis; + + acceptResultsBtn.Enabled = ((args.Flags & ButtonsEtc.AcceptResultsBtnEn) != 0); + acceptResultsBtn.BackColor = acceptResultsBtn.Enabled ? colorAcceptEn : colorAcceptDis; + + tryHeadsBtn.Enabled = ((args.Flags & ButtonsEtc.TryOpticalHeadsBtnEn) != 0); + tryHeadsBtn.BackColor = tryHeadsBtn.Enabled ? colorOtherEn : colorOtherDis; + + calibrationBtn.Enabled = ((args.Flags & ButtonsEtc.CalibrationBtnEn) != 0); + calibrationBtn.BackColor = calibrationBtn.Enabled ? colorOtherEn : colorOtherDis; + + sensitivityTestBtn.Enabled = ((args.Flags & ButtonsEtc.SensitivityTestBtnEn) != 0); + sensitivityTestBtn.BackColor = sensitivityTestBtn.Enabled ? colorOtherEn : colorOtherDis; + } + } +} diff --git a/TestBenchFramework/UiControls/BenchControlPanel.de.resx b/TestBenchFramework/UiControls/BenchControlPanel.de.resx new file mode 100644 index 000000000..8ef361b7d --- /dev/null +++ b/TestBenchFramework/UiControls/BenchControlPanel.de.resx @@ -0,0 +1,295 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + Verdana, 14.25pt + + + 104, 167 + + + 94, 70 + + + 0 Stopp + + + Verdana, 14.25pt + + + 8, 66 + + + 4 Start Prüfpunkt + + + Verdana, 14.25pt + + + 8, 167 + + + 5 Start Prüfung + + + Verdana, 14.25pt + + + 93, 35 + + + 6 Anf. + + + Verdana, 14.25pt + + + 104, 23 + + + 94, 35 + + + 7 Ende + + + Verdana, 11.25pt + + + 8, 77 + + + Opt.Köpfe testen + + + Verdana, 12pt + + + zurücks. + + + Verdana, 11.25pt + + + 104, 26 + + + Kalibrieren + + + Verdana, 14.25pt + + + 8, 23 + + + 8 Beh.1 + + + Verdana, 11.25pt + + + 9, 26 + + + Empfind- lichkeit + + + Verdana, 14.25pt + + + 104, 23 + + + 94, 35 + + + 9 Beh.2 + + + Verdana, 14.25pt + + + 138, 116 + + + 3 + + + Verdana, 14.25pt + + + 73, 116 + + + 2 + + + Verdana, 14.25pt + + + 8, 116 + + + 1 + + + 13, 3 + + + Prüfpunkt + + + 13, 252 + + + Spülen + + + 13, 397 + + + Leeren + + + 13, 470 + + + 207, 130 + + + Zubehör + + + Verdana, 10pt + + + bestätigen + + + 13, 325 + + + Ergebnisse + + + 235, 1000 + + \ No newline at end of file diff --git a/TestBenchFramework/UiControls/BenchControlPanel.resx b/TestBenchFramework/UiControls/BenchControlPanel.resx new file mode 100644 index 000000000..06514cf23 --- /dev/null +++ b/TestBenchFramework/UiControls/BenchControlPanel.resx @@ -0,0 +1,786 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + Verdana, 15.75pt + + + + NoControl + + + 106, 168 + + + 92, 70 + + + + 5 + + + Stop + + + stopBtn + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + testGroupBox + + + 6 + + + Verdana, 15.75pt + + + NoControl + + + 8, 67 + + + 190, 45 + + + 4 + + + Start Test + + + startTestBtn + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + testGroupBox + + + 4 + + + Verdana, 15.75pt + + + NoControl + + + 8, 168 + + + 92, 70 + + + 7 + + + Start Cycle + + + startCycleBtn + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + testGroupBox + + + 5 + + + Verdana, 15.75pt + + + NoControl + + + 8, 23 + + + 92, 35 + + + 8 + + + Begin + + + purgeBeginBtn + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + purgeGroupBox + + + 1 + + + Verdana, 15.75pt + + + NoControl + + + 106, 23 + + + 92, 35 + + + 9 + + + End + + + purgeEndBtn + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + purgeGroupBox + + + 0 + + + Verdana, 12pt + + + NoControl + + + 8, 26 + + + 92, 45 + + + 10 + + + Try heads + + + tryHeadsBtn + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + otherGroupBox + + + 3 + + + Verdana, 15.75pt + + + NoControl + + + 8, 20 + + + 92, 42 + + + 11 + + + Reset + + + resetResultsBtn + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox1 + + + 1 + + + Verdana, 12pt + + + NoControl + + + 106, 26 + + + 92, 45 + + + 12 + + + Calib- ration + + + calibrationBtn + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + otherGroupBox + + + 2 + + + Verdana, 15.75pt + + + NoControl + + + 8, 26 + + + 92, 35 + + + 13 + + + Tank 1 + + + emptyTank1Btn + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + emptyGroupBox + + + 0 + + + Verdana, 12pt + + + NoControl + + + 8, 77 + + + 92, 45 + + + 14 + + + Sensi- tivity + + + sensitivityTestBtn + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + otherGroupBox + + + 0 + + + Verdana, 15.75pt + + + NoControl + + + 106, 26 + + + 92, 35 + + + 15 + + + Tank 2 + + + emptyTank2Btn + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + emptyGroupBox + + + 1 + + + Verdana, 15.75pt + + + NoControl + + + 138, 117 + + + 60, 45 + + + 9 + + + Q3 + + + startQ3Btn + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + testGroupBox + + + 0 + + + Verdana, 15.75pt + + + NoControl + + + 73, 117 + + + 60, 45 + + + 8 + + + Q2 + + + startQ2Btn + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + testGroupBox + + + 1 + + + Verdana, 15.75pt + + + NoControl + + + 8, 117 + + + 60, 45 + + + 7 + + + Q1 + + + startQ1Btn + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + testGroupBox + + + 2 + + + Verdana, 15.75pt + + + 8, 25 + + + 190, 33 + + + 6 + + + testComboBox + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + testGroupBox + + + 3 + + + Verdana, 12pt + + + 7, 3 + + + 207, 246 + + + 17 + + + Test + + + testGroupBox + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 4 + + + Verdana, 12pt + + + 7, 253 + + + 207, 68 + + + 18 + + + Purge + + + purgeGroupBox + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 3 + + + Verdana, 12pt + + + 7, 397 + + + 207, 68 + + + 19 + + + Empty + + + emptyGroupBox + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 2 + + + False + + + Lucida Console, 8.25pt + + + 106, 77 + + + 91, 25 + + + 21 + + + Next + + + False + + + nextButton + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + otherGroupBox + + + 1 + + + Verdana, 12pt + + + 7, 469 + + + 207, 128 + + + 20 + + + Auxiliary + + + otherGroupBox + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 1 + + + Verdana, 15.75pt + + + NoControl + + + 106, 20 + + + 92, 42 + + + 15 + + + Accept + + + acceptResultsBtn + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox1 + + + 0 + + + Verdana, 12pt + + + 7, 325 + + + 207, 68 + + + 22 + + + Results + + + groupBox1 + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 0 + + + True + + + 9, 18 + + + Verdana, 11.25pt + + + 4, 4, 4, 4 + + + 224, 736 + + + BenchControlPanel + + + System.Windows.Forms.UserControl, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/UiControls/CameraPictureCtrl.Designer.cs b/TestBenchFramework/UiControls/CameraPictureCtrl.Designer.cs new file mode 100644 index 000000000..43d3a2edb --- /dev/null +++ b/TestBenchFramework/UiControls/CameraPictureCtrl.Designer.cs @@ -0,0 +1,141 @@ +namespace TBF.UiControls +{ + partial class CameraPictureCtrl + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.pictureBox = new System.Windows.Forms.PictureBox(); + this.groupBox = new System.Windows.Forms.GroupBox(); + this.ledPictureBox = new System.Windows.Forms.PictureBox(); + this.trackBar = new System.Windows.Forms.TrackBar(); + this.liveButton = new System.Windows.Forms.Button(); + this.focusButton = new System.Windows.Forms.Button(); + this.grabButton = new System.Windows.Forms.Button(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox)).BeginInit(); + this.groupBox.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.ledPictureBox)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.trackBar)).BeginInit(); + this.SuspendLayout(); + // + // pictureBox + // + this.pictureBox.Location = new System.Drawing.Point(6, 19); + this.pictureBox.Name = "pictureBox"; + this.pictureBox.Size = new System.Drawing.Size(320, 240); + this.pictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage; + this.pictureBox.TabIndex = 0; + this.pictureBox.TabStop = false; + // + // groupBox + // + this.groupBox.Controls.Add(this.ledPictureBox); + this.groupBox.Controls.Add(this.trackBar); + this.groupBox.Controls.Add(this.liveButton); + this.groupBox.Controls.Add(this.focusButton); + this.groupBox.Controls.Add(this.grabButton); + this.groupBox.Controls.Add(this.pictureBox); + this.groupBox.Location = new System.Drawing.Point(0, 0); + this.groupBox.Name = "groupBox"; + this.groupBox.Size = new System.Drawing.Size(332, 315); + this.groupBox.TabIndex = 1; + this.groupBox.TabStop = false; + this.groupBox.Text = "Camera "; + // + // ledPictureBox + // + this.ledPictureBox.Location = new System.Drawing.Point(6, 279); + this.ledPictureBox.Name = "ledPictureBox"; + this.ledPictureBox.Size = new System.Drawing.Size(15, 15); + this.ledPictureBox.TabIndex = 5; + this.ledPictureBox.TabStop = false; + // + // trackBar + // + this.trackBar.Location = new System.Drawing.Point(200, 264); + this.trackBar.Name = "trackBar"; + this.trackBar.Size = new System.Drawing.Size(126, 45); + this.trackBar.TabIndex = 4; + this.trackBar.Scroll += new System.EventHandler(this.trackBar_Scroll); + // + // liveButton + // + this.liveButton.Location = new System.Drawing.Point(81, 264); + this.liveButton.Name = "liveButton"; + this.liveButton.Size = new System.Drawing.Size(56, 45); + this.liveButton.TabIndex = 3; + this.liveButton.Text = "Live"; + this.liveButton.UseVisualStyleBackColor = true; + this.liveButton.Click += new System.EventHandler(this.liveButton_Click); + // + // focusButton + // + this.focusButton.Location = new System.Drawing.Point(138, 264); + this.focusButton.Name = "focusButton"; + this.focusButton.Size = new System.Drawing.Size(56, 45); + this.focusButton.TabIndex = 2; + this.focusButton.Text = "Focus"; + this.focusButton.UseVisualStyleBackColor = true; + this.focusButton.Click += new System.EventHandler(this.focusButton_Click); + // + // grabButton + // + this.grabButton.Location = new System.Drawing.Point(24, 264); + this.grabButton.Name = "grabButton"; + this.grabButton.Size = new System.Drawing.Size(56, 45); + this.grabButton.TabIndex = 1; + this.grabButton.Text = "Grab"; + this.grabButton.UseVisualStyleBackColor = true; + this.grabButton.Click += new System.EventHandler(this.grabButton_Click); + // + // CameraPictureCtrl + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.BackColor = System.Drawing.SystemColors.ButtonShadow; + this.Controls.Add(this.groupBox); + this.Name = "CameraPictureCtrl"; + this.Size = new System.Drawing.Size(334, 320); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox)).EndInit(); + this.groupBox.ResumeLayout(false); + this.groupBox.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.ledPictureBox)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.trackBar)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.PictureBox pictureBox; + private System.Windows.Forms.GroupBox groupBox; + private System.Windows.Forms.Button liveButton; + private System.Windows.Forms.Button focusButton; + private System.Windows.Forms.Button grabButton; + private System.Windows.Forms.PictureBox ledPictureBox; + private System.Windows.Forms.TrackBar trackBar; + } +} diff --git a/TestBenchFramework/UiControls/CameraPictureCtrl.cs b/TestBenchFramework/UiControls/CameraPictureCtrl.cs new file mode 100644 index 000000000..65dce8d66 --- /dev/null +++ b/TestBenchFramework/UiControls/CameraPictureCtrl.cs @@ -0,0 +1,63 @@ +using System; +using System.Drawing; +using System.Windows.Forms; +using TBF.BenchControl.Cameras.IdcCamera; + +namespace TBF.UiControls +{ + public partial class CameraPictureCtrl : UserControl + { + public PictureBox PictureBox { get { return pictureBox; } } + + /// + /// Setting the state updated the background color + /// + public IdcState CameraState + { + set + { + switch (value) + { + case IdcState.NotConnected: + ledPictureBox.BackColor = Color.Gray; + break; + case IdcState.Busy: + ledPictureBox.BackColor = Color.Orange; + break; + case IdcState.Idle: + case IdcState.OpCompleted: + ledPictureBox.BackColor = Color.LawnGreen; + break; + default: + ledPictureBox.BackColor = Color.Tomato; + break; + } + } + } + + public CameraPictureCtrl() + { + InitializeComponent(); + } + + private void grabButton_Click(object sender, EventArgs e) + { + + } + + private void liveButton_Click(object sender, EventArgs e) + { + + } + + private void focusButton_Click(object sender, EventArgs e) + { + + } + + private void trackBar_Scroll(object sender, EventArgs e) + { + + } + } +} diff --git a/TestBenchFramework/UiControls/CameraPictureCtrl.resx b/TestBenchFramework/UiControls/CameraPictureCtrl.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/TestBenchFramework/UiControls/CameraPictureCtrl.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/UiControls/IMetrologyDlgTab.cs b/TestBenchFramework/UiControls/IMetrologyDlgTab.cs new file mode 100644 index 000000000..38b5aca4a --- /dev/null +++ b/TestBenchFramework/UiControls/IMetrologyDlgTab.cs @@ -0,0 +1,18 @@ +using System.Collections.Generic; + +namespace TBF.UiControls +{ + interface IMetrologyDlgTab : ITabWithListViewEx + { + /// + /// Component entity that has a list of 'measurement-correction' pairs + /// to be updated in the database on OK. + /// + Entities.Component MeterEntity { get; set; } + + /// + /// A list of 'measurement-correction' pairs to be deleted from the database on OK. + /// + IList ToBeRemoved { get; set; } + } +} diff --git a/TestBenchFramework/UiControls/IParentOfListViewEx.cs b/TestBenchFramework/UiControls/IParentOfListViewEx.cs new file mode 100644 index 000000000..e10d88435 --- /dev/null +++ b/TestBenchFramework/UiControls/IParentOfListViewEx.cs @@ -0,0 +1,8 @@ + +namespace TBF.UiControls +{ + interface IParentOfListViewEx + { + void UpdateButtonStates(SharedButtons.SelectedItemPos selectedItemPos); + } +} diff --git a/TestBenchFramework/UiControls/ITabWithListViewEx.cs b/TestBenchFramework/UiControls/ITabWithListViewEx.cs new file mode 100644 index 000000000..06bce12ec --- /dev/null +++ b/TestBenchFramework/UiControls/ITabWithListViewEx.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace TBF.UiControls +{ + interface ITabWithListViewEx + { + void Unlock(); + void OkBtnClicked(); + void CancelBtnClicked(); + void AddOne(); + void RemoveSelected(); + void MoveUpSelected(); + void MoveDownSelected(); + } +} diff --git a/TestBenchFramework/UiControls/ListViewEx.cs b/TestBenchFramework/UiControls/ListViewEx.cs new file mode 100644 index 000000000..91f5eada6 --- /dev/null +++ b/TestBenchFramework/UiControls/ListViewEx.cs @@ -0,0 +1,451 @@ +using System; +using System.Collections; +using System.ComponentModel; +using System.Drawing; +using System.Data; +using System.Windows.Forms; +using System.Runtime.InteropServices; + +namespace TBF.UiControls +{ + /// + /// Event Handler for SubItem events + /// + public delegate void SubItemEventHandler(object sender, SubItemEventArgs e); + /// + /// Event Handler for SubItemEndEditing events + /// + public delegate void SubItemEndEditingEventHandler(object sender, SubItemEndEditingEventArgs e); + + + /// + /// Inherited ListView to allow in-place editing of subitems + /// + public class ListViewEx : System.Windows.Forms.ListView + { + #region Interop structs, imports and constants + /// + /// MessageHeader for WM_NOTIFY + /// + private struct NMHDR + { + public IntPtr hwndFrom; + public Int32 idFrom; + public Int32 code; + } + + + [DllImport("user32.dll")] + private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wPar, IntPtr lPar); + [DllImport("user32.dll", CharSet=CharSet.Ansi)] + private static extern IntPtr SendMessage(IntPtr hWnd, int msg, int len, ref int [] order); + + // ListView messages + private const int LVM_FIRST = 0x1000; + private const int LVM_GETCOLUMNORDERARRAY = (LVM_FIRST + 59); + + // Windows Messages that will abort editing + private const int WM_HSCROLL = 0x114; + private const int WM_VSCROLL = 0x115; + private const int WM_SIZE = 0x05; + private const int WM_NOTIFY = 0x4E; + + private const int HDN_FIRST = -300; + private const int HDN_BEGINDRAG = (HDN_FIRST-10); + private const int HDN_ITEMCHANGINGA = (HDN_FIRST-0); + private const int HDN_ITEMCHANGINGW = (HDN_FIRST-20); + #endregion + + /// + /// Required designer variable. + /// + private System.ComponentModel.Container components = null; + + public event SubItemEventHandler SubItemClicked; + public event SubItemEventHandler SubItemBeginEditing; + public event SubItemEndEditingEventHandler SubItemEndEditing; + + public ListViewEx() + { + // This call is required by the Windows.Forms Form Designer. + InitializeComponent(); + + base.FullRowSelect = true; + base.View = View.Details; + base.AllowColumnReorder = true; + } + + /// + /// Clean up any resources being used. + /// + protected override void Dispose( bool disposing ) + { + if( disposing ) + { + if( components != null ) + components.Dispose(); + } + base.Dispose( disposing ); + } + + #region Component Designer generated code + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + components = new System.ComponentModel.Container(); + } + #endregion + + private bool _doubleClickActivation = false; + /// + /// Is a double click required to start editing a cell? + /// + public bool DoubleClickActivation + { + get { return _doubleClickActivation; } + set { _doubleClickActivation = value; } + } + + + /// + /// Retrieve the order in which columns appear + /// + /// Current display order of column indices + public int[] GetColumnOrder() + { + IntPtr lPar = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(int)) * Columns.Count); + + IntPtr res = SendMessage(Handle, LVM_GETCOLUMNORDERARRAY, new IntPtr(Columns.Count), lPar); + if (res.ToInt32() == 0) // Something went wrong + { + Marshal.FreeHGlobal(lPar); + return null; + } + + int [] order = new int[Columns.Count]; + Marshal.Copy(lPar, order, 0, Columns.Count); + + Marshal.FreeHGlobal(lPar); + + return order; + } + + + /// + /// Find ListViewItem and SubItem Index at position (x,y) + /// + /// relative to ListView + /// relative to ListView + /// Item at position (x,y) + /// SubItem index + public int GetSubItemAt(int x, int y, out ListViewItem item) + { + item = this.GetItemAt(x, y); + + if (item != null) + { + int[] order = GetColumnOrder(); + Rectangle lviBounds; + int subItemX; + + lviBounds = item.GetBounds(ItemBoundsPortion.Entire); + subItemX = lviBounds.Left; + for (int i=0; i + /// Get bounds for a SubItem + /// + /// Target ListViewItem + /// Target SubItem index + /// Bounds of SubItem (relative to ListView) + public Rectangle GetSubItemBounds(ListViewItem Item, int SubItem) + { + int[] order = GetColumnOrder(); + + Rectangle subItemRect = Rectangle.Empty; + if (SubItem >= order.Length) + throw new IndexOutOfRangeException("SubItem "+SubItem+" out of range"); + + if (Item == null) + throw new ArgumentNullException("Item"); + + Rectangle lviBounds = Item.GetBounds(ItemBoundsPortion.Entire); + int subItemX = lviBounds.Left; + + ColumnHeader col; + int i; + for (i=0; i + /// Fire SubItemClicked + /// + ///Point of click/doubleclick + private void EditSubitemAt(Point p) + { + ListViewItem item; + int idx = GetSubItemAt(p.X, p.Y, out item); + if (idx >= 0) + { + OnSubItemClicked(new SubItemEventArgs(item, idx)); + } + } + + #endregion + + #region In-place editing functions + // The control performing the actual editing + private Control _editingControl; + // The LVI being edited + private ListViewItem _editItem; + // The SubItem being edited + private int _editSubItem; + + protected void OnSubItemBeginEditing(SubItemEventArgs e) + { + if (SubItemBeginEditing != null) SubItemBeginEditing(this, e); + } + + protected void OnSubItemEndEditing(SubItemEndEditingEventArgs e) + { + if (SubItemEndEditing != null) SubItemEndEditing(this, e); + } + + protected void OnSubItemClicked(SubItemEventArgs e) + { + if (SubItemClicked != null) SubItemClicked(this, e); + } + + + /// + /// Begin in-place editing of given cell + /// + /// Control used as cell editor + /// ListViewItem to edit + /// SubItem index to edit + public void StartEditing(Control c, ListViewItem Item, int SubItem) + { + OnSubItemBeginEditing(new SubItemEventArgs(Item, SubItem)); + + Rectangle rcSubItem = GetSubItemBounds(Item, SubItem); + + if (rcSubItem.X < 0) + { + // Left edge of SubItem not visible - adjust rectangle position and width + rcSubItem.Width += rcSubItem.X; + rcSubItem.X=0; + } + if (rcSubItem.X+rcSubItem.Width > this.Width) + { + // Right edge of SubItem not visible - adjust rectangle width + rcSubItem.Width = this.Width-rcSubItem.Left; + } + + // Subitem bounds are relative to the location of the ListView! + rcSubItem.Offset(Left, Top); + + // In case the editing control and the listview are on different parents, + // account for different origins + Point origin = new Point(0,0); + Point lvOrigin = this.Parent.PointToScreen(origin); + Point ctlOrigin = c.Parent.PointToScreen(origin); + + rcSubItem.Offset(lvOrigin.X-ctlOrigin.X, lvOrigin.Y-ctlOrigin.Y); + + // Position and show editor + c.Bounds = rcSubItem; + c.Text = Item.SubItems[SubItem].Text; + c.Visible = true; + c.BringToFront(); + c.Focus(); + + _editingControl = c; + _editingControl.Leave += new EventHandler(_editControl_Leave); + _editingControl.KeyPress += new KeyPressEventHandler(_editControl_KeyPress); + + _editItem = Item; + _editSubItem = SubItem; + } + + + private void _editControl_Leave(object sender, EventArgs e) + { + // cell editor losing focus + EndEditing(true); + } + + private void _editControl_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e) + { + switch (e.KeyChar) + { + case (char)(int)Keys.Escape: + { + EndEditing(false); + break; + } + + case (char)(int)Keys.Enter: + { + EndEditing(true); + break; + } + } + } + + /// + /// Accept or discard current value of cell editor control + /// + /// Use the _editingControl's Text as new SubItem text or discard changes? + public void EndEditing(bool AcceptChanges) + { + if (_editingControl == null) + return; + + SubItemEndEditingEventArgs e = new SubItemEndEditingEventArgs( + _editItem, // The item being edited + _editSubItem, // The subitem index being edited + AcceptChanges ? + _editingControl.Text : // Use editControl text if changes are accepted + _editItem.SubItems[_editSubItem].Text, // or the original subitem's text, if changes are discarded + !AcceptChanges // Cancel? + ); + + OnSubItemEndEditing(e); + + _editItem.SubItems[_editSubItem].Text = e.DisplayText; + + _editingControl.Leave -= new EventHandler(_editControl_Leave); + _editingControl.KeyPress -= new KeyPressEventHandler(_editControl_KeyPress); + + _editingControl.Visible = false; + + _editingControl = null; + _editItem = null; + _editSubItem = -1; + } + #endregion + } + + + /// + /// Event Args for SubItemClicked event + /// + public class SubItemEventArgs : EventArgs + { + int subItem = -1; /// Sub-item index + ListViewItem item = null; + + public int SubItem { get { return subItem; } } + public ListViewItem Item { get { return item; } } + + public SubItemEventArgs(ListViewItem item, int subItem) + { + this.subItem = subItem; + this.item = item; + } + } + + + /// + /// Event Args for SubItemEndEditingClicked event + /// + public class SubItemEndEditingEventArgs : SubItemEventArgs + { + string displayText = string.Empty; + bool cancel = true; + + public SubItemEndEditingEventArgs(ListViewItem item, int subItem, string displayText, bool cancel) : + base(item, subItem) + { + this.displayText = displayText; + this.cancel = cancel; + } + public string DisplayText + { + get { return displayText; } + set { displayText = value; } + } + public bool Cancel + { + get { return cancel; } + set { cancel = value; } + } + } +} diff --git a/TestBenchFramework/UiControls/ListViewEx.resx b/TestBenchFramework/UiControls/ListViewEx.resx new file mode 100644 index 000000000..7e323966c --- /dev/null +++ b/TestBenchFramework/UiControls/ListViewEx.resx @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 1.0.0.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.3102.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.3102.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + diff --git a/TestBenchFramework/UiControls/MetrologyDlgBalanceTab.Designer.cs b/TestBenchFramework/UiControls/MetrologyDlgBalanceTab.Designer.cs new file mode 100644 index 000000000..6fa35dcd5 --- /dev/null +++ b/TestBenchFramework/UiControls/MetrologyDlgBalanceTab.Designer.cs @@ -0,0 +1,179 @@ +namespace TBF.UiControls +{ + partial class MetrologyDlgBalanceTab + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.cmpntNameLabel = new System.Windows.Forms.Label(); + this.splitContainer1 = new System.Windows.Forms.SplitContainer(); + this.measuredLabel = new System.Windows.Forms.Label(); + this.label1 = new System.Windows.Forms.Label(); + this.listViewEx = new TBF.UiControls.ListViewEx(); + this.testGroupBox = new System.Windows.Forms.GroupBox(); + this.correctedLabel = new System.Windows.Forms.Label(); + this.measuredTextBox = new System.Windows.Forms.TextBox(); + this.correctedTextBox = new System.Windows.Forms.TextBox(); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit(); + this.splitContainer1.Panel1.SuspendLayout(); + this.splitContainer1.Panel2.SuspendLayout(); + this.splitContainer1.SuspendLayout(); + this.testGroupBox.SuspendLayout(); + this.SuspendLayout(); + // + // cmpntNameLabel + // + this.cmpntNameLabel.AutoSize = true; + this.cmpntNameLabel.Location = new System.Drawing.Point(97, 12); + this.cmpntNameLabel.Name = "cmpntNameLabel"; + this.cmpntNameLabel.Size = new System.Drawing.Size(88, 13); + this.cmpntNameLabel.TabIndex = 0; + this.cmpntNameLabel.Text = "componentName"; + // + // splitContainer1 + // + this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill; + this.splitContainer1.FixedPanel = System.Windows.Forms.FixedPanel.Panel1; + this.splitContainer1.Location = new System.Drawing.Point(0, 0); + this.splitContainer1.Name = "splitContainer1"; + this.splitContainer1.Orientation = System.Windows.Forms.Orientation.Horizontal; + // + // splitContainer1.Panel1 + // + this.splitContainer1.Panel1.Controls.Add(this.testGroupBox); + this.splitContainer1.Panel1.Controls.Add(this.label1); + this.splitContainer1.Panel1.Controls.Add(this.cmpntNameLabel); + // + // splitContainer1.Panel2 + // + this.splitContainer1.Panel2.Controls.Add(this.listViewEx); + this.splitContainer1.Size = new System.Drawing.Size(420, 300); + this.splitContainer1.SplitterDistance = 80; + this.splitContainer1.TabIndex = 1; + // + // measuredLabel + // + this.measuredLabel.AutoSize = true; + this.measuredLabel.Location = new System.Drawing.Point(6, 20); + this.measuredLabel.Name = "measuredLabel"; + this.measuredLabel.Size = new System.Drawing.Size(54, 13); + this.measuredLabel.TabIndex = 2; + this.measuredLabel.Text = "Measured"; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(14, 12); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(64, 13); + this.label1.TabIndex = 1; + this.label1.Text = "Component:"; + // + // listViewEx + // + this.listViewEx.AllowColumnReorder = true; + this.listViewEx.Dock = System.Windows.Forms.DockStyle.Fill; + this.listViewEx.DoubleClickActivation = false; + this.listViewEx.FullRowSelect = true; + this.listViewEx.GridLines = true; + this.listViewEx.Location = new System.Drawing.Point(0, 0); + this.listViewEx.Name = "listViewEx"; + this.listViewEx.Size = new System.Drawing.Size(420, 216); + this.listViewEx.TabIndex = 0; + this.listViewEx.UseCompatibleStateImageBehavior = false; + this.listViewEx.View = System.Windows.Forms.View.Details; + this.listViewEx.SelectedIndexChanged += new System.EventHandler(this.listViewEx_SelectedIndexChanged); + // + // testGroupBox + // + this.testGroupBox.Controls.Add(this.correctedTextBox); + this.testGroupBox.Controls.Add(this.measuredTextBox); + this.testGroupBox.Controls.Add(this.correctedLabel); + this.testGroupBox.Controls.Add(this.measuredLabel); + this.testGroupBox.Location = new System.Drawing.Point(245, 7); + this.testGroupBox.Name = "testGroupBox"; + this.testGroupBox.Size = new System.Drawing.Size(157, 64); + this.testGroupBox.TabIndex = 3; + this.testGroupBox.TabStop = false; + this.testGroupBox.Text = "Test"; + // + // correctedLabel + // + this.correctedLabel.AutoSize = true; + this.correctedLabel.Location = new System.Drawing.Point(7, 41); + this.correctedLabel.Name = "correctedLabel"; + this.correctedLabel.Size = new System.Drawing.Size(53, 13); + this.correctedLabel.TabIndex = 3; + this.correctedLabel.Text = "Corrected"; + // + // measuredTextBox + // + this.measuredTextBox.Location = new System.Drawing.Point(74, 13); + this.measuredTextBox.Name = "measuredTextBox"; + this.measuredTextBox.Size = new System.Drawing.Size(73, 20); + this.measuredTextBox.TabIndex = 4; + this.measuredTextBox.TextChanged += new System.EventHandler(this.measuredTextBox_TextChanged); + // + // correctedTextBox + // + this.correctedTextBox.Location = new System.Drawing.Point(74, 38); + this.correctedTextBox.Name = "correctedTextBox"; + this.correctedTextBox.ReadOnly = true; + this.correctedTextBox.Size = new System.Drawing.Size(73, 20); + this.correctedTextBox.TabIndex = 5; + // + // MetrologyDlgBalanceTab + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.splitContainer1); + this.Name = "MetrologyDlgBalanceTab"; + this.Size = new System.Drawing.Size(420, 300); + this.Load += new System.EventHandler(this.MetrologyDlgBalanceTab_Load); + this.splitContainer1.Panel1.ResumeLayout(false); + this.splitContainer1.Panel1.PerformLayout(); + this.splitContainer1.Panel2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit(); + this.splitContainer1.ResumeLayout(false); + this.testGroupBox.ResumeLayout(false); + this.testGroupBox.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Label cmpntNameLabel; + private System.Windows.Forms.SplitContainer splitContainer1; + private System.Windows.Forms.Label label1; + private ListViewEx listViewEx; + private System.Windows.Forms.Label measuredLabel; + private System.Windows.Forms.GroupBox testGroupBox; + private System.Windows.Forms.TextBox correctedTextBox; + private System.Windows.Forms.TextBox measuredTextBox; + private System.Windows.Forms.Label correctedLabel; + } +} diff --git a/TestBenchFramework/UiControls/MetrologyDlgBalanceTab.cs b/TestBenchFramework/UiControls/MetrologyDlgBalanceTab.cs new file mode 100644 index 000000000..aaa052735 --- /dev/null +++ b/TestBenchFramework/UiControls/MetrologyDlgBalanceTab.cs @@ -0,0 +1,234 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Windows.Forms; +using log4net; +using TBF.Resources; + +namespace TBF.UiControls +{ + public partial class MetrologyDlgBalanceTab : UserControl, IMetrologyDlgTab + { + static readonly ILog log = LogManager.GetLogger(typeof(MetrologyDlgBalanceTab)); + + /// + /// Component entity that has a list of 'measurement-correction' pairs + /// to be updated in the database on OK. + /// + public Entities.Component MeterEntity + { + get { return meterEntity; } + set { meterEntity = value; } + } + Entities.Component meterEntity; + + /// + /// A list of 'measurement-correction' pairs to be deleted from the database on OK. + /// + public IList ToBeRemoved + { + get { return toBeRemoved; } + set { toBeRemoved = value; } + } + IList toBeRemoved; + + MetrologyDlg parent; + bool unlocked; + Control measurementTextBox; + Control correctionTextBox; + + public MetrologyDlgBalanceTab() + { + InitializeComponent(); + toBeRemoved = new List(); + unlocked = false; + } + + private void MetrologyDlgBalanceTab_Load(object sender, System.EventArgs e) + { + if (meterEntity == null) return; + + parent = ParentForm as MetrologyDlg; + + /// Panel1 + cmpntNameLabel.Text = meterEntity.Name; + + testGroupBox.Text = Strings.Test_measured_corrected; + measuredLabel.Text = Strings.Measured; + correctedLabel.Text = Strings.Corrected; + measuredTextBox.Text = string.Empty; + correctedTextBox.Text = string.Empty; + + /// Panel2 + measurementTextBox = new TextBox(); + correctionTextBox = new TextBox(); + this.Controls.Add(measurementTextBox); + this.Controls.Add(correctionTextBox); + + listViewEx.SubItemClicked += new SubItemEventHandler(listViewEx_SubItemClicked); + listViewEx.SubItemEndEditing += new SubItemEndEditingEventHandler(listViewEx_SubItemEndEditing); + + listViewEx.Columns.Add(new ColumnHeader() { Text = Strings.Nr, Width = 60 }); + listViewEx.Columns.Add(new ColumnHeader() { Text = Strings.Mass_kg, Width = 100 }); + listViewEx.Columns.Add(new ColumnHeader() { Text = Strings.Correction_g, Width = 100 }); + + RefreshAll(); + } + + void RefreshAll() + { + listViewEx.Items.Clear(); + foreach (var corr in MeterEntity.Corrections) AddOneLVI(corr); + } + + void AddOneLVI(Entities.MeasurementCorrection corr) + { + int nr = listViewEx.Items.Count + 1; + ListViewItem lvi = new ListViewItem(nr.ToString()); + lvi.SubItems.Add(corr.Measurement.ToString()); + lvi.SubItems.Add((corr.Correction * 1000.0f).ToString()); + lvi.Tag = corr; + listViewEx.Items.Add(lvi); + } + + void listViewEx_SubItemClicked(object sender, SubItemEventArgs e) + { + if (unlocked && e.SubItem == 1) + { + listViewEx.StartEditing(measurementTextBox, e.Item, e.SubItem); + } + else if (unlocked && e.SubItem == 2) + { + listViewEx.StartEditing(correctionTextBox, e.Item, e.SubItem); + } + } + + void listViewEx_SubItemEndEditing(object sender, SubItemEndEditingEventArgs e) + { + float value; + if (e.SubItem == 1 && Utils.TryParseEFloat(e.DisplayText, out value) && value >= 0) + { + (e.Item.Tag as Entities.MeasurementCorrection).Measurement = value; + return; + } + else if (e.SubItem == 2 && Utils.TryParseEFloat(e.DisplayText, out value)) + { + (e.Item.Tag as Entities.MeasurementCorrection).Correction = value / 1000.0f; + return; + } + + e.DisplayText = e.Item.Text; + e.Cancel = true; + } + + public void Unlock() + { + unlocked = true; + + if (listViewEx.SelectedItems.Count == 1) + { + int ix = listViewEx.SelectedIndices[0]; + listViewEx.Focus(); + listViewEx.Items[ix].Selected = true; + listViewEx.Items[ix].EnsureVisible(); + } + } + + public void OkBtnClicked() + { + } + + public void CancelBtnClicked() + { + } + + public void AddOne() + { + Entities.MeasurementCorrection corr = new Entities.MeasurementCorrection(); + MeterEntity.Corrections.Add(corr); + AddOneLVI(corr); + + listViewEx.Focus(); + listViewEx.SelectedItems.Clear(); + listViewEx.Items[listViewEx.Items.Count - 1].Selected = true; + listViewEx.Items[listViewEx.Items.Count - 1].EnsureVisible(); + } + + public void RemoveSelected() + { + if (listViewEx.SelectedItems.Count != 1) return; + + int removeItemNr = listViewEx.SelectedIndices[0]; + + Entities.MeasurementCorrection selected = + (Entities.MeasurementCorrection)listViewEx.SelectedItems[0].Tag; + if (selected.Id != 0) toBeRemoved.Add(selected); + MeterEntity.Corrections.RemoveAt(removeItemNr); + RefreshAll(); + + if (removeItemNr < listViewEx.Items.Count) + { + listViewEx.Focus(); + listViewEx.Items[removeItemNr].Selected = true; + listViewEx.Items[removeItemNr].EnsureVisible(); + } + else + { + parent.UpdateButtonStates(SharedButtons.SelectedItemPos.None); + } + } + + public void MoveUpSelected() + { + } + + public void MoveDownSelected() + { + } + + /// + /// Event handler that indicates the selected item position + /// and updates 'Remove', 'Up' and 'Down' buttons in the parent dialog. + /// + private void listViewEx_SelectedIndexChanged(object sender, EventArgs e) + { + if (listViewEx.SelectedItems.Count != 1) + { + parent.UpdateButtonStates(SharedButtons.SelectedItemPos.None); + } + else if (listViewEx.Items.Count == 1) + { + parent.UpdateButtonStates(SharedButtons.SelectedItemPos.FirstAndLast); + } + else if (listViewEx.SelectedIndices[0] == 0) + { + parent.UpdateButtonStates(SharedButtons.SelectedItemPos.First); + } + else if (listViewEx.SelectedIndices[0] == (listViewEx.Items.Count - 1)) + { + parent.UpdateButtonStates(SharedButtons.SelectedItemPos.Last); + } + else + { + parent.UpdateButtonStates(SharedButtons.SelectedItemPos.Middle); + } + } + + private void measuredTextBox_TextChanged(object sender, EventArgs e) + { + float measured; + if (float.TryParse(measuredTextBox.Text, + NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign | NumberStyles.AllowExponent, + CultureInfo.CurrentCulture, + out measured) || + float.TryParse(measuredTextBox.Text, + NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign | NumberStyles.AllowExponent, + CultureInfo.InvariantCulture, + out measured)) + { + float corrected = BenchControl.Formulas.CorrectedValue(measured, meterEntity.Corrections); + correctedTextBox.Text = corrected.ToString(); + } + } + } +} diff --git a/TestBenchFramework/UiControls/MetrologyDlgBalanceTab.resx b/TestBenchFramework/UiControls/MetrologyDlgBalanceTab.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/TestBenchFramework/UiControls/MetrologyDlgBalanceTab.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/UiControls/MetrologyDlgFlowMeterTab.Designer.cs b/TestBenchFramework/UiControls/MetrologyDlgFlowMeterTab.Designer.cs new file mode 100644 index 000000000..8c0881a68 --- /dev/null +++ b/TestBenchFramework/UiControls/MetrologyDlgFlowMeterTab.Designer.cs @@ -0,0 +1,180 @@ +namespace TBF.UiControls +{ + partial class MetrologyDlgFlowMeterTab + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.splitContainer1 = new System.Windows.Forms.SplitContainer(); + this.label1 = new System.Windows.Forms.Label(); + this.cmpntNameLabel = new System.Windows.Forms.Label(); + this.listViewEx = new TBF.UiControls.ListViewEx(); + this.correctedTextBox = new System.Windows.Forms.TextBox(); + this.testGroupBox = new System.Windows.Forms.GroupBox(); + this.measuredTextBox = new System.Windows.Forms.TextBox(); + this.correctedLabel = new System.Windows.Forms.Label(); + this.measuredLabel = new System.Windows.Forms.Label(); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit(); + this.splitContainer1.Panel1.SuspendLayout(); + this.splitContainer1.Panel2.SuspendLayout(); + this.splitContainer1.SuspendLayout(); + this.testGroupBox.SuspendLayout(); + this.SuspendLayout(); + // + // splitContainer1 + // + this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill; + this.splitContainer1.FixedPanel = System.Windows.Forms.FixedPanel.Panel1; + this.splitContainer1.Location = new System.Drawing.Point(0, 0); + this.splitContainer1.Name = "splitContainer1"; + this.splitContainer1.Orientation = System.Windows.Forms.Orientation.Horizontal; + // + // splitContainer1.Panel1 + // + this.splitContainer1.Panel1.Controls.Add(this.testGroupBox); + this.splitContainer1.Panel1.Controls.Add(this.label1); + this.splitContainer1.Panel1.Controls.Add(this.cmpntNameLabel); + // + // splitContainer1.Panel2 + // + this.splitContainer1.Panel2.Controls.Add(this.listViewEx); + this.splitContainer1.Size = new System.Drawing.Size(420, 300); + this.splitContainer1.SplitterDistance = 80; + this.splitContainer1.TabIndex = 2; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(14, 12); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(64, 13); + this.label1.TabIndex = 1; + this.label1.Text = "Component:"; + // + // cmpntNameLabel + // + this.cmpntNameLabel.AutoSize = true; + this.cmpntNameLabel.Location = new System.Drawing.Point(97, 12); + this.cmpntNameLabel.Name = "cmpntNameLabel"; + this.cmpntNameLabel.Size = new System.Drawing.Size(88, 13); + this.cmpntNameLabel.TabIndex = 0; + this.cmpntNameLabel.Text = "componentName"; + // + // listViewEx + // + this.listViewEx.AllowColumnReorder = true; + this.listViewEx.Dock = System.Windows.Forms.DockStyle.Fill; + this.listViewEx.DoubleClickActivation = false; + this.listViewEx.FullRowSelect = true; + this.listViewEx.GridLines = true; + this.listViewEx.Location = new System.Drawing.Point(0, 0); + this.listViewEx.Name = "listViewEx"; + this.listViewEx.Size = new System.Drawing.Size(420, 216); + this.listViewEx.TabIndex = 0; + this.listViewEx.UseCompatibleStateImageBehavior = false; + this.listViewEx.View = System.Windows.Forms.View.Details; + this.listViewEx.SelectedIndexChanged += new System.EventHandler(this.listViewEx_SelectedIndexChanged); + // + // correctedTextBox + // + this.correctedTextBox.Location = new System.Drawing.Point(74, 38); + this.correctedTextBox.Name = "correctedTextBox"; + this.correctedTextBox.ReadOnly = true; + this.correctedTextBox.Size = new System.Drawing.Size(73, 20); + this.correctedTextBox.TabIndex = 5; + // + // testGroupBox + // + this.testGroupBox.Controls.Add(this.correctedTextBox); + this.testGroupBox.Controls.Add(this.measuredTextBox); + this.testGroupBox.Controls.Add(this.correctedLabel); + this.testGroupBox.Controls.Add(this.measuredLabel); + this.testGroupBox.Location = new System.Drawing.Point(245, 7); + this.testGroupBox.Name = "testGroupBox"; + this.testGroupBox.Size = new System.Drawing.Size(157, 64); + this.testGroupBox.TabIndex = 4; + this.testGroupBox.TabStop = false; + this.testGroupBox.Text = "Test"; + // + // measuredTextBox + // + this.measuredTextBox.Location = new System.Drawing.Point(74, 13); + this.measuredTextBox.Name = "measuredTextBox"; + this.measuredTextBox.Size = new System.Drawing.Size(73, 20); + this.measuredTextBox.TabIndex = 4; + this.measuredTextBox.TextChanged += new System.EventHandler(this.measuredTextBox_TextChanged); + // + // correctedLabel + // + this.correctedLabel.AutoSize = true; + this.correctedLabel.Location = new System.Drawing.Point(7, 41); + this.correctedLabel.Name = "correctedLabel"; + this.correctedLabel.Size = new System.Drawing.Size(53, 13); + this.correctedLabel.TabIndex = 3; + this.correctedLabel.Text = "Corrected"; + // + // measuredLabel + // + this.measuredLabel.AutoSize = true; + this.measuredLabel.Location = new System.Drawing.Point(6, 20); + this.measuredLabel.Name = "measuredLabel"; + this.measuredLabel.Size = new System.Drawing.Size(54, 13); + this.measuredLabel.TabIndex = 2; + this.measuredLabel.Text = "Measured"; + // + // MetrologyDlgFlowMeterTab + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.splitContainer1); + this.Name = "MetrologyDlgFlowMeterTab"; + this.Size = new System.Drawing.Size(420, 300); + this.Load += new System.EventHandler(this.MetrologyDlgFlowMeterTab_Load); + this.splitContainer1.Panel1.ResumeLayout(false); + this.splitContainer1.Panel1.PerformLayout(); + this.splitContainer1.Panel2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit(); + this.splitContainer1.ResumeLayout(false); + this.testGroupBox.ResumeLayout(false); + this.testGroupBox.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.SplitContainer splitContainer1; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label cmpntNameLabel; + private ListViewEx listViewEx; + private System.Windows.Forms.GroupBox testGroupBox; + private System.Windows.Forms.TextBox correctedTextBox; + private System.Windows.Forms.TextBox measuredTextBox; + private System.Windows.Forms.Label correctedLabel; + private System.Windows.Forms.Label measuredLabel; + + } +} diff --git a/TestBenchFramework/UiControls/MetrologyDlgFlowMeterTab.cs b/TestBenchFramework/UiControls/MetrologyDlgFlowMeterTab.cs new file mode 100644 index 000000000..4ad75a05a --- /dev/null +++ b/TestBenchFramework/UiControls/MetrologyDlgFlowMeterTab.cs @@ -0,0 +1,233 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Windows.Forms; +using log4net; +using TBF.Resources; + +namespace TBF.UiControls +{ + public partial class MetrologyDlgFlowMeterTab : UserControl, IMetrologyDlgTab + { + static readonly ILog log = LogManager.GetLogger(typeof(MetrologyDlgFlowMeterTab)); + + /// + /// Component entity that has a list of 'measurement-correction' pairs + /// to be updated in the database on OK. + /// + Entities.Component meterEntity; + public Entities.Component MeterEntity + { + get { return meterEntity; } + set { meterEntity = value; } + } + + /// + /// A list of 'measurement-correction' pairs to be deleted from the database on OK. + /// + public IList ToBeRemoved + { + get { return toBeRemoved; } + set { toBeRemoved = value; } + } + IList toBeRemoved; + + MetrologyDlg parent; + bool unlocked; + Control measurementTextBox; + Control correctionTextBox; + + public MetrologyDlgFlowMeterTab() + { + InitializeComponent(); + toBeRemoved = new List(); + } + + private void MetrologyDlgFlowMeterTab_Load(object sender, System.EventArgs e) + { + if (meterEntity == null) return; + + parent = ParentForm as MetrologyDlg; + + /// Panel1 + cmpntNameLabel.Text = meterEntity.Name; + + testGroupBox.Text = Strings.Test_measured_corrected; + measuredLabel.Text = Strings.Measured; + correctedLabel.Text = Strings.Corrected; + measuredTextBox.Text = string.Empty; + correctedTextBox.Text = string.Empty; + + /// Panel2 + measurementTextBox = new TextBox(); + correctionTextBox = new TextBox(); + this.Controls.Add(measurementTextBox); + this.Controls.Add(correctionTextBox); + + listViewEx.SubItemClicked += new SubItemEventHandler(listViewEx_SubItemClicked); + listViewEx.SubItemEndEditing += new SubItemEndEditingEventHandler(listViewEx_SubItemEndEditing); + + listViewEx.Columns.Add(new ColumnHeader() { Text = Strings.Nr, Width = 60 }); + listViewEx.Columns.Add(new ColumnHeader() { Text = Strings.Flow_m3h, Width = 100 }); + listViewEx.Columns.Add(new ColumnHeader() { Text = Strings.Correction_lph, Width = 100 }); + + RefreshAll(); + } + + void RefreshAll() + { + listViewEx.Items.Clear(); + foreach (var corr in MeterEntity.Corrections) AddOneLVI(corr); + } + + void AddOneLVI(Entities.MeasurementCorrection corr) + { + int nr = listViewEx.Items.Count + 1; + ListViewItem lvi = new ListViewItem(nr.ToString()); + lvi.SubItems.Add(corr.Measurement.ToString()); + lvi.SubItems.Add((corr.Correction * 1000.0f).ToString()); + lvi.Tag = corr; + listViewEx.Items.Add(lvi); + } + + void listViewEx_SubItemClicked(object sender, SubItemEventArgs e) + { + if (unlocked && e.SubItem == 1) + { + listViewEx.StartEditing(measurementTextBox, e.Item, e.SubItem); + } + else if (unlocked && e.SubItem == 2) + { + listViewEx.StartEditing(correctionTextBox, e.Item, e.SubItem); + } + } + + void listViewEx_SubItemEndEditing(object sender, SubItemEndEditingEventArgs e) + { + float value; + if (e.SubItem == 1 && Utils.TryParseEFloat(e.DisplayText, out value) && value >= 0) + { + (e.Item.Tag as Entities.MeasurementCorrection).Measurement = value; + return; + } + else if (e.SubItem == 2 && Utils.TryParseEFloat(e.DisplayText, out value)) + { + (e.Item.Tag as Entities.MeasurementCorrection).Correction = value / 1000.0f; + return; + } + + e.DisplayText = e.Item.Text; + e.Cancel = true; + } + + public void Unlock() + { + unlocked = true; + + if (listViewEx.SelectedItems.Count == 1) + { + int ix = listViewEx.SelectedIndices[0]; + listViewEx.Focus(); + listViewEx.Items[ix].Selected = true; + listViewEx.Items[ix].EnsureVisible(); + } + } + + public void OkBtnClicked() + { + } + + public void CancelBtnClicked() + { + } + + public void AddOne() + { + Entities.MeasurementCorrection corr = new Entities.MeasurementCorrection(); + MeterEntity.Corrections.Add(corr); + AddOneLVI(corr); + + listViewEx.Focus(); + listViewEx.SelectedItems.Clear(); + listViewEx.Items[listViewEx.Items.Count - 1].Selected = true; + listViewEx.Items[listViewEx.Items.Count - 1].EnsureVisible(); + } + + public void RemoveSelected() + { + if (listViewEx.SelectedItems.Count != 1) return; + + int removeItemNr = listViewEx.SelectedIndices[0]; + + Entities.MeasurementCorrection selected = + (Entities.MeasurementCorrection)listViewEx.SelectedItems[0].Tag; + if (selected.Id != 0) toBeRemoved.Add(selected); + MeterEntity.Corrections.RemoveAt(removeItemNr); + RefreshAll(); + + if (removeItemNr < listViewEx.Items.Count) + { + listViewEx.Focus(); + listViewEx.Items[removeItemNr].Selected = true; + listViewEx.Items[removeItemNr].EnsureVisible(); + } + else + { + parent.UpdateButtonStates(SharedButtons.SelectedItemPos.None); + } + } + + public void MoveUpSelected() + { + } + + public void MoveDownSelected() + { + } + + /// + /// Event handler that indicates the selected item position + /// and updates 'Remove', 'Up' and 'Down' buttons in the parent dialog. + /// + private void listViewEx_SelectedIndexChanged(object sender, EventArgs e) + { + if (listViewEx.SelectedItems.Count != 1) + { + parent.UpdateButtonStates(SharedButtons.SelectedItemPos.None); + } + else if (listViewEx.Items.Count == 1) + { + parent.UpdateButtonStates(SharedButtons.SelectedItemPos.FirstAndLast); + } + else if (listViewEx.SelectedIndices[0] == 0) + { + parent.UpdateButtonStates(SharedButtons.SelectedItemPos.First); + } + else if (listViewEx.SelectedIndices[0] == (listViewEx.Items.Count - 1)) + { + parent.UpdateButtonStates(SharedButtons.SelectedItemPos.Last); + } + else + { + parent.UpdateButtonStates(SharedButtons.SelectedItemPos.Middle); + } + } + + private void measuredTextBox_TextChanged(object sender, EventArgs e) + { + float measured; + if (float.TryParse(measuredTextBox.Text, + NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign | NumberStyles.AllowExponent, + CultureInfo.CurrentCulture, + out measured) || + float.TryParse(measuredTextBox.Text, + NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign | NumberStyles.AllowExponent, + CultureInfo.InvariantCulture, + out measured)) + { + float corrected = BenchControl.Formulas.CorrectedValue(measured, meterEntity.Corrections); + correctedTextBox.Text = corrected.ToString(); + } + } + } +} diff --git a/TestBenchFramework/UiControls/MetrologyDlgFlowMeterTab.resx b/TestBenchFramework/UiControls/MetrologyDlgFlowMeterTab.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/TestBenchFramework/UiControls/MetrologyDlgFlowMeterTab.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/UiControls/MetrologyDlgPressMeterTab.Designer.cs b/TestBenchFramework/UiControls/MetrologyDlgPressMeterTab.Designer.cs new file mode 100644 index 000000000..90fe9a750 --- /dev/null +++ b/TestBenchFramework/UiControls/MetrologyDlgPressMeterTab.Designer.cs @@ -0,0 +1,180 @@ +namespace TBF.UiControls +{ + partial class MetrologyDlgPressMeterTab + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.splitContainer1 = new System.Windows.Forms.SplitContainer(); + this.label1 = new System.Windows.Forms.Label(); + this.cmpntNameLabel = new System.Windows.Forms.Label(); + this.listViewEx = new TBF.UiControls.ListViewEx(); + this.correctedTextBox = new System.Windows.Forms.TextBox(); + this.testGroupBox = new System.Windows.Forms.GroupBox(); + this.measuredTextBox = new System.Windows.Forms.TextBox(); + this.correctedLabel = new System.Windows.Forms.Label(); + this.measuredLabel = new System.Windows.Forms.Label(); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit(); + this.splitContainer1.Panel1.SuspendLayout(); + this.splitContainer1.Panel2.SuspendLayout(); + this.splitContainer1.SuspendLayout(); + this.testGroupBox.SuspendLayout(); + this.SuspendLayout(); + // + // splitContainer1 + // + this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill; + this.splitContainer1.FixedPanel = System.Windows.Forms.FixedPanel.Panel1; + this.splitContainer1.Location = new System.Drawing.Point(0, 0); + this.splitContainer1.Name = "splitContainer1"; + this.splitContainer1.Orientation = System.Windows.Forms.Orientation.Horizontal; + // + // splitContainer1.Panel1 + // + this.splitContainer1.Panel1.Controls.Add(this.testGroupBox); + this.splitContainer1.Panel1.Controls.Add(this.label1); + this.splitContainer1.Panel1.Controls.Add(this.cmpntNameLabel); + // + // splitContainer1.Panel2 + // + this.splitContainer1.Panel2.Controls.Add(this.listViewEx); + this.splitContainer1.Size = new System.Drawing.Size(420, 300); + this.splitContainer1.SplitterDistance = 80; + this.splitContainer1.TabIndex = 2; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(14, 12); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(64, 13); + this.label1.TabIndex = 1; + this.label1.Text = "Component:"; + // + // cmpntNameLabel + // + this.cmpntNameLabel.AutoSize = true; + this.cmpntNameLabel.Location = new System.Drawing.Point(97, 12); + this.cmpntNameLabel.Name = "cmpntNameLabel"; + this.cmpntNameLabel.Size = new System.Drawing.Size(88, 13); + this.cmpntNameLabel.TabIndex = 0; + this.cmpntNameLabel.Text = "componentName"; + // + // listViewEx + // + this.listViewEx.AllowColumnReorder = true; + this.listViewEx.Dock = System.Windows.Forms.DockStyle.Fill; + this.listViewEx.DoubleClickActivation = false; + this.listViewEx.FullRowSelect = true; + this.listViewEx.GridLines = true; + this.listViewEx.Location = new System.Drawing.Point(0, 0); + this.listViewEx.Name = "listViewEx"; + this.listViewEx.Size = new System.Drawing.Size(420, 216); + this.listViewEx.TabIndex = 0; + this.listViewEx.UseCompatibleStateImageBehavior = false; + this.listViewEx.View = System.Windows.Forms.View.Details; + this.listViewEx.SelectedIndexChanged += new System.EventHandler(this.listViewEx_SelectedIndexChanged); + // + // correctedTextBox + // + this.correctedTextBox.Location = new System.Drawing.Point(74, 38); + this.correctedTextBox.Name = "correctedTextBox"; + this.correctedTextBox.ReadOnly = true; + this.correctedTextBox.Size = new System.Drawing.Size(73, 20); + this.correctedTextBox.TabIndex = 5; + // + // testGroupBox + // + this.testGroupBox.Controls.Add(this.correctedTextBox); + this.testGroupBox.Controls.Add(this.measuredTextBox); + this.testGroupBox.Controls.Add(this.correctedLabel); + this.testGroupBox.Controls.Add(this.measuredLabel); + this.testGroupBox.Location = new System.Drawing.Point(245, 7); + this.testGroupBox.Name = "testGroupBox"; + this.testGroupBox.Size = new System.Drawing.Size(157, 64); + this.testGroupBox.TabIndex = 4; + this.testGroupBox.TabStop = false; + this.testGroupBox.Text = "Test"; + // + // measuredTextBox + // + this.measuredTextBox.Location = new System.Drawing.Point(74, 13); + this.measuredTextBox.Name = "measuredTextBox"; + this.measuredTextBox.Size = new System.Drawing.Size(73, 20); + this.measuredTextBox.TabIndex = 4; + this.measuredTextBox.TextChanged += new System.EventHandler(this.measuredTextBox_TextChanged); + // + // correctedLabel + // + this.correctedLabel.AutoSize = true; + this.correctedLabel.Location = new System.Drawing.Point(7, 41); + this.correctedLabel.Name = "correctedLabel"; + this.correctedLabel.Size = new System.Drawing.Size(53, 13); + this.correctedLabel.TabIndex = 3; + this.correctedLabel.Text = "Corrected"; + // + // measuredLabel + // + this.measuredLabel.AutoSize = true; + this.measuredLabel.Location = new System.Drawing.Point(6, 20); + this.measuredLabel.Name = "measuredLabel"; + this.measuredLabel.Size = new System.Drawing.Size(54, 13); + this.measuredLabel.TabIndex = 2; + this.measuredLabel.Text = "Measured"; + // + // MetrologyDlgPressMeterTab + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.splitContainer1); + this.Name = "MetrologyDlgPressMeterTab"; + this.Size = new System.Drawing.Size(420, 300); + this.Load += new System.EventHandler(this.MetrologyDlgPressMeterTab_Load); + this.splitContainer1.Panel1.ResumeLayout(false); + this.splitContainer1.Panel1.PerformLayout(); + this.splitContainer1.Panel2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit(); + this.splitContainer1.ResumeLayout(false); + this.testGroupBox.ResumeLayout(false); + this.testGroupBox.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.SplitContainer splitContainer1; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label cmpntNameLabel; + private ListViewEx listViewEx; + private System.Windows.Forms.GroupBox testGroupBox; + private System.Windows.Forms.TextBox correctedTextBox; + private System.Windows.Forms.TextBox measuredTextBox; + private System.Windows.Forms.Label correctedLabel; + private System.Windows.Forms.Label measuredLabel; + + } +} diff --git a/TestBenchFramework/UiControls/MetrologyDlgPressMeterTab.cs b/TestBenchFramework/UiControls/MetrologyDlgPressMeterTab.cs new file mode 100644 index 000000000..2410a4921 --- /dev/null +++ b/TestBenchFramework/UiControls/MetrologyDlgPressMeterTab.cs @@ -0,0 +1,233 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Windows.Forms; +using log4net; +using TBF.Resources; + +namespace TBF.UiControls +{ + public partial class MetrologyDlgPressMeterTab : UserControl, IMetrologyDlgTab + { + static readonly ILog log = LogManager.GetLogger(typeof(MetrologyDlgPressMeterTab)); + + /// + /// Component entity that has a list of 'measurement-correction' pairs + /// to be updated in the database on OK. + /// + Entities.Component meterEntity; + public Entities.Component MeterEntity + { + get { return meterEntity; } + set { meterEntity = value; } + } + + /// + /// A list of 'measurement-correction' pairs to be deleted from the database on OK. + /// + public IList ToBeRemoved + { + get { return toBeRemoved; } + set { toBeRemoved = value; } + } + IList toBeRemoved; + + MetrologyDlg parent; + bool unlocked; + Control measurementTextBox; + Control correctionTextBox; + + public MetrologyDlgPressMeterTab() + { + InitializeComponent(); + toBeRemoved = new List(); + } + + private void MetrologyDlgPressMeterTab_Load(object sender, System.EventArgs e) + { + if (meterEntity == null) return; + + parent = ParentForm as MetrologyDlg; + + /// Panel1 + cmpntNameLabel.Text = meterEntity.Name; + + testGroupBox.Text = Strings.Test_measured_corrected; + measuredLabel.Text = Strings.Measured; + correctedLabel.Text = Strings.Corrected; + measuredTextBox.Text = string.Empty; + correctedTextBox.Text = string.Empty; + + /// Panel2 + measurementTextBox = new TextBox(); + correctionTextBox = new TextBox(); + this.Controls.Add(measurementTextBox); + this.Controls.Add(correctionTextBox); + + listViewEx.SubItemClicked += new SubItemEventHandler(listViewEx_SubItemClicked); + listViewEx.SubItemEndEditing += new SubItemEndEditingEventHandler(listViewEx_SubItemEndEditing); + + listViewEx.Columns.Add(new ColumnHeader() { Text = Strings.Nr, Width = 60 }); + listViewEx.Columns.Add(new ColumnHeader() { Text = Strings.Pressure_bar, Width = 100 }); + listViewEx.Columns.Add(new ColumnHeader() { Text = Strings.Correction_mbar, Width = 100 }); + + RefreshAll(); + } + + void RefreshAll() + { + listViewEx.Items.Clear(); + foreach (var corr in MeterEntity.Corrections) AddOneLVI(corr); + } + + void AddOneLVI(Entities.MeasurementCorrection corr) + { + int nr = listViewEx.Items.Count + 1; + ListViewItem lvi = new ListViewItem(nr.ToString()); + lvi.SubItems.Add(corr.Measurement.ToString()); + lvi.SubItems.Add((corr.Correction * 1000.0f).ToString()); + lvi.Tag = corr; + listViewEx.Items.Add(lvi); + } + + void listViewEx_SubItemClicked(object sender, SubItemEventArgs e) + { + if (unlocked && e.SubItem == 1) + { + listViewEx.StartEditing(measurementTextBox, e.Item, e.SubItem); + } + else if (unlocked && e.SubItem == 2) + { + listViewEx.StartEditing(correctionTextBox, e.Item, e.SubItem); + } + } + + void listViewEx_SubItemEndEditing(object sender, SubItemEndEditingEventArgs e) + { + float value; + if (e.SubItem == 1 && Utils.TryParseEFloat(e.DisplayText, out value) && value >= 0) + { + (e.Item.Tag as Entities.MeasurementCorrection).Measurement = value; + return; + } + else if (e.SubItem == 2 && Utils.TryParseEFloat(e.DisplayText, out value)) + { + (e.Item.Tag as Entities.MeasurementCorrection).Correction = value / 1000.0f; + return; + } + + e.DisplayText = e.Item.Text; + e.Cancel = true; + } + + public void Unlock() + { + unlocked = true; + + if (listViewEx.SelectedItems.Count == 1) + { + int ix = listViewEx.SelectedIndices[0]; + listViewEx.Focus(); + listViewEx.Items[ix].Selected = true; + listViewEx.Items[ix].EnsureVisible(); + } + } + + public void OkBtnClicked() + { + } + + public void CancelBtnClicked() + { + } + + public void AddOne() + { + Entities.MeasurementCorrection corr = new Entities.MeasurementCorrection(); + MeterEntity.Corrections.Add(corr); + AddOneLVI(corr); + + listViewEx.Focus(); + listViewEx.SelectedItems.Clear(); + listViewEx.Items[listViewEx.Items.Count - 1].Selected = true; + listViewEx.Items[listViewEx.Items.Count - 1].EnsureVisible(); + } + + public void RemoveSelected() + { + if (listViewEx.SelectedItems.Count != 1) return; + + int removeItemNr = listViewEx.SelectedIndices[0]; + + Entities.MeasurementCorrection selected = + (Entities.MeasurementCorrection)listViewEx.SelectedItems[0].Tag; + if (selected.Id != 0) toBeRemoved.Add(selected); + MeterEntity.Corrections.RemoveAt(removeItemNr); + RefreshAll(); + + if (removeItemNr < listViewEx.Items.Count) + { + listViewEx.Focus(); + listViewEx.Items[removeItemNr].Selected = true; + listViewEx.Items[removeItemNr].EnsureVisible(); + } + else + { + parent.UpdateButtonStates(SharedButtons.SelectedItemPos.None); + } + } + + public void MoveUpSelected() + { + } + + public void MoveDownSelected() + { + } + + /// + /// Event handler that indicates the selected item position + /// and updates 'Remove', 'Up' and 'Down' buttons in the parent dialog. + /// + private void listViewEx_SelectedIndexChanged(object sender, EventArgs e) + { + if (listViewEx.SelectedItems.Count != 1) + { + parent.UpdateButtonStates(SharedButtons.SelectedItemPos.None); + } + else if (listViewEx.Items.Count == 1) + { + parent.UpdateButtonStates(SharedButtons.SelectedItemPos.FirstAndLast); + } + else if (listViewEx.SelectedIndices[0] == 0) + { + parent.UpdateButtonStates(SharedButtons.SelectedItemPos.First); + } + else if (listViewEx.SelectedIndices[0] == (listViewEx.Items.Count - 1)) + { + parent.UpdateButtonStates(SharedButtons.SelectedItemPos.Last); + } + else + { + parent.UpdateButtonStates(SharedButtons.SelectedItemPos.Middle); + } + } + + private void measuredTextBox_TextChanged(object sender, EventArgs e) + { + float measured; + if (float.TryParse(measuredTextBox.Text, + NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign | NumberStyles.AllowExponent, + CultureInfo.CurrentCulture, + out measured) || + float.TryParse(measuredTextBox.Text, + NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign | NumberStyles.AllowExponent, + CultureInfo.InvariantCulture, + out measured)) + { + float corrected = BenchControl.Formulas.CorrectedValue(measured, meterEntity.Corrections); + correctedTextBox.Text = corrected.ToString(); + } + } + } +} diff --git a/TestBenchFramework/UiControls/MetrologyDlgPressMeterTab.resx b/TestBenchFramework/UiControls/MetrologyDlgPressMeterTab.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/TestBenchFramework/UiControls/MetrologyDlgPressMeterTab.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/UiControls/PathsBenchCtrl.cs b/TestBenchFramework/UiControls/PathsBenchCtrl.cs new file mode 100644 index 000000000..9835f65f5 --- /dev/null +++ b/TestBenchFramework/UiControls/PathsBenchCtrl.cs @@ -0,0 +1,247 @@ +using System.Collections.Generic; +using System.Globalization; +using System.Windows.Forms; +using log4net; +using TBF.BenchControl; +using TBF.BenchControl.GenericDevices; +using TBF.Resources; + +namespace TBF.UiControls +{ + public class PathsBenchCtrl : BaseWithListViewEx, ITabWithListViewEx + { + static readonly ILog log = LogManager.GetLogger(typeof(PathsBenchCtrl)); + + /// + /// Fixed ListViewEx columns + /// + enum Column + { + Name, + Qfrom, + Qto, + Tin, + Tout, + Pin, + Pout, + FixedColumnsCount, + } + readonly int fixedColumnsCount = (int)Column.FixedColumnsCount; + + PathsDlg parent; + Control parentControl; + Control[] editors; + + public PathsBenchCtrl() + : base() + { + FixedRowsCount = 1; + } + + public void Initialize(PathsDlg parent, Control parentControl) + { + this.parent = parent; + this.parentControl = parentControl; + + /// Load the paths + MyItems = parent.Session + .CreateQuery("FROM BenchPath ORDER BY ItemNr") + .List(); + + SubItemClicked += new SubItemEventHandler(listViewEx_SubItemClicked); + SubItemEndEditing += new SubItemEndEditingEventHandler(listViewEx_SubItemEndEditing); + + /// ListViewEx columns + Columns.Add(Strings.Name, 60 * parent.Dpi / PathsDlg.Dpi100pct); + Columns.Add(Strings.Q_from_m3h, 50 * parent.Dpi / PathsDlg.Dpi100pct); + Columns.Add(Strings.Q_to_m3h, 50 * parent.Dpi / PathsDlg.Dpi100pct); + Columns.Add(Strings.T_in, 50 * parent.Dpi / PathsDlg.Dpi100pct); + Columns.Add(Strings.T_out, 50 * parent.Dpi / PathsDlg.Dpi100pct); + Columns.Add(Strings.P_in, 50 * parent.Dpi / PathsDlg.Dpi100pct); + Columns.Add(Strings.P_out, 50 * parent.Dpi / PathsDlg.Dpi100pct); + foreach (var vlv in parent.Valves) Columns.Add(vlv.Cfg.Name, 50 * parent.Dpi / PathsDlg.Dpi100pct); + + /// Temperatures, pressures + ComboBox tInCBox = new ComboBox(); + ComboBox tOutCBox = new ComboBox(); + ComboBox prInCBox = new ComboBox(); + ComboBox prOutCBox = new ComboBox(); + foreach (var cmpnt in parent.TbfComponents) + { + if (cmpnt is BenchControl.GenericDevices.ITempMeter) + { + tInCBox.Items.Add(cmpnt.Cfg.Name); + tOutCBox.Items.Add(cmpnt.Cfg.Name); + } + if (cmpnt is BenchControl.GenericDevices.IPressureMeter) + { + prInCBox.Items.Add(cmpnt.Cfg.Name); + prOutCBox.Items.Add(cmpnt.Cfg.Name); + } + } + + editors = new Control[fixedColumnsCount + 64]; + /// + editors[(int)Column.Name] = new TextBox(); /// Name + editors[(int)Column.Qfrom] = new TextBox(); /// Q_from + editors[(int)Column.Qto] = new TextBox(); /// Q_to + editors[(int)Column.Tin] = tInCBox; + editors[(int)Column.Tout] = tOutCBox; + editors[(int)Column.Pin] = prInCBox; + editors[(int)Column.Pout] = prOutCBox; + /// Prepare valve combo-boxes (max. 64 valves) + for (int i = 0; i < 64; i++) + { + ComboBox cb = new ComboBox(); + cb.Items.Add("---"); + cb.Items.Add(Strings.open); + cb.Items.Add(Strings.close); + editors[fixedColumnsCount + i] = cb; + } + /// + for (int i = 0; i < editors.Length; i++) parent.Controls.Add(editors[i]); + + base.RedrawAll(); + } + + void listViewEx_SubItemClicked(object sender, SubItemEventArgs e) + { + if (!Unlocked || e.SubItem >= editors.Length) return; + if ((e.Item.Tag is Entities.IHasItemNr) && + ((e.Item.Tag as Entities.IHasItemNr).ItemNr < FixedRowsCount) && + (e.SubItem < fixedColumnsCount)) + { + return; + } + StartEditing(editors[e.SubItem], e.Item, e.SubItem); + } + + void listViewEx_SubItemEndEditing(object sender, SubItemEndEditingEventArgs e) + { + } + + public override void DrawOne(object myItem) + { + Entities.BenchPath entity =(Entities.BenchPath)myItem; + BenchControl.BenchPath path = new BenchControl.BenchPath(entity, parent.TbfComponents); + + ListViewItem lvi = new ListViewItem(entity.Name); + lvi.SubItems.Add(path.Qfrom.ToString()); + lvi.SubItems.Add(path.Qto.ToString()); + lvi.SubItems.Add(path.TempIn != null ? path.TempIn.Cfg.Name : "---"); + lvi.SubItems.Add(path.TempOut != null ? path.TempOut.Cfg.Name : "---"); + lvi.SubItems.Add(path.PressIn != null ? path.PressIn.Cfg.Name : "---"); + lvi.SubItems.Add(path.PressOut != null ? path.PressOut.Cfg.Name : "---"); + + foreach (var valve in parent.Valves) + { + if (path.ValvesOpen != null && path.ValvesOpen.Contains(valve)) + { + lvi.SubItems.Add(Strings.open); + } + else if (path.ValvesClose != null && path.ValvesClose.Contains(valve)) + { + lvi.SubItems.Add(Strings.close); + } + else + { + lvi.SubItems.Add("---"); + } + } + + lvi.Tag = entity; + + Items.Add(lvi); + } + + public override void UpdateOne(ListViewItem lvi, object myItem) + { + Entities.BenchPath entity = (Entities.BenchPath)myItem; + + entity.Name = lvi.Text; + + float Qfrom; + bool allOk = Utils.TryParseUFloat(lvi.SubItems[(int)Column.Qfrom].Text, out Qfrom); + entity.Qfrom = Qfrom; + + float Qto; + allOk &= Utils.TryParseUFloat(lvi.SubItems[(int)Column.Qto].Text, out Qto); + entity.Qto = Qto; + + entity.TempIn = lvi.SubItems[(int)Column.Tin].Text; + entity.TempOut = lvi.SubItems[(int)Column.Tout].Text; + entity.PressIn = lvi.SubItems[(int)Column.Pin].Text; + entity.PressOut = lvi.SubItems[(int)Column.Pout].Text; + + string valvesOpen = string.Empty; + string valvesClose = string.Empty; + for (int j = 0; j < parent.Valves.Count; j++) + { + string text = lvi.SubItems[fixedColumnsCount + j].Text; + if (text.Equals(Strings.open)) + { + if (valvesOpen != string.Empty) valvesOpen += ";"; + valvesOpen += parent.Valves[j].Cfg.Name; + } + if (text.Equals(Strings.close)) + { + if (valvesClose != string.Empty) valvesClose += ";"; + valvesClose += parent.Valves[j].Cfg.Name; + } + } + entity.ValvesOpen = valvesOpen; + entity.ValvesClose = valvesClose; + } + + /// + /// Update the entities and save them to the database + /// + public new void OkBtnClicked() + { + base.OkBtnClicked(); + + foreach (var entity in ToBeRemovedItems) + { + FluentCommon.DeleteFromDb(parent.Session, entity); + } + foreach (var entity in MyItems) + { + FluentCommon.SaveToDb(parent.Session, entity); + } + } + + public void AddOne() + { + Entities.BenchPath entity; + + if (MyItems.Count < FixedRowsCount) + { + entity = new Entities.BenchPath(new BenchControl.BenchPath(Strings._none_, MyItems.Count)); + } + else + { + /// Find an unused test name + string newName; + for (int nameId = 1; true; nameId++) + { + newName = Strings.New_bench_path_name + nameId.ToString(); + bool notUsed = true; + foreach (var t in MyItems) if (t.Name.Equals(newName)) notUsed = false; + if (notUsed) break; + } + entity = new Entities.BenchPath(new BenchControl.BenchPath(newName, MyItems.Count)); + } + + base.AddOne(entity); + } + + public new void RemoveSelected() + { + bool lastOneRemoved = base.RemoveSelected(); + if (lastOneRemoved && parent != null) + { + parent.UpdateButtonStates(SharedButtons.SelectedItemPos.None); + } + } + } +} diff --git a/TestBenchFramework/UiControls/PathsFeedingCtrl.cs b/TestBenchFramework/UiControls/PathsFeedingCtrl.cs new file mode 100644 index 000000000..e6abdc80d --- /dev/null +++ b/TestBenchFramework/UiControls/PathsFeedingCtrl.cs @@ -0,0 +1,225 @@ +using System.Collections.Generic; +using System.Globalization; +using System.Windows.Forms; +using log4net; +using TBF.BenchControl; +using TBF.BenchControl.GenericDevices; +using TBF.Resources; + +namespace TBF.UiControls +{ + public class PathsFeedingCtrl : BaseWithListViewEx, ITabWithListViewEx + { + static readonly ILog log = LogManager.GetLogger(typeof(PathsFeedingCtrl)); + + /// + /// Fixed ListViewEx columns + /// + enum Column + { + Name, + Qfrom, + Qto, + Pump, + FixedColumnsCount, + } + readonly int fixedColumnsCount = (int)Column.FixedColumnsCount; + + PathsDlg parent; + Control parentControl; + Control[] editors; + + public PathsFeedingCtrl() + : base() + { + FixedRowsCount = 1; + } + + public void Initialize(PathsDlg parent, Control parentControl) + { + this.parent = parent; + this.parentControl = parentControl; + + /// Load the paths + MyItems = parent.Session + .CreateQuery("FROM FeedingPath ORDER BY ItemNr") + .List(); + + SubItemClicked += new SubItemEventHandler(listViewEx_SubItemClicked); + SubItemEndEditing += new SubItemEndEditingEventHandler(listViewEx_SubItemEndEditing); + + /// ListViewEx columns + Columns.Add(Strings.Name, 60 * parent.Dpi / PathsDlg.Dpi100pct); + Columns.Add(Strings.Q_from_m3h, 50 * parent.Dpi / PathsDlg.Dpi100pct); + Columns.Add(Strings.Q_to_m3h, 50 * parent.Dpi / PathsDlg.Dpi100pct); + Columns.Add(Strings.Pump, 60 * parent.Dpi / PathsDlg.Dpi100pct); + foreach (var vlv in parent.Valves) Columns.Add(vlv.Cfg.Name, 50 * parent.Dpi / PathsDlg.Dpi100pct); + + /// Pump + ComboBox pumpCBox = new ComboBox(); + pumpCBox.Items.Add("---"); + foreach (var cmpnt in parent.TbfComponents) + { + if (cmpnt is IPump) pumpCBox.Items.Add(cmpnt.Cfg.Name); + } + + editors = new Control[fixedColumnsCount + 64]; + /// + editors[(int)Column.Name] = new TextBox(); /// Name + editors[(int)Column.Qfrom] = new TextBox(); /// Q_from + editors[(int)Column.Qto] = new TextBox(); /// Q_to + editors[(int)Column.Pump] = pumpCBox; + /// Prepare valve combo-boxes (max. 64 valves) + for (int i = 0; i < 64; i++) + { + ComboBox cb = new ComboBox(); + cb.Items.Add("---"); + cb.Items.Add(Strings.open); + cb.Items.Add(Strings.close); + editors[fixedColumnsCount + i] = cb; + } + /// + for (int i = 0; i < editors.Length; i++) parent.Controls.Add(editors[i]); + + base.RedrawAll(); + } + + void listViewEx_SubItemClicked(object sender, SubItemEventArgs e) + { + if (!Unlocked || e.SubItem >= editors.Length) return; + if ((e.Item.Tag is Entities.IHasItemNr) && + ((e.Item.Tag as Entities.IHasItemNr).ItemNr < FixedRowsCount) && + (e.SubItem < fixedColumnsCount)) + { + return; + } + StartEditing(editors[e.SubItem], e.Item, e.SubItem); + } + + void listViewEx_SubItemEndEditing(object sender, SubItemEndEditingEventArgs e) + { + } + + public override void DrawOne(object myItem) + { + Entities.FeedingPath entity =(Entities.FeedingPath)myItem; + BenchControl.FeedingPath path = new BenchControl.FeedingPath(entity, parent.TbfComponents); + + ListViewItem lvi = new ListViewItem(entity.Name); + lvi.SubItems.Add(path.Qfrom.ToString()); + lvi.SubItems.Add(path.Qto.ToString()); + lvi.SubItems.Add(path.Pump != null ? path.Pump.Cfg.Name : "---"); + + foreach (var valve in parent.Valves) + { + if (path.ValvesOpen != null && path.ValvesOpen.Contains(valve)) + { + lvi.SubItems.Add(Strings.open); + } + else if (path.ValvesClose != null && path.ValvesClose.Contains(valve)) + { + lvi.SubItems.Add(Strings.close); + } + else + { + lvi.SubItems.Add("---"); + } + } + + lvi.Tag = entity; + + Items.Add(lvi); + } + + public override void UpdateOne(ListViewItem lvi, object myItem) + { + Entities.FeedingPath entity = (Entities.FeedingPath)myItem; + + entity.Name = lvi.Text; + + float Qfrom; + bool allOk = Utils.TryParseUFloat(lvi.SubItems[(int)Column.Qfrom].Text, out Qfrom); + entity.Qfrom = Qfrom; + + float Qto; + allOk &= Utils.TryParseUFloat(lvi.SubItems[(int)Column.Qto].Text, out Qto); + entity.Qto = Qto; + + ComboBox pumpCB = editors[(int)Column.Pump] as ComboBox; + if (pumpCB.Items.Contains(lvi.SubItems[(int)Column.Pump].Text)) + { + entity.Pump = lvi.SubItems[(int)Column.Pump].Text.Equals("---") ? string.Empty : lvi.SubItems[(int)Column.Pump].Text; + } + + string valvesOpen = string.Empty; + string valvesClose = string.Empty; + for (int j = 0; j < parent.Valves.Count; j++) + { + string text = lvi.SubItems[fixedColumnsCount + j].Text; + if (text.Equals(Strings.open)) + { + if (valvesOpen != string.Empty) valvesOpen += ";"; + valvesOpen += parent.Valves[j].Cfg.Name; + } + if (text.Equals(Strings.close)) + { + if (valvesClose != string.Empty) valvesClose += ";"; + valvesClose += parent.Valves[j].Cfg.Name; + } + } + entity.ValvesOpen = valvesOpen; + entity.ValvesClose = valvesClose; + } + + /// + /// Update the entities and save them to the database + /// + public new void OkBtnClicked() + { + base.OkBtnClicked(); + + foreach (var entity in ToBeRemovedItems) + { + FluentCommon.DeleteFromDb(parent.Session, entity); + } + foreach (var entity in MyItems) + { + FluentCommon.SaveToDb(parent.Session, entity); + } + } + + public void AddOne() + { + Entities.FeedingPath entity; + + if (MyItems.Count < FixedRowsCount) + { + entity = new Entities.FeedingPath(new BenchControl.FeedingPath(Strings._none_, MyItems.Count)); + } + else + { + /// Find an unused test name + string newName; + for (int nameId = 1; true; nameId++) + { + newName = Strings.New_feeding_path_name + nameId.ToString(); + bool notUsed = true; + foreach (var t in MyItems) if (t.Name.Equals(newName)) notUsed = false; + if (notUsed) break; + } + entity = new Entities.FeedingPath(new BenchControl.FeedingPath(newName, MyItems.Count)); + } + + base.AddOne(entity); + } + + public new void RemoveSelected() + { + bool lastOneRemoved = base.RemoveSelected(); + if (lastOneRemoved && parent != null) + { + parent.UpdateButtonStates(SharedButtons.SelectedItemPos.None); + } + } + } +} diff --git a/TestBenchFramework/UiControls/PathsMetersCtrl.cs b/TestBenchFramework/UiControls/PathsMetersCtrl.cs new file mode 100644 index 000000000..473e5de18 --- /dev/null +++ b/TestBenchFramework/UiControls/PathsMetersCtrl.cs @@ -0,0 +1,179 @@ +using System.Collections.Generic; +using System.Globalization; +using System.Windows.Forms; +using log4net; +using TBF.BenchControl; +using TBF.BenchControl.GenericDevices; +using TBF.Resources; + +namespace TBF.UiControls +{ + public class PathsMetersCtrl : BaseWithListViewEx, ITabWithListViewEx + { + static readonly ILog log = LogManager.GetLogger(typeof(PathsMetersCtrl)); + + /// + /// Fixed ListViewEx columns + /// + enum Column + { + Name, + Qfrom, + Qto, + FixedColumnsCount, + } + readonly int fixedColumnsCount = (int)Column.FixedColumnsCount; + + PathsDlg parent; + Control parentControl; + Control[] editors; + + public PathsMetersCtrl() + : base() + { + } + + public void Initialize(PathsDlg parent, Control parentControl) + { + this.parent = parent; + this.parentControl = parentControl; + + /// Load the paths + MyItems = parent.Session + .CreateQuery("FROM MetersPath ORDER BY ItemNr") + .List(); + + SubItemClicked += new SubItemEventHandler(listViewEx_SubItemClicked); + SubItemEndEditing += new SubItemEndEditingEventHandler(listViewEx_SubItemEndEditing); + + IList readers = new List(); + foreach (var cmpnt in parent.TbfComponents) + { + if (cmpnt is IRegisterReader) readers.Add(cmpnt as IRegisterReader); + } + + /// ListViewEx columns + Columns.Add(Strings.Name, 60 * parent.Dpi / PathsDlg.Dpi100pct); + Columns.Add(Strings.Q_from_m3h, 50 * parent.Dpi / PathsDlg.Dpi100pct); + Columns.Add(Strings.Q_to_m3h, 50 * parent.Dpi / PathsDlg.Dpi100pct); + for (int i = 0; i < Program.WMsCount; i++) Columns.Add(Strings.Sensor_ + (i+1).ToString()); + + /// Editors + editors = new Control[fixedColumnsCount + Program.WMsCount]; + /// + editors[(int)Column.Name] = new TextBox(); /// Name + editors[(int)Column.Qfrom] = new TextBox(); /// Q_from + editors[(int)Column.Qto] = new TextBox(); /// Q_to + /// Prepare valve combo-boxes (max. 64 valves) + for (int i = 0; i < Program.WMsCount; i++) + { + ComboBox cb = new ComboBox(); + foreach (var rr in readers) cb.Items.Add(rr.Cfg.Name); + editors[fixedColumnsCount + i] = cb; + } + /// + for (int i = 0; i < editors.Length; i++) parent.Controls.Add(editors[i]); + + base.RedrawAll(); + } + + void listViewEx_SubItemClicked(object sender, SubItemEventArgs e) + { + if (!Unlocked || e.SubItem >= editors.Length) return; + StartEditing(editors[e.SubItem], e.Item, e.SubItem); + } + + void listViewEx_SubItemEndEditing(object sender, SubItemEndEditingEventArgs e) + { + } + + public override void DrawOne(object myItem) + { + Entities.MetersPath entity =(Entities.MetersPath)myItem; + BenchControl.MetersPath path = new BenchControl.MetersPath(entity, parent.TbfComponents); + + ListViewItem lvi = new ListViewItem(entity.Name); + lvi.SubItems.Add(path.Qfrom.ToString()); + lvi.SubItems.Add(path.Qto.ToString()); + + for (int i = 0; i < Program.WMsCount; i++) + { + if (path.RegisterReaders != null && path.RegisterReaders[i] != null) + { + lvi.SubItems.Add(path.RegisterReaders[i].Cfg.Name); + } + else + { + lvi.SubItems.Add("---"); + } + } + + lvi.Tag = entity; + + Items.Add(lvi); + } + + public override void UpdateOne(ListViewItem lvi, object myItem) + { + Entities.MetersPath entity = (Entities.MetersPath)myItem; + + entity.Name = lvi.Text; + + float Qfrom; + bool allOk = Utils.TryParseUFloat(lvi.SubItems[(int)Column.Qfrom].Text, out Qfrom); + entity.Qfrom = Qfrom; + + float Qto; + allOk &= Utils.TryParseUFloat(lvi.SubItems[(int)Column.Qto].Text, out Qto); + entity.Qto = Qto; + + for (int j = 0; j < Program.WMsCount; j++) + { + entity.SetSensor(j, lvi.SubItems[fixedColumnsCount + j].Text); + } + } + + /// + /// Update the entities and save them to the database + /// + public new void OkBtnClicked() + { + base.OkBtnClicked(); + + foreach (var entity in ToBeRemovedItems) + { + FluentCommon.DeleteFromDb(parent.Session, entity); + } + foreach (var entity in MyItems) + { + FluentCommon.SaveToDb(parent.Session, entity); + } + } + + public void AddOne() + { + /// Find an unused test name + string newName; + for (int nameId = 1; true; nameId++) + { + newName = Strings.New_sensors_path_name + nameId.ToString(); + bool notUsed = true; + foreach (var t in MyItems) if (t.Name.Equals(newName)) notUsed = false; + if (notUsed) break; + } + + Entities.MetersPath entity = new Entities.MetersPath(new BenchControl.MetersPath(newName, MyItems.Count)); + + base.AddOne(entity); + } + + public new void RemoveSelected() + { + bool lastOneRemoved = base.RemoveSelected(); + if (lastOneRemoved && parent != null) + { + parent.UpdateButtonStates(SharedButtons.SelectedItemPos.None); + } + } + } +} diff --git a/TestBenchFramework/UiControls/PathsOutputCtrl.cs b/TestBenchFramework/UiControls/PathsOutputCtrl.cs new file mode 100644 index 000000000..ec106407d --- /dev/null +++ b/TestBenchFramework/UiControls/PathsOutputCtrl.cs @@ -0,0 +1,255 @@ +using System.Collections.Generic; +using System.Globalization; +using System.Windows.Forms; +using log4net; +using TBF.BenchControl; +using TBF.BenchControl.GenericDevices; +using TBF.Resources; + +namespace TBF.UiControls +{ + public class PathsOutputCtrl : BaseWithListViewEx, ITabWithListViewEx + { + static readonly ILog log = LogManager.GetLogger(typeof(PathsOutputCtrl)); + + /// + /// Fixed ListViewEx columns + /// + enum Column + { + Name, + Qfrom, + Qto, + RV, + Ref, + Div, + Tdiv, + Scale, + EmptV, + FixedColumnsCount, + } + readonly int fixedColumnsCount = (int)Column.FixedColumnsCount; + + PathsDlg parent; + Control parentControl; + Control[] editors; + + public PathsOutputCtrl() + : base() + { + FixedRowsCount = 1; + } + + public void Initialize(PathsDlg parent, Control parentControl) + { + this.parent = parent; + this.parentControl = parentControl; + + /// Load the paths + MyItems = parent.Session + .CreateQuery("FROM OutputPath ORDER BY ItemNr") + .List(); + + SubItemClicked += new SubItemEventHandler(listViewEx_SubItemClicked); + SubItemEndEditing += new SubItemEndEditingEventHandler(listViewEx_SubItemEndEditing); + + /// ListViewEx columns + Columns.Add(Strings.Name, 60 * parent.Dpi / PathsDlg.Dpi100pct); + Columns.Add(Strings.Q_from_m3h, 50 * parent.Dpi / PathsDlg.Dpi100pct); + Columns.Add(Strings.Q_to_m3h, 50 * parent.Dpi / PathsDlg.Dpi100pct); + Columns.Add(Strings.Reg_valve, 80 * parent.Dpi / PathsDlg.Dpi100pct); + Columns.Add(Strings.Reference, 85 * parent.Dpi / PathsDlg.Dpi100pct); + Columns.Add(Strings.Diverter, 60 * parent.Dpi / PathsDlg.Dpi100pct); + Columns.Add(Strings.T_div, 70 * parent.Dpi / PathsDlg.Dpi100pct); + Columns.Add(Strings.Balance, 50 * parent.Dpi / PathsDlg.Dpi100pct); + Columns.Add(Strings.Emptying_valve, 80 * parent.Dpi / PathsDlg.Dpi100pct); + foreach (var vlv in parent.Valves) Columns.Add(vlv.Cfg.Name, 50 * parent.Dpi / PathsDlg.Dpi100pct); + + /// Prepare fixed columns combo boxes + ComboBox regulValveComboBox = new ComboBox(); + ComboBox flowMeterComboBox = new ComboBox(); + ComboBox diverterComboBox = new ComboBox(); + ComboBox balanceComboBox = new ComboBox(); + ComboBox tempMeterDivComboBox = new ComboBox(); + ComboBox emptyValveComboBox = new ComboBox(); + foreach (var cmpnt in parent.TbfComponents) + { + if (cmpnt is IRegulValve) regulValveComboBox.Items.Add(cmpnt.Cfg.Name); + if (cmpnt is IFlowMeter) flowMeterComboBox.Items.Add(cmpnt.Cfg.Name); + if (cmpnt is IDiverter) diverterComboBox.Items.Add(cmpnt.Cfg.Name); + if (cmpnt is IBalance) balanceComboBox.Items.Add(cmpnt.Cfg.Name); + if (cmpnt is ITempMeter) tempMeterDivComboBox.Items.Add(cmpnt.Cfg.Name); + if (cmpnt is IValve && (cmpnt as IValve).CoupledTo == null) emptyValveComboBox.Items.Add(cmpnt.Cfg.Name); + } + + editors = new Control[fixedColumnsCount + 64]; + /// + editors[(int)Column.Name] = new TextBox(); /// Name + editors[(int)Column.Qfrom] = new TextBox(); /// Q_from + editors[(int)Column.Qto] = new TextBox(); /// Q_to + editors[(int)Column.RV] = regulValveComboBox; + editors[(int)Column.Ref] = flowMeterComboBox; + editors[(int)Column.Div] = diverterComboBox; + editors[(int)Column.Tdiv] = tempMeterDivComboBox; + editors[(int)Column.Scale] = balanceComboBox; + editors[(int)Column.EmptV] = emptyValveComboBox; + /// Prepare valve combo-boxes (max. 64 valves) + for (int i = 0; i < 64; i++) + { + ComboBox cb = new ComboBox(); + cb.Items.Add("---"); + cb.Items.Add(Strings.open); + cb.Items.Add(Strings.close); + editors[fixedColumnsCount + i] = cb; + } + /// + for (int i = 0; i < editors.Length; i++) parent.Controls.Add(editors[i]); + + base.RedrawAll(); + } + + void listViewEx_SubItemClicked(object sender, SubItemEventArgs e) + { + if (!Unlocked || e.SubItem >= editors.Length) return; + if ((e.Item.Tag is Entities.IHasItemNr) && + ((e.Item.Tag as Entities.IHasItemNr).ItemNr < FixedRowsCount) && + (e.SubItem < fixedColumnsCount)) + { + return; + } + StartEditing(editors[e.SubItem], e.Item, e.SubItem); + } + + void listViewEx_SubItemEndEditing(object sender, SubItemEndEditingEventArgs e) + { + } + + public override void DrawOne(object myItem) + { + Entities.OutputPath entity =(Entities.OutputPath)myItem; + BenchControl.OutputPath path = new BenchControl.OutputPath(entity, parent.TbfComponents); + + ListViewItem lvi = new ListViewItem(entity.Name); + lvi.SubItems.Add(path.Qfrom.ToString()); + lvi.SubItems.Add(path.Qto.ToString()); + lvi.SubItems.Add(path.RegulValve != null ? path.RegulValve.Cfg.Name : "---"); + lvi.SubItems.Add(path.FlowMeter != null ? path.FlowMeter.Cfg.Name : "---"); + lvi.SubItems.Add(path.Diverter != null ? path.Diverter.Cfg.Name : "---"); + lvi.SubItems.Add(path.TempDiv != null ? path.TempDiv.Cfg.Name : "---"); + lvi.SubItems.Add(path.Balance != null ? path.Balance.Cfg.Name : "---"); + lvi.SubItems.Add(path.EmptyTankValve != null ? path.EmptyTankValve.Cfg.Name : "---"); + + foreach (var valve in parent.Valves) + { + if (path.ValvesOpen != null && path.ValvesOpen.Contains(valve)) + { + lvi.SubItems.Add(Strings.open); + } + else if (path.ValvesClose != null && path.ValvesClose.Contains(valve)) + { + lvi.SubItems.Add(Strings.close); + } + else + { + lvi.SubItems.Add("---"); + } + } + + lvi.Tag = entity; + + Items.Add(lvi); + } + + public override void UpdateOne(ListViewItem lvi, object myItem) + { + Entities.OutputPath entity = (Entities.OutputPath)myItem; + + entity.Name = lvi.Text; + + float Qfrom; + bool allOk = Utils.TryParseUFloat(lvi.SubItems[(int)Column.Qfrom].Text, out Qfrom); + entity.Qfrom = Qfrom; + + float Qto; + allOk &= Utils.TryParseUFloat(lvi.SubItems[(int)Column.Qto].Text, out Qto); + entity.Qto = Qto; + + entity.RegulValve = lvi.SubItems[(int)Column.RV].Text; + entity.FlowMeter = lvi.SubItems[(int)Column.Ref].Text; + entity.Diverter = lvi.SubItems[(int)Column.Div].Text; + entity.TempDiv = lvi.SubItems[(int)Column.Tdiv].Text; + entity.Balance = lvi.SubItems[(int)Column.Scale].Text; + entity.EmptyTankValve = lvi.SubItems[(int)Column.EmptV].Text; + + string valvesOpen = string.Empty; + string valvesClose = string.Empty; + for (int j = 0; j < parent.Valves.Count; j++) + { + string text = lvi.SubItems[fixedColumnsCount + j].Text; + if (text.Equals(Strings.open)) + { + if (valvesOpen != string.Empty) valvesOpen += ";"; + valvesOpen += parent.Valves[j].Cfg.Name; + } + if (text.Equals(Strings.close)) + { + if (valvesClose != string.Empty) valvesClose += ";"; + valvesClose += parent.Valves[j].Cfg.Name; + } + } + entity.ValvesOpen = valvesOpen; + entity.ValvesClose = valvesClose; + } + + /// + /// Update the entities and save them to the database + /// + public new void OkBtnClicked() + { + base.OkBtnClicked(); + + foreach (var entity in ToBeRemovedItems) + { + FluentCommon.DeleteFromDb(parent.Session, entity); + } + foreach (var entity in MyItems) + { + FluentCommon.SaveToDb(parent.Session, entity); + } + } + + public void AddOne() + { + Entities.OutputPath entity; + + if (MyItems.Count < FixedRowsCount) + { + entity = new Entities.OutputPath(new BenchControl.OutputPath(Strings._none_, MyItems.Count)); + } + else + { + /// Find an unused test name + string newName; + for (int nameId = 1; true; nameId++) + { + newName = Strings.New_output_path_name + nameId.ToString(); + bool notUsed = true; + foreach (var t in MyItems) if (t.Name.Equals(newName)) notUsed = false; + if (notUsed) break; + } + entity = new Entities.OutputPath(new BenchControl.OutputPath(newName, MyItems.Count)); + } + + base.AddOne(entity); + } + + public new void RemoveSelected() + { + bool lastOneRemoved = base.RemoveSelected(); + if (lastOneRemoved && parent != null) + { + parent.UpdateButtonStates(SharedButtons.SelectedItemPos.None); + } + } + } +} diff --git a/TestBenchFramework/UiControls/ProcedureParamsCtrl.Designer.cs b/TestBenchFramework/UiControls/ProcedureParamsCtrl.Designer.cs new file mode 100644 index 000000000..ce8d54906 --- /dev/null +++ b/TestBenchFramework/UiControls/ProcedureParamsCtrl.Designer.cs @@ -0,0 +1,62 @@ +namespace TBF.UiControls +{ + partial class ProcedureParamsCtrl + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.listViewEx = new TBF.UiControls.ListViewEx(); + this.SuspendLayout(); + // + // listViewEx + // + this.listViewEx.AllowColumnReorder = true; + this.listViewEx.Dock = System.Windows.Forms.DockStyle.Fill; + this.listViewEx.DoubleClickActivation = false; + this.listViewEx.FullRowSelect = true; + this.listViewEx.GridLines = true; + this.listViewEx.Location = new System.Drawing.Point(0, 0); + this.listViewEx.Name = "listViewEx"; + this.listViewEx.Size = new System.Drawing.Size(150, 150); + this.listViewEx.TabIndex = 1; + this.listViewEx.UseCompatibleStateImageBehavior = false; + this.listViewEx.View = System.Windows.Forms.View.Details; + // + // ProcedureParams + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.listViewEx); + this.Name = "ProcedureParams"; + this.ResumeLayout(false); + + } + + #endregion + + private ListViewEx listViewEx; + } +} diff --git a/TestBenchFramework/UiControls/ProcedureParamsCtrl.cs b/TestBenchFramework/UiControls/ProcedureParamsCtrl.cs new file mode 100644 index 000000000..538e49a2b --- /dev/null +++ b/TestBenchFramework/UiControls/ProcedureParamsCtrl.cs @@ -0,0 +1,165 @@ +using System; +using System.Collections.Generic; +using System.Windows.Forms; +using TBF.BenchControl.Generic; +using TBF.Resources; + +namespace TBF.UiControls +{ + /// /---------------\ + /// / Path or other \ + /// |------------------------------ + /// | param1 param2 param3 ... + /// Component1 | + /// Component2 | + /// ... | + /// + public partial class ProcedureParamsCtrl : UserControl + { + ProcedureDlg parent; + bool showSensorsColumn; + int nrFixedColumns; + IList selectedCmpnts; + IList cmpntsParams; + + int paramsCount; + Control[] editors; + bool unlocked; + public void Unlock(){ unlocked = true; } + + public ProcedureParamsCtrl() + { + InitializeComponent(); + cmpntsParams = new List(); + } + + public ProcedureParamsCtrl(ProcedureDlg parent, IList selectedCmpnts, bool showSensorsColumn) + : this() + { + this.parent = parent; + this.selectedCmpnts = selectedCmpnts; + this.showSensorsColumn = showSensorsColumn; + nrFixedColumns = (showSensorsColumn ? 2 : 1); + unlocked = false; + + this.SuspendLayout(); + Dock = System.Windows.Forms.DockStyle.Fill; + listViewEx.Dock = System.Windows.Forms.DockStyle.Fill; + listViewEx.AllowColumnReorder = false; + listViewEx.DoubleClickActivation = false; + listViewEx.FullRowSelect = true; + listViewEx.GridLines = true; + listViewEx.Location = new System.Drawing.Point(0, 0); + listViewEx.TabIndex = 0; + listViewEx.UseCompatibleStateImageBehavior = false; + listViewEx.View = System.Windows.Forms.View.Details; + ResumeLayout(false); + } + + public void Initialize() + { + if (selectedCmpnts == null) return; + + IParamsProvider sampleToCreateHeader = null; + + foreach (var cmpnt in selectedCmpnts) + { + if (cmpnt != null && cmpnt.Cfg.Factory.HasProcedureParams) + { + IParamsProvider procedureParams = BenchControl.TbfComponents.GetProcedureParams(cmpnt, parent.LoadedProcedure); + if (procedureParams != null) + { + if (sampleToCreateHeader == null) sampleToCreateHeader = procedureParams; + } + else + { + Entities.ComponentProcedure entity = new Entities.ComponentProcedure(); + entity.CmpntName = cmpnt.Cfg.Name; + entity.Procedure = parent.LoadedProcedure; + procedureParams = cmpnt.Cfg.Factory.GetProcedureParams(entity); + } + cmpntsParams.Add(procedureParams); + } + else + { + cmpntsParams.Add(null); + } + } + + if (sampleToCreateHeader != null) + { + if (showSensorsColumn) listViewEx.Columns.Add(Strings.Sensor_, 60); + listViewEx.Columns.Add(Strings.Component, 80); + + paramsCount = sampleToCreateHeader.ParamsCount(); + editors = new Control[paramsCount]; + for (int i = 0; i < paramsCount; i++) + { + listViewEx.Columns.Add(sampleToCreateHeader.ParamName(i), 80); + editors[i] = new TextBox(); + this.Controls.Add(editors[i]); + } + } + + listViewEx.SubItemClicked += new SubItemEventHandler(listViewEx_SubItemClicked); + listViewEx.SubItemEndEditing += new SubItemEndEditingEventHandler(listViewEx_SubItemEndEditing); + + RedrawAll(); + } + + private void listViewEx_SubItemClicked(object sender, SubItemEventArgs e) + { + if (!unlocked || e.Item.Tag == null || e.SubItem < nrFixedColumns || e.SubItem >= nrFixedColumns + editors.Length) return; + listViewEx.StartEditing(editors[e.SubItem - nrFixedColumns], e.Item, e.SubItem); + } + + private void listViewEx_SubItemEndEditing(object sender, SubItemEndEditingEventArgs e) + { + string message; + if ((e.Item.Tag as IParamsProvider).ValidateParam(e.SubItem - nrFixedColumns, e.DisplayText, out message)) + { + (e.Item.Tag as IParamsProvider).UpdateParam(e.SubItem - nrFixedColumns, e.DisplayText); + } + } + + + public void RedrawAll() + { + listViewEx.Items.Clear(); + foreach (var item in cmpntsParams) DrawOne(item); + } + + void DrawOne(IParamsProvider item) + { + if (item == null) + { + listViewEx.Items.Add(new ListViewItem()); + return; + } + + ListViewItem lvi; + if (showSensorsColumn) + { + lvi = new ListViewItem((listViewEx.Items.Count + 1).ToString()); + lvi.SubItems.Add(selectedCmpnts[listViewEx.Items.Count].Cfg.Name); + } + else + { + lvi = new ListViewItem(selectedCmpnts[listViewEx.Items.Count].Cfg.Name); + } + for (int i = 0; i < paramsCount; i++) lvi.SubItems.Add(item.ToString(i)); + lvi.Tag = item; + listViewEx.Items.Add(lvi); + } + + public void UpdateAll() + { + if (!unlocked) return; + + foreach (ListViewItem lvi in listViewEx.Items) + { + if (lvi.Tag is IParamsProvider) (lvi.Tag as IParamsProvider).UpdateDbEntity(); + } + } + } +} diff --git a/TestBenchFramework/UiControls/ProcedureParamsCtrl.resx b/TestBenchFramework/UiControls/ProcedureParamsCtrl.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/TestBenchFramework/UiControls/ProcedureParamsCtrl.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/UiControls/ProceduresCtrl.cs b/TestBenchFramework/UiControls/ProceduresCtrl.cs new file mode 100644 index 000000000..d6ec05f55 --- /dev/null +++ b/TestBenchFramework/UiControls/ProceduresCtrl.cs @@ -0,0 +1,204 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Windows.Forms; +using NHibernate; +using log4net; +using TBF.BenchControl; +using TBF.BenchControl.GenericDevices; +using TBF.Resources; + +namespace TBF.UiControls +{ + public class ProceduresCtrl : BaseWithListViewEx, ITabWithListViewEx + { + static readonly ILog log = LogManager.GetLogger(typeof(ProceduresCtrl)); + + /// + /// ListViewEx columns + /// + enum Column + { + Name, + Description, + ColumnsCount, + } + readonly int columnsCount = (int)Column.ColumnsCount; + + ProceduresDlg parent; + Control parentControl; + Control[] editors; + + ISession session; + + public ProceduresCtrl() + : base() + { + Name = "ProceduresCtrl"; + } + + public void Initialize(ProceduresDlg parent, Control parentControl) + { + this.parent = parent; + this.parentControl = parentControl; + + SubItemClicked += new SubItemEventHandler(listViewEx_SubItemClicked); + SubItemEndEditing += new SubItemEndEditingEventHandler(listViewEx_SubItemEndEditing); + + /// ListViewEx columns + Columns.Add(Strings.Name, 100 * parent.Dpi / PathsDlg.Dpi100pct); + Columns.Add(Strings.DescriptionColHdr, 300 * parent.Dpi / PathsDlg.Dpi100pct); + + editors = new Control[columnsCount]; + /// + editors[(int)Column.Name] = new TextBox(); /// Name + editors[(int)Column.Description] = new TextBox(); /// Description + /// + for (int i = 0; i < editors.Length; i++) parent.Controls.Add(editors[i]); + + ReloadAndRedrawAll(); + } + + void ReloadAndRedrawAll() + { + /// Load the procedures + session = FluentCommon.CreateSession(Database.Procedures); + MyItems = session.CreateQuery("FROM Procedure ORDER BY ItemNr") + .List(); + + base.RedrawAll(); + } + + void listViewEx_SubItemClicked(object sender, SubItemEventArgs e) + { + } + + void listViewEx_SubItemEndEditing(object sender, SubItemEndEditingEventArgs e) + { + } + + public override void DrawOne(object myItem) + { + Entities.Procedure entity = (Entities.Procedure)myItem; + + ListViewItem lvi = new ListViewItem(entity.Name); + lvi.SubItems.Add(entity.Description); + lvi.Tag = entity; + + Items.Add(lvi); + } + + public override void UpdateOne(ListViewItem lvi, object myItem) + { + Entities.Procedure entity = (Entities.Procedure)myItem; + entity.Name = lvi.Text; + entity.Description = lvi.SubItems[(int)Column.Description].Text; + } + + /// + /// Update the entities and save them to the database + /// + public new void OkBtnClicked() + { + base.OkBtnClicked(); + + foreach (var entity in ToBeRemovedItems) + { + FluentCommon.DeleteFromDb(session, entity); + } + foreach (var entity in MyItems) + { + FluentCommon.SaveToDb(session, entity); + } + + Program.MainWnd.ReloadProcedures(); + } + + public void AddOne() + { + /// Find an unused test name + string newName; + for (int nameId = 1; true; nameId++) + { + newName = Strings.New_procedure_name + nameId.ToString(); + bool notUsed = true; + foreach (var t in MyItems) if (t.Name.Equals(newName)) notUsed = false; + if (notUsed) break; + } + + base.AddOne(new Entities.Procedure(newName, MyItems.Count)); + } + + public new void RemoveSelected() + { + bool lastOneRemoved = base.RemoveSelected(); + if (lastOneRemoved && parent != null) + { + parent.UpdateButtonStates(SharedButtons.SelectedItemPos.None); + } + } + + public void editButton_Click(object sender, EventArgs e) + { + if (SelectedItems.Count != 1) return; + int dbId = (SelectedItems[0].Tag as Entities.Procedure).Id; + + if (dbId == 0) + { + session.SaveOrUpdate(SelectedItems[0].Tag as Entities.Procedure); + } + + dbId = (SelectedItems[0].Tag as Entities.Procedure).Id; + + /// + /// Entities.Procedure has to be loaded in a different session otherwise + /// the database would be updated in case the dialog was closed with 'Cancel' button. + /// + using (ISession editSession = FluentCommon.CreateSession(Database.Procedures)) + { + IList procedure = editSession + .CreateQuery("FROM Procedure WHERE Id = :id") + .SetParameter("id", dbId) + .List(); + if (procedure.Count != 1) return; + + ProcedureDlg dlg = new ProcedureDlg(procedure[0]); + if (dlg.ShowDialog() == DialogResult.OK) + { + parent.Unlock(); + using (var transaction = editSession.BeginTransaction()) + { + editSession.SaveOrUpdate(procedure[0]); + transaction.Commit(); + } + + } + } + + ReloadAndRedrawAll(); + } + + public void copyButton_Click(object sender, EventArgs e) + { + if (SelectedItems.Count != 1) return; + + Entities.Procedure selectedProcedure = (Entities.Procedure)SelectedItems[0].Tag; + + /// Make a copy of the selected procedure + Entities.Procedure newProcedure = selectedProcedure.Clone(); + newProcedure.Name = selectedProcedure.Name + Strings.New_name_copy; + newProcedure.CreationUser = Entities.User.CurrentUser.Name; + newProcedure.CreationTime = DateTime.Now; + + if ((new ProcedureDlg(newProcedure)).ShowDialog() == DialogResult.OK) + { + using (var transaction = session.BeginTransaction()) + { + session.SaveOrUpdate(newProcedure); + transaction.Commit(); + } + base.AddOne(newProcedure); + } + } + } +} diff --git a/TestBenchFramework/UiControls/SharedButtons.Designer.cs b/TestBenchFramework/UiControls/SharedButtons.Designer.cs new file mode 100644 index 000000000..c2f28abed --- /dev/null +++ b/TestBenchFramework/UiControls/SharedButtons.Designer.cs @@ -0,0 +1,215 @@ +namespace TBF.UiControls +{ + partial class SharedButtons + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.removeButton = new System.Windows.Forms.Button(); + this.addButton = new System.Windows.Forms.Button(); + this.unlockButton = new System.Windows.Forms.Button(); + this.cancelButton = new System.Windows.Forms.Button(); + this.okButton = new System.Windows.Forms.Button(); + this.upButton = new System.Windows.Forms.Button(); + this.downButton = new System.Windows.Forms.Button(); + this.editButton = new System.Windows.Forms.Button(); + this.copyButton = new System.Windows.Forms.Button(); + this.newTabButton = new System.Windows.Forms.Button(); + this.renameTabButton = new System.Windows.Forms.Button(); + this.removeTabButton = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // removeButton + // + this.removeButton.ImeMode = System.Windows.Forms.ImeMode.NoControl; + this.removeButton.Location = new System.Drawing.Point(10, 179); + this.removeButton.Name = "removeButton"; + this.removeButton.Size = new System.Drawing.Size(80, 40); + this.removeButton.TabIndex = 4; + this.removeButton.Text = " Remove"; + this.removeButton.UseVisualStyleBackColor = true; + this.removeButton.Click += new System.EventHandler(this.removeBtn_Click); + // + // addButton + // + this.addButton.ImeMode = System.Windows.Forms.ImeMode.NoControl; + this.addButton.Location = new System.Drawing.Point(10, 136); + this.addButton.Name = "addButton"; + this.addButton.Size = new System.Drawing.Size(80, 40); + this.addButton.TabIndex = 3; + this.addButton.Text = " Add"; + this.addButton.UseVisualStyleBackColor = true; + this.addButton.Click += new System.EventHandler(this.addBtn_Click); + // + // unlockButton + // + this.unlockButton.ImeMode = System.Windows.Forms.ImeMode.NoControl; + this.unlockButton.Location = new System.Drawing.Point(10, 7); + this.unlockButton.Name = "unlockButton"; + this.unlockButton.Size = new System.Drawing.Size(80, 40); + this.unlockButton.TabIndex = 0; + this.unlockButton.Text = "Unlock"; + this.unlockButton.UseVisualStyleBackColor = true; + this.unlockButton.Click += new System.EventHandler(this.unlockBtn_Click); + // + // cancelButton + // + this.cancelButton.ImeMode = System.Windows.Forms.ImeMode.NoControl; + this.cancelButton.Location = new System.Drawing.Point(10, 93); + this.cancelButton.Name = "cancelButton"; + this.cancelButton.Size = new System.Drawing.Size(80, 40); + this.cancelButton.TabIndex = 2; + this.cancelButton.Text = "Cancel"; + this.cancelButton.UseVisualStyleBackColor = true; + this.cancelButton.Click += new System.EventHandler(this.cancelBtn_Click); + // + // okButton + // + this.okButton.ImeMode = System.Windows.Forms.ImeMode.NoControl; + this.okButton.Location = new System.Drawing.Point(10, 50); + this.okButton.Name = "okButton"; + this.okButton.Size = new System.Drawing.Size(80, 40); + this.okButton.TabIndex = 1; + this.okButton.Text = "OK"; + this.okButton.UseVisualStyleBackColor = true; + this.okButton.Click += new System.EventHandler(this.okBtn_Click); + // + // upButton + // + this.upButton.ImeMode = System.Windows.Forms.ImeMode.NoControl; + this.upButton.Location = new System.Drawing.Point(10, 222); + this.upButton.Name = "upButton"; + this.upButton.Size = new System.Drawing.Size(80, 40); + this.upButton.TabIndex = 5; + this.upButton.Text = " Up"; + this.upButton.UseVisualStyleBackColor = true; + this.upButton.Click += new System.EventHandler(this.upBtn_Click); + // + // downButton + // + this.downButton.ImeMode = System.Windows.Forms.ImeMode.NoControl; + this.downButton.Location = new System.Drawing.Point(10, 265); + this.downButton.Name = "downButton"; + this.downButton.Size = new System.Drawing.Size(80, 40); + this.downButton.TabIndex = 6; + this.downButton.Text = " Down"; + this.downButton.UseVisualStyleBackColor = true; + this.downButton.Click += new System.EventHandler(this.downBtn_Click); + // + // editButton + // + this.editButton.ImeMode = System.Windows.Forms.ImeMode.NoControl; + this.editButton.Location = new System.Drawing.Point(10, 308); + this.editButton.Name = "editButton"; + this.editButton.Size = new System.Drawing.Size(80, 40); + this.editButton.TabIndex = 7; + this.editButton.Text = " Edit"; + this.editButton.UseVisualStyleBackColor = true; + this.editButton.Click += new System.EventHandler(this.editBtn_Click); + // + // copyButton + // + this.copyButton.ImeMode = System.Windows.Forms.ImeMode.NoControl; + this.copyButton.Location = new System.Drawing.Point(10, 351); + this.copyButton.Name = "copyButton"; + this.copyButton.Size = new System.Drawing.Size(80, 40); + this.copyButton.TabIndex = 8; + this.copyButton.Text = " Copy"; + this.copyButton.UseVisualStyleBackColor = true; + this.copyButton.Click += new System.EventHandler(this.copyBtn_Click); + // + // newTabButton + // + this.newTabButton.ImeMode = System.Windows.Forms.ImeMode.NoControl; + this.newTabButton.Location = new System.Drawing.Point(10, 394); + this.newTabButton.Name = "newTabButton"; + this.newTabButton.Size = new System.Drawing.Size(80, 40); + this.newTabButton.TabIndex = 9; + this.newTabButton.Text = "New Tab"; + this.newTabButton.UseVisualStyleBackColor = true; + this.newTabButton.Click += new System.EventHandler(this.newTabButton_Click); + // + // renameTabButton + // + this.renameTabButton.ImeMode = System.Windows.Forms.ImeMode.NoControl; + this.renameTabButton.Location = new System.Drawing.Point(10, 437); + this.renameTabButton.Name = "renameTabButton"; + this.renameTabButton.Size = new System.Drawing.Size(80, 40); + this.renameTabButton.TabIndex = 10; + this.renameTabButton.Text = "Rename Tab"; + this.renameTabButton.UseVisualStyleBackColor = true; + this.renameTabButton.Click += new System.EventHandler(this.renameTabButton_Click); + // + // removeTabButton + // + this.removeTabButton.ImeMode = System.Windows.Forms.ImeMode.NoControl; + this.removeTabButton.Location = new System.Drawing.Point(10, 480); + this.removeTabButton.Name = "removeTabButton"; + this.removeTabButton.Size = new System.Drawing.Size(80, 40); + this.removeTabButton.TabIndex = 11; + this.removeTabButton.Text = "Remove Tab"; + this.removeTabButton.UseVisualStyleBackColor = true; + this.removeTabButton.Click += new System.EventHandler(this.removeTabButton_Click); + // + // SharedButtons + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.removeTabButton); + this.Controls.Add(this.renameTabButton); + this.Controls.Add(this.newTabButton); + this.Controls.Add(this.copyButton); + this.Controls.Add(this.editButton); + this.Controls.Add(this.downButton); + this.Controls.Add(this.upButton); + this.Controls.Add(this.removeButton); + this.Controls.Add(this.addButton); + this.Controls.Add(this.unlockButton); + this.Controls.Add(this.cancelButton); + this.Controls.Add(this.okButton); + this.Name = "SharedButtons"; + this.Size = new System.Drawing.Size(100, 649); + this.Load += new System.EventHandler(this.SharedDlgButtons_Load); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Button removeButton; + private System.Windows.Forms.Button addButton; + private System.Windows.Forms.Button unlockButton; + private System.Windows.Forms.Button cancelButton; + private System.Windows.Forms.Button okButton; + private System.Windows.Forms.Button upButton; + private System.Windows.Forms.Button downButton; + private System.Windows.Forms.Button editButton; + private System.Windows.Forms.Button copyButton; + private System.Windows.Forms.Button newTabButton; + private System.Windows.Forms.Button renameTabButton; + private System.Windows.Forms.Button removeTabButton; + } +} diff --git a/TestBenchFramework/UiControls/SharedButtons.cs b/TestBenchFramework/UiControls/SharedButtons.cs new file mode 100644 index 000000000..b49280ad4 --- /dev/null +++ b/TestBenchFramework/UiControls/SharedButtons.cs @@ -0,0 +1,251 @@ +using System; +using System.Windows.Forms; +using TBF.Resources; + +namespace TBF.UiControls +{ + public partial class SharedButtons : UserControl + { + /// + /// Masks to specify the enabled state and the visibility of buttons. + /// Unlock button is hard coded in this control, cannot be set from the parent. + /// + public enum Buttons + { + None = 0, + OK = 1, /// always visible, text = 'Close' when locked + Cancel = 2, /// always visible + Add = 4, /// optional + Remove = 8, /// optional + Up = 16, /// optional + Down = 32, /// optional + Edit = 64, /// optional + Copy = 128, /// optional + NewTab = 256, /// optional + RenameTab = 512, /// optional + RemoveTab = 1024, /// optional + } + + /// + /// Optional buttons are Add, Remove, Up, Down, Edit and Copy. + /// OK and Cancel buttons are always visible (after unlock), but not always enabled. + /// + public Buttons OptionalButtons; + + public enum LockState + { + Locked, /// 'Unlock', 'Close' (=OK) are shown, all the othere are hidden + Unlocked, /// Unlock, Ok, Cancel, Add,Remove and all optional buttons are shown + } + LockState lockState; + + /// + /// Used by controls to indicate which item is selected + /// and to appropriately update Remove, Up and Down Buttons. + /// + public enum SelectedItemPos + { + None, + First, + Last, + FirstAndLast, + Middle, + } + + public Grp.GID RequiredGroupMembership; + + Entities.User originalUser; + + /// + /// Default constructor + /// + public SharedButtons() + { + originalUser = Entities.User.CurrentUser; + lockState = LockState.Locked; + OptionalButtons = Buttons.None; + RequiredGroupMembership = Grp.GID.None; + InitializeComponent(); + } + + /// + /// Initialize the buttons when the dialog is loaded + /// + /// + /// + private void SharedDlgButtons_Load(object sender, EventArgs e) + { + unlockButton.Text = Strings.UnlockBtnText; + okButton.Text = Strings.CloseBtnText; + cancelButton.Text = Strings.CancelBtnText; + addButton.Text = Strings.AddBtnText; + removeButton.Text = Strings.RemoveBtnText; + upButton.Text = Strings.UpBtnText; + downButton.Text = Strings.DownBtnText; + editButton.Text = Strings.EditBtnText; + copyButton.Text = Strings.CopyBtnText; + newTabButton.Text = Strings.NewTabBtnText; + renameTabButton.Text = Strings.RenameTabBtnText; + removeTabButton.Text = Strings.RemoveTabBtnText; + + cancelButton.Hide(); + addButton.Hide(); + removeButton.Hide(); + upButton.Hide(); + downButton.Hide(); + editButton.Hide(); + copyButton.Hide(); + newTabButton.Hide(); + renameTabButton.Hide(); + removeTabButton.Hide(); + + /// Reposition 'Edit' and 'Copy" buttons in case both 'Up' and 'Down' are hidden + if (((OptionalButtons & Buttons.Up) == 0) && + ((OptionalButtons & Buttons.Down) == 0)) + { + editButton.Top = upButton.Top; + copyButton.Top = downButton.Top; + } + + /// Reposition Tab-related button in case both 'Edit' and 'Copy" are hidden + if (((OptionalButtons & Buttons.Edit) == 0) && + ((OptionalButtons & Buttons.Copy) == 0)) + { + removeTabButton.Top = newTabButton.Top + 15; + newTabButton.Top = editButton.Top + 15; + renameTabButton.Top = copyButton.Top + 15; + } + +#if DEBUG + //unlockBtn_Click(sender, e); +#endif + } + + /// + /// Update the visibility of buttons and OK button text when the dialog is unlocked + /// + public void UnlockButtons() + { + unlockButton.Enabled = false; + okButton.Text = Strings.OkBtnText; + cancelButton.Show(); + if ((OptionalButtons & Buttons.Add) != 0) addButton.Show(); + if ((OptionalButtons & Buttons.Remove) != 0) removeButton.Show(); + if ((OptionalButtons & Buttons.Up) != 0) upButton.Show(); + if ((OptionalButtons & Buttons.Down) != 0) downButton.Show(); + if ((OptionalButtons & Buttons.Edit) != 0) editButton.Show(); + if ((OptionalButtons & Buttons.Copy) != 0) copyButton.Show(); + if ((OptionalButtons & Buttons.NewTab) != 0) newTabButton.Show(); + if ((OptionalButtons & Buttons.RenameTab) != 0) renameTabButton.Show(); + if ((OptionalButtons & Buttons.RemoveTab) != 0) removeTabButton.Show(); + + lockState = LockState.Unlocked; + } + + /// + /// Enable specified buttons + /// + public void EnableButtons(Buttons buttons) + { + SetEnabled(buttons, true); + } + + /// + /// Disable specified buttons + /// + public void DisableButtons(Buttons buttons) + { + SetEnabled(buttons, false); + } + + public void SetEnabled(Buttons buttons, bool value) + { + if ((buttons & Buttons.OK) != 0) okButton.Enabled = value; + if ((buttons & Buttons.Cancel) != 0) cancelButton.Enabled = value; + if ((buttons & Buttons.Add) != 0) addButton.Enabled = value; + if ((buttons & Buttons.Remove) != 0) removeButton.Enabled = value; + if ((buttons & Buttons.Up) != 0) upButton.Enabled = value; + if ((buttons & Buttons.Down) != 0) downButton.Enabled = value; + if ((buttons & Buttons.Edit) != 0) editButton.Enabled = value; + if ((buttons & Buttons.Copy) != 0) copyButton.Enabled = value; + if ((buttons & Buttons.NewTab) != 0) newTabButton.Enabled = value; + if ((buttons & Buttons.RenameTab) != 0) renameTabButton.Enabled = value; + if ((buttons & Buttons.RemoveTab) != 0) removeTabButton.Enabled = value; + } + + void RestoreUser() + { + Entities.User.CurrentUser = originalUser; + Program.MainWnd.UpdateUser(); + } + + /// + /// Events invoked when buttons are clicked (and in case of Unlock kbutton also accepted) + /// + public event EventHandler Unlocked; + public event EventHandler OKClicked; + public event EventHandler CancelClicked; + public event EventHandler AddClicked; + public event EventHandler RemoveClicked; + public event EventHandler UpClicked; + public event EventHandler DownClicked; + public event EventHandler EditClicked; + public event EventHandler CopyClicked; + public event EventHandler NewTabClicked; + public event EventHandler RenameTabClicked; + public event EventHandler RemoveTabClicked; + + /// + /// 'Unlock' button handler + /// + /// + /// + private void unlockBtn_Click(object sender, EventArgs e) + { + if (lockState == LockState.Locked) + { + if (!Entities.User.CurrentUser.IsMemberOf(RequiredGroupMembership)) + { + if ((new LoginDlg(RequiredGroupMembership)).ShowDialog() != DialogResult.OK) return; + } + else if (Program.LocalSettings.AlwaysAskPasswdWhenUnlocking) + { + if ((new LoginDlg(Entities.User.CurrentUser.Name, RequiredGroupMembership)).ShowDialog() != DialogResult.OK) return; + } + + UnlockButtons(); + + if (Unlocked != null) Unlocked(sender, e); + } + } + + /// + /// 'OK'/'Close' button handler. Handled as 'Cancel' in the locked state ('Close' button). + /// + private void okBtn_Click(object sender, EventArgs e) + { + if (lockState == LockState.Locked) + { + if (CancelClicked != null) CancelClicked(sender, e); + } + else + { + if (OKClicked != null) OKClicked(sender, e); + } + } + + /// + /// All remaining handlers: + /// + private void cancelBtn_Click(object s, EventArgs e) { if (CancelClicked != null) CancelClicked(s, e); } + private void addBtn_Click(object s, EventArgs e) { if (AddClicked != null) AddClicked(s, e); } + private void removeBtn_Click(object s, EventArgs e) { if (RemoveClicked != null) RemoveClicked(s, e); } + private void upBtn_Click(object s, EventArgs e) { if (UpClicked != null) UpClicked(s, e); } + private void downBtn_Click(object s, EventArgs e) { if (DownClicked != null) DownClicked(s, e); } + private void editBtn_Click(object s, EventArgs e) { if (EditClicked != null) EditClicked(s, e); } + private void copyBtn_Click(object s, EventArgs e) { if (CopyClicked != null) CopyClicked(s, e); } + private void newTabButton_Click(object s, EventArgs e) { if (NewTabClicked != null) NewTabClicked(s, e); } + private void renameTabButton_Click(object s, EventArgs e) { if (RenameTabClicked != null) RenameTabClicked(s, e); } + private void removeTabButton_Click(object s, EventArgs e) { if (RemoveTabClicked != null) RemoveTabClicked(s, e); } + } +} diff --git a/TestBenchFramework/UiControls/SharedButtons.resx b/TestBenchFramework/UiControls/SharedButtons.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/TestBenchFramework/UiControls/SharedButtons.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/UiControls/TestParamsCtrl.Designer.cs b/TestBenchFramework/UiControls/TestParamsCtrl.Designer.cs new file mode 100644 index 000000000..6d91a66c0 --- /dev/null +++ b/TestBenchFramework/UiControls/TestParamsCtrl.Designer.cs @@ -0,0 +1,62 @@ +namespace TBF.UiControls +{ + partial class TestParamsCtrl + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.listViewEx = new TBF.UiControls.ListViewEx(); + this.SuspendLayout(); + // + // listViewEx + // + this.listViewEx.AllowColumnReorder = true; + this.listViewEx.Dock = System.Windows.Forms.DockStyle.Fill; + this.listViewEx.DoubleClickActivation = false; + this.listViewEx.FullRowSelect = true; + this.listViewEx.GridLines = true; + this.listViewEx.Location = new System.Drawing.Point(0, 0); + this.listViewEx.Name = "listViewEx"; + this.listViewEx.Size = new System.Drawing.Size(150, 150); + this.listViewEx.TabIndex = 0; + this.listViewEx.UseCompatibleStateImageBehavior = false; + this.listViewEx.View = System.Windows.Forms.View.Details; + // + // TestParamsCtrl + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.listViewEx); + this.Name = "TestParamsCtrl"; + this.ResumeLayout(false); + + } + + #endregion + + private ListViewEx listViewEx; + } +} diff --git a/TestBenchFramework/UiControls/TestParamsCtrl.cs b/TestBenchFramework/UiControls/TestParamsCtrl.cs new file mode 100644 index 000000000..76beb53d2 --- /dev/null +++ b/TestBenchFramework/UiControls/TestParamsCtrl.cs @@ -0,0 +1,193 @@ +using System; +using System.Collections.Generic; +using System.Windows.Forms; +using TBF.BenchControl.Generic; +using TBF.Resources; + +namespace TBF.UiControls +{ + // /-----------\ + // / Component \ + // |------------------------------ + // | param1 param2 param3 ... + // Test1 | + // Test2 | + // ... | + // + public partial class TestParamsCtrl : UserControl + { + ProcedureDlg parent; + bool showTestsColumn; + BenchControl.Generic.IComponent cmpnt; + + IList testsParams; + + int paramsCount; + + Control[] editors; + + bool unlocked; + public void Unlock(){ unlocked = true; } + + public TestParamsCtrl() + { + InitializeComponent(); + testsParams = new List(); + } + + public TestParamsCtrl(ProcedureDlg parent, BenchControl.Generic.IComponent cmpnt, bool showTestsColumn) + : this() + { + this.parent = parent; + this.showTestsColumn = showTestsColumn; + this.cmpnt = cmpnt; + unlocked = false; + + this.SuspendLayout(); + Dock = System.Windows.Forms.DockStyle.Fill; + listViewEx.Dock = System.Windows.Forms.DockStyle.Fill; + listViewEx.AllowColumnReorder = false; + listViewEx.DoubleClickActivation = false; + listViewEx.FullRowSelect = true; + listViewEx.GridLines = true; + listViewEx.Location = new System.Drawing.Point(0, 0); + listViewEx.TabIndex = 0; + listViewEx.UseCompatibleStateImageBehavior = false; + listViewEx.View = System.Windows.Forms.View.Details; + ResumeLayout(false); + } + + public void Initialize() + { + IParamsProvider sampleToCreateHeader = null; + + /// For each test (with an appropriate method in case of ITestMethod-s) + foreach (var test in parent.LoadedProcedure.Tests) + { + if (!(cmpnt is BenchControl.GenericDevices.ITestMethod) || test.Method == cmpnt.Cfg.Name) + { + /// Load ComponentTest entity or create it if it does not exist + IParamsProvider testParams = BenchControl.TbfComponents.GetTestParams(cmpnt, test); + if (testParams != null) + { + if (sampleToCreateHeader == null) sampleToCreateHeader = testParams; + } + else + { + Entities.ComponentTest entity = new Entities.ComponentTest(); + entity.CmpntName = cmpnt.Cfg.Name; + entity.Test = test; + testParams = cmpnt.Cfg.Factory.GetTestParams(entity); + } + testsParams.Add(testParams); + } + else + { + /// In case of ITestMethod: Insert null for a test without an appropriate method. + testsParams.Add(null); + } + } + + /// Create the header + if (sampleToCreateHeader != null) + { + if (showTestsColumn) listViewEx.Columns.Add(Strings.Test, 70); + + paramsCount = sampleToCreateHeader.ParamsCount(); + editors = new Control[paramsCount]; + for (int i = 0; i < paramsCount; i++) + { + listViewEx.Columns.Add(sampleToCreateHeader.ParamName(i), 90); + editors[i] = new TextBox(); + this.Controls.Add(editors[i]); + } + } + + listViewEx.SubItemClicked += new SubItemEventHandler(listViewEx_SubItemClicked); + listViewEx.SubItemEndEditing += new SubItemEndEditingEventHandler(listViewEx_SubItemEndEditing); + + RedrawAll(); + } + + private void listViewEx_SubItemClicked(object sender, SubItemEventArgs e) + { + int itemNr = showTestsColumn ? (e.SubItem - 1) : e.SubItem; + + if (!unlocked || e.Item.Tag == null || itemNr >= editors.Length || itemNr < 0) return; + listViewEx.StartEditing(editors[itemNr], e.Item, e.SubItem); + } + + private void listViewEx_SubItemEndEditing(object sender, SubItemEndEditingEventArgs e) + { + string message; + int itemNr = showTestsColumn ? (e.SubItem - 1) : e.SubItem; + + if ((e.Item.Tag as IParamsProvider).ValidateParam(itemNr, e.DisplayText, out message)) + { + (e.Item.Tag as IParamsProvider).UpdateParam(itemNr, e.DisplayText); + } + } + + public void RedrawAll() + { + listViewEx.Items.Clear(); + for (int i = 0; i < testsParams.Count && i < parent.LoadedProcedure.Tests.Count; i++) + { + DrawOne(testsParams[i], parent.LoadedProcedure.Tests[i].Name); + } + } + + void DrawOne(IParamsProvider item, string testName) + { + if (item == null) + { + listViewEx.Items.Add(new ListViewItem()); + return; + } + + ListViewItem lvi; + if (showTestsColumn) + { + lvi = new ListViewItem(testName); + lvi.SubItems.Add(item.ToString(0)); + } + else + { + lvi = new ListViewItem(item.ToString(0)); + } + for (int i = 1; i < paramsCount; i++) lvi.SubItems.Add(item.ToString(i)); + + lvi.Tag = item; + listViewEx.Items.Add(lvi); + } + + public void AddOne(Entities.Test test) + { + if (test.Method == cmpnt.Cfg.Name) + { + Entities.ComponentTest entity = new Entities.ComponentTest(); + entity.CmpntName = test.Method; + entity.Test = test; + IParamsProvider testParams = + new BenchControl.TestMethods.CombinedWithDetection.CombinedWithDetTestParams(entity, cmpnt.Cfg.Name, test); + testsParams.Add(testParams); + DrawOne(testParams, test.Name); + } + else + { + testsParams.Add(null); + DrawOne(null, null); + } + } + + public void UpdateAll() + { + if (!unlocked) return; + + foreach (ListViewItem lvi in listViewEx.Items) + { + if (lvi.Tag is IParamsProvider) (lvi.Tag as IParamsProvider).UpdateDbEntity(); + } + } + } +} diff --git a/TestBenchFramework/UiControls/TestParamsCtrl.resx b/TestBenchFramework/UiControls/TestParamsCtrl.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/TestBenchFramework/UiControls/TestParamsCtrl.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/UiControls/TestProgressCtrl.Designer.cs b/TestBenchFramework/UiControls/TestProgressCtrl.Designer.cs new file mode 100644 index 000000000..c7a90353c --- /dev/null +++ b/TestBenchFramework/UiControls/TestProgressCtrl.Designer.cs @@ -0,0 +1,73 @@ +namespace TBF.UiControls +{ + partial class TestProgressCtrl + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.testNameLabel = new System.Windows.Forms.Label(); + this.testProgressBar = new System.Windows.Forms.ProgressBar(); + this.SuspendLayout(); + // + // testNameLabel + // + this.testNameLabel.AutoSize = true; + this.testNameLabel.Font = new System.Drawing.Font("Verdana", 11.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238))); + this.testNameLabel.Location = new System.Drawing.Point(3, 5); + this.testNameLabel.Name = "testNameLabel"; + this.testNameLabel.Size = new System.Drawing.Size(51, 18); + this.testNameLabel.TabIndex = 0; + this.testNameLabel.Text = "label1"; + this.testNameLabel.Click += new System.EventHandler(this.TestProgressCtrl_Click); + // + // testProgressBar + // + this.testProgressBar.Location = new System.Drawing.Point(105, 2); + this.testProgressBar.Name = "testProgressBar"; + this.testProgressBar.Size = new System.Drawing.Size(100, 25); + this.testProgressBar.TabIndex = 1; + this.testProgressBar.Click += new System.EventHandler(this.TestProgressCtrl_Click); + // + // TestProgressCtrl + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.testProgressBar); + this.Controls.Add(this.testNameLabel); + this.Name = "TestProgressCtrl"; + this.Size = new System.Drawing.Size(207, 29); + this.Click += new System.EventHandler(this.TestProgressCtrl_Click); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label testNameLabel; + private System.Windows.Forms.ProgressBar testProgressBar; + } +} diff --git a/TestBenchFramework/UiControls/TestProgressCtrl.cs b/TestBenchFramework/UiControls/TestProgressCtrl.cs new file mode 100644 index 000000000..3d778ca19 --- /dev/null +++ b/TestBenchFramework/UiControls/TestProgressCtrl.cs @@ -0,0 +1,77 @@ +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace TBF.UiControls +{ + public partial class TestProgressCtrl : UserControl + { + public enum Result + { + NotDone, + Passed, + Failed, + } + + public Result TestResult + { + set + { + //switch (value) + //{ + // case Result.NotDone: resultPictureBox.Image = Properties.Resources.TestNotDoneImage; break; + // case Result.Passed: resultPictureBox.Image = Properties.Resources.TestPassedImage; break; + // case Result.Failed: resultPictureBox.Image = Properties.Resources.TestFailedImage; break; + //} + } + } + + public bool Selected; + + string testName; + public string TestName { get { return testName; } } + + int repetitionNr; + public int RepetitionNr { get { return repetitionNr; } } + + public string Title { set { testNameLabel.Text = value; } } + + public float Progress { set { testProgressBar.Value = (int)(100.499f * value); } } + public ProgressBar TestProgressBar { get { return testProgressBar; } } + + public TestProgressCtrl() + { + InitializeComponent(); + this.Progress = 0; + this.TestResult = UiControls.TestProgressCtrl.Result.NotDone; + } + + public TestProgressCtrl(string testName, int repetitionNr, int testRepeats) + : this() + { + this.testName = testName; + this.repetitionNr = repetitionNr; + this.Title = testName + string.Format(" ({0}/{1})", repetitionNr, testRepeats); + } + + public TestProgressCtrl(string testName) + : this(testName, 1, 1) + { + this.Title = testName; + } + + private void TestProgressCtrl_Click(object sender, System.EventArgs e) + { + if (Selected) + { + Selected = false; + BackColor = Color.Transparent; + } + else + { + Selected = true; + BackColor = Color.Orange; + } + } + } +} diff --git a/TestBenchFramework/UiControls/TestProgressCtrl.resx b/TestBenchFramework/UiControls/TestProgressCtrl.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/TestBenchFramework/UiControls/TestProgressCtrl.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestBenchFramework/UiControls/TransitionStepsCtrl.cs b/TestBenchFramework/UiControls/TransitionStepsCtrl.cs new file mode 100644 index 000000000..9dff7062f --- /dev/null +++ b/TestBenchFramework/UiControls/TransitionStepsCtrl.cs @@ -0,0 +1,219 @@ +using System.Collections.Generic; +using System.Windows.Forms; +using log4net; +using TBF.BenchControl; +using TBF.BenchControl.GenericDevices; +using TBF.Resources; + +namespace TBF.UiControls +{ + public partial class TransitionStepsCtrl : BaseWithListViewEx, ITabWithListViewEx + { + static readonly ILog log = LogManager.GetLogger(typeof(TransitionStepsCtrl)); + + /// + /// Fixed ListViewEx columns + /// + enum Column + { + Duration, + FixedColumnsCount, + } + readonly int fixedCount = (int)Column.FixedColumnsCount; + + Entities.TransitionSequence sequence; + + TransitionsDlg parent; + Control parentControl; + Control[] editors; + + int vCount; /// Number of valves + int regvCount; /// Number of regulating valves + + public TransitionStepsCtrl() + : base() + { + } + + public void Initialize(Entities.TransitionSequence sequence, TransitionsDlg parent, Control parentControl) + { + this.sequence = sequence; + this.parent = parent; + this.parentControl = parentControl; + Name = sequence.Name; + MyItems = sequence.TransitionSteps; + + SubItemClicked += new SubItemEventHandler(listViewEx_SubItemClicked); + SubItemEndEditing += new SubItemEndEditingEventHandler(listViewEx_SubItemEndEditing); + + vCount = parent.Valves.Count; + regvCount = parent.RegulValves.Count; + + /// + /// ListViewEx columns + /// + Columns.Add(Strings.Duration_s, 60 * parent.Dpi / PathsDlg.Dpi100pct); + foreach (var vlv in parent.Valves) + { + Columns.Add(vlv.Cfg.Name, 50 * parent.Dpi / PathsDlg.Dpi100pct); + } + foreach (var rvlv in parent.RegulValves) + { + Columns.Add(rvlv.Cfg.Name + " [%]", 50 * parent.Dpi / PathsDlg.Dpi100pct); + } + + /// + /// Prepare valve combo-boxes (max. 64 valves) + /// + editors = new Control[fixedCount + vCount + regvCount]; + + editors[0] = new TextBox(); /// Duration + parent.Controls.Add(editors[0]); + + for (int i = fixedCount; i < fixedCount + vCount; i++) + { + ComboBox cb = new ComboBox(); + cb.Items.Add("---"); + cb.Items.Add(Strings.open); + cb.Items.Add(Strings.close); + editors[i] = cb; + parent.Controls.Add(cb); + } + + for (int i = fixedCount + vCount; i < fixedCount + vCount + regvCount; i++) + { + editors[i] = new TextBox(); + parent.Controls.Add(editors[i]); + } + + base.RedrawAll(); + } + + void listViewEx_SubItemClicked(object sender, SubItemEventArgs e) + { + if (!Unlocked || e.SubItem >= editors.Length) return; + StartEditing(editors[e.SubItem], e.Item, e.SubItem); + } + + void listViewEx_SubItemEndEditing(object sender, SubItemEndEditingEventArgs e) + { + if (e.SubItem == (int)Column.Duration) + { + int duration; + if (!int.TryParse(e.DisplayText, out duration) || duration <= 0) + { + e.DisplayText = e.Item.Text; + e.Cancel = true; + } + } + } + + public override void DrawOne(object myItem) + { + Entities.TransitionStep step = (Entities.TransitionStep)myItem; + + IList valvesOpen = new List(); + if (step.ValvesOpen != null) + { + string[] vOpen = step.ValvesOpen.Split(new char[] { ';' }); + foreach (var vName in vOpen) valvesOpen.Add((IValve)TbfComponents.FindComponent(vName, parent.TbfComponents)); + } + + IList valvesClose = new List(); + if (step.ValvesClose != null) + { + string[] vClose = step.ValvesClose.Split(new char[] { ';' }); + foreach (var vName in vClose) valvesClose.Add((IValve)TbfComponents.FindComponent(vName, parent.TbfComponents)); + } + + ListViewItem lvi = new ListViewItem(step.Duration.ToString()); + + foreach (var valve in parent.Valves) + { + if (valvesOpen != null && valvesOpen.Contains(valve)) + { + lvi.SubItems.Add(Strings.open); + } + else if (valvesClose != null && valvesClose.Contains(valve)) + { + lvi.SubItems.Add(Strings.close); + } + else + { + lvi.SubItems.Add("---"); + } + } + + string[] rvPosStr = (step.RegulValvesPct != null) ? step.RegulValvesPct.Split(new char[] { ';' }) + : new string[0]; + for (int i = 0; i < regvCount; i++) + { + lvi.SubItems.Add((i < rvPosStr.Length) ? rvPosStr[i] : "---"); + } + + lvi.Tag = step; + + Items.Add(lvi); + } + + public override void UpdateOne(ListViewItem lvi, object myItem) + { + Entities.TransitionStep step = (Entities.TransitionStep)myItem; + + /// Duration + try + { + step.Duration = int.Parse(lvi.Text); + if (step.Duration < 2) throw (new System.Exception()); + } + catch { lvi.Text = step.Duration.ToString(); } + + /// Valves + string valvesOpen = string.Empty; + string valvesClose = string.Empty; + for (int j = 0; j < vCount; j++) + { + string text = lvi.SubItems[fixedCount + j].Text; + if (text.Equals(Strings.open)) + { + if (valvesOpen != string.Empty) valvesOpen += ";"; + valvesOpen += parent.Valves[j].Cfg.Name; + } + if (text.Equals(Strings.close)) + { + if (valvesClose != string.Empty) valvesClose += ";"; + valvesClose += parent.Valves[j].Cfg.Name; + } + } + step.ValvesOpen = valvesOpen; + step.ValvesClose = valvesClose; + + string regulValvesPct = string.Empty; + for (int j = fixedCount + vCount; j < fixedCount + vCount + regvCount; j++) + { + if (regulValvesPct.Length > 0) regulValvesPct += ";"; + float fdummy; + if (lvi.SubItems[j].Text.Equals("---") || + (Utils.TryParseUFloat(lvi.SubItems[j].Text, out fdummy) && (fdummy >= 0) && (fdummy <= 100.0f))) + { + regulValvesPct += lvi.SubItems[j].Text; + } + } + step.RegulValvesPct = regulValvesPct; + } + + public void AddOne() + { + base.AddOne(new Entities.TransitionStep(MyItems.Count, sequence)); + } + + public new void RemoveSelected() + { + bool lastItemRemoved = base.RemoveSelected(); + if (lastItemRemoved && parent != null) + { + parent.UpdateButtonStates(SharedButtons.SelectedItemPos.None); + } + } + } +} diff --git a/TestBenchFramework/Utils.cs b/TestBenchFramework/Utils.cs new file mode 100644 index 000000000..f3b188420 --- /dev/null +++ b/TestBenchFramework/Utils.cs @@ -0,0 +1,136 @@ +using System.Collections.Generic; +using System.Globalization; + +namespace TBF +{ + public class Utils + { + /// + /// Parse unsigned float + /// + public static bool TryParseUFloat(string text, out float result) + { + return float.TryParse(text, NumberStyles.AllowDecimalPoint, CultureInfo.CurrentCulture, out result) || + float.TryParse(text, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out result); + } + public static float ParseUFloat(string text, float dfltVal) + { + float result; + if (float.TryParse(text, NumberStyles.AllowDecimalPoint, CultureInfo.CurrentCulture, out result)) return result; + if (float.TryParse(text, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out result)) return result; + return dfltVal; + } + public static float ParseUFloat(string text) + { + return ParseUFloat(text, 0); + } + + /// + /// Parse float, sign allowed + /// + public static bool TryParseSFloat(string text, out float result) + { + return float.TryParse(text, NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign, CultureInfo.CurrentCulture, out result) || + float.TryParse(text, NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign, CultureInfo.InvariantCulture, out result); + } + public static float ParseSFloat(string text, float dfltVal) + { + float result; + if (float.TryParse(text, NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign, CultureInfo.CurrentCulture, out result)) return result; + if (float.TryParse(text, NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign, CultureInfo.InvariantCulture, out result)) return result; + return dfltVal; + } + public static float ParseSFloat(string text) + { + return ParseSFloat(text, 0); + } + + /// + /// Parse float, sign allowed, exponent allowed + /// + public static bool TryParseEFloat(string text, out float result) + { + return float.TryParse(text, NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign | NumberStyles.AllowExponent, CultureInfo.CurrentCulture, out result) || + float.TryParse(text, NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign | NumberStyles.AllowExponent, CultureInfo.InvariantCulture, out result); + } + public static float ParseEFloat(string text, float dfltVal) + { + float result; + if (float.TryParse(text, NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign | NumberStyles.AllowExponent, CultureInfo.CurrentCulture, out result)) return result; + if (float.TryParse(text, NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign | NumberStyles.AllowExponent, CultureInfo.InvariantCulture, out result)) return result; + return dfltVal; + } + public static float ParseEFloat(string text) + { + return ParseEFloat(text, 0); + } + + /// + /// Get a list of IValve-s from an entity implementing IHasValves + /// + /// Entity implementing IHasValves + /// A list of IValves + public static IList ValvesOpen(Entities.IHasValves entity) + { + var valvesOpen = new List(); + if (entity != null && entity.ValvesOpen != null && entity.ValvesOpen != string.Empty) + { + string[] vOpen = entity.ValvesOpen.Split(new char[] { ';' }); + foreach (var vName in vOpen) + { + valvesOpen.Add((BenchControl.GenericDevices.IValve)BenchControl + .TbfComponents.FindComponent(vName)); + } + } + return valvesOpen; + } + + /// + /// Get a list of IValve-s from an entity implementing IHasValves + /// + /// Entity implementing IHasValves + /// A list of IValves + public static IList ValvesClose(Entities.IHasValves entity) + { + var valvesClose = new List(); + if (entity != null && entity.ValvesClose != null && entity.ValvesClose != string.Empty) + { + string[] vClose = entity.ValvesClose.Split(new char[] { ';' }); + foreach (var vName in vClose) + { + valvesClose.Add((BenchControl.GenericDevices.IValve)BenchControl + .TbfComponents.FindComponent(vName)); + } + } + return valvesClose; + } + + /// + /// Get an array of RegulValve positions from a TransitionStep entity + /// + /// TransitionStep entity + /// float[] of regulation valve positions from 0 to 100.0f + public static float[] RegulValvesPositions(Entities.TransitionStep step) + { + int regvCount = BenchControl.Sequences.SequenceBase.RegulValves.Count; + float[] result = new float[regvCount]; + + string[] rvPosStr = (step.RegulValvesPct != null) ? step.RegulValvesPct.Split(new char[] { ';' }) : new string[0]; + for (int i = 0; i < regvCount; i++) + { + float fdummy; + if ((i < rvPosStr.Length) && Utils.TryParseUFloat(rvPosStr[i], out fdummy) && + (fdummy >= 0) && (fdummy <= 100.0f)) + { + result[i] = fdummy; + } + else // if (rvPosStr[i].Equals("---")) + { + result[i] = -1.0f; /// Negative value means no regulation valve position change + } + } + + return result; + } + } +} diff --git a/TestBenchFramework/app.config b/TestBenchFramework/app.config new file mode 100644 index 000000000..86fcc8b74 --- /dev/null +++ b/TestBenchFramework/app.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/TestBenchFramework/packages.config b/TestBenchFramework/packages.config new file mode 100644 index 000000000..0808d8c6e --- /dev/null +++ b/TestBenchFramework/packages.config @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/TestBenchFramework/x64/SQLite.Interop.dll b/TestBenchFramework/x64/SQLite.Interop.dll new file mode 100644 index 0000000000000000000000000000000000000000..30e752000fa1c3d010f9d4b8c344e13bd1c94e6f GIT binary patch literal 1123840 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

!LDY9h>DwLNEf|rP}k#6~AR2j}o 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

M)g4cKN5;yDdza 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