diff --git a/App.xaml b/App.xaml
index 02a4e92..786d926 100644
--- a/App.xaml
+++ b/App.xaml
@@ -1,11 +1,17 @@
+ StartupUri="MainWindow.xaml">
-
-
-
-
-
+
+
+
+
\ No newline at end of file
diff --git a/App.xaml.cs b/App.xaml.cs
index d773f1d..2092a27 100644
--- a/App.xaml.cs
+++ b/App.xaml.cs
@@ -1,91 +1,8 @@
-using System;
-using System.IO;
-using System.Windows;
-using System.Windows.Media.Imaging;
+using System.Windows;
namespace S7Explorer
{
public partial class App : Application
{
- protected override void OnStartup(StartupEventArgs e)
- {
- base.OnStartup(e);
-
- // AÑADIR ESTO: Registrar proveedor de codificación para soportar codificaciones adicionales (CP850, etc.)
- System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
-
- // Asegurarnos de que existe la carpeta Resources para los íconos
- EnsureResourcesExist();
-
- // Configurar manejo de excepciones no controladas
- AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
- Current.DispatcherUnhandledException += Current_DispatcherUnhandledException;
- }
-
- private void EnsureResourcesExist()
- {
- try
- {
- // Directorio de recursos
- string resourcesDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Resources");
- if (!Directory.Exists(resourcesDir))
- {
- Directory.CreateDirectory(resourcesDir);
- }
-
- // Crear íconos básicos si no existen
- CreateDefaultIconIfNotExists(resourcesDir, "project.png");
- CreateDefaultIconIfNotExists(resourcesDir, "device.png");
- CreateDefaultIconIfNotExists(resourcesDir, "folder.png");
- CreateDefaultIconIfNotExists(resourcesDir, "db.png");
- CreateDefaultIconIfNotExists(resourcesDir, "fb.png");
- CreateDefaultIconIfNotExists(resourcesDir, "fc.png");
- CreateDefaultIconIfNotExists(resourcesDir, "ob.png");
- CreateDefaultIconIfNotExists(resourcesDir, "symbol.png");
- CreateDefaultIconIfNotExists(resourcesDir, "default.png");
- }
- catch (Exception)
- {
- // Ignorar errores en la creación de recursos - no son críticos
- }
- }
-
- private void CreateDefaultIconIfNotExists(string directory, string filename)
- {
- string filePath = Path.Combine(directory, filename);
- if (!File.Exists(filePath))
- {
- // Crear un ícono simple - en una aplicación real, incluirías recursos reales
- BitmapSource bmp = BitmapSource.Create(16, 16, 96, 96, System.Windows.Media.PixelFormats.Bgr32, null, new byte[16 * 16 * 4], 16 * 4);
-
- using (var fileStream = new FileStream(filePath, FileMode.Create))
- {
- BitmapEncoder encoder = new PngBitmapEncoder();
- encoder.Frames.Add(BitmapFrame.Create(bmp));
- encoder.Save(fileStream);
- }
- }
- }
-
- private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
- {
- HandleException(e.ExceptionObject as Exception);
- }
-
- private void Current_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
- {
- HandleException(e.Exception);
- e.Handled = true;
- }
-
- private void HandleException(Exception ex)
- {
- if (ex == null) return;
-
- MessageBox.Show($"Ha ocurrido un error inesperado: {ex.Message}\n\nDetalles: {ex.StackTrace}",
- "Error", MessageBoxButton.OK, MessageBoxImage.Error);
-
- // Aquí podrías añadir registro de errores
- }
}
}
\ No newline at end of file
diff --git a/DotNetSiemensPLCToolBoxLibrary.xml b/DotNetSiemensPLCToolBoxLibrary.xml
new file mode 100644
index 0000000..65d88cb
--- /dev/null
+++ b/DotNetSiemensPLCToolBoxLibrary.xml
@@ -0,0 +1,2422 @@
+
+
+
+ DotNetSiemensPLCToolBoxLibrary
+
+
+
+
+ can scan an given ipadress/port conmbinations if they are available
+
+
+
+
+
+ specifies the timeout to wait before canceling an adress probing
+
+
+
+
+
+
+
+ contains all adresses, that have been found. the value is only valid after the scan is completed
+
+
+
+
+
+
+
+ specifies if the scanner is stll runing
+
+
+
+
+
+
+
+ specifies the amount of thread, currently running
+
+
+
+
+
+
+
+ Specifies the maximum amount of threads to use for the scanning
+
+
+
+
+
+
+
+ Starts an asynchronous scanning of the given adresses
+
+
+
+
+
+
+ blocks until the scan has completed
+
+
+
+
+
+ tries to abort the adress scanning
+
+
+
+
+
+ Starts an synchronous scan for the Adress range
+
+
+
+
+
+
+
+ Thread wrapper to wrap the thread and its local variables
+
+
+
+
+ Library specific:
+ *
+
+
+
+ Set the default Response timeout
+
+ Time in Microseconds
+
+
+
+ Send File to NC
+
+ Path + Filename
+ DateTime: dt.ToString("yyMMddHHmmss")
+ Filedata to send
+ buffer.Length
+
+
+
+
+ This put's a String as a S7 String to the PLC
+
+
+
+
+
+
+
+
+ This put's a String as a Char-Array to the PLC
+
+
+
+
+
+
+
+
+ This put's a String as a S7 String to the PLC
+
+
+
+
+
+
+
+
+ This put's a String as a Char-Array to the PLC
+
+
+
+
+
+
+
+
+ 1 = PG Connection, 2 = OP Connection
+
+
+
+
+ default 1,5s
+
+
+
+
+ Sets the keep-alive interval for the socket.
+
+ The socket.
+ Time between two keep alive "pings".
+ Time between two keep alive "pings" when first one fails.
+ If the keep alive infos were succefully modified.
+
+
+
+ Status of the socket client
+
+
+
+ client is not connected with the server
+
+
+ the client try to connect the server
+
+
+ the client try to connect the server
+
+
+ the client is connected
+
+
+
+ On a Socket Server, allow multiple Clients
+
+
+
+
+ Constructor for untiitests
+
+
+
+
+ Constructor wich uses a LibNoDavaeConnectionConfiguration from outside.
+
+
+
+
+
+ Is the Connection established?
+
+
+
+
+ Connect to the PLC with the selected Configuration
+ ///
+
+
+
+ Internal Helper function that checks if the PLC is connectec, reconnects automatially or throws an Exception
+ Call this function befor accessing the PLC Communication
+
+
+
+
+ This Disconnects from the PLC and the Adapter
+
+
+
+
+ Stop execution of the User Program in the Controller
+ WARNING! use with caution!
+
+
+
+
+ Start execution of the User Program in the Controller
+ WARNING! use with caution!
+
+
+
+
+ Read the current time of the controllers system time
+
+
+
+
+
+ Set the controllers current system time
+
+
+
+
+
+ This Starts a Request for the Status of a PLC FunctionBlock
+
+
+
+
+
+
+
+
+ Send the password to the PLC for authentication. this is only necessary if the controllers password protection is active
+
+
+
+
+
+
+ Get the current Execution status from the controller
+
+
+
+
+
+ Load an full or partial list of all currently loaded code and data blocks in the controller
+
+ the block type that will be listed
+ Returns an list of string short names of the existing blocks such as "DB1" "FC987"...
+
+
+
+ Load an full or partial list of all currently loaded code and data blocks in the controller
+
+ the block type that will be listed
+ Returns an list of Block Names containing the block types and numbers
+
+
+
+ Returns the amount of blocks per block type in the PLC
+
+ An Dictionary containing the block count for each Block type in the PLC
+
+
+
+ Load the basic header information from the PLC. This is more efficient than loading whole MC7 code from the plc
+
+
+
+
+ Load the basic header information from the PLC. This is more efficient than loading whole MC7 code from the plc
+
+
+
+
+
+
+
+ Returns the data block size of th Requested data block
+
+ The short name representation of the data block. such as "DB1" or "DB992"
+
+
+
+
+ Get the MC7 Code from the controller of the requested block. The MC7 code represents the whole code and all header information of the block
+
+ The short name representation of the data block. such as "DB1" or "DB992"
+
+
+
+
+ Downloads an MC7 formatted block to the PLC. WARNING use with caution!
+
+ The short name representation of the data block. such as "DB1" or "DB992"
+ An buffer containing the MC7 code of the block to download
+
+
+
+ Deletes an code or data block from the connected controller. WARNING use with cation!
+
+ The short name representation of the data block. such as "DB1" or "DB992"
+
+
+
+ Upload an System State list (SZL) from the controller that hold configuration, state and capability information
+ For information about SZLNummbers and indexes please consult the information from SIEMENS regarding SFC51 "RDSYSST"
+
+ The System State list Number
+ The System State sub list number
+
+
+
+
+ Upload an System State list (SZL) from the controller that hold configuration, state and capability information
+ For information about SZLNummbers and indexes please consult the information from SIEMENS regarding SFC51 "RDSYSST"
+
+ The System State list Number
+ The System State sub list number
+
+
+
+
+ Read the Controllers Diagnostic buffer containing controller events
+
+
+
+
+
+ Compress the Memory of the PLC. This performs an "de-fragmentation" of the PLCs memory
+ in order to produce bigger "chunks" of free memory.
+
+ This function takes a very, very long time to process
+
+
+
+ Copy the Content of the volatile RAM memory to the Non-volatile ROM memory
+
+
+
+
+ This Function Reads Values from the PLC it needs a Array of LibNodaveValues
+ It tries to Optimize how the Values are Read from the PLC
+
+ The List of values to be read form the controller
+
+
+
+ This function read Values from the PLC but also tries to verify the data-block sizes against
+ the current sizes in the controller. If an requested TAG exceeds the data-blocks current size
+ the item will be set to "ItemDoesNotExist". This will only affect Tags reading from data-blocks
+
+ The list of tags to read from the controller
+ Read the data-blocks length and cache them for future requests.
+ This function potentially improves read performance when there are many tags with different data block length.
+ if the tag exceeds the data-blocks length, it will fail before sending it to the controller
+
+
+
+ This Function Reads Values from the PLC it needs a Array of LibNodaveValues
+ It tries to Optimize how the Values are Read from the PLC
+
+ The List of values to be read form the controller
+
+
+
+ Read PLC Tags using the Fetch/Write mechanism
+
+
+
+
+
+
+ Read one single value from the PLC
+
+ An Simatic Address Identifier. see for syntax
+ The PLC data type to load and convert
+
+
+
+
+ Read one single value from the PLC
+
+ An Simatic Address Identifier. see for syntax
+ The PLC data type to load and convert
+
+
+
+
+ Read one single value from the PLC
+
+ An Simatic Address Identifier. see for syntax
+
+
+
+
+ Read one single value from the PLC
+
+ An Simatic Address Identifier. see for syntax
+
+
+
+
+ Read one single value from the NCK
+
+ An Sinumerik Address Identifier. see for syntax
+
+
+
+
+ Read one single value from the NCK
+
+ An Sinumerik Address Identifier. see for syntax
+
+
+
+
+ This Function Reads One LibNoDave Value from the PLC
+
+
+
+
+
+
+ This Function Reads a List of LibNoDaveValues from a Byte Array.
+ This can be used if you want to send Variables via a TCP Byte Stream from a PLC, and this
+ Function is also used for the optimized reading.
+
+ List of the Values
+ ByteArray
+
+
+
+
+ Writes a single Value to the PLC
+
+
+
+
+
+ Remove all PLC tags currently in the write Queue. This aborts the pending write requests.
+
+
+
+
+ Add an new PLC tag to the Queue to be written to the PLC
+
+
+
+
+
+ Write all pending PLC tags in the Queue to the PLC
+
+
+
+
+ Write an list of values to the PLC
+
+ The list of Values to write to the controller
+
+
+
+ Write an list of values to the PLC
+
+ The list of Values to write to the controller
+ If set to true, write optimation is enabled, but then, the order of your written values can varry, also a 4 byte value can be splittet written to the plc!
+
+
+
+ Load complete file from NC
+
+ full filename inc. path
+ Start PI-Service F_XFER before upload
+
+
+
+
+ Load complete file from NC
+
+ full filename inc. path
+ Start PI-Service F_XFER before upload
+
+
+
+
+ Load complete file from NC
+
+ full filename inc. path
+ size of the file (buffer)
+ Start PI-Service F_XFER before upload
+
+
+
+
+ Load complete file from NC
+
+ full filename inc. path
+ size of the file (buffer)
+ Start PI-Service F_XFER before upload
+
+
+
+
+ Load complete file from NC
+
+ full filename inc. path
+ size of the file (buffer)
+ Start PI-Service F_XFER before upload
+
+
+
+
+ Load file size from NC
+
+ full filename inc. path
+ Start PI-Service F_XFER before upload
+
+
+
+
+ Transfer file to NC
+
+ full filename inc. path
+ DateTime Format: yyMMddHHmmss
+ Data of the file
+
+
+
+ Name of the connection. This value can be freely defined by the user
+
+
+
+
+ the entry point of the Simatic NEt configuration to be used.
+ Please refer to the Simatic Net documentation for details.
+ by default is S7ONLINE
+
+
+
+
+ The Rack where the destination CPU is inserted. This value should be 0 in almost all cases.
+ Only in Multi CPU configurations this needs to be adjusted.
+
+
+
+
+ The slot where the destination CPU is inserted in the selected Rack.
+ This value depends on the particular hardware configuration of the CPU.
+ Usually it is 2 for S7-300 CPUs and 3 for S7-400 CPUs
+ On Redundant H-CPU configurations this value must be set accordingly, in order for the comunication to work properly
+
+
+
+
+ The MPI address of the remote CPU. this depends on the particular hardware configuration and is usually
+ set to 2 by default.
+ Only relevant for MPI connections
+
+
+
+
+ The IP-Adress or Hostname of the CPU's ethernet connection.
+ Only relevant for ISO over TCP connections.
+
+
+
+
+ The TCP Port to be used for connecting the CPU via ISO over TCP.
+ This value usually should set to the default 102 (ISO Transport Service Access Point (TSAP) Class 0 protocol)
+
+
+
+
+ The local MPI Address to be used by the MPI adapter to comunicate with the CPU.
+ By convention the address 0 is reserved for Programing devices.
+
+
+
+
+ The Com port name where the MPI adapter is connected to.
+ if an RS232 to USB adapter is used (such as the Siamtic USB-MPI adapter)
+ the Virtual com port name of the adapter must be chosen.
+
+
+
+
+ Defines the Connection resource to be used in the PLC
+
+
+
+
+ Defines how the connection to the PLC should be established
+
+
+
+
+ defines the Bus speed for the connected MPI adapter
+ The default MPI bus speed is 19200 bit / second
+
+
+
+
+ defines the Bus speed for the connected MPI adapter
+ The default MPI bus speed is 19200 bit / second
+
+
+
+
+ Com port parity to use for MPI connection. By default MPI uses Even parity
+
+
+
+
+ The timeout to wait for responses from the PLC
+ in microseconds
+
+
+
+
+ Used for serialization only.
+
+ The Problem is that the XML Serializer can not serialize Timespans. So serialize an "hidden" integer instead
+
+
+
+ The default Timeout to be used for ISO over TCP conection
+ In miliseconds
+
+
+
+
+ Used for serialization only.
+
+ The Problem is that the XML Serializer can not serialize Timespans. So serialize an "hidden" integer instead
+
+
+
+ Empty Constructor for Serialization
+
+
+
+
+ Normal Constructor of the Config Object
+
+
+
+
+
+ Normal Constructor of the Config Object
+
+
+
+
+
+ Normal Constructor of the Config Object
+
+
+
+
+
+ Normal Constructor of the Config Object
+
+
+
+
+
+ Reads the configuration from an Stream
+
+
+
+
+
+
+ Try to repair the configuration file if an error is encoutnerd
+
+
+
+
+
+
+ Replace the numerical enumeration value with its textual Value
+
+ The original Config file content to search in
+ The Name of the property to replace the value on
+ The type of Enumeration of the property in question
+
+
+
+
+ Connection via MPI adapter connected to an Serial Com Port
+
+
+
+
+ Connection via PPI protocoll of an MPI/PB adapter. This is usually used for S7-200 family
+
+
+
+
+ Connection via the AS511 Protocoll used by S5 series PLCs
+
+
+
+
+ Connection via the Simatic Net libraries. Simatic Net must be installed
+
+
+
+
+ Connections via the TCP/IP protocoll
+
+
+
+
+ Connections via TCP/IP to an CP243 for S7-200 series PLCs
+
+
+
+
+ Communication Speeds for Profibus and MPI bus connection Adapters.
+ The possible speeds can not be chosen freely, but are rather defined by the ProfiBus Standard
+
+
+
+
+ 9.6 kbps
+
+
+
+
+ 19.2 kbps
+
+
+
+
+ 187,5 kbps
+
+
+
+
+ 0,5 Mbps
+
+
+
+
+ 1.5 Mbps
+
+
+
+
+ 45.45 kbps
+
+
+
+
+ 93.75 kbps
+
+
+
+
+ Defines the type of connection resource to use for communiction with the PLC
+ Depending on the connection partner and connection type, the range of values is automatically limited to valid values or the value of the connection resource is assigned permanently.
+
+
+
+
+ Unknown connection resource
+
+
+
+
+ Programming device connection
+ Free connection (not configured)
+ At least one resource per CPU is reserved for programming device connections. However, for certain S7-300 CPUs it is possible to reserve multiple resources in the CPU properties.
+ S7 connections that are typically set up from a programming device or from a PC (with ES functionality). This type of connection is used to configure and program the addressed station/module as well as to test and commission it;
+ afterwards, the connection is typically cleared again. This connection resource allows both read and write access (e.g., monitoring and loading).
+
+
+
+
+ OP connection
+ Free connection (not configured)
+ At least one resource per CPU is reserved for OP connections. However, for certain S7-300 CPUs it is possible to reserve multiple resources in the CPU properties.
+ S7 connections that are typically set up from an OP or from a PC (with OS functionality). This type of connection is used to monitor the addressed station/module with regard to the process that is being controlled.
+
+
+
+
+ Other
+ Free connection (configured, unspecified connection)
+ This connection resource can operate multiple connections. Use: Connection configured at one end with unspecified connection partner! The connection partner does not have to be configured if the connection resource 0x03 is addressed.
+ Use is not specified. For example, this resource is used automatically when an S7 connection configured at both ends is configured from an S7-400 to an S7-300.
+
+
+
+
+ CPU
+ Connections that are typically set up from a CPU to another module (CPU, FM, etc.) within a subnet. The connection setup is initiated by the application program,
+ in which a connection configuration does not exist. This type of connection allows process data to be exchanged between the modules. For certain S7-300 CPUs, it is possible to reserve resources for S7 basic communication.
+
+
+
+
+ Create an new Nck tag from an existing one by copying its information
+
+
+
+
+
+
+ Create an new Nck tag from an existing one by copying its information
+
+
+
+
+
+
+ Represents on single data Tag or data unit that can be read or written to the controller
+
+
+
+
+ This is a Property which addresses the values you've read with a Name
+
+
+
+
+ The byte offset or Byte address of the data in the controller. Represents the start of the data
+
+
+
+
+ Represents the Bit offset of the data int the controller. Only relevant for boolean values
+ Will be ignored for non boolean values
+
+
+
+
+ The Item does not exist in the controller, or the data can not be read completely from the controller (byte size wrong,..)
+
+
+
+
+ Create an new PLC Tag
+
+
+
+
+ Create an new PLC tag from an existing one by copying its information
+
+
+
+
+
+ Create an new PLC Tag
+
+ The Simatic Address for the data in the controller such as:
+ Inputs: I4.0, IB4, IW4 , ID4
+ Outputs: Q124.0, QB124, QW124, QD124
+ Markers: M11.0, MB10, MW10, MD10
+ Timers: T34
+ Counters: C23
+ Data Block: DB5.DBX2.0, DB5.DBW6
+ Arrays and String: "P#DB25.DBX0.0 BYTE 14"; "P#M0.0 WORD 2"; "P#I0.0 DWORD 5"
+
+ The data type to be read from the Controller
+
+
+
+ The initalizationString can be a PLC Address like: "DB100.DBW2" or a init String like: "User,DB100.DBW2,Word,Decimal"
+
+
+
+
+
+ The Data block number of the tag. If the TagDataSource is not in an data-block this number is 0
+
+
+
+
+ Specifies the area where the PLCTags data is located in the controller
+
+
+
+
+ The tats display type. Defines how the tags data should be represented
+
+
+
+
+ The type of data of the tag
+
+
+
+
+ An list of values of the previous read requests from the controller
+
+
+
+
+ Sets or gets the amount of values to be kept as oldValues after each read request
+
+
+
+
+ This Tag can not be splittet into more then one PDU (if there are a few rest Bytes in a PDU aviable)
+ --> If this is set, the Tag is not allowed to be bigger!
+ This bit should be set in all Tags wich are used for indirect Addressing! (Becaus eit could be you read 2 bytes of a double, then the value chages in the plc, then you read the rest!)
+ This is also used when Writing the Value, and when set, it is not splitted. When the Value is bigger then a PDU, an error occurs
+
+
+
+
+ Defines the length of Array data types. Only valid (and used!) with String, CharArray and ByteArray Type!
+
+
+
+
+ Helper Property to Set the Value, because the Setter of the normal Value Sets Control Value!
+
+
+
+
+ Value of the Tag. The Setter of this Property sets Controlvalue, because the Tag firstly got this Value when it's written!
+
+
+
+
+ This Parses the PLCTag From a Byte Array
+ this is used, when the Tag is not Read via my Functions, but the PLCTags are used as Wrapper
+
+
+
+
+
+
+ Creates a struct of a specified type by an array of bytes.
+
+ The struct type
+ The array of bytes
+ The object depending on the struct type or null if fails(array-length != struct-length
+
+
+
+ Gets the size of the struct in bytes.
+
+ the type of the struct
+ the number of bytes
+
+
+
+ Creates a byte array depending on the struct type.
+
+ The struct object
+ A byte array or null if fails.
+
+
+
+ This is a internal used Tag for Read optimazions
+
+
+
+
+ · Byte 1: B#16#04: CPU-Schutzstufe, Bedienschalterstellungen und Prüfsummen
+ · Byte 0:Standard-CPU: B#16#00H-CPU: Bits 0 bis 2: Baugruppenträger-Nr.Bit 3: 0 = Reserve-CPU, 1 = Master-CPUBits 4 bis 7: 1111
+
+
+
+
+ Durch Betriebsartenschalter eingestellte Schutzstufe (1, 2, 3)
+
+
+
+
+ Parametrierte Schutzstufe (0, 1, 2, 3; 0: kein Paßword vergeben, parametrierte Schutzstufe ungültig).
+
+
+
+
+ Gültige Schutzstufe der CPU
+
+
+
+
+ Stellung des Betriebsartenschalters (1:RUN, 2:RUN-P, 3:STOP, 4:MRES, 0:undefiniert bzw. nicht ermittelbar)
+
+
+
+
+ Stellung des Anlaufartenschalters (1:CRST, 2:WRST, 0:undefiniert, nicht vorhanden oder nicht ermittelbar)
+
+
+
+
+ Reserviert
+
+
+
+
+ Kennung für die Gültigkeit der vier folgenden Prüfsummen (0: ungültig)
+
+
+
+
+ Prüfsumme 1 der Hardwarekonfiguration (Intel-Format):Exklusiv-Oder-Verknüpfung über die Längen aller Systemdatenbausteine
+
+
+
+
+ Prüfsumme 2 der Hardwarekonfiguration (Intel-Format):Exklusiv-Oder-Verknüpfung über die Prüfsummen aller Systemdatenbausteine
+
+
+
+
+ Prüfsumme 1 des Anwenderprogramms (Intel-Format):Exklusiv-Oder-Verknüpfung über die Längen der folgenden Bausteine: OBs, DBs, FBs, FCs
+
+
+
+
+ Prüfsumme 2 des Anwenderprogramms (Intel-Format):Exklusiv-Oder-Verknüpfung über die Prüfsummen der folgenden Bausteine: OBs, DBs, FBs, FCs
+
+
+
+
+ Reserviert
+
+
+
+
+ Anforderung von Schutzstufe 2 bzw. 3 durch SFC 109 (1: Anforderung ist erfolgt)
+
+
+
+
+ Aktivierung von Schutzstufe 2 bzw. 3 durch SFC 109 (1: Aktivierung ist erfolgt)
+
+
+
+
+ Reserviert
+
+
+
+
+ Options that define how Step7 Project will behave when opened by this library.
+
+
+
+
+ use the FB instance declartion symbolics for displaying Instance DB Variables
+ Otherwise it is using the Symbolics stored for each individual instance DB, which may be different than the Function Block
+ The Step7 Default is TRUE. Simatic Manager always shows the FB declarations.
+
+
+
+
+ Base Block for all Blocks, Subblocks are VATBlock, FunctionBlock, DataBlock, (DataBlockS5, FunctionBlockS5 maybe)
+
+
+
+
+ This can be Information about a PLC Block (DB, FC,...) or a Block in the Source Folder
+
+
+
+
+ This can be Information about a PLC Block (DB, FC,...) or a Block in the Source Folder
+
+
+
+
+ Description of S5Parameter.
+
+
+
+
+ Description of S5ParameterFormat.
+
+
+
+
+ Description of S5ParameterType.
+
+
+
+
+ With this function you get the Structure with expanden Arrays!
+
+
+
+
+
+
+ The blocks version
+
+ This field does not correspond to the Version field in Simatic Manager
+
+
+
+ The Block Attributes that contain information about the block status and special properties
+
+
+
+
+ The Block Attributes defined from the Simatic Manager in Attributes Tab
+
+
+
+
+ The total lenght of the Block. Correspnds to the "Load Memory Requirement" in Simatic Manager
+
+
+
+
+ The Title of the Block from the S7 Project file. it is not the online name of the block.
+
+ The Header name of an online block is in the "Name" field
+
+
+
+ The Author of the Block
+
+ Limited to 8 chars
+
+
+
+ The Family of the Block
+
+ Limited to 8 chars
+
+
+
+ The version of the Block
+
+ Limited from 0.0 to 9.9
+
+
+
+ Timestamp of the last change to the blocks MC7 code
+
+
+
+
+ Timestamp of the last change to the interface of the blocks
+
+
+
+
+ Timestamp of the last interface change associated with the plaintext database record
+ If a block is uploaded to the project with a timestamp conflict, this field contains the previous modified date of the interface before the upload
+
+
+
+
+ The total size of the Interface table
+
+ this is an internal property, that is not shown in Simatic Manager
+
+
+
+ The total size of the Segement table in the header
+
+ this is an internal property, that is not shown in Simatic Manager
+
+
+
+ The size of the local Temp data stack. Only aplicable to OB, FC or FB blocks
+
+
+
+
+ The actual MC7 code size of the block. This corresonds to the "MC7" field in Simatic Manager
+
+
+
+
+ the Work memory requirement from Simatic Manager
+
+
+
+
+ The block has currently set an Password
+
+ be aware that the block can also be be marked as protected via the "BlockAttributes"
+
+
+
+ The checksum of the Blocks MC7 code (without the actual values of Datablocks)
+ This property can be used to detect Block changes
+
+
+
+
+ The block exists in the controller, and is also linked into execution.
+ if this attribute is FALSE:
+ -For Code blocks such as FB or FC, this means that they are existing in the controller but not actually executed
+ -For data blocks this means, that they do not have any Actual values assigned to them. Any attempt to read current data from them will fail.
+
+
+ This corresponds to the "Unlinked" attribute in the Simatic manager, which actually shows the status in reverse
+ This Attribute is only false when either especifically selected from simatic manager (only possible for Datablocks)
+ or during a breif period when an Code block is alrady downloaded, but not yet linked (usually part of the "Block Download" process
+
+
+
+
+ This is an standard block from the default library
+
+
+
+
+ The block is protected by an Password
+
+
+
+
+ Only applies to datablocks. if an DB is non retentive, its actual data get reset to its initial values every time the controller
+ restarts
+
+
+
+
+ This is an Safety Block in an Safety PLC.
+
+
+
+
+ Returns true if dt1 and dt2 are not equal
+ Also checks that both values are not the default value (DateTime.MinValue)
+
+
+
+
+ With this function you get the Structure with expanden Arrays!
+
+
+
+
+
+ This function is used, when a Member is added or Removed, or the Type is changed so the the Addresses are recalculated!
+
+
+
+
+ an declaration for an FB as Multi instance parameter. May only occur in STATIC Block declaration
+
+
+
+
+ an declaration for an System-FB as Multi instance parameter. May only occur in STATIC Block declaration
+
+
+
+
+ Returns the Number of Lines this Command needs (Calls needs more then 1 Line)
+
+
+
+
+
+ N: NC Daten
+
+
+
+
+ B: Daten Betriebsartengruppe
+
+
+
+
+ C: Kanalzugeordnete Daten
+
+
+
+
+ A: Achsspezifische Grundeinstellungen
+
+
+
+
+ T: Wergzeugdaten
+
+
+
+
+ V: Vorschubantrieb
+
+
+
+
+ H: Hauptantrieb
+
+
+
+
+ M: MMC-Daten
+
+
+
+
+ ?: Unbekannt
+
+
+
+
+ Represents an PLC Block type and name
+
+
+
+
+ The type of Block
+
+
+
+
+ The number of the Block
+
+
+
+
+ The programming language in which an S7Block was created
+
+
+
+
+ "Anweisungsliste" or AWL for short. The English term is
+ "Statement list" or STL
+
+
+
+
+ "Kontaktplan" or KOP for short. The English term is
+ "Ladder" or Lad
+
+
+
+
+ "Funktionsplan" or FUP for short. The English term is
+ "Functional Block diagram" or FDB
+
+
+
+
+ "Structured Text" or SCL for short
+
+
+
+
+ The Datablock declaration language. Only used for Datablocks
+
+
+
+
+ Graphset language
+
+
+
+
+ Continous Function Chart
+
+
+
+
+ Sequencial Funcion Chart
+
+
+
+
+ Same as AWL but for Safty blocks
+
+
+
+
+ Same as KOP but for Safty blocks
+
+
+
+
+ Same as FUP but for Safty blocks
+
+
+
+
+ Same as SCL but for Safty blocks
+
+
+
+
+ Same as DB but for Safty blocks
+
+
+
+
+ F-Call blocks are special code blocks that are neceseary to Execute Safty Programms
+ Only applicable on Safety CPU's
+
+
+
+
+ This is the Main Folder, it Contains a BlockInfos Folder and a Symbol Table!
+
+
+
+
+ Base Abstract Class for every Project Folder.
+
+
+
+
+ Read all blocks from the S7 Project and cache them into the 'tmpBlocks' field.
+
+
+
+
+
+ Help class, used to hold unparsed raw data read from the S7 Project files from disk
+
+
+
+
+ Reads the raw data from the S7 Project files, without parsing the data
+
+ The Block info object that identifies the block to read from Disk
+
+
+
+
+ Reads the raw data from the S7 Project files, without parsing the data
+
+ The blockname to be read from disk. eg. DB2, FB38....
+
+
+
+
+ Reads an Block from the Project and returns the block data that is stored in the S7 Project
+
+ The blockname to be read from disk. eg. DB2, FB38....
+
+
+
+
+ Reads an Block from the Project and returns the block data that is stored in the S7 Project
+
+ The blockname to be read from disk. eg. DB2, FB38....
+ Defines options that determine how the Block will be converted
+
+
+
+
+ Reads an Block from the Project and returns the block data that is stored in the S7 Project
+
+ The Block info object that identifies the block to read from Disk
+
+
+
+
+ Reads an Block from the Project and returns the block data that is stored in the S7 Project
+
+ The Block info object that identifies the block to read from Disk
+ Defines options that determine how the Block will be converted
+
+
+
+
+ Converts the MC7 code of the block interface to S7DataRow
+
+
+
+
+ With this Function you get the AWL Source of a Block, so that it can be imported into Step7
+
+ The BlockInfo from the Block you wish to get the Source of!
+
+
+
+
+ Base Abstract Class for every Project Folder.
+
+
+
+
+ Returns the symbol list as a string that
+ is formatted in the same way as an export from
+ the Simatic Symbol Editor when saving it as .SDF
+ (System Data Format) type.
+
+
+
+
+
+
+ Data type of an field / key
+
+
+
+
+ Binary
+
+
+
+
+ String
+
+
+
+
+ Date (YYYYMMDD)
+
+
+
+
+ Number (Double)
+
+
+
+
+ Float
+
+
+
+
+ Logical (Boolean) Byte
+
+
+
+
+ Memo
+
+
+
+
+ DateTime
+
+
+
+
+ Format of a tag header key
+
+
+
+
+ Right, Left, DTOC
+
+
+
+
+ Descending
+
+
+
+
+ String
+
+
+
+
+ Distinct
+
+
+
+
+ Unique
+
+
+
+
+ The format of the index key
+
+
+
+
+ Calculated
+
+
+
+
+ DataField
+
+
+
+
+ Find te position of a Key within the BinaryTree
+
+ The key to find
+ The BinaryTree Node that contains the Key
+
+
+
+ The NodeKey of this BinaryTree
+
+
+
+
+ Get the least tree (furthest away from root)
+
+
+
+
+ Get the highest tree (closest to the root or root)
+
+
+
+
+ Address of the next available node
+
+
+
+
+ Length of a key without overhead
+
+
+
+
+ Number of Keys per Page/Node
+
+
+
+
+ Datatype of the Key
+
+
+
+
+ Length of a key entry (must be devidable by 4)
+
+
+
+
+ Is this Index a unique key?
+
+
+
+
+ Syntax definition of the key
+
+
+
+
+ Builds a NodeKey from this Index
+
+ The created NodeKey
+
+
+
+ Tells if the Key is unique or not
+
+
+
+
+ A MDX-Structure (Part of a MDX-File)
+
+
+
+
+ Read the MDX subentry from the parent MDXFile structure
+
+ A binary reader that contains the filestream of the MDX File
+ The byte length of the TagTableHeader
+ The start position of the first tag table header
+ "True" if the operation was successfull
+
+
+
+ Represents a complete MDX file, containing all sub indexes, headers and read / write methods
+
+
+
+
+ Destructor
+
+
+
+
+ Dispose this object
+
+
+
+
+ Read node from the parent MDX Entry
+
+ The BinaryReader that contains the MDXFile Stream
+
+
+
+ Sets / Returns the next lower level of the b-tree structrue, containing the nodes
+
+
+
+
+ Sets / Returns the previous node page of the index
+
+
+
+
+ Custom Type to represent Step7 float datatype with integrated conversion functions.
+
+
+
+
+ Create a float from a byte array, containing a S7 float value
+
+ The BCD byte array
+
+
+
+ Create a float from a double value
+
+ The double value to create the float from
+
+
+
+ Compare this NodeFloat object against another
+
+ The NodeFloat object you want to compare
+
+
+
+
+ The value of this NodeFloat as Double
+
+
+
+
+ The value of this NodeFloat as String
+
+
+
+
+ The value of this NodeFloat as byte array
+
+
+
+
+ A node key with a dynamic type (string, float, double)
+
+
+
+
+ This Function Writes directly to a DBF File.
+ It reads the Field list, and writes to the correct position.
+ To access the deleted flag, use DELETED_FLAG as column Name
+
+
+
+
+
+
+
+
+
+ The header of a DBF file
+
+
+
+
+ The header of a DBT file
+
+
+
+
+ The header of a memo
+
+
+
+
+ The DBF field descriptor structure. There will be one of these for each column in the table.
+
+
+
+
+ A MDX4 Tag Table Header
+
+
+
+
+ Extracts a MDX4TagTableHeader from a Stream
+
+ The BinaryReader that contains the MDX4TTH structure
+ The total length of a single MDX4TTH structrue + overhead
+ The start position in the stream
+ An MDX4TagTableHeader structure or null (if the operation failed)
+
+
+
+ A MDX7 Tag Table Header
+
+
+
+
+ Extracts a MDX7TagTableHeader from a Stream
+
+ The BinaryReader that contains the MDX7TTH structure
+ The total length of a single MDX7TTH structrue + overhead
+ The start position in the stream
+ An MDX7TagTableHeader structure or null (if the operation failed)
+
+
+
+ A MDX file header
+
+
+
+
+ A MDX tag header
+
+
+
+
+ Extracts a MDXTagHeader from a Stream
+
+ The BinaryReader that contains the MDXTH structure
+ The total length of a single MDXTH structrue + overhead
+ The start position in the stream
+ An MDXTagHeader structure or null (if the operation failed)
+
+
+
+ Write this MDXTagHeader to the current position of a Stream
+
+ A BinaryWriter to write the MDXTH to
+
+
+
+ Contains functions to convert dBase data types to .NET types and the other way around
+
+
+
+
+ Converts a logical byte ('L') to a boolean value
+
+ the logical byte from dBase
+ The boolean value
+
+
+
+ Converts a boolean value to a dBase logical byte
+
+ The boolean value to convert
+ A dBase logical byte
+
+
+
+ Converts a float byte array('F') to a double value
+
+ The float byte array from dBase
+ The double value
+
+
+
+ Converts a double value to a dBase Float byte array
+
+ The double value to convert
+ A dBase float byte array
+
+
+
+ Converts a timestamp byte array('T') to a datetime value
+
+ The timestamp byte array from dBase(8 bytes long)
+ The datetime value
+
+
+
+ Converts a datetime value to a dBase timestamp byte array
+
+ The double value to convert
+ A dBase float byte array
+
+
+
+ Converts a character byte array('C') to a string value
+
+ The character byte array from dBase
+ A string value
+
+
+
+ Converts a string value to a dBase character byte array
+
+ The string value to convert
+ A dBase character byte array
+
+
+
+ Converts a datetime byte array('D') to a DateTime value
+
+ The datetime byte array from dBase
+ A datetime value
+
+
+
+ Converts a DateTime value to a dBase datetime byte array
+
+ The DateTime value to convert
+ A dBase DateTime byte array
+
+
+
+ Differentiate between Integer or Decimal numbers comming from dBase
+
+ the number byte array from dBase
+ True if the submittet byte array is a decimal number
+
+
+
+ Converts a number byte array('N') to a Decimal value
+
+ The number byte array from dBase
+ A Decimal value
+
+
+
+ Converts a number byte array('N') to a Integer value
+
+ The number byte array from dBase
+ A Integer value
+
+
+
+ Converts a Decimal value to a dBase datetime byte array
+
+ The decimal value to convert
+ A dBase number byte array
+
+
+
+ Converts a Integer value to a dBase datetime byte array
+
+ The integer value to convert
+ A dBase number byte array
+
+
+
+ Convert a Julian Date to a .NET DateTime structure
+ Implemented from pseudo code at http://en.wikipedia.org/wiki/Julian_day
+
+ Julian Date to convert (days since 01/01/4713 BC)
+ DateTime
+
+
+
+ Defines a MemoryStream that does not sit on the Large Object Heap, thus avoiding memory fragmentation.
+
+
+
+
+ Defines the default chunk size. Currently defined as 0x10000.
+
+
+
+
+ Initializes a new instance of the class.
+
+
+
+
+ Initializes a new instance of the class.
+
+ Size of the underlying chunks.
+
+
+
+ Initializes a new instance of the class based on the specified byte array.
+
+ The array of unsigned bytes from which to create the current stream.
+
+
+
+ Initializes a new instance of the class based on the specified byte array.
+
+ Size of the underlying chunks.
+ The array of unsigned bytes from which to create the current stream.
+
+
+
+ Gets or sets a value indicating whether to free the underlying chunks on dispose.
+
+ true if [free on dispose]; otherwise, false.
+
+
+
+ Releases the unmanaged resources used by the and optionally releases the managed resources.
+
+ true to release both managed and unmanaged resources; false to release only unmanaged resources.
+
+
+
+ When overridden in a derived class, clears all buffers for this stream and causes any buffered data to be written to the underlying device.
+ This implementation does nothing.
+
+
+
+
+ When overridden in a derived class, reads a sequence of bytes from the current stream and advances the position within the stream by the number of bytes read.
+
+ An array of bytes. When this method returns, the buffer contains the specified byte array with the values between and ( + - 1) replaced by the bytes read from the current source.
+ The zero-based byte offset in at which to begin storing the data read from the current stream.
+ The maximum number of bytes to be read from the current stream.
+
+ The total number of bytes read into the buffer. This can be less than the number of bytes requested if that many bytes are not currently available, or zero (0) if the end of the stream has been reached.
+
+
+ The sum of and is larger than the buffer length.
+
+
+ is null.
+
+
+ or is negative.
+
+
+ Methods were called after the stream was closed.
+
+
+
+
+ Reads a byte from the stream and advances the position within the stream by one byte, or returns -1 if at the end of the stream.
+
+
+ The unsigned byte cast to an Int32, or -1 if at the end of the stream.
+
+
+ Methods were called after the stream was closed.
+
+
+
+
+ When overridden in a derived class, sets the position within the current stream.
+
+ A byte offset relative to the parameter.
+ A value of type indicating the reference point used to obtain the new position.
+
+ The new position within the current stream.
+
+
+ Methods were called after the stream was closed.
+
+
+
+
+ When overridden in a derived class, sets the length of the current stream.
+
+ The desired length of the current stream in bytes.
+
+ Methods were called after the stream was closed.
+
+
+
+
+ Converts the current stream to a byte array.
+
+ An array of bytes
+
+
+
+ When overridden in a derived class, writes a sequence of bytes to the current stream and advances the current position within this stream by the number of bytes written.
+
+ An array of bytes. This method copies bytes from to the current stream.
+ The zero-based byte offset in at which to begin copying bytes to the current stream.
+ The number of bytes to be written to the current stream.
+
+ The sum of and is greater than the buffer length.
+
+
+ is null.
+
+
+ or is negative.
+
+
+ Methods were called after the stream was closed.
+
+
+
+
+ Writes a byte to the current position in the stream and advances the position within the stream by one byte.
+
+ The byte to write to the stream.
+
+ Methods were called after the stream was closed.
+
+
+
+
+ Writes to the specified stream.
+
+ The stream.
+
+
+
+ When overridden in a derived class, gets a value indicating whether the current stream supports reading.
+
+
+ true if the stream supports reading; otherwise, false.
+
+
+
+
+ When overridden in a derived class, gets a value indicating whether the current stream supports seeking.
+
+
+ true if the stream supports seeking; otherwise, false.
+
+
+
+
+ When overridden in a derived class, gets a value indicating whether the current stream supports writing.
+
+
+ true if the stream supports writing; otherwise, false.
+
+
+
+
+ When overridden in a derived class, gets the length in bytes of the stream.
+
+
+
+ A long value representing the length of the stream in bytes.
+
+
+ Methods were called after the stream was closed.
+
+
+
+
+ Gets or sets the size of the underlying chunks. Cannot be greater than or equal to 85000.
+
+ The chunks size.
+
+
+
+ When overridden in a derived class, gets or sets the position within the current stream.
+
+
+
+ The current position within the stream.
+
+
+ Methods were called after the stream was closed.
+
+
+
+
+ Konvertiert eine allgemeine Liste in ein Array aus Objekten
+
+ Liste
+ Liste als Array
+
+
+
+ Konvertiert eine allgemeine Liste in ein Array eines bestimmten Typs
+
+ Zieltyp des Rückgabearrays
+ Liste
+ Liste als Array
+
+
+
+ We could use that to simply load SDB0 from the plc and then parse the bytes directly
+
+
+
+
+
+
+ This is a Helper Function wich is used by GetSourceBlock
+
+
+
+
+
+
+
+ Returns the Parameter as an Int!
+
+
+
+
+
+
+ This Function Returns a byte Array of a Value Parameter
+
+
+
+
+
+
+ This Function Returns the Hex Value of a Parameter Pointer of a UC or CC.
+
+
+
+
+
+
+ These functions to Convert from MC7 to AWL could not be done withou the help of Steffen Krayer !
+ Many of the Code is from him (From his Delphi Prog) and also he created Excel sheets wich decribe
+ how MC7 for most of the AWL Commands looks.
+
+
+ The general structure of an online block is as follows:
+ 0 - 35 Block header
+ 36 - x MC7 code for Code blocks; Current data for datablocks
+ x - x Interface
+ x - x Start Values (if any)
+ x - x Segment table
+ Len -36 Block footer. The footer is always located 36 bytes at the end of the block
+
+ all values x are depending on the blocks layout and apropiate length fields must be parsed from code
+
+
+
+
+ This value marks the lenght of the actual Block header, and since the MC7 code immeadiatly follows,
+ also marks the start of the MC7 Code or Datablock body
+
+
+
+
+ This value marks the lenght of the actual Block footer which is always situatted at the end of the MC7 code data
+
+
+
+
+ Parse the Header and Footer information from an online MC7Code byte blob
+
+ The online MC7 Code blob from the PLC
+ The Mnemoric that should be used when parsing the Blocks data
+
+
+
+
+ This class is responsible for parsing Interface declarations from MC7. It parses all variables from the interface declaration and optionally fills in the startvalues and
+ actual values. This class is used by the MC7 converter
+
+
+ The Interface of an MC7 block is structured as follows:
+ Header:
+ 0 Block Type: 0x05 (DB) 0x10 (DI)
+ 1-2 Again Block Number or FB Number on a DI (but bytes swapped)
+ 3-4 Interface Length minus this header (7 bytes)
+ 5-6 Start Value Length
+
+ Interface:
+ 7-x Line 1
+ x-x Line 2
+ ...
+
+ for more information about the format of an Interface Line, please look at GetVarTypeEN
+
+
+
+
+ Represents the Type of Parameter in an Interfacer, Not the Datatype.
+ Basically ther are In, Out, INOUT, Static and Temp
+ The _Init versions are the same with the above, except they have initial values that must ge parsed
+ the _EX_ version are slightly different, in that they include an extra parameter in the interface declaration row.
+ I think this parameter is some kind of BitFiled declaring some options, but i am not sure what it is? See GetVarEn function for details
+
+
+
+
+ Goes down in the parameter rows and finds the datarow corresponding to the In, Out or InOut parameter that corresponds to Index
+ It goes throught the interface of the Function of FunctionBlock the same way as S7 would (first In, Out then InOut
+
+ The interface of the block
+ The number of the Parameter of the block
+
+
+
+
+ Compares the structure of two Interface declarations and returns true if they are compatible and false if not
+ They are compatible if the Structure and Datatypes match up. Datarow names are ignored, since the interface remain
+ compatible as long as the general structure matches up.
+ Also Actual values are ignores
+
+ The first interface to compare
+ The second interface to campare
+
+
+
+
+ Parses the interface from an Step7 Source code as stored in Step7 Project Files
+
+ The Step7 Code to be parsed
+ An list of Parameters that where found in the Step7 Declaration
+ The block type that is beeing Parsed
+ Indicates if an block is an Instance DB
+ The BlocksOffline Folder where the parsed block code belongs to
+ The Block where the Parsed Step7 code belongs to
+ the current values of the DB, if it is an DB
+
+
+
+
+ Find and assign the Actual value of an Intervace to an given S7Datarow
+
+
+
+ OUT: an pointer for tracking the current value position in the parsing process
+
+
+
+ Parses the interface from an MC7 Interface block
+
+ The interface bytes from the MC7 code
+ The corresponding Current data values. Only valid for DB
+ OUT: The parsed Parameter list
+ the block type of the block interface to be parsed
+ Indicates if the data block belongs to an Function block
+ The block header
+
+
+
+
+ Parses an Interface parameter Row from the Interface of an MC7 block
+
+ The Parent Interface Row of the rows to be parsed
+ The Interface parameter data type"/>
+ The parameter row is inside an struct
+ the parameter row is inside an array
+ The variable name to be used for the current row
+ the interface bytes from the MC7 Code
+ OUT: the current parsing position
+ The current data bytes from the MC7 code
+ OUT: the current parsing position for Initial values
+ OUT: the parsed parameter row number
+ OUT: The current parsing stack depth
+ The prefix to be used to generate the variable names from
+ The block, where the interface belongs to
+
+
+
+ Get corresponding current value. These values essentially have the exact same layout as one is familiar with the "GetBytes" interfaces
+ From the communication library.
+
+ The data-type of the interface row
+ Either an Array containing the Start Values or Actual Values
+ OUT: Current position of parsing
+ the parsed value acording to the given datatyep and adress. If the datatype is invalid (such as struct) it returns Null
+
+
+
+ Get corresponding Initial value
+
+ The data-type of the interface row
+ Either an Array containing the Start Values or Actual Values
+ OUT: Current position of parsing
+ the parsed value acording to the given datatyep and adress. If the datatype is invalid (such as struct) it returns Null
+
+ The Initial values are encoded in an compacted manner. Meaning, if an varialbe does not have an
+ Initial value, it does not appear in the start values list!
+ this means the valpos must be tracked, and increased every time an Avlue was parsed from the array
+
+ WARNING! be aware that for somehow reason Siemens encoded the Startvalues in Little Endien format,
+ completly contrary to the comon S7 format! This means one can not use the Libnodave.Getxxx funcions,
+ but rather has to use the usual Bitconverter
+
+ Basically the logic here uses the default libnodave.getxxx function, but with Bitconverter instead.
+
+
+
+
+ Small helper class to keep track of the current Variable name
+
+
+
+
+ Returns the next Variable name and increments the internal Variable count
+
+
+
+
+
+ This Function Returens a Step7 Project Instance for every Project Folder in the Path.
+
+
+
+
+
+
+ This Function Returens a Step7 Project Instance for every Project Folder in the Path.
+
+
+
+
+
+
+ Parses the AWL Text and returns the S7Blocks
+
+
+ Can be null
+
+
+
+
+ Sets the keep-alive interval for the socket.
+
+ The socket.
+ Time between two keep alive "pings".
+ Time between two keep alive "pings" when first one fails.
+ If the keep alive infos were succefully modified.
+
+
+
diff --git a/Helpers/SearchHelper.cs b/Helpers/SearchHelper.cs
new file mode 100644
index 0000000..0a80b44
--- /dev/null
+++ b/Helpers/SearchHelper.cs
@@ -0,0 +1,143 @@
+using S7Explorer.Models;
+using S7Explorer.Services;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace S7Explorer.Helpers
+{
+ public class SearchHelper
+ {
+ private readonly LogService _logService;
+
+ public SearchHelper()
+ {
+ _logService = LogService.Instance;
+ }
+
+ public List Search(ProjectStructure project, string searchText, bool caseSensitive, bool useRegex)
+ {
+ _logService.LogInfo($"Searching for '{searchText}' (Case sensitive: {caseSensitive}, Regex: {useRegex})");
+
+ List results = new List();
+
+ try
+ {
+ if (string.IsNullOrWhiteSpace(searchText))
+ return results;
+
+ // Prepare regex if needed
+ Regex? regex = null;
+ if (useRegex)
+ {
+ try
+ {
+ RegexOptions options = caseSensitive ? RegexOptions.None : RegexOptions.IgnoreCase;
+ regex = new Regex(searchText, options);
+ }
+ catch (Exception ex)
+ {
+ _logService.LogError($"Invalid regex pattern: {ex.Message}");
+ return results;
+ }
+ }
+
+ // Search blocks
+ SearchProjectItem(project.BlocksFolder, results, searchText, caseSensitive, regex);
+
+ // Search symbols
+ SearchProjectItem(project.SymbolsFolder, results, searchText, caseSensitive, regex);
+
+ // Search hardware
+ SearchProjectItem(project.HardwareFolder, results, searchText, caseSensitive, regex);
+
+ _logService.LogInfo($"Found {results.Count} results");
+ return results;
+ }
+ catch (Exception ex)
+ {
+ _logService.LogError($"Error during search: {ex.Message}");
+ return results;
+ }
+ }
+
+ private void SearchProjectItem(ProjectItem item, List results, string searchText,
+ bool caseSensitive, Regex? regex)
+ {
+ // Check name
+ bool nameMatch = MatchesSearch(item.Name, searchText, caseSensitive, regex);
+
+ // For blocks, check content and comments
+ bool contentMatch = false;
+ if (item is BlockItem blockItem)
+ {
+ contentMatch = MatchesSearch(blockItem.BlockContent, searchText, caseSensitive, regex) ||
+ MatchesSearch(blockItem.BlockComment, searchText, caseSensitive, regex);
+ }
+
+ // For symbols, check address, type, and comment
+ else if (item is SymbolItem symbolItem)
+ {
+ contentMatch = MatchesSearch(symbolItem.SymbolAddress, searchText, caseSensitive, regex) ||
+ MatchesSearch(symbolItem.SymbolDataType, searchText, caseSensitive, regex) ||
+ MatchesSearch(symbolItem.SymbolComment, searchText, caseSensitive, regex);
+ }
+
+ // For hardware, check module info
+ else if (item is HardwareItem hardwareItem)
+ {
+ contentMatch = MatchesSearch(hardwareItem.ModuleType, searchText, caseSensitive, regex) ||
+ MatchesSearch(hardwareItem.OrderNumber, searchText, caseSensitive, regex) ||
+ MatchesSearch(hardwareItem.Position, searchText, caseSensitive, regex) ||
+ MatchesSearch(hardwareItem.Address, searchText, caseSensitive, regex);
+ }
+
+ if (nameMatch || contentMatch)
+ {
+ results.Add(new SearchResult
+ {
+ Item = item,
+ MatchType = nameMatch ? (contentMatch ? MatchType.Both : MatchType.Name) : MatchType.Content
+ });
+ }
+
+ // Search children recursively
+ foreach (var child in item.Children)
+ {
+ SearchProjectItem(child, results, searchText, caseSensitive, regex);
+ }
+ }
+
+ private bool MatchesSearch(string text, string searchText, bool caseSensitive, Regex? regex)
+ {
+ if (string.IsNullOrEmpty(text))
+ return false;
+
+ if (regex != null)
+ return regex.IsMatch(text);
+
+ return caseSensitive
+ ? text.Contains(searchText)
+ : text.ToLower().Contains(searchText.ToLower());
+ }
+ }
+
+ public class SearchResult
+ {
+ public ProjectItem Item { get; set; } = null!;
+ public MatchType MatchType { get; set; }
+
+ public override string ToString()
+ {
+ return $"{Item.Name} - {MatchType}";
+ }
+ }
+
+ public enum MatchType
+ {
+ Name,
+ Content,
+ Both
+ }
+}
\ No newline at end of file
diff --git a/Helpers/TreeViewHelper.cs b/Helpers/TreeViewHelper.cs
new file mode 100644
index 0000000..b5df093
--- /dev/null
+++ b/Helpers/TreeViewHelper.cs
@@ -0,0 +1,98 @@
+using S7Explorer.Models;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+
+namespace S7Explorer.Helpers
+{
+ public static class TreeViewHelper
+ {
+ public static ProjectItem? FindItemByPath(ObservableCollection items, string path)
+ {
+ if (string.IsNullOrEmpty(path))
+ return null;
+
+ string[] parts = path.Split('/');
+ return FindItemByParts(items, parts, 0);
+ }
+
+ private static ProjectItem? FindItemByParts(IEnumerable items, string[] parts, int level)
+ {
+ if (level >= parts.Length)
+ return null;
+
+ var matchingItem = items.FirstOrDefault(i => i.Name == parts[level]);
+ if (matchingItem == null)
+ return null;
+
+ if (level == parts.Length - 1)
+ return matchingItem;
+
+ return FindItemByParts(matchingItem.Children, parts, level + 1);
+ }
+
+ public static ProjectItem? FindItemByName(ObservableCollection items, string name)
+ {
+ foreach (var item in items)
+ {
+ if (item.Name == name)
+ return item;
+
+ var found = FindItemByName(item.Children, name);
+ if (found != null)
+ return found;
+ }
+
+ return null;
+ }
+
+ public static List FindItemsByText(ObservableCollection items, string text)
+ {
+ List results = new List();
+ FindItemsByTextRecursive(items, text.ToLower(), results);
+ return results;
+ }
+
+ private static void FindItemsByTextRecursive(IEnumerable items, string text, List results)
+ {
+ foreach (var item in items)
+ {
+ if (item.Name.ToLower().Contains(text))
+ results.Add(item);
+
+ FindItemsByTextRecursive(item.Children, text, results);
+ }
+ }
+
+ public static void ExpandToItem(ProjectItem item)
+ {
+ // Expand all parent items to make the item visible
+ ProjectItem? current = item.Parent;
+ while (current != null)
+ {
+ current.IsExpanded = true;
+ current = current.Parent;
+ }
+ }
+
+ public static void ExpandAll(ProjectItem item)
+ {
+ item.IsExpanded = true;
+
+ foreach (var child in item.Children)
+ {
+ ExpandAll(child);
+ }
+ }
+
+ public static void CollapseAll(ProjectItem item)
+ {
+ item.IsExpanded = false;
+
+ foreach (var child in item.Children)
+ {
+ CollapseAll(child);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/LinqExtensions.cs b/LinqExtensions.cs
deleted file mode 100644
index 44f8906..0000000
--- a/LinqExtensions.cs
+++ /dev/null
@@ -1,69 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-
-namespace S7Explorer
-{
- ///
- /// Extensiones LINQ para funcionalidades específicas de la aplicación
- ///
- public static class LinqExtensions
- {
- ///
- /// Cuenta elementos en una colección que cumplen un predicado
- ///
- public static int Count(this IEnumerable source, Func predicate)
- {
- if (source == null)
- return 0;
-
- return source.Where(predicate).Count();
- }
-
- ///
- /// Verifica si una colección contiene al menos un elemento
- ///
- public static bool Any(this IEnumerable source)
- {
- if (source == null)
- return false;
-
- return source.Any(item => true);
- }
-
- ///
- /// Verifica si una colección contiene al menos un elemento que cumpla un predicado
- ///
- public static bool Any(this IEnumerable source, Func predicate)
- {
- if (source == null)
- return false;
-
- using (var enumerator = source.GetEnumerator())
- {
- while (enumerator.MoveNext())
- {
- if (predicate(enumerator.Current))
- return true;
- }
- }
-
- return false;
- }
-
- ///
- /// Selecciona elementos de una colección que cumplen un predicado
- ///
- public static IEnumerable Where(this IEnumerable source, Func predicate)
- {
- if (source == null)
- yield break;
-
- foreach (var item in source)
- {
- if (predicate(item))
- yield return item;
- }
- }
- }
-}
\ No newline at end of file
diff --git a/MainWindow.xaml b/MainWindow.xaml
new file mode 100644
index 0000000..b91adfb
--- /dev/null
+++ b/MainWindow.xaml
@@ -0,0 +1,126 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/MainWindow.xaml.cs b/MainWindow.xaml.cs
new file mode 100644
index 0000000..67ab631
--- /dev/null
+++ b/MainWindow.xaml.cs
@@ -0,0 +1,96 @@
+using S7Explorer.Models;
+using S7Explorer.Services;
+using S7Explorer.ViewModels;
+using System;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Media;
+
+namespace S7Explorer
+{
+ public enum LogLevel
+ {
+ Debug,
+ Info,
+ Warning,
+ Error
+ }
+
+ public class LogEntry
+ {
+ public DateTime Timestamp { get; set; }
+ public LogLevel Level { get; set; }
+ public string Message { get; set; } = string.Empty;
+
+ public override string ToString()
+ {
+ return $"[{Timestamp:yyyy-MM-dd HH:mm:ss}] [{Level}] {Message}";
+ }
+ }
+
+ public partial class MainWindow : Window
+ {
+ private MainViewModel ViewModel;
+
+ public MainWindow()
+ {
+ InitializeComponent();
+ ViewModel = new MainViewModel();
+ DataContext = ViewModel;
+ }
+
+ private void TreeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs