feat: Add symbol loading functionality from ASC files
- Implemented a new utility class `SymbolLoader` to parse Siemens ASC symbol files and save the output in JSON format. - Created a `SymbolProcessor` class to handle symbol-based variable processing, including loading symbols and expanding configurations. - Developed frontend components `FilePathWidget` and `SymbolSelectorWidget` for file selection and symbol selection respectively. - Added API endpoints for loading symbols and browsing files. - Introduced test scripts for validating the symbol loader and endpoint functionality. - Added sample ASC and JSON files for testing purposes.
This commit is contained in:
parent
16355c4106
commit
e3b1b48556
|
@ -0,0 +1,674 @@
|
|||
"_CYCL_EXC ","OB 1 ","OB 1 ","Cycle Execution "
|
||||
"_StepMove ","FC 1851 ","FC 1851 ","MIX - "
|
||||
"AG_RECV ","FC 206 ","FC 206 ","AG RECEIVE "
|
||||
"AG_SEND ","FC 205 ","FC 205 ","AG_SEND "
|
||||
"AI_CTM304 ","PEW 844 ","WORD ","CTM304 - Product Conductivity "
|
||||
"AI_CTS301 ","PEW 850 ","WORD ","CTS301 - Local Cip Return Conductivity "
|
||||
"AO_RVP305 ","PAW 828 ","WORD ","RVP305 - Syrup 2 Tank Level Valve "
|
||||
"AO_RVS318 ","PAW 850 ","WORD ","RVS318 - Local Cip Heating Valve "
|
||||
"AO_ToFillerEqPress ","PAW 840 ","WORD ","FILLER - Product Saturation Pressure [0.0 <20> 100.0 Bar/10] "
|
||||
"APCO ","VAT 22 "," "," "
|
||||
"AUX AMPOLLINI ","M 5.0 ","BOOL ","Always OFF - AMPOLLINI USE "
|
||||
"AUX Blink_0.1S ","M 0.0 ","BOOL ","PLC Blink 0.1 Sec. 10Hz "
|
||||
"AUX Blink_0.2S ","M 0.1 ","BOOL ","PLC Blink 0.2 Sec. 5Hz "
|
||||
"AUX Blink_0.4S ","M 0.2 ","BOOL ","PLC Blink 0.4 Sec. 2,5Hz "
|
||||
"AUX Blink_0.5S ","M 0.3 ","BOOL ","PLC Blink 0.5 Sec. 2Hz "
|
||||
"AUX Blink_0.8S ","M 0.4 ","BOOL ","PLC Blink 0.8 Sec. 1,25Hz "
|
||||
"AUX Blink_1.0S ","M 0.5 ","BOOL ","PLC Blink 1.0 Sec. 1Hz "
|
||||
"AUX Blink_1.6S ","M 0.6 ","BOOL ","PLC Blink 1.6 Sec. 0,625Hz "
|
||||
"AUX Blink_2.0S ","M 0.7 ","BOOL ","PLC Blink 2.0 Sec. 0,5Hz "
|
||||
"AUX CASSARINO ","M 5.3 ","BOOL ","Always OFF - CASSARINO USE "
|
||||
"AUX Clock_0.1s ","M 1.7 ","BOOL ","TIMER 0.1 sec. CLOCK "
|
||||
"AUX Clock_1.0s ","M 1.5 ","BOOL ","TIMER 1.0 sec. CLOCK "
|
||||
"AUX FALSE ","M 3.0 ","BOOL ","Always OFF "
|
||||
"AUX FALSE_Test ","M 1.0 ","BOOL ","Always OFF for debugging purpose "
|
||||
"AUX FIELD OFF ","MB 7 ","BYTE ","Always OFF - FIELD USE "
|
||||
"AUX FIELD SPARE 70 ","M 7.0 ","BOOL ","Always OFF - FIELD SPARE 7.0 USE "
|
||||
"AUX FIELD SPARE 71 ","M 7.1 ","BOOL ","Always OFF - FIELD SPARE 7.1 USE "
|
||||
"AUX FIELD SPARE 72 ","M 7.2 ","BOOL ","Always OFF - FIELD SPARE 7.2 USE "
|
||||
"AUX FIELD SPARE 73 ","M 7.3 ","BOOL ","Always OFF - FIELD SPARE 7.3 USE "
|
||||
"AUX FIELD SPARE 74 ","M 7.4 ","BOOL ","Always OFF - FIELD SPARE 7.4 USE "
|
||||
"AUX FIELD SPARE 75 ","M 7.5 ","BOOL ","Always OFF - FIELD SPARE 7.5 USE "
|
||||
"AUX FIELD SPARE 76 ","M 7.6 ","BOOL ","Always OFF - FIELD SPARE 7.6 USE "
|
||||
"AUX FIELD SPARE 77 ","M 7.7 ","BOOL ","Always OFF - FIELD SPARE 7.7 USE "
|
||||
"AUX FP_Clock_0.1s ","M 2.0 ","BOOL ","FP TIMER 0.1 sec. CLOCK "
|
||||
"AUX FP_Clock_1.0s ","M 2.1 ","BOOL ","FP TIMER 1.0 sec. CLOCK "
|
||||
"AUX MARCHI ","M 6.0 ","BOOL ","Always OFF - MARCHI USE "
|
||||
"AUX MASTER OFF ","MB 4 ","BYTE ","Always OFF - MASTER USE "
|
||||
"AUX MASTER VALIDATION ","M 4.0 ","BOOL ","Always OFF - Master Validation Waiting "
|
||||
"AUX MORI ","M 5.2 ","BOOL ","Always OFF - MORI USE "
|
||||
"AUX PASSERA ","M 5.1 ","BOOL ","Always OFF - PASSERA USE "
|
||||
"AUX PESCI ","M 6.1 ","BOOL ","Always OFF - PESCI USE "
|
||||
"AUX SSAE CUSTOMIZATION ","M 4.1 ","BOOL ","Always OFF - SSAE Customization "
|
||||
"AUX Start CPU ","M 1.2 ","BOOL ","Start CPU "
|
||||
"AUX TEST OFF ","MB 6 ","BYTE ","Always OFF - TEST USE "
|
||||
"AUX TEST SPARE 62 ","M 6.2 ","BOOL ","Always OFF - TEST SPARE 6.2 USE "
|
||||
"AUX TEST SPARE 63 ","M 6.3 ","BOOL ","Always OFF - TEST SPARE 6.3 USE "
|
||||
"AUX TEST SPARE 64 ","M 6.4 ","BOOL ","Always OFF - TEST SPARE 6.4 USE "
|
||||
"AUX TEST SPARE 65 ","M 6.5 ","BOOL ","Always OFF - TEST SPARE 6.5 USE "
|
||||
"AUX TEST SPARE 66 ","M 6.6 ","BOOL ","Always OFF - TEST SPARE 6.6 USE "
|
||||
"AUX TEST SPARE 67 ","M 6.7 ","BOOL ","Always OFF - TEST SPARE 6.7 USE "
|
||||
"AUX TRUE ","M 3.1 ","BOOL ","Always ON "
|
||||
"AUX UTE OFF ","MB 5 ","BYTE ","Always OFF - UTE USE "
|
||||
"AUX UTE SPARE 54 ","M 5.4 ","BOOL ","Always OFF - UTE SPARE 5.4 USE "
|
||||
"AUX UTE SPARE 55 ","M 5.5 ","BOOL ","Always OFF - UTE SPARE 5.5 USE "
|
||||
"AUX UTE SPARE 56 ","M 5.6 ","BOOL ","Always OFF - UTE SPARE 5.6 USE "
|
||||
"AUX UTE SPARE 57 ","M 5.7 ","BOOL ","Always OFF - UTE SPARE 5.7 USE "
|
||||
"AVS Valve Fault DB ","DB 959 ","DB 959 ","MIX - AVS Valve Fault DB "
|
||||
"Baialage ","FC 1804 ","FC 1804 ","MIX - Baialage "
|
||||
"Blender_Constants ","DB 972 ","DB 972 ","MIX - Blender Constants "
|
||||
"Blender_Procedure Data ","DB 930 ","FB 1800 ","MIX - Blender_ProcedureCall Data "
|
||||
"Blender_ProcedureCall ","FB 1800 ","FB 1800 ","MIX - Blender_Procedure Call "
|
||||
"Blender_Variables ","DB 971 ","DB 971 ","MIX - Blender Variables "
|
||||
"Blender_Variables_Pers ","DB 970 ","DB 970 ","MIX - Blender Variables - Persistent "
|
||||
"BlenderCtrl__Main ","FC 2000 ","FC 2000 ","MIX - Blender Ctrl Main "
|
||||
"BlenderCtrl_All Auto ","FC 2036 ","FC 2036 ","MIX - BlenderCtrl_All Auto "
|
||||
"BlenderCtrl_CIPModeInit ","FC 2013 ","FC 2013 ","MIX - CIP Mode Init "
|
||||
"BlenderCtrl_InitErrors ","FC 2001 ","FC 2001 ","MIX - Init Errors "
|
||||
"BlenderCtrl_MachineInit ","FC 2003 ","FC 2003 ","MIX - BlenderCtrl_MachineInit "
|
||||
"BlenderCtrl_ManualActive","FC 2037 ","FC 2037 ","MIX - ManualActive "
|
||||
"BlenderCtrl_MFM Command ","FC 2033 ","FC 2033 ","MIX - MFM Command "
|
||||
"BlenderCtrl_ProdModeInit","FC 2012 ","FC 2012 ","MIX - Production Mode Init "
|
||||
"BlenderCtrl_ResetSPWord ","FC 2014 ","FC 2014 ","MIX - BlenderCtrl_ResetSPWord "
|
||||
"BlenderCtrl_UpdatePWord ","FC 2034 ","FC 2034 ","MIX - _Blender_Ctrl_Main.Update_P_Word "
|
||||
"BlenderPID__Main ","FB 1750 ","FB 1750 ","MIX - Blender PID Main "
|
||||
"BlenderPID__Main_Data ","DB 950 ","FB 1750 ","MIX - Blender_PID_Main_Data "
|
||||
"BlenderPID_ActualRecipe ","FB 1919 ","FB 1919 "," "
|
||||
"BlenderPID_BlendingFault","FB 1753 ","FB 1753 ","MIX - PID_Blending_Fault "
|
||||
"BlenderPID_FlowMeterErro","FC 1915 ","FC 1915 ","MIX - Flow_Meter_Error "
|
||||
"BlenderPID_NextRecipe ","FC 1916 ","FC 1916 ","MIX - Next_Recipe "
|
||||
"BlenderPID_PIDFFCalc ","FB 1752 ","FB 1752 ","MIX - PID_FF_Calc "
|
||||
"BlenderPID_PIDInitParam ","FB 1755 ","FB 1755 ","MIX - PID_Init_Parameters "
|
||||
"BlenderPID_PIDResInteg ","FC 1914 ","FC 1914 ","MIX - PID_Reset_Integral "
|
||||
"BlenderPID_PIDSPCalc ","FB 1751 ","FB 1751 ","MIX - PID_SP_Calc "
|
||||
"BlenderPIDCtrl__Loop ","FB 1729 ","FB 1729 ","MIX - PID Block Main "
|
||||
"BlenderPIDCtrl_Monitor ","FB 1787 ","FB 1787 ","MIX - PID_Monitor "
|
||||
"BlenderPIDCtrl_PresRelea","FC 1917 ","FC 1917 ","MIX - Pressure_Release "
|
||||
"BlenderPIDCtrl_SaveInteg","FB 1788 ","FB 1788 ","MIX - Save_Integral "
|
||||
"BlenderPIDCtrl_SaveValve","FC 1918 ","FC 1918 ","MIX - Save_Valve_Out "
|
||||
"BlenderPIDCtrl_WriteAnOu","FC 1925 ","FC 1925 ","MIX - BlenderPIDCtrl_WriteAnOu "
|
||||
"BlenderRinse ","FC 2019 ","FC 2019 ","MIX - Blender Rinse "
|
||||
"BlenderRinse_Done ","FC 2042 ","FC 2042 ","MIX - Rinse Done "
|
||||
"BlenderRun__Control ","FC 2015 ","FC 2015 ","MIX - Blender Run Control "
|
||||
"BlenderRun_MeasFil_Data ","DB 974 ","FB 1719 ","MIX - Measure Filler Speed Data "
|
||||
"BlenderRun_MeasFilSpeed ","FB 1719 ","FB 1719 ","MIX - Measure Filler Speed "
|
||||
"BlenderRun_ProdTime ","FC 2040 ","FC 2040 ","MIX - Production Time "
|
||||
"BlenderRun_SelectConstan","FC 2038 ","FC 2038 ","MIX - Select Blender Constant "
|
||||
"BlenderRun_Stopping ","FC 2041 ","FC 2041 ","MIX - Stopping Blender "
|
||||
"BlendFill StartUp ","FB 1814 ","FB 1814 ","MIX - BlendFill StartUp "
|
||||
"BlendFill StartUp_Seq ","FC 1814 ","FC 1814 ","MIX - Blend Fill System StartUp Sequencer "
|
||||
"BLKMOV ","SFC 20 ","SFC 20 ","MIX - Copy Variables "
|
||||
"Block_compare ","FC 61 ","FC 61 "," "
|
||||
"Block_move ","FC 60 ","FC 60 ","Move blocks from DB to DB "
|
||||
"BrixTracking ","FB 1801 ","FB 1801 ","MIX - Brix Tracking "
|
||||
"BrixTracking_Data ","DB 975 ","FB 1801 ","MIX - Brix Tracking Data "
|
||||
"BrixTracking_ProdSamples","FB 1705 ","FB 1705 ","MIX - Prod Samples "
|
||||
"BrixTracking_SampleTime ","FB 1706 ","FB 1706 ","MIX - Sample Time Calc "
|
||||
"Buffer_Tank_Flooding_DB ","DB 101 ","DB 101 ","Buffer Tank Flooding DB "
|
||||
"Buffer_Tank_Flushing ","FC 101 ","FC 101 ","Product Tank Flushing "
|
||||
"CarboWaterLine ","FB 1802 ","FB 1802 ","MIX - CarboWaterLine "
|
||||
"CarboWaterLine_Seq ","FC 1802 ","FC 1802 ","MIX - CarboWaterLine Sequencer "
|
||||
"Cetrifugal_Head ","FC 1842 ","FC 1842 ","MIX - Cetrifugal_Head "
|
||||
"CIP CVQ ","FC 1905 ","FC 1905 ","MIX - CIP_CVQ "
|
||||
"CIP Prog Control ","FC 82 ","FC 82 ","MIX - CIP program condition control "
|
||||
"CIP_Link_Type ","UDT 900 ","UDT 900 ","MIX - CIP_Link_Type "
|
||||
"CIP_Program_Variables ","DB 963 ","DB 963 ","MIX - CIP Program Variables "
|
||||
"CIP_Simple_Type ","UDT 901 ","UDT 901 ","MIX - CIP_Simple_Type "
|
||||
"CIP_SimpleProgr_Init ","FC 1936 ","FC 1936 ","MIX - CIP_SimpleProgr_Initialize "
|
||||
"CIP_Step_Type ","UDT 903 ","UDT 903 ","MIX - CIP_Step_Type "
|
||||
"CIP_Step_Type_New ","UDT 899 ","UDT 899 ","MIX - CIP_Step_Type "
|
||||
"CIP_WaitEvent_Type ","UDT 902 ","UDT 902 ","MIX - CIP_WaitEvent_Type "
|
||||
"CIPLocal ","FC 1933 ","FC 1933 ","MIX - CIP Local "
|
||||
"CIPLocal_DSCtrl ","FC 1940 ","FC 1940 ","MIX - ICS "
|
||||
"CIPLocal_ExecSimpleCIP ","FC 1935 ","FC 1935 ","MIX - Execute CIP program "
|
||||
"CIPLocal_ExecStep ","FC 1941 ","FC 1941 ","MIX - "
|
||||
"CIPLocal_ManualVolDosing","FC 1943 ","FC 1943 ","MIX - CIP Local Manual Volume Dosing "
|
||||
"CIPLocal_ProgInizialize ","FC 1937 ","FC 1937 ","MIX - CIP program inizialization "
|
||||
"CIPLocal_ProgStepDown ","FC 1938 ","FC 1938 ","MIX - "
|
||||
"CIPLocal_ProgStepUp ","FC 1939 ","FC 1939 ","MIX - "
|
||||
"CIPLocal_SyrupPipeCIP ","FC 1944 ","FC 1944 ","MIX - CIP Local Syrup Pipe CIP "
|
||||
"CIPLocal_WaitEvent_Ctrl ","FC 1934 ","FC 1934 ","MIX - CIPLocal_WaitEvent_Ctrl "
|
||||
"CIPLocal_WaterPipeCIP ","FC 1942 ","FC 1942 ","MIX - CIP Local Water Pipe CIP "
|
||||
"CIPMain ","FC 1930 ","FC 1930 ","MIX - "
|
||||
"CIPMain_Flood ","FC 1931 ","FC 1931 ","MIX - "
|
||||
"CIPMain_Total Drain ","FC 1932 ","FC 1932 ","MIX - "
|
||||
"CIPRecipe#01 ","DB 501 ","DB 501 ","CIPRecipe#01 "
|
||||
"CIPRecipe#02 ","DB 502 ","DB 502 ","CIPRecipe#02 "
|
||||
"CIPRecipe#03 ","DB 503 ","DB 503 ","CIPRecipe#03 "
|
||||
"CIPRecipe#04 ","DB 504 ","DB 504 ","CIPRecipe#04 "
|
||||
"CIPRecipe#05 ","DB 505 ","DB 505 ","CIPRecipe#05 "
|
||||
"CIPRecipe#06 ","DB 506 ","DB 506 ","CIPRecipe#06 "
|
||||
"CIPRecipe#07 ","DB 507 ","DB 507 ","CIPRecipe#07 "
|
||||
"CIPRecipe#08 ","DB 508 ","DB 508 ","CIPRecipe#08 "
|
||||
"CIPRecipe#09 ","DB 509 ","DB 509 ","CIPRecipe#09 "
|
||||
"CIPRecipe#10 ","DB 510 ","DB 510 ","CIPRecipe#10 "
|
||||
"CIPRecipe#11 ","DB 511 ","DB 511 ","CIPRecipe#11 "
|
||||
"CIPRecipe#12 ","DB 512 ","DB 512 ","CIPRecipe#12 "
|
||||
"CIPRecipe#13 ","DB 513 ","DB 513 ","CIPRecipe#13 "
|
||||
"CIPRecipe#14 ","DB 514 ","DB 514 ","CIPRecipe#14 "
|
||||
"CIPRecipe#15 ","DB 515 ","DB 515 ","CIPRecipe#15 "
|
||||
"CIPRecipe#26 ","DB 526 ","DB 526 ","CIPRecipe#26 "
|
||||
"CIPRecipe#27 ","DB 527 ","DB 527 ","CIPRecipe#27 "
|
||||
"CIPRecipe#28 ","DB 528 ","DB 528 ","CIPRecipe#28 "
|
||||
"CIPRecipe#29 ","DB 529 ","DB 529 ","CIPRecipe#29 "
|
||||
"CIPRecipe#30 ","DB 530 ","DB 530 ","CIPRecipe#30 "
|
||||
"CIPRepComment ","MW 602 ","INT ","CIP Report Comment "
|
||||
"CIPRepFaultPresent ","M 601.4 ","BOOL ","CIP Report Fault Present "
|
||||
"CIPReportDB ","DB 600 ","DB 600 "," "
|
||||
"CIPReportManager ","FC 600 ","FC 600 "," "
|
||||
"CIPRepStarted ","M 600.0 ","BOOL ","CIP Report Started "
|
||||
"CIPSimple_Drain ","DB 543 ","DB 543 ","MIX - ICS "
|
||||
"CIPSimple_Empty ","DB 540 ","DB 540 ","MIX - ICS "
|
||||
"CIPSimple_Flood ","DB 544 ","DB 544 ","MIX - ICS "
|
||||
"CIPSimple_Recirculation ","DB 542 ","DB 542 ","MIX - ICS "
|
||||
"CIPSimple_Recover ","DB 547 ","DB 547 ","MIX - ICS "
|
||||
"CIPSimple_Rinse ","DB 541 ","DB 541 ","MIX - ICS "
|
||||
"CIPSimple_RinseCO2 ","DB 545 ","DB 545 ","MIX - ICS "
|
||||
"CIPSimple_Start ","DB 546 ","DB 546 ","MIX - ICS "
|
||||
"CLK_0.1S ","M 1931.0 ","BOOL ","MIX - CLK_0.1S "
|
||||
"CLK_0.1S_SUPPORT ","M 1930.0 ","BOOL ","MIX - CLK_0.1S_SUPPORT "
|
||||
"CLK_0.2S ","M 1931.1 ","BOOL ","MIX - CLK_0.2S "
|
||||
"CLK_0.2S_SUPPORT ","M 1930.1 ","BOOL ","MIX - CLK_0.2S_SUPPORT "
|
||||
"CLK_0.4S ","M 1931.2 ","BOOL ","MIX - CLK_0.4S "
|
||||
"CLK_0.4S_SUPPORT ","M 1930.2 ","BOOL ","MIX - CLK_0.4S_SUPPORT "
|
||||
"CLK_0.5S ","M 1931.3 ","BOOL ","MIX - CLK_0.5S "
|
||||
"CLK_0.5S_SUPPORT ","M 1930.3 ","BOOL ","MIX - CLK_0.5S_SUPPORT "
|
||||
"CLK_0.8S ","M 1931.4 ","BOOL ","MIX - CLK_0.8S "
|
||||
"CLK_0.8S_SUPPORT ","M 1930.4 ","BOOL ","MIX - CLK_0.8S SUPPORT "
|
||||
"CLK_1.0S ","M 1931.5 ","BOOL ","MIX - CLK_1.0S "
|
||||
"CLK_1.0S_SUPPORT ","M 1930.5 ","BOOL ","MIX - CLK_1.0S_SUPPORT "
|
||||
"CLK_1.6S ","M 1931.6 ","BOOL ","MIX - CLK_1.6S "
|
||||
"CLK_1.6S_SUPPORT ","M 1930.6 ","BOOL ","MIX - CLK_1.6S_SUPPORT "
|
||||
"CLK_2.0S ","M 1931.7 ","BOOL ","MIX - CLK_2.0S "
|
||||
"CLK_2.0S_SUPPORT ","M 1930.7 ","BOOL ","MIX - CLK_2.0S_SUPPORT "
|
||||
"Clock Signal ","FC 1860 ","FC 1860 ","MIX - Clock Generation "
|
||||
"CO2 Solubility ","FC 1911 ","FC 1911 ","MIX - CO2_Solubility "
|
||||
"CO2EqPress ","FC 1908 ","FC 1908 ","MIX - CO2_Eq_Press "
|
||||
"CO2InjPressure ","FC 1923 ","FC 1923 ","MIX - CO2_Injection_Pressure "
|
||||
"CO2Tracking ","FB 1818 ","FB 1818 ","MIX - CO2Tracking "
|
||||
"CO2Tracking_Data ","DB 976 ","FB 1818 ","MIX - CO2 Tracking Data "
|
||||
"CO2Tracking_ProdSamples ","FB 1709 ","FB 1709 ","MIX - CO2Tracking_ProdSamples "
|
||||
"CO2Tracking_SampleTime ","FB 1710 ","FB 1710 ","MIX - CO2Tracking_SampleTime "
|
||||
"Co2TrackingLatch ","M 1906.7 ","BOOL ","MIX - FP******* "
|
||||
"Co2TrackingReq ","M 1906.6 ","BOOL ","MIX - FP****** "
|
||||
"COMM_FLT ","OB 87 ","OB 87 ","Communication Fault "
|
||||
"COMPLETE RESTART ","OB 100 ","OB 100 ","Complete Restart "
|
||||
"CONCAT ","FC 2 ","FC 2 ","Concatenate String "
|
||||
"CPU_DP Global Diag ","FC 14 ","FC 14 ","CPU and Profibus detailed diagnostic "
|
||||
"CTRLCoolingSystem ","FC 1700 ","FC 1700 "," "
|
||||
"CTS301_Conductiv_State ","PEB 1114 ","BYTE ","MIX - Profibus Variables "
|
||||
"CTS301_Conductivity ","PED 1110 ","REAL ","MIX - Profibus Variables "
|
||||
"CTS301_Temperat_State ","PEB 1119 ","BYTE ","MIX - Profibus Variables "
|
||||
"CTS301_Temperature ","PED 1115 ","REAL ","MIX - Profibus Variables "
|
||||
"CTS302_Conductiv_State ","PEB 1124 ","BYTE ","MIX - Profibus Variables "
|
||||
"CTS302_Conductivity ","PED 1120 ","REAL ","MIX - Profibus Variables "
|
||||
"CTS302_Temperat_State ","PEB 1129 ","BYTE ","MIX - Profibus Variables "
|
||||
"CTS302_Temperature ","PED 1125 ","REAL ","MIX - Profibus Variables "
|
||||
"CTUD ","SFB 2 ","SFB 2 ","MIX - Count Up / Down "
|
||||
"CVQ_1p7_8_Perc ","FC 1913 ","FC 1913 ","MIX - CVQ_1p7_8_Perc "
|
||||
"CYC_INT5 ","OB 35 ","OB 35 ","Cyclic Interrupt 5 "
|
||||
"D_ACT_DP ","SFC 12 ","SFC 12 ","MIX - Deactivating and Activating DP Slaves "
|
||||
"Danfoss Diag ","UDT 88 ","UDT 88 "," "
|
||||
"DAR_Logic ","FB 2124 ","FB 2124 "," "
|
||||
"DAR_Logic_DB ","DB 2124 ","FB 2124 "," "
|
||||
"DeairCO2TempComp ","FC 1909 ","FC 1909 ","MIX - Deair_CO2_Temp_Comp "
|
||||
"DeaireationValve ","FC 1924 ","FC 1924 ","MIX - "
|
||||
"Deaireator StartUp ","FB 1803 ","FB 1803 ","MIX - Deaireator StartUp "
|
||||
"Deaireator StartUp_Seq ","FC 1803 ","FC 1803 ","MIX - Deaireator StartUp Sequencer "
|
||||
"Delay ","FB 1708 ","FB 1708 ","MIX - Delay "
|
||||
"DELETE ","FC 4 ","FC 4 ","Delete String "
|
||||
"DeltaP ","FC 1921 ","FC 1921 ","MIX - Delta_P "
|
||||
"DETAIL_DP_DIAG ","FB 125 ","FB 125 ","Profibus Network detailed Diagnostic "
|
||||
"DETAIL_DP_DIAG_i ","DB 14 ","FB 125 ","Profibus Network detailed Diagnostic Data "
|
||||
"Device ","UDT 81 ","UDT 81 "," "
|
||||
"DI_Air_InletPress_OK ","E 30.0 ","BOOL ","Air Pressure Switch "
|
||||
"DI_AuxVoltage_On ","E 5.1 ","BOOL ","Electrical Panel Restored "
|
||||
"DI_AVM308_Close ","E 110.2 ","BOOL ","MIX - Product Tank Inlet - Close FBK "
|
||||
"DI_AVM308_Open ","E 100.2 ","BOOL ","MIX - Product Tank Inlet - Open FBK "
|
||||
"DI_AVM309_Close ","E 110.7 ","BOOL ","MIX - Product Tank Loading - Close FBK "
|
||||
"DI_AVM309_Open ","E 100.7 ","BOOL ","MIX - Product Tank Loading - Open FBK "
|
||||
"DI_AVM311_Close ","E 110.6 ","BOOL ","MIX - Product Tank Blow Off - Close FBK "
|
||||
"DI_AVM311_Open ","E 100.6 ","BOOL ","MIX - Product Tank Blow Off - Open FBK "
|
||||
"DI_AVM313_Close ","E 111.0 ","BOOL ","MIX - Product Recirculation - Close FBK "
|
||||
"DI_AVM313_Open ","E 101.0 ","BOOL ","MIX - Product Recirculation - Open FBK "
|
||||
"DI_AVM315_Close ","E 111.1 ","BOOL ","MIX - Product Tank Drain - Close FBK "
|
||||
"DI_AVM315_Open ","E 101.1 ","BOOL ","MIX - Product Tank Drain - Open FBK "
|
||||
"DI_AVM317_Close ","E 111.2 ","BOOL ","MIX - Product Tank Spray Ball - Close FBK "
|
||||
"DI_AVM317_Open ","E 101.2 ","BOOL ","MIX - Product Tank Spray Ball - Open FBK "
|
||||
"DI_AVM321_Close ","E 111.3 ","BOOL ","MIX - Product Tank Over Fill - Close FBK "
|
||||
"DI_AVM321_Open ","E 101.3 ","BOOL ","MIX - Product Tank Over Fill - Open FBK "
|
||||
"DI_AVM322_Close ","E 111.4 ","BOOL ","MIX - Water Pump PPN301 Priming - Close FBK "
|
||||
"DI_AVM322_Open ","E 101.4 ","BOOL ","MIX - Water Pump PPN301 Priming - Open FBK "
|
||||
"DI_AVM324_Close ","E 111.5 ","BOOL ","MIX - Water Chiller Pipe Drain - Close FBK "
|
||||
"DI_AVM324_Open ","E 101.5 ","BOOL ","MIX - Water Chiller Pipe Drain - Open FBK "
|
||||
"DI_AVM326_Close ","E 111.6 ","BOOL ","MIX - CO2 Injection Shut Off - Close FBK "
|
||||
"DI_AVM326_Open ","E 101.6 ","BOOL ","MIX - CO2 Injection Shut Off - Open FBK "
|
||||
"DI_AVM327_Close ","E 312.4 ","BOOL ","MIX - Blendfill Still Water By-Pass Mixproof 1 - Close FBK "
|
||||
"DI_AVM327_Open ","E 302.4 ","BOOL ","MIX - Blendfill Still Water By-Pass Mixproof 1 - Open FBK "
|
||||
"DI_AVM328_Close ","E 301.4 ","BOOL ","MIX - Blendfill Still Water By-Pass Mixproof 2 - Close FBK "
|
||||
"DI_AVM328_Open ","E 201.4 ","BOOL ","MIX - Blendfill Still Water By-Pass Mixproof 2 - Open FBK "
|
||||
"DI_AVM329_Close ","E 301.6 ","BOOL ","MIX - Blendfill Still Water By-Pass Mixproof 3 - Close FBK "
|
||||
"DI_AVM329_Open ","E 201.6 ","BOOL ","MIX - Blendfill Still Water By-Pass Mixproof 3 - Open FBK "
|
||||
"DI_AVM331_Close ","E 301.7 ","BOOL ","MIX - No Blendfill Still Water By-Pass to Mixer - Close FBK "
|
||||
"DI_AVM331_Open ","E 201.7 ","BOOL ","MIX - No Blendfill Still Water By-Pass to Mixer - Open FBK "
|
||||
"DI_AVM341_Close ","E 111.7 ","BOOL ","MIX - CO2 Inlet - Close FBK "
|
||||
"DI_AVM341_Open ","E 101.7 ","BOOL ","MIX - CO2 Inlet - Open FBK "
|
||||
"DI_AVM342_Close ","E 112.0 ","BOOL ","MIX - N2 Inlet - Close FBK "
|
||||
"DI_AVM342_Open ","E 102.0 ","BOOL ","MIX - N2 Inlet - Open FBK "
|
||||
"DI_AVM345_Close ","E 112.1 ","BOOL ","MIX - Product Chiller Inlet Drain - Close FBK "
|
||||
"DI_AVM345_Open ","E 102.1 ","BOOL ","MIX - Product Chiller Inlet Drain - Open FBK "
|
||||
"DI_AVM346_Close ","E 112.2 ","BOOL ","MIX - Filler CO2 - Close FBK "
|
||||
"DI_AVM346_Open ","E 102.2 ","BOOL ","MIX - Filler CO2 - Open FBK "
|
||||
"DI_AVM348_Close ","E 112.4 ","BOOL ","MIX - Product Chiller Outlet Drain - Close FBK "
|
||||
"DI_AVM348_Open ","E 102.4 ","BOOL ","MIX - Product Chiller Outlet Drain - Open FBK "
|
||||
"DI_AVM349_Close ","E 312.0 ","BOOL ","MIX - Product Chiller Outlet Drain - Close FBK "
|
||||
"DI_AVM349_Open ","E 302.0 ","BOOL ","MIX - Product Chiller Outlet Drain - Open FBK "
|
||||
"DI_AVM362_Close ","E 112.3 ","BOOL ","MIX - Product Outlet - Close FBK "
|
||||
"DI_AVM362_Open ","E 102.3 ","BOOL ","MIX - Product Outlet - Open FBK "
|
||||
"NE_STRNG ","FC 29 ","FC 29 ","Not Equal String "
|
||||
"Net BlendFill Eth ","DB 806 ","FB 1 ","MIX - Net FIller Simonazzi Blendfill Ethernet "
|
||||
"Net Cip Sidel Eth ","DB 809 ","FB 1 ","MIX - Net CipRoom Sidel Ethernet "
|
||||
"Net CIP System Eth ","DB 803 ","FB 1 ","MIX - Net CipRoom Ethernet "
|
||||
"Net Dosing Sys Prof ","DB 810 ","DB 810 ","MIX - Net Dosing System Profibus "
|
||||
"Net Filler Eth ","DB 805 ","FB 1 ","MIX - Net FIller Simonazzi no Blendfill Ethernet "
|
||||
"Net Filler Sidel Eth ","DB 807 ","FB 1 ","MIX - Net FIller Sidel Ethernet "
|
||||
"Net Pasto Eth ","DB 804 ","FB 1 ","MIX - Net PastoRoom Ethernet "
|
||||
"Net ProdRoom Eth ","DB 808 ","FB 1 ","MIX - Net PrdRoom Ethernet "
|
||||
"Net SyrupRoom Eth ","DB 802 ","FB 1 "," "
|
||||
"OBNL_FLT ","OB 85 ","OB 85 ","OB Not Loaded Fault "
|
||||
"ONS_R ","FC 1920 ","FC 1920 ","MIX - ONS_R "
|
||||
"Output ","FC 2026 ","FC 2026 ","MIX - Output "
|
||||
"Output_AnalogValueToHMI ","FC 2017 ","FC 2017 ","MIX - Analog Value To HMI "
|
||||
"Output_CO2InjPress ","FC 2021 ","FC 2021 ","MIX - Output_CO2InjPress "
|
||||
"PAmPDS_Aux_Real_IN ","MD 1752 ","REAL ","MIX - Aux Real Input "
|
||||
"PAmPDS_SYR_Devis_Tmr ","T 178 ","TIMER ","MIX - mPDS_SYR_PA_Ctrl_Read "
|
||||
"PID ","UDT 85 ","UDT 85 "," "
|
||||
"PID MAIN Data ","DB 729 ","FB 1729 ","MIX - Data for PID Block Main "
|
||||
"PID_AVN30x ","FB 1795 ","FB 1795 "," "
|
||||
"PID_AVN30x_Data ","DB 995 ","FB 1795 "," "
|
||||
"PID_Continuos ","FB 41 ","FB 41 ","CONTINUOS PID CONTROLLER "
|
||||
"PID_EHS30X ","FB 1790 ","FB 1790 ","MIX - PID_CIP_TempElectric "
|
||||
"PID_EHS30X_Data ","DB 987 ","FB 1790 ","MIX - PID_CIP_Temp_Data_Electric "
|
||||
"PID_Filling_Head ","FB 1791 ","FB 1791 ","MIX - PID_Filling_Head "
|
||||
"PID_Filling_Head-TE ","FB 17910 ","FB 17910 "," "
|
||||
"PID_Filling_Head_Calc ","FB 1792 ","FB 1792 ","MIX - _Filling_Head_PID_Ctrl.Calcolous "
|
||||
"PID_Filling_Head_Calc-TE","FB 17920 ","FB 17920 "," "
|
||||
"PID_Filling_Head_Data ","DB 990 ","FB 1791 ","MIX - PID_Filling_Head_Data "
|
||||
"PID_Filling_Head+SFC20 ","FB 17912 ","FB 17912 ","MIX - PID_Filling_Head-No BLKMOV ma move semplice "
|
||||
"PID_Filling_HeadNoSFC20 ","FB 17911 ","FB 17911 ","MIX - PID_Filling_Head-No BLKMOV solo DB1013 "
|
||||
"PID_RMM301 ","FB 1780 ","FB 1780 ","MIX - PID_Water "
|
||||
"PID_RMM301_Data ","DB 980 ","FB 1780 ","MIX - PID_Water_Data "
|
||||
"PID_RMM303 ","FB 1782 ","FB 1782 ","MIX - PID_CarboCO2 "
|
||||
"PID_RMM303_Data ","DB 982 ","FB 1782 ","MIX - PID_CarboCO2_Data "
|
||||
"PID_RMM304 ","FB 1794 ","FB 1794 ","MIX - PID_Gas2 "
|
||||
"PID_RMM304_Data ","DB 994 ","FB 1794 ","MIX - PID_GAS2_Data "
|
||||
"PID_RMP302 ","FB 1781 ","FB 1781 ","MIX - PID_Syrup "
|
||||
"PID_RMP302_Data ","DB 981 ","FB 1781 ","MIX - PID_Syrup_Data "
|
||||
"PID_RVM301 ","FB 1783 ","FB 1783 ","MIX - PID_Press_CO2 "
|
||||
"PID_RVM301_Data ","DB 983 ","FB 1783 ","MIX - PID_Press_CO2_Data "
|
||||
"PID_RVM302 ","FB 1779 ","FB 1779 "," "
|
||||
"PID_RVM302_Data ","DB 779 ","FB 1779 "," "
|
||||
"PID_RVM304 ","FB 1784 ","FB 1784 ","MIX - Prod_Tank_Press_Release "
|
||||
"PID_RVM304_Data ","DB 984 ","FB 1784 ","MIX - PID_Prod_Tank_Press_Release "
|
||||
"PID_RVM319 ","FB 1785 ","FB 1785 "," "
|
||||
"PID_RVM319_Data ","DB 985 ","FB 1785 "," "
|
||||
"PID_RVN302 ","FB 1793 ","FB 1793 ","MIX - PID_Water_Level "
|
||||
"PID_RVN302_Data ","DB 992 ","FB 1793 ","MIX - PID_Water_Level_Data "
|
||||
"PID_RVP303 ","FB 1789 ","FB 1789 ","MIX - PID_Syrup_Level "
|
||||
"PID_RVP303_Data ","DB 989 ","FB 1789 ","MIX - PID_Syrup_Level_Data "
|
||||
"PID_RVS318 ","FB 1786 ","FB 1786 ","MIX - PID_CIP_Temp "
|
||||
"PID_RVS318_Data ","DB 986 ","FB 1786 ","MIX - PID_CIP_Temp_Data_Steam "
|
||||
"PID_Variables ","DB 961 ","DB 961 ","MIX - PID Variables "
|
||||
"PIDControl ","FB 40 ","FB 40 ","PID Management "
|
||||
"Pneumatic Valve Ctrl ","FC 2020 ","FC 2020 ","MIX - Pneumatic Valve Ctrl "
|
||||
"Pneumatic Valve Fault ","FC 1969 ","FC 1969 ","MIX - Pneumatic Valve Fault "
|
||||
"Pneumatic Valve Fault DB","DB 969 ","DB 969 ","MIX - Pneumatic Valve Fault DB "
|
||||
"PPM O2 ","FC 1910 ","FC 1910 ","MIX - PPM_O2 "
|
||||
"PPM303_B00_ControlReady ","M 1941.0 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPM303_B00_RefValue_LSB ","M 1943.0 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPM303_B01_DriveReady ","M 1941.1 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPM303_B01_RefValue_MSB ","M 1943.1 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPM303_B02_Brake ","M 1943.2 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPM303_B02_Coasting ","M 1941.2 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPM303_B03_Coast ","M 1943.3 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPM303_B03_Trip ","M 1941.3 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPM303_B04_Error ","M 1941.4 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPM303_B04_QuickStop ","M 1943.4 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPM303_B05_HoldOutputFrq","M 1943.5 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPM303_B05_Reserved ","M 1941.5 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPM303_B06_RampStop ","M 1943.6 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPM303_B06_Triplock ","M 1941.6 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPM303_B07_Reset ","M 1943.7 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPM303_B07_Warning ","M 1941.7 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPM303_B08_Jog ","M 1942.0 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPM303_B08_Speed_OK ","M 1940.0 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPM303_B09_BusControl ","M 1940.1 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPM303_B09_RampSelection","M 1942.1 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPM303_B10_DataValid ","M 1942.2 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPM303_B10_FreqLimit_OK ","M 1940.2 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPM303_B11_InOperation ","M 1940.3 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPM303_B11_Relay01Active","M 1942.3 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPM303_B12_Drive_OK ","M 1940.4 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPM303_B12_Relay04Active","M 1942.4 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPM303_B13_SetUp_LSB ","M 1942.5 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPM303_B13_Voltage_OK ","M 1940.5 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPM303_B14_SetUp_MSB ","M 1942.6 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPM303_B14_Torque_OK ","M 1940.6 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPM303_B15_Reverse ","M 1942.7 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPM303_B15_Timer_OK ","M 1940.7 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPM303_FC_Control_Word ","MW 1942 ","WORD ","MIX - PPM303_ProductPump_CtrlWord_VFC_Ctrl "
|
||||
"PPM303_FC_Status_Word ","MW 1940 ","WORD ","MIX - PPM303_ProductPump_StatusWord_VFC_Ctrl "
|
||||
"PPM303_VFC_Ctrl ","FC 1871 ","FC 1871 ","MIX - PPM303_ProductPump_VFC_Ctrl "
|
||||
"PPM306_B00_ControlReady ","M 1917.0 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPM306_B00_RefValue_LSB ","M 1919.0 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPM306_B01_DriveReady ","M 1917.1 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPM306_B01_RefValue_MSB ","M 1919.1 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPM306_B02_Brake ","M 1919.2 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPM306_B02_Coasting ","M 1917.2 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPM306_B03_Coast ","M 1919.3 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPM306_B03_Trip ","M 1917.3 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPM306_B04_Error ","M 1917.4 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPM306_B04_QuickStop ","M 1919.4 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPM306_B05_HoldOutputFrq","M 1919.5 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPM306_B05_Reserved ","M 1917.5 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPM306_B06_RampStop ","M 1919.6 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPM306_B06_Triplock ","M 1917.6 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPM306_B07_Reset ","M 1919.7 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPM306_B07_Warning ","M 1917.7 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPM306_B08_Jog ","M 1918.0 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPM306_B08_Speed_OK ","M 1916.0 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPM306_B09_BusControl ","M 1916.1 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPM306_B09_RampSelection","M 1918.1 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPM306_B10_DataValid ","M 1918.2 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPM306_B10_FreqLimit_OK ","M 1916.2 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPM306_B11_InOperation ","M 1916.3 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPM306_B11_Relay01Active","M 1918.3 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPM306_B12_Drive_OK ","M 1916.4 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPM306_B12_Relay04Active","M 1918.4 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPM306_B13_SetUp_LSB ","M 1918.5 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPM306_B13_Voltage_OK ","M 1916.5 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPM306_B14_SetUp_MSB ","M 1918.6 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPM306_B14_Torque_OK ","M 1916.6 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPM306_B15_Reverse ","M 1918.7 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPM306_B15_Timer_OK ","M 1916.7 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPM306_FC_Control_Word ","MW 1918 ","WORD ","MIX - PPM306_RecirculationPump_CtrlWord_VFC_Ctrl "
|
||||
"PPM306_FC_Status_Word ","MW 1916 ","WORD ","MIX - PPM306_RecirculationPump_StatusWord_VFC_Ctrl "
|
||||
"PPM306_VFC_Ctrl ","FC 1874 ","FC 1874 ","MIX - PPM306_RecirculationPump_VFC_Ctrl "
|
||||
"PPM307_B00_ControlReady ","M 1855.0 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPM307_B00_RefValue_LSB ","M 1857.0 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPM307_B01_DriveReady ","M 1855.1 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPM307_B01_RefValue_MSB ","M 1857.1 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPM307_B02_Brake ","M 1857.2 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPM307_B02_Coasting ","M 1855.2 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPM307_B03_Coast ","M 1857.3 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPM307_B03_Trip ","M 1855.3 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPM307_B04_Error ","M 1855.4 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPM307_B04_QuickStop ","M 1857.4 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPM307_B05_HoldOutputFrq","M 1857.5 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPM307_B05_Reserved ","M 1855.5 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPM307_B06_RampStop ","M 1857.6 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPM307_B06_Triplock ","M 1855.6 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPM307_B07_Reset ","M 1857.7 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPM307_B07_Warning ","M 1855.7 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPM307_B08_Jog ","M 1856.0 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPM307_B08_Speed_OK ","M 1854.0 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPM307_B09_BusControl ","M 1854.1 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPM307_B09_RampSelection","M 1856.1 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPM307_B10_DataValid ","M 1856.2 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPM307_B10_FreqLimit_OK ","M 1854.2 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPM307_B11_InOperation ","M 1854.3 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPM307_B11_Relay01Active","M 1856.3 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPM307_B12_Drive_OK ","M 1854.4 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPM307_B12_Relay04Active","M 1856.4 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPM307_B13_SetUp_LSB ","M 1856.5 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPM307_B13_Voltage_OK ","M 1854.5 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPM307_B14_SetUp_MSB ","M 1856.6 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPM307_B14_Torque_OK ","M 1854.6 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPM307_B15_Reverse ","M 1856.7 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPM307_B15_Timer_OK ","M 1854.7 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPM307_FC_Control_Word ","MW 1856 ","WORD ","MIX - PPM307_BoosterPump_CtrlWord_VFC_Ctrl "
|
||||
"PPM307_FC_Status_Word ","MW 1854 ","WORD ","MIX - PPM307_BoosterPump_StatusWord_VFC_Ctrl "
|
||||
"PPM307_VFC_Ctrl ","FC 1876 ","FC 1876 ","MIX - PPM307_BoosterPump_VFC_Ctrl "
|
||||
"PPN301_B00_ControlReady ","M 1933.0 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPN301_B00_RefValue_LSB ","M 1935.0 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPN301_B01_DriveReady ","M 1933.1 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPN301_B01_RefValue_MSB ","M 1935.1 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPN301_B02_Brake ","M 1935.2 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPN301_B02_Coasting ","M 1933.2 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPN301_B03_Coast ","M 1935.3 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPN301_B03_Trip ","M 1933.3 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPN301_B04_Error ","M 1933.4 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPN301_B04_QuickStop ","M 1935.4 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPN301_B05_HoldOutputFrq","M 1935.5 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPN301_B05_Reserved ","M 1933.5 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPN301_B06_RampStop ","M 1935.6 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPN301_B06_Triplock ","M 1933.6 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPN301_B07_Reset ","M 1935.7 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPN301_B07_Warning ","M 1933.7 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPN301_B08_Jog ","M 1934.0 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPN301_B08_Speed_OK ","M 1932.0 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPN301_B09_BusControl ","M 1932.1 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPN301_B09_RampSelection","M 1934.1 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPN301_B10_DataValid ","M 1934.2 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPN301_B10_FreqLimit_OK ","M 1932.2 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPN301_B11_InOperation ","M 1932.3 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPN301_B11_Relay01Active","M 1934.3 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPN301_B12_Drive_OK ","M 1932.4 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPN301_B12_Relay04Active","M 1934.4 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPN301_B13_SetUp_LSB ","M 1934.5 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPN301_B13_Voltage_OK ","M 1932.5 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPN301_B14_SetUp_MSB ","M 1934.6 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPN301_B14_Torque_OK ","M 1932.6 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPN301_B15_Reverse ","M 1934.7 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPN301_B15_Timer_OK ","M 1932.7 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPN301_FC_Control_Word ","MW 1934 ","WORD ","MIX - PPN301_WaterPump_CtrlWord_VFC_Ctrl "
|
||||
"PPN301_FC_Status_Word ","MW 1932 ","WORD ","MIX - PPN301_WaterPump_StatusWord_VFC_Ctrl "
|
||||
"PPN301_VFC_Ctrl ","FC 1872 ","FC 1872 ","MIX - PPN301_WaterPump_VFC_Ctrl "
|
||||
"PPN304_B00_ControlReady ","M 2013.0 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPN304_B00_RefValue_LSB ","M 2015.0 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPN304_B01_DriveReady ","M 2013.1 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPN304_B01_RefValue_MSB ","M 2015.1 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPN304_B02_Brake ","M 2015.2 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPN304_B02_Coasting ","M 2013.2 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPN304_B03_Coast ","M 2015.3 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPN304_B03_Trip ","M 2013.3 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPN304_B04_Error ","M 2013.4 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPN304_B04_QuickStop ","M 2015.4 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPN304_B05_HoldOutputFrq","M 2015.5 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPN304_B05_Reserved ","M 2013.5 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPN304_B06_RampStop ","M 2015.6 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPN304_B06_Triplock ","M 2013.6 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPN304_B07_Reset ","M 2015.7 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPN304_B07_Warning ","M 2013.7 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPN304_B08_Jog ","M 2014.0 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPN304_B08_Speed_OK ","M 2012.0 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPN304_B09_BusControl ","M 2012.1 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPN304_B09_RampSelection","M 2014.1 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPN304_B10_DataValid ","M 2014.2 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPN304_B10_FreqLimit_OK ","M 2012.2 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPN304_B11_InOperation ","M 2012.3 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPN304_B11_Relay01Active","M 2014.3 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPN304_B12_Drive_OK ","M 2012.4 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPN304_B12_Relay04Active","M 2014.4 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPN304_B13_SetUp_LSB ","M 2014.5 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPN304_B13_Voltage_OK ","M 2012.5 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPN304_B14_SetUp_MSB ","M 2014.6 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPN304_B14_Torque_OK ","M 2012.6 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPN304_B15_Reverse ","M 2014.7 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPN304_B15_Timer_OK ","M 2012.7 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPN304_FC_Control_Word ","MW 2014 ","WORD ","MIX - PPN304_VacuumPump_CtrlWord_VFC_Ctrl "
|
||||
"PPN304_FC_Status_Word ","MW 2012 ","WORD ","MIX - PPN304_VacuumPump_StatusWord_VFC_Ctrl "
|
||||
"PPN304_VFC_Ctrl ","FC 1875 ","FC 1875 ","MIX - PPN304_VacuumPump_VFC_Ctrl "
|
||||
"PPP302_B00_ControlReady ","M 1937.0 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPP302_B00_RefValue_LSB ","M 1939.0 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPP302_B01_DriveReady ","M 1937.1 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPP302_B01_RefValue_MSB ","M 1939.1 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPP302_B02_Brake ","M 1939.2 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPP302_B02_Coasting ","M 1937.2 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPP302_B03_Coast ","M 1939.3 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPP302_B03_Trip ","M 1937.3 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPP302_B04_Error ","M 1937.4 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPP302_B04_QuickStop ","M 1939.4 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPP302_B05_HoldOutputFrq","M 1939.5 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPP302_B05_Reserved ","M 1937.5 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPP302_B06_RampStop ","M 1939.6 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPP302_B06_Triplock ","M 1937.6 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPP302_B07_Reset ","M 1939.7 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPP302_B07_Warning ","M 1937.7 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPP302_B08_Jog ","M 1938.0 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPP302_B08_Speed_OK ","M 1936.0 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPP302_B09_BusControl ","M 1936.1 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPP302_B09_RampSelection","M 1938.1 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPP302_B10_DataValid ","M 1938.2 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPP302_B10_FreqLimit_OK ","M 1936.2 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPP302_B11_InOperation ","M 1936.3 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPP302_B11_Relay01Active","M 1938.3 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPP302_B12_Drive_OK ","M 1936.4 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPP302_B12_Relay04Active","M 1938.4 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPP302_B13_SetUp_LSB ","M 1938.5 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPP302_B13_Voltage_OK ","M 1936.5 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPP302_B14_SetUp_MSB ","M 1938.6 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPP302_B14_Torque_OK ","M 1936.6 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPP302_B15_Reverse ","M 1938.7 ","BOOL ","MIX - FC_Control_Word "
|
||||
"PPP302_B15_Timer_OK ","M 1936.7 ","BOOL ","MIX - FC_Status_Word "
|
||||
"PPP302_FC_Control_Word ","MW 1938 ","WORD ","MIX - PPP302_SyrupPump_CtrlWord_VFC_Ctrl "
|
||||
"PPP302_FC_Status_Word ","MW 1936 ","WORD ","MIX - PPP302_SyrupPump_StatusWord_VFC_Ctrl "
|
||||
"PPP302_VFC_Ctrl ","FC 1873 ","FC 1873 ","MIX - PPP302_SyrupPump_VFC_Ctrl "
|
||||
"PRDRepComment ","MW 606 ","INT ","PRODUCTION Report Comment "
|
||||
"PRDRepExtFaultPresent ","M 604.7 ","BOOL ","PRODUCTION Report External Fault Present "
|
||||
"PRDRepExtFaultPresentAux","M 604.6 ","BOOL ","PRODUCTION Report External Fault Present Aux "
|
||||
"PRDRepFaultPresent ","M 604.4 ","BOOL ","PRODUCTION Report Fault Present "
|
||||
"PRDRepFaultPresentAux ","M 604.5 ","BOOL ","PRODUCTION Report Fault Present Aux "
|
||||
"PRDRepStarted ","M 604.0 ","BOOL ","PRODUCTION Report Started "
|
||||
"Press_Request ","M 1904.4 ","BOOL ","MIX - FP ****** "
|
||||
"PROC Pump Hz_to_Pressure","FC 1989 ","FC 1989 "," "
|
||||
"PROC Pump Parameters ","FC 1990 ","FC 1990 "," "
|
||||
"PROC Pump Pressure_to_Hz","FC 1988 ","FC 1988 "," "
|
||||
"PROC Water Density ","FC 1996 ","FC 1996 "," "
|
||||
"Procedure_rins_syrup ","M 1000.1 ","BOOL ","Procedure_rins_syrup_open_valv "
|
||||
"Procedure_rins_syrupP ","M 1000.0 ","BOOL ","Procedure_rins_syrup_pulse "
|
||||
"Procedure_Variables ","DB 960 ","DB 960 ","MIX - Procedure Variables "
|
||||
"Prod Tank Drain ","FB 1807 ","FB 1807 ","MIX - ProdTank Drain "
|
||||
"Prod Tank Drain_Seq ","FC 1807 ","FC 1807 ","MIX - Prod Tank Drain Sequencer "
|
||||
"Prod Tank PressCtrl ","FC 2016 ","FC 2016 ","MIX - Product Tank PressCtrl "
|
||||
"Prod Tank RunOut ","FB 1808 ","FB 1808 ","MIX - ProdTank RunOut "
|
||||
"Prod Tank RunOut_Seq ","FC 1808 ","FC 1808 ","MIX - Prod Tank RunOut Sequencer "
|
||||
"ProdBrixRecovery ","FB 1806 ","FB 1806 ","MIX - ProdBrixRecovery "
|
||||
"ProdBrixRecovery_BrixCal","FC 1806 ","FC 1806 ","MIX - ProdBrixRecovery Brix Calc "
|
||||
"ProdBrixRecoveryReq ","M 1907.0 ","BOOL ","MIX - FP ****** "
|
||||
"ProdPipeDrainReset ","M 1905.3 ","BOOL ","MIX - FP ****** "
|
||||
"ProdPipeRunOutReset ","M 1904.5 ","BOOL ","MIX - FP ****** "
|
||||
"ProdReportDB ","DB 601 ","DB 601 "," "
|
||||
"ProdReportManager ","FC 601 ","FC 601 "," "
|
||||
"ProdTankDrainReq ","M 1905.4 ","BOOL ","MIX - FP ****** "
|
||||
"ProdTankDrainReset ","M 1905.5 ","BOOL ","MIX - FP ****** "
|
||||
"ProdTankRunOutReq ","M 1904.7 ","BOOL ","MIX - FP ****** "
|
||||
"ProdTankRunOutReq_ONS ","M 1904.2 ","BOOL ","MIX - FP ****** "
|
||||
"ProdTankRunOutReset ","M 1905.0 ","BOOL ","MIX - FP ****** "
|
||||
"ProductAvailable ","FB 1823 ","FB 1823 ","MIX - ProductAvailable "
|
||||
"ProductLiterInTank ","FC 1951 ","FC 1951 ","MIX - Product Liter In Tank "
|
||||
"ProductPipeDrain ","FB 1824 ","FB 1824 ","MIX - ProductPipeDrain "
|
||||
"ProductPipeDrain_Seq ","FC 1824 ","FC 1824 ","MIX - ProductPipeDrain_Seq "
|
||||
"ProductPipeRunOut ","FB 1825 ","FB 1825 ","MIX - ProductPipeRunOut "
|
||||
"ProductPipeRunOut_Seq ","FC 1825 ","FC 1825 ","MIX - ProductPipeRunOut_Seq "
|
||||
"ProductQuality ","FC 2008 ","FC 2008 ","MIX - Product Quality "
|
||||
"ProductQuality_Messages ","FC 2030 ","FC 2030 ","MIX - Messages "
|
||||
"Profibus Network ","FC 11 ","FC 11 ","Profibus node diagnostic "
|
||||
"Profibus_Variables ","DB 973 ","DB 973 ","MIX - Profibus datas from instruments "
|
||||
"PROG_ERR ","OB 121 ","OB 121 ","Programming Error "
|
||||
"PulsePressure ","FC 1838 ","FC 1838 ","MIX - PulsePressure "
|
||||
"PumpsControl ","FC 1870 ","FC 1870 ","MIX - PumpsControl "
|
||||
"QCO Monitor ","FC 100 ","FC 100 "," "
|
||||
"QCO Phase ","UDT 101 ","UDT 101 "," "
|
||||
"QCO Timer ","UDT 100 ","UDT 100 "," "
|
||||
"QCO Timing ","VAT 11 "," "," "
|
||||
"QCO Timing DB ","DB 100 ","DB 100 "," "
|
||||
"RACK_FLT ","OB 86 ","OB 86 ","Loss of Rack Fault "
|
||||
"RD_REC ","SFC 59 ","SFC 59 ","MIX - Read a Data Record "
|
||||
"RD_SINFO ","SFC 6 ","SFC 6 ","Read OB Start Information "
|
||||
"RDSYSST ","SFC 51 ","SFC 51 ","MIX - Read a System Status List or Partial List "
|
||||
"READ_DBL ","SFC 83 ","SFC 83 ","Read Data Block out of Load Memory "
|
||||
"ReadAnalogIn ","FC 1971 ","FC 1971 ","MIX - Read Analog Data "
|
||||
"ReadAnalogIn_Fault_DB ","DB 871 ","DB 871 ","MIX - ReadAnalogIn DB "
|
||||
"Recipe #01 ","DB 401 ","DB 401 ","Recipe 1 "
|
||||
"Recipe #02 ","DB 402 ","DB 402 ","Recipe 2 "
|
||||
"Recipe #03 ","DB 403 ","DB 403 ","Recipe 3 "
|
||||
"Recipe #04 ","DB 404 ","DB 404 ","Recipe 4 "
|
||||
"Recipe #05 ","DB 405 ","DB 405 ","Recipe 5 "
|
||||
"Recipe #06 ","DB 406 ","DB 406 ","Recipe 6 "
|
||||
"Recipe #07 ","DB 407 ","DB 407 ","Recipe 7 "
|
||||
"Recipe #08 ","DB 408 ","DB 408 ","Recipe 8 "
|
||||
"Recipe #09 ","DB 409 ","DB 409 ","Recipe 9 "
|
||||
"Recipe #10 ","DB 410 ","DB 410 ","Recipe 10 "
|
||||
"Recipe #11 ","DB 411 ","DB 411 ","Recipe 11 "
|
||||
"Recipe #12 ","DB 412 ","DB 412 ","Recipe 12 "
|
||||
"Recipe #13 ","DB 413 ","DB 413 ","Recipe 13 "
|
||||
"Recipe #14 ","DB 414 ","DB 414 ","Recipe 14 "
|
||||
"Recipe #15 ","DB 415 ","DB 415 ","Recipe 15 "
|
||||
"Recipe #16 ","DB 416 ","DB 416 ","Recipe 16 "
|
||||
"Recipe #17 ","DB 417 ","DB 417 ","Recipe 17 "
|
||||
"Recipe #18 ","DB 418 ","DB 418 ","Recipe 18 "
|
||||
"Recipe #19 ","DB 419 ","DB 419 ","Recipe 19 "
|
||||
"Recipe #20 ","DB 420 ","DB 420 ","Recipe 20 "
|
||||
"Recipe #21 ","DB 421 ","DB 421 ","Recipe 21 "
|
||||
"Recipe #22 ","DB 422 ","DB 422 ","Recipe 22 "
|
||||
"Recipe #23 ","DB 423 ","DB 423 ","Recipe 23 "
|
||||
"Recipe #24 ","DB 424 ","DB 424 ","Recipe 24 "
|
||||
"Recipe #25 ","DB 425 ","DB 425 ","Recipe 25 "
|
||||
"Recipe #26 ","DB 426 ","DB 426 ","Recipe 26 "
|
||||
"Recipe #27 ","DB 427 ","DB 427 ","Recipe 27 "
|
||||
"Recipe #28 ","DB 428 ","DB 428 ","Recipe 28 "
|
||||
"Recipe #29 ","DB 429 ","DB 429 ","Recipe 29 "
|
||||
"Recipe #30 ","DB 430 ","DB 430 ","Recipe 30 "
|
||||
"Recipe #31 ","DB 431 ","DB 431 ","Recipe 31 "
|
||||
"Recipe #32 ","DB 432 ","DB 432 ","Recipe 32 "
|
||||
"Recipe #33 ","DB 433 ","DB 433 ","Recipe 33 "
|
||||
"Recipe #34 ","DB 434 ","DB 434 ","Recipe 34 "
|
||||
"Recipe #35 ","DB 435 ","DB 435 ","Recipe 35 "
|
||||
"Recipe #36 ","DB 436 ","DB 436 ","Recipe 36 "
|
||||
"Recipe #37 ","DB 437 ","DB 437 ","Recipe 37 "
|
||||
"Recipe #38 ","DB 438 ","DB 438 ","Recipe 38 "
|
||||
"Recipe #39 ","DB 439 ","DB 439 ","Recipe 39 "
|
||||
"Recipe #40 ","DB 440 ","DB 440 ","Recipe 40 "
|
||||
"Recipe #41 ","DB 441 ","DB 441 ","Recipe 41 "
|
||||
"Recipe #42 ","DB 442 ","DB 442 ","Recipe 42 "
|
||||
"Recipe #43 ","DB 443 ","DB 443 ","Recipe 43 "
|
||||
"Recipe #44 ","DB 444 ","DB 444 ","Recipe 44 "
|
||||
"Recipe #45 ","DB 445 ","DB 445 ","Recipe 45 "
|
||||
"Recipe #46 ","DB 446 ","DB 446 ","Recipe 46 "
|
||||
"Recipe #47 ","DB 447 ","DB 447 ","Recipe 47 "
|
||||
"Recipe #48 ","DB 448 ","DB 448 ","Recipe 48 "
|
||||
"Recipe #49 ","DB 449 ","DB 449 ","Recipe 49 "
|
||||
"Recipe #50 ","DB 450 ","DB 450 ","Recipe 50 "
|
||||
"Recipe_Prod ","UDT 904 ","UDT 904 ","MIX - Recipe_Prod "
|
||||
"RecipeCalculation ","FC 1798 ","FC 1798 ","MIX - Recipe Calculation "
|
||||
"RecipeEditDataSave ","DB 400 ","DB 400 ","Recipe Data Edit -Save data "
|
||||
"RecipeManagement - CIP ","FB 1799 ","FB 1799 ","CIP Link Recipe Edit, Save, Delete, Copy ... "
|
||||
"RecipeManagement - Prod ","FB 1798 ","FB 1798 ","MIX - Main Machine Recipe Edit, Save, Delete, Copy ... "
|
||||
"RecipeManagement_DataCIP","DB 399 ","FB 1799 ","MIX - CIP Recipe Management Data "
|
||||
"RecipeManagement_DataPrd","DB 398 ","FB 1798 ","MIX - Recipe Management Data "
|
||||
"REPLACE ","FC 31 ","FC 31 ","Replace Part of String "
|
||||
"ReportCIPSimpleData ","UDT 601 ","UDT 601 "," "
|
||||
"Reset Init ONS Prod Pump","M 1904.3 ","BOOL ","MIX - FP Reset Init ONS Prod Pump "
|
||||
"Safeties ","FC 2022 ","FC 2022 ","MIX - Safeties "
|
||||
"SE Timer ","FC 39 ","FC 39 ","SE Timer "
|
||||
"Sel_Check_Brix_Data ","DB 931 ","FB 1703 ","MIX - MSE Slope of Sel Check Brix Source Data "
|
||||
"SEL_I ","FC 1847 ","FC 1847 ","MIX - Selection Switch between 2 integers "
|
||||
"SEL_R ","FC 1846 ","FC 1846 ","MIX - Selection Switch between 2 reals "
|
||||
"SelCheckBrixSource ","FC 2010 ","FC 2010 ","MIX - Sel Check Brix Source "
|
||||
"SFM Profibus ","M 1951.6 ","BOOL ","MIX - Profibus network fault "
|
||||
"Signal Exchange Filler ","VAT 17 "," "," "
|
||||
"Signal Gen ","FB 1721 ","FB 1721 ","MIX - Signal Gen "
|
||||
"Signal_Gen_Data ","DB 943 ","FB 1721 ","MIX - TASK0 "
|
||||
"SlewLimit ","FB 1702 ","FB 1702 ","MIX - Slew_Limit "
|
||||
"SLIM_Block ","FC 2027 ","FC 2027 ","MIX - SLIM Block "
|
||||
"SLIM_Variables ","DB 968 ","DB 968 ","MIX - SLIM Variables "
|
||||
"SpeedAdjust ","FC 1906 ","FC 1906 ","MIX - Speed_Adjust "
|
||||
"Statistical_Analisys ","FB 1704 ","FB 1704 ","MIX - Statistical Analisys "
|
||||
"StatusScroll_Time ","T 143 ","TIMER ","MIX - StatusScroll "
|
||||
"SyrAutoCorrBlink2Sec ","M 1906.5 ","BOOL ","MIX - FP******* "
|
||||
"SyrAutoCorrLatch ","M 1905.7 ","BOOL ","MIX - FP ****** "
|
||||
"SyrAutoCorrReq ","M 1905.6 ","BOOL ","MIX - FP ****** "
|
||||
"SyrBrix Autocorrection ","FB 1809 ","FB 1809 ","MIX - SyrBrix Autocorrection "
|
||||
"SyrBrix_SyrupCorrPerc ","FC 1809 ","FC 1809 ","MIX - Syrup Corr Perc "
|
||||
"SyrLast400Liters ","M 2002.0 ","BOOL ","From Syrup Room last 400 liter "
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -8,7 +8,8 @@
|
|||
"plc_config": {
|
||||
"ip": "10.1.33.11",
|
||||
"rack": 0,
|
||||
"slot": 2
|
||||
"slot": 2,
|
||||
"symbols_path": "C:/Users/migue/Downloads/symSAE452.asc"
|
||||
},
|
||||
"udp_config": {
|
||||
"host": "127.0.0.1",
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,79 @@
|
|||
{
|
||||
"symbols": [
|
||||
{
|
||||
"name": "AI_RVM301",
|
||||
"plc_address": "PEW 826",
|
||||
"data_type": "word",
|
||||
"description": "RVM301 - Product Tank Pressure Valve",
|
||||
"area": "pew",
|
||||
"db": null,
|
||||
"offset": 826,
|
||||
"bit": null
|
||||
},
|
||||
{
|
||||
"name": "AO_RVP305",
|
||||
"plc_address": "PAW 828",
|
||||
"data_type": "word",
|
||||
"description": "RVP305 - Syrup 2 Tank Level Valve",
|
||||
"area": "paw",
|
||||
"db": null,
|
||||
"offset": 828,
|
||||
"bit": null
|
||||
},
|
||||
{
|
||||
"name": "DI_AVM308_Close",
|
||||
"plc_address": "E 110.2",
|
||||
"data_type": "bool",
|
||||
"description": "MIX - Product Tank Inlet - Close FBK",
|
||||
"area": "e",
|
||||
"db": null,
|
||||
"offset": 110,
|
||||
"bit": 2
|
||||
},
|
||||
{
|
||||
"name": "DI_AVM308_Open",
|
||||
"plc_address": "E 100.2",
|
||||
"data_type": "bool",
|
||||
"description": "MIX - Product Tank Inlet - Open FBK",
|
||||
"area": "e",
|
||||
"db": null,
|
||||
"offset": 100,
|
||||
"bit": 2
|
||||
},
|
||||
{
|
||||
"name": "PPM303_FC_Control_Word",
|
||||
"plc_address": "MW 1942",
|
||||
"data_type": "word",
|
||||
"description": "MIX - PPM303_ProductPump_CtrlWord_VFC_Ctrl",
|
||||
"area": "mw",
|
||||
"db": null,
|
||||
"offset": 1942,
|
||||
"bit": null
|
||||
},
|
||||
{
|
||||
"name": "AUX Blink_0.1S",
|
||||
"plc_address": "M 0.0",
|
||||
"data_type": "bool",
|
||||
"description": "PLC Blink 0.1 Sec. 10Hz",
|
||||
"area": "m",
|
||||
"db": null,
|
||||
"offset": 0,
|
||||
"bit": 0
|
||||
},
|
||||
{
|
||||
"name": "AUX Blink_1.0S",
|
||||
"plc_address": "M 0.5",
|
||||
"data_type": "bool",
|
||||
"description": "PLC Blink 1.0 Sec. 1Hz",
|
||||
"area": "m",
|
||||
"db": null,
|
||||
"offset": 0,
|
||||
"bit": 5
|
||||
}
|
||||
],
|
||||
"total_count": 7,
|
||||
"metadata": {
|
||||
"format_version": "1.0",
|
||||
"description": "PLC symbols loaded from ASC file"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
"AI_RVM301 ","PEW 826 ","WORD ","RVM301 - Product Tank Pressure Valve"
|
||||
"AO_RVP305 ","PAW 828 ","WORD ","RVP305 - Syrup 2 Tank Level Valve"
|
||||
"DI_AVM308_Close ","E 110.2 ","BOOL ","MIX - Product Tank Inlet - Close FBK"
|
||||
"DI_AVM308_Open ","E 100.2 ","BOOL ","MIX - Product Tank Inlet - Open FBK"
|
||||
"PPM303_FC_Control_Word ","MW 1942 ","WORD ","MIX - PPM303_ProductPump_CtrlWord_VFC_Ctrl"
|
||||
"Blender_Variables ","DB 971 ","DB 971 ","MIX - Blender Variables"
|
||||
"AUX Blink_0.1S ","M 0.0 ","BOOL ","PLC Blink 0.1 Sec. 10Hz"
|
||||
"AUX Blink_1.0S ","M 0.5 ","BOOL ","PLC Blink 1.0 Sec. 1Hz"
|
|
@ -24,80 +24,114 @@
|
|||
"description": "Array of PLC variables for this dataset",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"title": "Variable Name",
|
||||
"description": "Human-readable name for the variable"
|
||||
},
|
||||
"area": {
|
||||
"type": "string",
|
||||
"title": "Memory Area",
|
||||
"enum": [
|
||||
"db",
|
||||
"mw",
|
||||
"m",
|
||||
"pew",
|
||||
"pe",
|
||||
"paw",
|
||||
"pa",
|
||||
"e",
|
||||
"a",
|
||||
"mb"
|
||||
"oneOf": [
|
||||
{
|
||||
"title": "Manual Configuration",
|
||||
"description": "Manually configure PLC variable parameters",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"title": "Variable Name",
|
||||
"description": "Human-readable name for the variable"
|
||||
},
|
||||
"area": {
|
||||
"type": "string",
|
||||
"title": "Memory Area",
|
||||
"enum": [
|
||||
"db",
|
||||
"mw",
|
||||
"m",
|
||||
"pew",
|
||||
"pe",
|
||||
"paw",
|
||||
"pa",
|
||||
"e",
|
||||
"a",
|
||||
"mb"
|
||||
]
|
||||
},
|
||||
"db": {
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
],
|
||||
"title": "DB Number",
|
||||
"minimum": 1,
|
||||
"maximum": 9999
|
||||
},
|
||||
"offset": {
|
||||
"type": "integer",
|
||||
"title": "Offset",
|
||||
"minimum": 0,
|
||||
"maximum": 8191
|
||||
},
|
||||
"bit": {
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
],
|
||||
"title": "Bit Position",
|
||||
"minimum": 0,
|
||||
"maximum": 7
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"title": "Data Type",
|
||||
"enum": [
|
||||
"real",
|
||||
"int",
|
||||
"bool",
|
||||
"dint",
|
||||
"word",
|
||||
"byte",
|
||||
"uint",
|
||||
"udint",
|
||||
"sint",
|
||||
"usint"
|
||||
]
|
||||
},
|
||||
"streaming": {
|
||||
"type": "boolean",
|
||||
"title": "Stream to PlotJuggler",
|
||||
"description": "Include this variable in UDP streaming",
|
||||
"default": false
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"name",
|
||||
"area",
|
||||
"offset",
|
||||
"type"
|
||||
]
|
||||
},
|
||||
"db": {
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
],
|
||||
"title": "DB Number",
|
||||
"minimum": 1,
|
||||
"maximum": 9999
|
||||
},
|
||||
"offset": {
|
||||
"type": "integer",
|
||||
"title": "Offset",
|
||||
"minimum": 0,
|
||||
"maximum": 8191
|
||||
},
|
||||
"bit": {
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
],
|
||||
"title": "Bit Position",
|
||||
"minimum": 0,
|
||||
"maximum": 7
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"title": "Data Type",
|
||||
"enum": [
|
||||
"real",
|
||||
"int",
|
||||
"bool",
|
||||
"dint",
|
||||
"word",
|
||||
"byte",
|
||||
"uint",
|
||||
"udint",
|
||||
"sint",
|
||||
"usint"
|
||||
{
|
||||
"title": "Symbol-based Configuration",
|
||||
"description": "Use a symbol from the loaded ASC file",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"title": "Variable Name",
|
||||
"description": "Human-readable name for the variable (auto-filled from symbol)"
|
||||
},
|
||||
"symbol": {
|
||||
"type": "string",
|
||||
"title": "PLC Symbol",
|
||||
"description": "Select a symbol from the loaded ASC file",
|
||||
"options": {
|
||||
"widget": "symbol-selector"
|
||||
}
|
||||
},
|
||||
"streaming": {
|
||||
"type": "boolean",
|
||||
"title": "Stream to PlotJuggler",
|
||||
"description": "Include this variable in UDP streaming",
|
||||
"default": false
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"symbol"
|
||||
]
|
||||
},
|
||||
"streaming": {
|
||||
"type": "boolean",
|
||||
"title": "Stream to PlotJuggler",
|
||||
"description": "Include this variable in UDP streaming",
|
||||
"default": false
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"name",
|
||||
"area",
|
||||
"offset",
|
||||
"type"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,6 +63,14 @@
|
|||
"slot": {
|
||||
"title": "Slot",
|
||||
"type": "integer"
|
||||
},
|
||||
"symbols_path": {
|
||||
"title": "Symbols File Path",
|
||||
"description": "Path to the ASC symbol file for this PLC",
|
||||
"type": "string",
|
||||
"options": {
|
||||
"widget": "file-path"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
|
|
|
@ -56,6 +56,11 @@
|
|||
"ui:column": 3,
|
||||
"ui:widget": "updown"
|
||||
},
|
||||
"symbols_path": {
|
||||
"ui:column": 12,
|
||||
"ui:widget": "file-path",
|
||||
"ui:placeholder": "Select ASC symbol file..."
|
||||
},
|
||||
"ui:column": 12,
|
||||
"ui:layout": [
|
||||
[
|
||||
|
@ -71,12 +76,19 @@
|
|||
"name": "slot",
|
||||
"width": 3
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"name": "symbols_path",
|
||||
"width": 12
|
||||
}
|
||||
]
|
||||
],
|
||||
"ui:order": [
|
||||
"ip",
|
||||
"rack",
|
||||
"slot"
|
||||
"slot",
|
||||
"symbols_path"
|
||||
]
|
||||
},
|
||||
"udp_config": {
|
||||
|
|
|
@ -9,19 +9,20 @@
|
|||
"preview": "vite preview --host"
|
||||
},
|
||||
"dependencies": {
|
||||
"@rjsf/core": "^5.24.12",
|
||||
"@rjsf/chakra-ui": "^5.24.12",
|
||||
"@rjsf/validator-ajv8": "^5.24.12",
|
||||
"@chakra-ui/react": "^2.8.2",
|
||||
"@emotion/react": "^11.13.0",
|
||||
"@emotion/styled": "^11.13.0",
|
||||
"@rjsf/chakra-ui": "^5.24.12",
|
||||
"@rjsf/core": "^5.24.12",
|
||||
"@rjsf/validator-ajv8": "^5.24.12",
|
||||
"framer-motion": "^11.2.12",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-icons": "^5.5.0",
|
||||
"react-router-dom": "^6.26.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-react": "^4.3.1",
|
||||
"vite": "^5.4.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import { customWidgets } from './CustomWidgets'
|
||||
import { widgets } from '../rjsf/widgets'
|
||||
import VariableSelectorWidget from '../rjsf/VariableSelectorWidget'
|
||||
import FilePathWidget from './FilePathWidget'
|
||||
import SymbolSelectorWidget from './SymbolSelectorWidget'
|
||||
|
||||
// Comprehensive widget collection that merges all available widgets
|
||||
// for full UI schema support with layouts
|
||||
|
@ -23,6 +25,16 @@ export const allWidgets = {
|
|||
'variable-selector': VariableSelectorWidget,
|
||||
VariableSelectorWidget: VariableSelectorWidget,
|
||||
|
||||
// File path widget for ASC symbol files
|
||||
filePath: FilePathWidget,
|
||||
'file-path': FilePathWidget,
|
||||
FilePathWidget: FilePathWidget,
|
||||
|
||||
// Symbol selector widget for PLC symbols
|
||||
symbolSelector: SymbolSelectorWidget,
|
||||
'symbol-selector': SymbolSelectorWidget,
|
||||
SymbolSelectorWidget: SymbolSelectorWidget,
|
||||
|
||||
// PLC-specific widget aliases (if available)
|
||||
plcArea: widgets.PlcAreaWidget,
|
||||
plcDataType: widgets.PlcDataTypeWidget,
|
||||
|
|
|
@ -0,0 +1,173 @@
|
|||
import React, { useState } from 'react'
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Input,
|
||||
HStack,
|
||||
VStack,
|
||||
Text,
|
||||
useToast,
|
||||
Icon,
|
||||
Tooltip
|
||||
} from '@chakra-ui/react'
|
||||
import { FiFolder, FiUpload, FiFile } from 'react-icons/fi'
|
||||
|
||||
const FilePathWidget = ({ value, onChange, label, disabled, readonly, required, placeholder }) => {
|
||||
const [isLoading, setIsLoading] = useState(false)
|
||||
const [loadingSymbols, setLoadingSymbols] = useState(false)
|
||||
const toast = useToast()
|
||||
|
||||
const handleBrowseFile = async () => {
|
||||
try {
|
||||
setIsLoading(true)
|
||||
|
||||
const response = await fetch('/api/utils/browse-file', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
title: 'Select ASC Symbol File',
|
||||
filetypes: [['ASC Files', '*.asc'], ['All Files', '*.*']]
|
||||
})
|
||||
})
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
if (data.success && data.file_path) {
|
||||
onChange(data.file_path)
|
||||
toast({
|
||||
title: 'File Selected',
|
||||
description: `Selected: ${data.file_path}`,
|
||||
status: 'success',
|
||||
duration: 3000,
|
||||
isClosable: true,
|
||||
})
|
||||
} else if (data.cancelled) {
|
||||
// User cancelled - no action needed
|
||||
} else {
|
||||
throw new Error(data.error || 'Failed to select file')
|
||||
}
|
||||
} catch (error) {
|
||||
toast({
|
||||
title: 'Error',
|
||||
description: `Failed to browse file: ${error.message}`,
|
||||
status: 'error',
|
||||
duration: 5000,
|
||||
isClosable: true,
|
||||
})
|
||||
} finally {
|
||||
setIsLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
const handleLoadSymbols = async () => {
|
||||
if (!value) {
|
||||
toast({
|
||||
title: 'No File Selected',
|
||||
description: 'Please select an ASC file first',
|
||||
status: 'warning',
|
||||
duration: 3000,
|
||||
isClosable: true,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
setLoadingSymbols(true)
|
||||
|
||||
const response = await fetch('/api/symbols/load', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
asc_file_path: value
|
||||
})
|
||||
})
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
if (data.success) {
|
||||
toast({
|
||||
title: 'Symbols Loaded',
|
||||
description: `Successfully loaded ${data.symbols_count} symbols`,
|
||||
status: 'success',
|
||||
duration: 3000,
|
||||
isClosable: true,
|
||||
})
|
||||
} else {
|
||||
throw new Error(data.error || 'Failed to load symbols')
|
||||
}
|
||||
} catch (error) {
|
||||
toast({
|
||||
title: 'Error',
|
||||
description: `Failed to load symbols: ${error.message}`,
|
||||
status: 'error',
|
||||
duration: 5000,
|
||||
isClosable: true,
|
||||
})
|
||||
} finally {
|
||||
setLoadingSymbols(false)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Box>
|
||||
{label && (
|
||||
<Text fontSize="sm" fontWeight="medium" mb={2}>
|
||||
{label} {required && <Text as="span" color="red.500">*</Text>}
|
||||
</Text>
|
||||
)}
|
||||
|
||||
<VStack spacing={3} align="stretch">
|
||||
<HStack spacing={2}>
|
||||
<Input
|
||||
value={value || ''}
|
||||
onChange={(e) => onChange(e.target.value)}
|
||||
placeholder={placeholder || 'Enter file path or browse...'}
|
||||
disabled={disabled}
|
||||
readOnly={readonly}
|
||||
flex={1}
|
||||
/>
|
||||
|
||||
<Tooltip label="Browse for ASC file">
|
||||
<Button
|
||||
leftIcon={<Icon as={FiFolder} />}
|
||||
onClick={handleBrowseFile}
|
||||
isLoading={isLoading}
|
||||
disabled={disabled || readonly}
|
||||
variant="outline"
|
||||
size="md"
|
||||
>
|
||||
Browse
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</HStack>
|
||||
|
||||
<HStack spacing={2} justify="flex-end">
|
||||
<Button
|
||||
leftIcon={<Icon as={FiUpload} />}
|
||||
onClick={handleLoadSymbols}
|
||||
isLoading={loadingSymbols}
|
||||
disabled={disabled || readonly || !value}
|
||||
colorScheme="blue"
|
||||
size="sm"
|
||||
variant="solid"
|
||||
>
|
||||
Load Symbols
|
||||
</Button>
|
||||
|
||||
{value && (
|
||||
<Text fontSize="xs" color="gray.500" flex={1}>
|
||||
<Icon as={FiFile} mr={1} />
|
||||
{value.split('\\').pop() || value.split('/').pop()}
|
||||
</Text>
|
||||
)}
|
||||
</HStack>
|
||||
</VStack>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
export default FilePathWidget
|
|
@ -0,0 +1,361 @@
|
|||
import React, { useState, useEffect, useMemo } from 'react'
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Input,
|
||||
VStack,
|
||||
HStack,
|
||||
Text,
|
||||
useToast,
|
||||
Icon,
|
||||
Badge,
|
||||
Flex,
|
||||
Spinner,
|
||||
InputGroup,
|
||||
InputLeftElement,
|
||||
Select,
|
||||
Tooltip,
|
||||
Modal,
|
||||
ModalOverlay,
|
||||
ModalContent,
|
||||
ModalHeader,
|
||||
ModalFooter,
|
||||
ModalBody,
|
||||
ModalCloseButton,
|
||||
useDisclosure
|
||||
} from '@chakra-ui/react'
|
||||
import { FiSearch, FiX, FiList, FiInfo } from 'react-icons/fi'
|
||||
|
||||
const SymbolSelectorWidget = ({ value, onChange, label, disabled, readonly, required, placeholder }) => {
|
||||
const [symbols, setSymbols] = useState([])
|
||||
const [searchQuery, setSearchQuery] = useState('')
|
||||
const [isLoading, setIsLoading] = useState(false)
|
||||
const [selectedSymbol, setSelectedSymbol] = useState(null)
|
||||
const { isOpen, onOpen, onClose } = useDisclosure()
|
||||
const toast = useToast()
|
||||
|
||||
// Find the selected symbol from the loaded symbols
|
||||
useEffect(() => {
|
||||
if (value && symbols.length > 0) {
|
||||
const found = symbols.find(symbol => symbol.name === value)
|
||||
setSelectedSymbol(found || null)
|
||||
} else {
|
||||
setSelectedSymbol(null)
|
||||
}
|
||||
}, [value, symbols])
|
||||
|
||||
// Load symbols on component mount
|
||||
useEffect(() => {
|
||||
loadSymbols()
|
||||
}, [])
|
||||
|
||||
const loadSymbols = async () => {
|
||||
try {
|
||||
setIsLoading(true)
|
||||
|
||||
const response = await fetch('/api/symbols')
|
||||
const data = await response.json()
|
||||
|
||||
if (data.success) {
|
||||
setSymbols(data.symbols || [])
|
||||
} else {
|
||||
throw new Error(data.error || 'Failed to load symbols')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error loading symbols:', error)
|
||||
toast({
|
||||
title: 'Error',
|
||||
description: `Failed to load symbols: ${error.message}`,
|
||||
status: 'error',
|
||||
duration: 5000,
|
||||
isClosable: true,
|
||||
})
|
||||
} finally {
|
||||
setIsLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
// Filter symbols based on search query
|
||||
const filteredSymbols = useMemo(() => {
|
||||
if (!searchQuery.trim()) {
|
||||
return symbols.slice(0, 100) // Limit initial display
|
||||
}
|
||||
|
||||
const query = searchQuery.toLowerCase()
|
||||
return symbols.filter(symbol =>
|
||||
symbol.name.toLowerCase().includes(query) ||
|
||||
symbol.description.toLowerCase().includes(query) ||
|
||||
symbol.plc_address.toLowerCase().includes(query)
|
||||
).slice(0, 50) // Limit search results
|
||||
}, [symbols, searchQuery])
|
||||
|
||||
const handleSymbolSelect = (symbol) => {
|
||||
setSelectedSymbol(symbol)
|
||||
onChange(symbol.name)
|
||||
onClose()
|
||||
|
||||
toast({
|
||||
title: 'Symbol Selected',
|
||||
description: `Selected: ${symbol.name}`,
|
||||
status: 'success',
|
||||
duration: 2000,
|
||||
isClosable: true,
|
||||
})
|
||||
}
|
||||
|
||||
const handleClearSelection = () => {
|
||||
setSelectedSymbol(null)
|
||||
onChange('')
|
||||
|
||||
toast({
|
||||
title: 'Selection Cleared',
|
||||
description: 'Symbol selection has been cleared',
|
||||
status: 'info',
|
||||
duration: 2000,
|
||||
isClosable: true,
|
||||
})
|
||||
}
|
||||
|
||||
const SymbolCard = ({ symbol, onClick }) => (
|
||||
<Box
|
||||
border="1px"
|
||||
borderColor="gray.200"
|
||||
borderRadius="md"
|
||||
p={3}
|
||||
cursor="pointer"
|
||||
_hover={{ bg: 'gray.50', borderColor: 'blue.300' }}
|
||||
_active={{ bg: 'gray.100' }}
|
||||
onClick={() => onClick(symbol)}
|
||||
>
|
||||
<VStack align="start" spacing={1}>
|
||||
<HStack justify="space-between" w="full">
|
||||
<Text fontWeight="semibold" fontSize="sm" color="blue.600">
|
||||
{symbol.name}
|
||||
</Text>
|
||||
<Badge colorScheme="gray" fontSize="xs">
|
||||
{symbol.data_type}
|
||||
</Badge>
|
||||
</HStack>
|
||||
|
||||
<Text fontSize="xs" color="gray.600" fontFamily="mono">
|
||||
{symbol.plc_address}
|
||||
</Text>
|
||||
|
||||
{symbol.description && (
|
||||
<Text fontSize="xs" color="gray.500" noOfLines={2}>
|
||||
{symbol.description}
|
||||
</Text>
|
||||
)}
|
||||
|
||||
<HStack spacing={2} fontSize="xs">
|
||||
<Badge colorScheme="blue" variant="subtle">
|
||||
{symbol.area?.toUpperCase()}
|
||||
</Badge>
|
||||
{symbol.db && (
|
||||
<Badge colorScheme="green" variant="subtle">
|
||||
DB{symbol.db}
|
||||
</Badge>
|
||||
)}
|
||||
<Badge colorScheme="purple" variant="subtle">
|
||||
@{symbol.offset}
|
||||
</Badge>
|
||||
{symbol.bit !== null && symbol.bit !== undefined && (
|
||||
<Badge colorScheme="orange" variant="subtle">
|
||||
.{symbol.bit}
|
||||
</Badge>
|
||||
)}
|
||||
</HStack>
|
||||
</VStack>
|
||||
</Box>
|
||||
)
|
||||
|
||||
return (
|
||||
<Box>
|
||||
{label && (
|
||||
<Text fontSize="sm" fontWeight="medium" mb={2}>
|
||||
{label} {required && <Text as="span" color="red.500">*</Text>}
|
||||
</Text>
|
||||
)}
|
||||
|
||||
<VStack spacing={3} align="stretch">
|
||||
<HStack spacing={2}>
|
||||
<Input
|
||||
value={value || ''}
|
||||
onChange={(e) => onChange(e.target.value)}
|
||||
placeholder={placeholder || 'Enter symbol name or select...'}
|
||||
disabled={disabled}
|
||||
readOnly={readonly}
|
||||
flex={1}
|
||||
/>
|
||||
|
||||
<Button
|
||||
leftIcon={<Icon as={FiList} />}
|
||||
onClick={onOpen}
|
||||
disabled={disabled || readonly || symbols.length === 0}
|
||||
variant="outline"
|
||||
size="md"
|
||||
>
|
||||
Select
|
||||
</Button>
|
||||
|
||||
{value && (
|
||||
<Button
|
||||
leftIcon={<Icon as={FiX} />}
|
||||
onClick={handleClearSelection}
|
||||
disabled={disabled || readonly}
|
||||
variant="outline"
|
||||
size="md"
|
||||
colorScheme="red"
|
||||
>
|
||||
Clear
|
||||
</Button>
|
||||
)}
|
||||
</HStack>
|
||||
|
||||
{selectedSymbol && (
|
||||
<Box
|
||||
border="1px"
|
||||
borderColor="blue.200"
|
||||
borderRadius="md"
|
||||
p={3}
|
||||
bg="blue.50"
|
||||
>
|
||||
<VStack align="start" spacing={1}>
|
||||
<HStack justify="space-between" w="full">
|
||||
<Text fontWeight="semibold" fontSize="sm" color="blue.700">
|
||||
{selectedSymbol.name}
|
||||
</Text>
|
||||
<Badge colorScheme="blue">
|
||||
{selectedSymbol.data_type}
|
||||
</Badge>
|
||||
</HStack>
|
||||
|
||||
<Text fontSize="xs" color="blue.600" fontFamily="mono">
|
||||
{selectedSymbol.plc_address}
|
||||
</Text>
|
||||
|
||||
{selectedSymbol.description && (
|
||||
<Text fontSize="xs" color="blue.500">
|
||||
{selectedSymbol.description}
|
||||
</Text>
|
||||
)}
|
||||
|
||||
<HStack spacing={2} fontSize="xs">
|
||||
<Badge colorScheme="blue">
|
||||
{selectedSymbol.area?.toUpperCase()}
|
||||
</Badge>
|
||||
{selectedSymbol.db && (
|
||||
<Badge colorScheme="green">
|
||||
DB{selectedSymbol.db}
|
||||
</Badge>
|
||||
)}
|
||||
<Badge colorScheme="purple">
|
||||
@{selectedSymbol.offset}
|
||||
</Badge>
|
||||
{selectedSymbol.bit !== null && selectedSymbol.bit !== undefined && (
|
||||
<Badge colorScheme="orange">
|
||||
.{selectedSymbol.bit}
|
||||
</Badge>
|
||||
)}
|
||||
</HStack>
|
||||
</VStack>
|
||||
</Box>
|
||||
)}
|
||||
|
||||
{symbols.length === 0 && !isLoading && (
|
||||
<Text fontSize="sm" color="gray.500" textAlign="center">
|
||||
No symbols loaded. Please load an ASC file first in PLC Configuration.
|
||||
</Text>
|
||||
)}
|
||||
</VStack>
|
||||
|
||||
{/* Symbol Selection Modal */}
|
||||
<Modal isOpen={isOpen} onClose={onClose} size="xl" scrollBehavior="inside">
|
||||
<ModalOverlay />
|
||||
<ModalContent maxH="80vh">
|
||||
<ModalHeader>
|
||||
<VStack align="start" spacing={2}>
|
||||
<Text>Select PLC Symbol</Text>
|
||||
<HStack w="full" spacing={2}>
|
||||
<InputGroup flex={1}>
|
||||
<InputLeftElement>
|
||||
<Icon as={FiSearch} color="gray.400" />
|
||||
</InputLeftElement>
|
||||
<Input
|
||||
placeholder="Search symbols by name, address, or description..."
|
||||
value={searchQuery}
|
||||
onChange={(e) => setSearchQuery(e.target.value)}
|
||||
/>
|
||||
</InputGroup>
|
||||
<Button
|
||||
leftIcon={<Icon as={FiX} />}
|
||||
onClick={() => setSearchQuery('')}
|
||||
variant="outline"
|
||||
size="md"
|
||||
disabled={!searchQuery}
|
||||
>
|
||||
Clear
|
||||
</Button>
|
||||
</HStack>
|
||||
</VStack>
|
||||
</ModalHeader>
|
||||
<ModalCloseButton />
|
||||
|
||||
<ModalBody>
|
||||
{isLoading ? (
|
||||
<Flex justify="center" align="center" h="200px">
|
||||
<VStack spacing={3}>
|
||||
<Spinner size="lg" color="blue.500" />
|
||||
<Text>Loading symbols...</Text>
|
||||
</VStack>
|
||||
</Flex>
|
||||
) : filteredSymbols.length > 0 ? (
|
||||
<VStack spacing={2} align="stretch">
|
||||
<Text fontSize="sm" color="gray.600">
|
||||
{filteredSymbols.length} symbol{filteredSymbols.length !== 1 ? 's' : ''} found
|
||||
{searchQuery && ` for "${searchQuery}"`}
|
||||
</Text>
|
||||
|
||||
{filteredSymbols.map((symbol, index) => (
|
||||
<SymbolCard
|
||||
key={`${symbol.name}-${index}`}
|
||||
symbol={symbol}
|
||||
onClick={handleSymbolSelect}
|
||||
/>
|
||||
))}
|
||||
|
||||
{searchQuery && filteredSymbols.length >= 50 && (
|
||||
<Text fontSize="sm" color="orange.500" textAlign="center" fontStyle="italic">
|
||||
Showing first 50 results. Try a more specific search.
|
||||
</Text>
|
||||
)}
|
||||
</VStack>
|
||||
) : (
|
||||
<Flex justify="center" align="center" h="200px">
|
||||
<VStack spacing={3}>
|
||||
<Icon as={FiInfo} size="40px" color="gray.400" />
|
||||
<Text color="gray.500" textAlign="center">
|
||||
{searchQuery ? `No symbols found for "${searchQuery}"` : 'No symbols available'}
|
||||
</Text>
|
||||
{!searchQuery && symbols.length === 0 && (
|
||||
<Text fontSize="sm" color="gray.400" textAlign="center">
|
||||
Load an ASC file in PLC Configuration to see symbols
|
||||
</Text>
|
||||
)}
|
||||
</VStack>
|
||||
</Flex>
|
||||
)}
|
||||
</ModalBody>
|
||||
|
||||
<ModalFooter>
|
||||
<Button onClick={onClose}>
|
||||
Close
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
export default SymbolSelectorWidget
|
253
main.py
253
main.py
|
@ -11,8 +11,19 @@ import time
|
|||
from datetime import datetime
|
||||
import os
|
||||
import sys
|
||||
|
||||
try:
|
||||
import tkinter as tk
|
||||
from tkinter import filedialog
|
||||
|
||||
TKINTER_AVAILABLE = True
|
||||
except ImportError:
|
||||
TKINTER_AVAILABLE = False
|
||||
print("Warning: tkinter not available. File browse functionality will be limited.")
|
||||
from core import PLCDataStreamer
|
||||
from utils.json_manager import JSONManager, SchemaManager
|
||||
from utils.symbol_loader import SymbolLoader
|
||||
from utils.symbol_processor import SymbolProcessor
|
||||
|
||||
app = Flask(__name__)
|
||||
CORS(
|
||||
|
@ -2135,6 +2146,248 @@ def main():
|
|||
sys.exit(1)
|
||||
|
||||
|
||||
# ==============================================================================
|
||||
# Symbol Management API Endpoints
|
||||
# ==============================================================================
|
||||
|
||||
|
||||
@app.route("/api/utils/browse-file", methods=["POST"])
|
||||
def browse_file():
|
||||
"""Open file dialog to browse for ASC symbol files."""
|
||||
try:
|
||||
if not TKINTER_AVAILABLE:
|
||||
return (
|
||||
jsonify(
|
||||
{
|
||||
"success": False,
|
||||
"error": "File browser not available. Please enter the file path manually.",
|
||||
}
|
||||
),
|
||||
400,
|
||||
)
|
||||
|
||||
data = request.get_json()
|
||||
title = data.get("title", "Select File")
|
||||
filetypes = data.get("filetypes", [["All Files", "*.*"]])
|
||||
|
||||
# Create a temporary tkinter root window
|
||||
root = tk.Tk()
|
||||
root.withdraw() # Hide the root window
|
||||
root.attributes("-topmost", True) # Bring to front
|
||||
|
||||
# Open file dialog
|
||||
file_path = filedialog.askopenfilename(title=title, filetypes=filetypes)
|
||||
|
||||
root.destroy() # Clean up
|
||||
|
||||
if file_path:
|
||||
return jsonify({"success": True, "file_path": file_path})
|
||||
else:
|
||||
return jsonify({"success": True, "cancelled": True})
|
||||
|
||||
except Exception as e:
|
||||
return jsonify({"success": False, "error": str(e)}), 500
|
||||
|
||||
|
||||
@app.route("/api/symbols/load", methods=["POST"])
|
||||
def load_symbols():
|
||||
"""Load symbols from ASC file and save to JSON."""
|
||||
try:
|
||||
data = request.get_json()
|
||||
asc_file_path = data.get("asc_file_path")
|
||||
|
||||
if not asc_file_path:
|
||||
return (
|
||||
jsonify({"success": False, "error": "ASC file path is required"}),
|
||||
400,
|
||||
)
|
||||
|
||||
if not os.path.exists(asc_file_path):
|
||||
return (
|
||||
jsonify(
|
||||
{"success": False, "error": f"ASC file not found: {asc_file_path}"}
|
||||
),
|
||||
404,
|
||||
)
|
||||
|
||||
# Initialize symbol loader with optional logger
|
||||
logger = None
|
||||
try:
|
||||
logger = (
|
||||
streamer.event_logger if "streamer" in globals() and streamer else None
|
||||
)
|
||||
except:
|
||||
pass # Use None logger if streamer is not available
|
||||
|
||||
symbol_loader = SymbolLoader(logger)
|
||||
|
||||
# Load symbols and save to JSON
|
||||
json_output_path = project_path("config", "data", "plc_symbols.json")
|
||||
|
||||
# Ensure the directory exists
|
||||
os.makedirs(os.path.dirname(json_output_path), exist_ok=True)
|
||||
|
||||
symbols_count = symbol_loader.load_asc_and_save_json(
|
||||
asc_file_path, json_output_path
|
||||
)
|
||||
|
||||
# Log the success
|
||||
if logger:
|
||||
logger.log_event(
|
||||
"info",
|
||||
"symbols_loaded",
|
||||
f"Loaded {symbols_count} symbols from {asc_file_path}",
|
||||
)
|
||||
|
||||
return jsonify(
|
||||
{
|
||||
"success": True,
|
||||
"symbols_count": symbols_count,
|
||||
"json_path": json_output_path,
|
||||
}
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
error_msg = f"Error loading symbols: {str(e)}"
|
||||
print(f"DEBUG - Symbol loading error: {error_msg}") # Debug print
|
||||
print(f"DEBUG - Exception type: {type(e).__name__}")
|
||||
|
||||
# Print full stack trace
|
||||
import traceback
|
||||
|
||||
print("DEBUG - Full stack trace:")
|
||||
traceback.print_exc()
|
||||
|
||||
# Log the error
|
||||
if "streamer" in globals() and streamer and streamer.event_logger:
|
||||
streamer.event_logger.log_event("error", "symbols_load_failed", error_msg)
|
||||
|
||||
return jsonify({"success": False, "error": error_msg}), 500
|
||||
|
||||
|
||||
@app.route("/api/symbols", methods=["GET"])
|
||||
def get_symbols():
|
||||
"""Get loaded symbols from JSON file."""
|
||||
try:
|
||||
json_path = project_path("config", "data", "plc_symbols.json")
|
||||
|
||||
if not os.path.exists(json_path):
|
||||
return jsonify({"success": True, "symbols": [], "total_count": 0})
|
||||
|
||||
with open(json_path, "r", encoding="utf-8") as file:
|
||||
symbols_data = json.load(file)
|
||||
|
||||
return jsonify({"success": True, **symbols_data})
|
||||
|
||||
except Exception as e:
|
||||
return jsonify({"success": False, "error": str(e)}), 500
|
||||
|
||||
|
||||
@app.route("/api/symbols/search", methods=["POST"])
|
||||
def search_symbols():
|
||||
"""Search symbols by name or description."""
|
||||
try:
|
||||
data = request.get_json()
|
||||
query = data.get("query", "").lower()
|
||||
limit = data.get("limit", 50)
|
||||
|
||||
json_path = project_path("config", "data", "plc_symbols.json")
|
||||
|
||||
if not os.path.exists(json_path):
|
||||
return jsonify({"success": True, "symbols": [], "total_count": 0})
|
||||
|
||||
with open(json_path, "r", encoding="utf-8") as file:
|
||||
symbols_data = json.load(file)
|
||||
|
||||
all_symbols = symbols_data.get("symbols", [])
|
||||
|
||||
if not query:
|
||||
# Return first N symbols if no query
|
||||
filtered_symbols = all_symbols[:limit]
|
||||
else:
|
||||
# Search in name and description
|
||||
filtered_symbols = []
|
||||
for symbol in all_symbols:
|
||||
if (
|
||||
query in symbol.get("name", "").lower()
|
||||
or query in symbol.get("description", "").lower()
|
||||
):
|
||||
filtered_symbols.append(symbol)
|
||||
|
||||
if len(filtered_symbols) >= limit:
|
||||
break
|
||||
|
||||
return jsonify(
|
||||
{
|
||||
"success": True,
|
||||
"symbols": filtered_symbols,
|
||||
"total_count": len(filtered_symbols),
|
||||
"query": query,
|
||||
}
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
return jsonify({"success": False, "error": str(e)}), 500
|
||||
|
||||
|
||||
@app.route("/api/symbols/process-variables", methods=["POST"])
|
||||
def process_symbol_variables():
|
||||
"""Process dataset variables, expanding symbol-based ones."""
|
||||
try:
|
||||
data = request.get_json()
|
||||
variables = data.get("variables", [])
|
||||
|
||||
if not variables:
|
||||
return (
|
||||
jsonify({"success": False, "error": "Variables array is required"}),
|
||||
400,
|
||||
)
|
||||
|
||||
# Initialize symbol processor with optional logger
|
||||
logger = None
|
||||
try:
|
||||
logger = (
|
||||
streamer.event_logger if "streamer" in globals() and streamer else None
|
||||
)
|
||||
except:
|
||||
pass # Use None logger if streamer is not available
|
||||
|
||||
symbol_processor = SymbolProcessor(logger)
|
||||
|
||||
# Get symbols path
|
||||
symbols_path = project_path("config", "data", "plc_symbols.json")
|
||||
|
||||
if not os.path.exists(symbols_path):
|
||||
return (
|
||||
jsonify(
|
||||
{
|
||||
"success": False,
|
||||
"error": "No symbols file found. Please load an ASC file first.",
|
||||
}
|
||||
),
|
||||
404,
|
||||
)
|
||||
|
||||
# Process variables
|
||||
processed_variables = symbol_processor.process_dataset_variables(
|
||||
variables, symbols_path
|
||||
)
|
||||
|
||||
# Validate the processed variables
|
||||
validation = symbol_processor.validate_symbol_variables(variables, symbols_path)
|
||||
|
||||
return jsonify(
|
||||
{
|
||||
"success": True,
|
||||
"processed_variables": processed_variables,
|
||||
"validation": validation,
|
||||
}
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
return jsonify({"success": False, "error": str(e)}), 500
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
# Initialize streamer instance
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
"should_connect": true,
|
||||
"should_stream": true,
|
||||
"active_datasets": [
|
||||
"Test",
|
||||
"DAR",
|
||||
"Fast",
|
||||
"Test"
|
||||
"Fast"
|
||||
]
|
||||
},
|
||||
"auto_recovery_enabled": true,
|
||||
"last_update": "2025-08-14T16:00:39.031573"
|
||||
"last_update": "2025-08-14T16:52:19.757206"
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
import requests
|
||||
import json
|
||||
|
||||
# Test the symbols load endpoint
|
||||
url = "http://localhost:5050/api/symbols/load"
|
||||
data = {
|
||||
"asc_file_path": "D:/Proyectos/Scripts/Siemens/S7_snap7_Stremer_n_Log/config/data/test_symbols.asc"
|
||||
}
|
||||
|
||||
try:
|
||||
response = requests.post(url, json=data)
|
||||
print(f"Status Code: {response.status_code}")
|
||||
print(f"Response Headers: {response.headers}")
|
||||
print(f"Response Text: {response.text}")
|
||||
|
||||
if response.headers.get("content-type", "").startswith("application/json"):
|
||||
result = response.json()
|
||||
print(f"JSON Response: {json.dumps(result, indent=2)}")
|
||||
else:
|
||||
print("Response is not JSON, probably HTML error page")
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
|
@ -0,0 +1,67 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Test script for symbol loader functionality.
|
||||
"""
|
||||
import sys
|
||||
import os
|
||||
|
||||
# Add the project root to Python path
|
||||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
from utils.symbol_loader import SymbolLoader
|
||||
|
||||
|
||||
def test_symbol_loader():
|
||||
"""Test the symbol loader with the sample ASC file."""
|
||||
|
||||
# Create a simple logger for testing
|
||||
class SimpleLogger:
|
||||
def info(self, msg):
|
||||
print(f"INFO: {msg}")
|
||||
|
||||
def warning(self, msg):
|
||||
print(f"WARNING: {msg}")
|
||||
|
||||
def error(self, msg):
|
||||
print(f"ERROR: {msg}")
|
||||
|
||||
logger = SimpleLogger()
|
||||
loader = SymbolLoader(logger)
|
||||
|
||||
# Test file paths
|
||||
test_asc_file = "config/data/test_symbols.asc"
|
||||
output_json_file = "config/data/test_output.json"
|
||||
|
||||
try:
|
||||
print(f"Testing symbol loading from: {test_asc_file}")
|
||||
|
||||
if not os.path.exists(test_asc_file):
|
||||
print(f"ERROR: Test file not found: {test_asc_file}")
|
||||
return False
|
||||
|
||||
# Load symbols
|
||||
symbols_count = loader.load_asc_and_save_json(test_asc_file, output_json_file)
|
||||
|
||||
print(f"SUCCESS: Loaded {symbols_count} symbols")
|
||||
print(f"Output saved to: {output_json_file}")
|
||||
|
||||
# Verify output file
|
||||
if os.path.exists(output_json_file):
|
||||
with open(output_json_file, "r", encoding="utf-8") as f:
|
||||
import json
|
||||
|
||||
data = json.load(f)
|
||||
print(f"JSON contains {len(data.get('symbols', []))} symbols")
|
||||
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"ERROR: {type(e).__name__}: {e}")
|
||||
import traceback
|
||||
|
||||
traceback.print_exc()
|
||||
return False
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_symbol_loader()
|
|
@ -0,0 +1,255 @@
|
|||
"""
|
||||
Symbol loader utility for parsing Siemens ASC symbol files.
|
||||
"""
|
||||
|
||||
import csv
|
||||
import json
|
||||
import re
|
||||
from typing import Dict, List, Optional
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
class SymbolLoader:
|
||||
"""Utility class for loading and parsing Siemens ASC symbol files."""
|
||||
|
||||
def __init__(self, logger):
|
||||
self.logger = logger
|
||||
|
||||
def parse_asc_file(self, file_path: str) -> List[Dict]:
|
||||
"""
|
||||
Parse a Siemens ASC symbol file.
|
||||
|
||||
Format: "variable_name","plc_address","data_type","description"
|
||||
|
||||
Args:
|
||||
file_path: Path to the ASC file
|
||||
|
||||
Returns:
|
||||
List of symbol dictionaries
|
||||
"""
|
||||
symbols = []
|
||||
|
||||
try:
|
||||
# Try different encodings for ASC files
|
||||
encodings = ["utf-8", "cp1252", "iso-8859-1", "latin-1"]
|
||||
content = None
|
||||
|
||||
for encoding in encodings:
|
||||
try:
|
||||
with open(file_path, "r", encoding=encoding) as file:
|
||||
content = file.read()
|
||||
break
|
||||
except UnicodeDecodeError:
|
||||
continue
|
||||
|
||||
if content is None:
|
||||
raise Exception("Could not decode file with any supported encoding")
|
||||
|
||||
# Parse the content using CSV reader
|
||||
import io
|
||||
|
||||
csv_reader = csv.reader(io.StringIO(content))
|
||||
|
||||
for line_num, row in enumerate(csv_reader, 1):
|
||||
try:
|
||||
if len(row) >= 4:
|
||||
symbol = self._parse_symbol_row(row)
|
||||
if symbol:
|
||||
symbols.append(symbol)
|
||||
else:
|
||||
if self.logger:
|
||||
self.logger.log_event(
|
||||
"warning",
|
||||
"symbol_parse_warning",
|
||||
f"Line {line_num}: Invalid format - not enough columns",
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
if self.logger:
|
||||
self.logger.log_event(
|
||||
"warning",
|
||||
"symbol_parse_warning",
|
||||
f"Line {line_num}: Error parsing - {str(e)}",
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
if self.logger:
|
||||
self.logger.log_event(
|
||||
"error", "symbol_load_error", f"Error reading ASC file: {str(e)}"
|
||||
)
|
||||
raise
|
||||
|
||||
if self.logger:
|
||||
self.logger.log_event(
|
||||
"info",
|
||||
"symbols_loaded",
|
||||
f"Loaded {len(symbols)} symbols from {file_path}",
|
||||
)
|
||||
return symbols
|
||||
|
||||
def _parse_symbol_row(self, row: List[str]) -> Optional[Dict]:
|
||||
"""
|
||||
Parse a single symbol row.
|
||||
|
||||
Args:
|
||||
row: List of string values from CSV row
|
||||
|
||||
Returns:
|
||||
Symbol dictionary or None if parsing fails
|
||||
"""
|
||||
try:
|
||||
variable_name = row[0].strip()
|
||||
plc_address = row[1].strip()
|
||||
data_type = row[2].strip()
|
||||
description = row[3].strip() if len(row) > 3 else ""
|
||||
|
||||
# Skip empty or invalid entries
|
||||
if not variable_name or not plc_address:
|
||||
return None
|
||||
|
||||
# Parse PLC address to extract components
|
||||
address_info = self._parse_plc_address(plc_address)
|
||||
if not address_info:
|
||||
if self.logger:
|
||||
self.logger.log_event(
|
||||
"warning",
|
||||
"symbol_parse_warning",
|
||||
f"Could not parse PLC address: {plc_address}",
|
||||
)
|
||||
return None
|
||||
|
||||
symbol = {
|
||||
"name": variable_name,
|
||||
"plc_address": plc_address,
|
||||
"data_type": data_type.lower(),
|
||||
"description": description,
|
||||
**address_info,
|
||||
}
|
||||
|
||||
return symbol
|
||||
|
||||
except Exception as e:
|
||||
if self.logger:
|
||||
self.logger.log_event(
|
||||
"warning",
|
||||
"symbol_parse_warning",
|
||||
f"Error parsing symbol row: {str(e)}",
|
||||
)
|
||||
return None
|
||||
|
||||
def _parse_plc_address(self, address: str) -> Optional[Dict]:
|
||||
"""
|
||||
Parse PLC address string to extract area, DB, offset, and bit.
|
||||
|
||||
Examples:
|
||||
- "DB 100.DBX 20.5" -> area: db, db: 100, offset: 20, bit: 5
|
||||
- "MW 100" -> area: mw, offset: 100
|
||||
- "M 10.5" -> area: m, offset: 10, bit: 5
|
||||
- "PEW 826" -> area: pew, offset: 826
|
||||
|
||||
Args:
|
||||
address: PLC address string
|
||||
|
||||
Returns:
|
||||
Dictionary with parsed address components
|
||||
"""
|
||||
address = address.strip().upper()
|
||||
|
||||
# DB address pattern: DB xxx.DBX yyy.z or DB xxx.DBD yyy, etc.
|
||||
db_pattern = r"DB\s+(\d+)\.DB[XBWD]\s+(\d+)(?:\.(\d+))?"
|
||||
db_match = re.match(db_pattern, address)
|
||||
if db_match:
|
||||
db_num = int(db_match.group(1))
|
||||
offset = int(db_match.group(2))
|
||||
bit = int(db_match.group(3)) if db_match.group(3) else None
|
||||
|
||||
return {"area": "db", "db": db_num, "offset": offset, "bit": bit}
|
||||
|
||||
# Memory word patterns: MW, MD, etc.
|
||||
memory_pattern = r"(MW|MD|MB|M)\s+(\d+)(?:\.(\d+))?"
|
||||
memory_match = re.match(memory_pattern, address)
|
||||
if memory_match:
|
||||
area_type = memory_match.group(1).lower()
|
||||
offset = int(memory_match.group(2))
|
||||
bit = int(memory_match.group(3)) if memory_match.group(3) else None
|
||||
|
||||
return {"area": area_type, "db": None, "offset": offset, "bit": bit}
|
||||
|
||||
# Process input/output patterns: PEW, PAW, E, A, etc.
|
||||
io_pattern = r"(PEW|PED|PEB|PE|PAW|PAD|PAB|PA|E|A)\s+(\d+)(?:\.(\d+))?"
|
||||
io_match = re.match(io_pattern, address)
|
||||
if io_match:
|
||||
area_type = io_match.group(1).lower()
|
||||
offset = int(io_match.group(2))
|
||||
bit = int(io_match.group(3)) if io_match.group(3) else None
|
||||
|
||||
return {"area": area_type, "db": None, "offset": offset, "bit": bit}
|
||||
|
||||
# Timer and Counter patterns
|
||||
timer_counter_pattern = r"(T|C)\s+(\d+)"
|
||||
tc_match = re.match(timer_counter_pattern, address)
|
||||
if tc_match:
|
||||
area_type = tc_match.group(1).lower()
|
||||
offset = int(tc_match.group(2))
|
||||
|
||||
return {"area": area_type, "db": None, "offset": offset, "bit": None}
|
||||
|
||||
if self.logger:
|
||||
self.logger.log_event(
|
||||
"warning",
|
||||
"symbol_parse_warning",
|
||||
f"Unrecognized address format: {address}",
|
||||
)
|
||||
return None
|
||||
|
||||
def save_symbols_to_json(self, symbols: List[Dict], output_path: str):
|
||||
"""
|
||||
Save symbols to JSON file.
|
||||
|
||||
Args:
|
||||
symbols: List of symbol dictionaries
|
||||
output_path: Path to output JSON file
|
||||
"""
|
||||
try:
|
||||
symbols_data = {
|
||||
"symbols": symbols,
|
||||
"total_count": len(symbols),
|
||||
"metadata": {
|
||||
"format_version": "1.0",
|
||||
"description": "PLC symbols loaded from ASC file",
|
||||
},
|
||||
}
|
||||
|
||||
with open(output_path, "w", encoding="utf-8") as file:
|
||||
json.dump(symbols_data, file, indent=2, ensure_ascii=False)
|
||||
|
||||
if self.logger:
|
||||
self.logger.log_event(
|
||||
"info",
|
||||
"symbols_saved",
|
||||
f"Saved {len(symbols)} symbols to {output_path}",
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
if self.logger:
|
||||
self.logger.log_event(
|
||||
"error",
|
||||
"symbol_save_error",
|
||||
f"Error saving symbols to JSON: {str(e)}",
|
||||
)
|
||||
raise
|
||||
|
||||
def load_asc_and_save_json(self, asc_file_path: str, json_output_path: str) -> int:
|
||||
"""
|
||||
Complete workflow: load ASC file and save to JSON.
|
||||
|
||||
Args:
|
||||
asc_file_path: Path to ASC file
|
||||
json_output_path: Path to output JSON file
|
||||
|
||||
Returns:
|
||||
Number of symbols loaded
|
||||
"""
|
||||
symbols = self.parse_asc_file(asc_file_path)
|
||||
self.save_symbols_to_json(symbols, json_output_path)
|
||||
return len(symbols)
|
|
@ -0,0 +1,221 @@
|
|||
"""
|
||||
Symbol-based variable processor for expanding symbol references.
|
||||
"""
|
||||
|
||||
import json
|
||||
from typing import Dict, List, Optional
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
class SymbolProcessor:
|
||||
"""Utility for processing symbol-based variable configurations."""
|
||||
|
||||
def __init__(self, logger=None):
|
||||
self.logger = logger
|
||||
self._symbols_cache = None
|
||||
self._symbols_cache_path = None
|
||||
|
||||
def load_symbols(self, symbols_path: str) -> Dict:
|
||||
"""
|
||||
Load symbols from JSON file with caching.
|
||||
|
||||
Args:
|
||||
symbols_path: Path to plc_symbols.json file
|
||||
|
||||
Returns:
|
||||
Dictionary with symbols data
|
||||
"""
|
||||
if self._symbols_cache is None or self._symbols_cache_path != symbols_path:
|
||||
|
||||
try:
|
||||
with open(symbols_path, "r", encoding="utf-8") as file:
|
||||
self._symbols_cache = json.load(file)
|
||||
self._symbols_cache_path = symbols_path
|
||||
|
||||
if self.logger:
|
||||
self.logger.info(
|
||||
f"Loaded {len(self._symbols_cache.get('symbols', []))} symbols"
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
if self.logger:
|
||||
self.logger.error(f"Error loading symbols: {str(e)}")
|
||||
self._symbols_cache = {"symbols": [], "total_count": 0}
|
||||
|
||||
return self._symbols_cache
|
||||
|
||||
def find_symbol(self, symbol_name: str, symbols_data: Dict) -> Optional[Dict]:
|
||||
"""
|
||||
Find a symbol by name.
|
||||
|
||||
Args:
|
||||
symbol_name: Name of the symbol to find
|
||||
symbols_data: Symbols data dictionary
|
||||
|
||||
Returns:
|
||||
Symbol dictionary or None if not found
|
||||
"""
|
||||
symbols = symbols_data.get("symbols", [])
|
||||
|
||||
for symbol in symbols:
|
||||
if symbol.get("name") == symbol_name:
|
||||
return symbol
|
||||
|
||||
return None
|
||||
|
||||
def expand_symbol_variable(self, variable_config: Dict, symbols_data: Dict) -> Dict:
|
||||
"""
|
||||
Expand a symbol-based variable configuration into manual configuration.
|
||||
|
||||
Args:
|
||||
variable_config: Variable configuration with 'symbol' field
|
||||
symbols_data: Symbols data dictionary
|
||||
|
||||
Returns:
|
||||
Expanded variable configuration with area, offset, type, etc.
|
||||
"""
|
||||
symbol_name = variable_config.get("symbol")
|
||||
if not symbol_name:
|
||||
return variable_config
|
||||
|
||||
symbol = self.find_symbol(symbol_name, symbols_data)
|
||||
if not symbol:
|
||||
if self.logger:
|
||||
self.logger.warning(f"Symbol '{symbol_name}' not found")
|
||||
return variable_config
|
||||
|
||||
# Create expanded configuration
|
||||
expanded = {
|
||||
"name": variable_config.get("name") or symbol.get("name", symbol_name),
|
||||
"area": symbol.get("area"),
|
||||
"offset": symbol.get("offset"),
|
||||
"type": self._map_symbol_type_to_plc_type(symbol.get("data_type", "")),
|
||||
"streaming": variable_config.get("streaming", False),
|
||||
}
|
||||
|
||||
# Add optional fields if present
|
||||
if symbol.get("db") is not None:
|
||||
expanded["db"] = symbol.get("db")
|
||||
|
||||
if symbol.get("bit") is not None:
|
||||
expanded["bit"] = symbol.get("bit")
|
||||
|
||||
# Keep original symbol reference for reference
|
||||
expanded["_symbol_name"] = symbol_name
|
||||
expanded["_symbol_address"] = symbol.get("plc_address", "")
|
||||
expanded["_symbol_description"] = symbol.get("description", "")
|
||||
|
||||
return expanded
|
||||
|
||||
def _map_symbol_type_to_plc_type(self, symbol_type: str) -> str:
|
||||
"""
|
||||
Map symbol data type to PLC data type.
|
||||
|
||||
Args:
|
||||
symbol_type: Data type from symbol
|
||||
|
||||
Returns:
|
||||
Mapped PLC data type
|
||||
"""
|
||||
type_mapping = {
|
||||
"bool": "bool",
|
||||
"byte": "byte",
|
||||
"word": "word",
|
||||
"dword": "dint",
|
||||
"int": "int",
|
||||
"dint": "dint",
|
||||
"real": "real",
|
||||
"uint": "uint",
|
||||
"udint": "udint",
|
||||
"sint": "sint",
|
||||
"usint": "usint",
|
||||
"time": "dint",
|
||||
"date": "word",
|
||||
"time_of_day": "dint",
|
||||
"string": "string",
|
||||
}
|
||||
|
||||
return type_mapping.get(symbol_type.lower(), "word")
|
||||
|
||||
def process_dataset_variables(
|
||||
self, dataset_variables: List[Dict], symbols_path: str
|
||||
) -> List[Dict]:
|
||||
"""
|
||||
Process a list of dataset variables, expanding symbol-based ones.
|
||||
|
||||
Args:
|
||||
dataset_variables: List of variable configurations
|
||||
symbols_path: Path to symbols JSON file
|
||||
|
||||
Returns:
|
||||
List of processed variables with symbol-based ones expanded
|
||||
"""
|
||||
symbols_data = self.load_symbols(symbols_path)
|
||||
processed_variables = []
|
||||
|
||||
for variable in dataset_variables:
|
||||
if "symbol" in variable:
|
||||
# This is a symbol-based variable, expand it
|
||||
expanded = self.expand_symbol_variable(variable, symbols_data)
|
||||
processed_variables.append(expanded)
|
||||
else:
|
||||
# This is a manual configuration, keep as-is
|
||||
processed_variables.append(variable.copy())
|
||||
|
||||
return processed_variables
|
||||
|
||||
def validate_symbol_variables(
|
||||
self, dataset_variables: List[Dict], symbols_path: str
|
||||
) -> Dict:
|
||||
"""
|
||||
Validate symbol-based variables and report any issues.
|
||||
|
||||
Args:
|
||||
dataset_variables: List of variable configurations
|
||||
symbols_path: Path to symbols JSON file
|
||||
|
||||
Returns:
|
||||
Validation results dictionary
|
||||
"""
|
||||
symbols_data = self.load_symbols(symbols_path)
|
||||
results = {
|
||||
"valid": True,
|
||||
"errors": [],
|
||||
"warnings": [],
|
||||
"symbol_count": 0,
|
||||
"manual_count": 0,
|
||||
}
|
||||
|
||||
for i, variable in enumerate(dataset_variables):
|
||||
if "symbol" in variable:
|
||||
results["symbol_count"] += 1
|
||||
symbol_name = variable.get("symbol")
|
||||
|
||||
if not symbol_name:
|
||||
results["valid"] = False
|
||||
results["errors"].append(f"Variable {i}: Empty symbol name")
|
||||
continue
|
||||
|
||||
symbol = self.find_symbol(symbol_name, symbols_data)
|
||||
if not symbol:
|
||||
results["valid"] = False
|
||||
results["errors"].append(
|
||||
f"Variable {i}: Symbol '{symbol_name}' not found"
|
||||
)
|
||||
continue
|
||||
|
||||
# Check if symbol has required fields
|
||||
if not symbol.get("area"):
|
||||
results["warnings"].append(
|
||||
f"Variable {i}: Symbol '{symbol_name}' missing area"
|
||||
)
|
||||
|
||||
if symbol.get("offset") is None:
|
||||
results["warnings"].append(
|
||||
f"Variable {i}: Symbol '{symbol_name}' missing offset"
|
||||
)
|
||||
|
||||
else:
|
||||
results["manual_count"] += 1
|
||||
|
||||
return results
|
Loading…
Reference in New Issue