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:
Miguel 2025-08-14 16:53:31 +02:00
parent 16355c4106
commit e3b1b48556
20 changed files with 29889 additions and 3999 deletions

674
.examples/symbolics.asc Normal file
View File

@ -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

View File

@ -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",

20779
config/data/plc_symbols.json Normal file

File diff suppressed because it is too large Load Diff

View File

@ -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"
}
}

View 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"

View File

@ -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"
]
}
}

View File

@ -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": [

View File

@ -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": {

View File

@ -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"
}
}
}

View File

@ -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,

View File

@ -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

View File

@ -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
View File

@ -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

View File

@ -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"
}

23
test_endpoint.py Normal file
View File

@ -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}")

67
test_symbol_loader.py Normal file
View File

@ -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()

255
utils/symbol_loader.py Normal file
View File

@ -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)

221
utils/symbol_processor.py Normal file
View File

@ -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