diff --git a/LecturaDM.sln b/LecturaDM.sln new file mode 100644 index 0000000..24c66c2 --- /dev/null +++ b/LecturaDM.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.14.37314.3 d17.14 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LecturaDM", "LecturaDM\LecturaDM.csproj", "{141E22A4-743C-4BA9-993D-E9567E795412}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {141E22A4-743C-4BA9-993D-E9567E795412}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {141E22A4-743C-4BA9-993D-E9567E795412}.Debug|Any CPU.Build.0 = Debug|Any CPU + {141E22A4-743C-4BA9-993D-E9567E795412}.Release|Any CPU.ActiveCfg = Release|Any CPU + {141E22A4-743C-4BA9-993D-E9567E795412}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {3C23E5E6-ADAD-41F2-99AC-98A314405931} + EndGlobalSection +EndGlobal diff --git a/LecturaDM/Lectura.txt b/LecturaDM/Lectura.txt new file mode 100644 index 0000000..e69de29 diff --git a/LecturaDM/LecturaDM.csproj b/LecturaDM/LecturaDM.csproj new file mode 100644 index 0000000..59296f0 --- /dev/null +++ b/LecturaDM/LecturaDM.csproj @@ -0,0 +1,25 @@ + + + + Exe + net8.0 + enable + enable + + + + + ..\..\..\..\Cognex\DataMan SDK 5.6.3\Binaries\PC\Cognex.DataMan.CogNamer.PC.dll + + + ..\..\..\..\Cognex\DataMan SDK 5.6.3\Binaries\PC\Cognex.DataMan.SDK.Discovery.PC.dll + + + ..\..\..\..\Cognex\DataMan SDK 5.6.3\Binaries\PC\Cognex.DataMan.SDK.PC.dll + + + ..\..\..\..\Cognex\DataMan SDK 5.6.3\Binaries\PC\Cognex.DataMan.SDK.Utils.PC.dll + + + + diff --git a/LecturaDM/Program.cs b/LecturaDM/Program.cs new file mode 100644 index 0000000..3d1d223 --- /dev/null +++ b/LecturaDM/Program.cs @@ -0,0 +1,372 @@ +using System; +using System.IO; +using System.Net; +using System.Threading; +using System.Xml; +using System.Text.RegularExpressions; +using Cognex.DataMan.SDK; + +class Program +{ + private static Mutex _mutex = new Mutex(true, "EscudoLecturaDMCognex"); + private static AutoResetEvent _esperaLectura = new AutoResetEvent(false); + private static bool _lecturaExitosa = false; + private static object _lock = new object(); + + private static string _configDirectory = "C:\\Jabil DM Config Station\\Files\\"; + private static string _configPath = ""; + private static string _resultLecturaPath = ""; + private static string _lecturaDataPath = ""; + + private static volatile bool _triggerEnviado = false; + + // ARREGLOS PARA EL RESPALDO + private static string[] _backupStandard = new string[4]; + private static string[] _backupToken = new string[4]; + private static string[] _backupDelimiter = new string[4]; + private static bool _configModificada = false; + + static void Main(string[] args) + { + _configPath = Path.Combine(_configDirectory, "ConfigIP.txt"); + _resultLecturaPath = Path.Combine(_configDirectory, "ResultLectura.txt"); + _lecturaDataPath = Path.Combine(_configDirectory, "Lectura.txt"); + + if (!_mutex.WaitOne(TimeSpan.Zero, true)) + { + Console.ForegroundColor = ConsoleColor.Yellow; + Console.WriteLine("[ALERTA] Ya hay una instancia de LecturaDM corriendo. Abortando colisión..."); + Console.ResetColor(); + return; + } + + try + { + Console.WriteLine("=========================================="); + Console.WriteLine(" PROGRAMA: LECTURA DM GEOMETRÍA "); + Console.WriteLine("==========================================\n"); + + ActualizarResultControl("0"); + + if (!File.Exists(_configPath)) + { + Console.WriteLine($"[ERROR] No se encontró el archivo base: {_configPath}"); + ActualizarResultControl("2"); + Thread.Sleep(3000); + return; + } + + string[] configLines = File.ReadAllLines(_configPath); + if (configLines.Length < 2) + { + Console.WriteLine("[ERROR] El archivo ConfigIP.txt no tiene el formato correcto."); + ActualizarResultControl("2"); + Thread.Sleep(3000); + return; + } + + string ipString = configLines[1].Trim(); + if (!IPAddress.TryParse(ipString, out var lectorIp)) + { + Console.WriteLine($"[ERROR] La IP '{ipString}' no es válida."); + ActualizarResultControl("2"); + Thread.Sleep(3000); + return; + } + + Console.WriteLine($"Conectando al DataMan en la IP: {lectorIp}..."); + EthSystemConnector connector = new EthSystemConnector(lectorIp); + DataManSystem myDevice = new DataManSystem(connector); + + try + { + myDevice.Connect(5000); + Console.ForegroundColor = ConsoleColor.Green; + Console.WriteLine("[OK] Conectado con éxito."); + Console.ResetColor(); + + try { myDevice.SendCommand("TRIGGER OFF"); } catch { } + Thread.Sleep(100); + try { myDevice.SendCommand("SET TRIGGER.TYPE 0"); } catch { } + + // ===================================================================== + // FASE DE RESPALDO Y MODIFICACIÓN + // ===================================================================== + Console.WriteLine("[SISTEMA] Respaldando y preparando perfiles..."); + _configModificada = true; + + for (int i = 0; i <= 3; i++) + { + try { myDevice.SendCommand($"SET FORMAT.PROG-TARG {i}"); } + catch { continue; } + + try { _backupStandard[i] = myDevice.SendCommand("GET FORMAT.STANDARD").PayLoad.Trim(); } catch { } + try { _backupToken[i] = myDevice.SendCommand("GET FORMAT.TOKEN").PayLoad.Trim(' ', '"'); } catch { } + try { _backupDelimiter[i] = myDevice.SendCommand("GET FORMAT.DELIMITER").PayLoad.Trim(); } catch { } + + // INYECTAMOS EL TOKEN COMPLETO PARA OBLIGARLA A DARNOS EL XML + try { myDevice.SendCommand("SET FORMAT.STANDARD ON"); } catch { } + try { myDevice.SendCommand("SET FORMAT.TOKEN \"\""); } catch { } + try { myDevice.SendCommand("SET FORMAT.DELIMITER 5"); } catch { } + } + + myDevice.SetResultTypes(ResultTypes.ReadString | ResultTypes.ReadXml); + + myDevice.XmlResultArrived += (sender, e) => + { + if (!_triggerEnviado) return; + + lock (_lock) + { + if (_lecturaExitosa) return; + + if (string.IsNullOrEmpty(e.XmlResult)) return; + + try + { + XmlDocument doc = new XmlDocument(); + doc.LoadXml(e.XmlResult); + + XmlNode? statusNode = doc.SelectSingleNode("//general/status"); + if (statusNode == null || !statusNode.InnerText.ToUpper().Contains("GOOD READ")) + return; + + // ======= DIAGNÓSTICO TEMPORAL - BORRAR DESPUÉS ======= + /*Console.WriteLine("=== XML EXTERIOR COMPLETO ==="); + Console.WriteLine(e.XmlResult); + Console.WriteLine("=== FIN XML EXTERIOR ==="); + + XmlNode? outerFullString_diag = doc.SelectSingleNode("//general/full_string"); + + if (outerFullString_diag != null) + { + Console.WriteLine("=== CONTENIDO FULL_STRING EXTERIOR ==="); + Console.WriteLine($"InnerText: [{outerFullString_diag.InnerText}]"); + Console.WriteLine($"InnerXml: [{outerFullString_diag.InnerXml}]"); + Console.WriteLine($"Encoding attr: [{outerFullString_diag.Attributes?["encoding"]?.Value ?? "ninguno"}]"); + Console.WriteLine("=== FIN FULL_STRING ==="); + } + */ + + // El full_string exterior contiene otro XML completo como texto + XmlNode? outerFullString = doc.SelectSingleNode("//general/full_string"); + if (outerFullString == null) return; + + string innerXmlText = outerFullString.InnerText; + + // Si está en base64, decodificar + string? enc = outerFullString.Attributes?["encoding"]?.Value; + if (enc != null && enc.ToLower() == "base64") + { + try + { + byte[] bytes = Convert.FromBase64String(innerXmlText); + innerXmlText = System.Text.Encoding.UTF8.GetString(bytes); + } + catch { } + } + + string posX = "0"; + string posY = "0"; + string angulo = "0"; + string codigoFinal = ""; + + try + { + // CDATA: extraer el código real + var matchCdata = Regex.Match(innerXmlText, @""); + if (matchCdata.Success) + codigoFinal = matchCdata.Groups[1].Value.Trim(); + + // Primer punto de code_position = posición del código + var matchX = Regex.Match(innerXmlText, @"\s*\s*([\d]+)\s*([\d]+)"); + if (matchX.Success) + { + posX = matchX.Groups[1].Value; + posY = matchX.Groups[2].Value; + } + + // Ángulo + var matchAng = Regex.Match(innerXmlText, @"([\d]+)"); + if (matchAng.Success) + angulo = matchAng.Groups[1].Value; + } + catch (Exception ex) + { + Console.WriteLine($"[AVISO] Error extrayendo datos: {ex.Message}"); + } + + if (string.IsNullOrEmpty(codigoFinal)) + codigoFinal = innerXmlText; + + if (string.IsNullOrEmpty(codigoFinal)) return; + + Console.ForegroundColor = ConsoleColor.Cyan; + Console.WriteLine($"\n[ÉXITO]"); + Console.WriteLine($"-> Lectura: {codigoFinal}"); + Console.WriteLine($"-> Posición X: {posX}"); + Console.WriteLine($"-> Posición Y: {posY}"); + Console.WriteLine($"-> Ángulo: {angulo}°"); + Console.ResetColor(); + + _lecturaExitosa = true; + GuardarDatosLectura(codigoFinal, posX, posY, angulo); + ActualizarResultControl("1"); + _esperaLectura.Set(); + } + catch (Exception ex) + { + Console.WriteLine($"[ERROR PARSEO XML]: {ex.Message}"); + } + } + }; + + Console.WriteLine("[SISTEMA] Drenando buffer de red..."); + Thread.Sleep(600); + + Console.WriteLine("[SISTEMA] Habilitando recepción..."); + _triggerEnviado = true; + + Console.WriteLine("Enviando disparo por software..."); + myDevice.SendCommand("TRIGGER ON"); + + _esperaLectura.WaitOne(10000); + + if (!_lecturaExitosa) + { + Console.ForegroundColor = ConsoleColor.Red; + Console.WriteLine("\n[TIEMPO AGOTADO] No se detectó código o falló la captura."); + Console.ResetColor(); + ActualizarResultControl("2"); + } + } + catch (Exception ex) + { + Console.ForegroundColor = ConsoleColor.Red; + Console.WriteLine($"\n[ERROR CRÍTICO] Problema de conexión: {ex.Message}"); + Console.ResetColor(); + ActualizarResultControl("2"); + } + finally + { + // ===================================================================== + // FASE DE RESTAURACIÓN + // ===================================================================== + try { myDevice.SendCommand("TRIGGER OFF"); } catch { } + Thread.Sleep(100); + + if (_configModificada) + { + Console.WriteLine("[SISTEMA] Restaurando formato de salida original de la cámara..."); + for (int i = 0; i <= 3; i++) + { + try { myDevice.SendCommand($"SET FORMAT.PROG-TARG {i}"); } catch { continue; } + + if (!string.IsNullOrEmpty(_backupStandard[i])) + try { myDevice.SendCommand($"SET FORMAT.STANDARD {_backupStandard[i]}"); } catch { } + + if (!string.IsNullOrEmpty(_backupDelimiter[i])) + try { myDevice.SendCommand($"SET FORMAT.DELIMITER {_backupDelimiter[i]}"); } catch { } + + if (!string.IsNullOrEmpty(_backupToken[i])) + try { myDevice.SendCommand($"SET FORMAT.TOKEN \"{_backupToken[i]}\""); } catch { } + else + try { myDevice.SendCommand("SET FORMAT.TOKEN \"\""); } catch { } + } + } + + try { myDevice.Disconnect(); } catch { } + } + + Console.WriteLine("\nEl programa finalizará en 3 segundos..."); + Thread.Sleep(3000); + } + finally + { + _mutex.ReleaseMutex(); + } + } + + private static void ActualizarResultControl(string estado) + { + try + { + // Paso 1: Escribir en la carpeta local del .exe + string localResultPath = "ResultLectura.txt"; + string localCopiaPath = "ResultLectura_Copia.txt"; + + File.WriteAllText(localCopiaPath, estado); + + if (File.Exists(localResultPath)) + { + File.Delete(localResultPath); + Thread.Sleep(100); + } + + File.Move(localCopiaPath, localResultPath); + Console.WriteLine("[SISTEMA] ResultLectura.txt actualizado localmente con estado: " + estado); + + // Paso 2: Copiar al configDirectory + Thread.Sleep(100); + string configCopiaPath = Path.Combine(_configDirectory, "ResultLectura_Copia.txt"); + File.Copy(localResultPath, configCopiaPath, true); + + if (File.Exists(_resultLecturaPath)) + { + File.Delete(_resultLecturaPath); + Thread.Sleep(100); + } + + File.Move(configCopiaPath, _resultLecturaPath); + Console.WriteLine("[SISTEMA] ResultLectura.txt copiado a configDirectory."); + } + catch (Exception ex) + { + Console.ForegroundColor = ConsoleColor.Red; + Console.WriteLine($"[ERROR ARCHIVO CONTROL] No se pudo guardar estado: {ex.Message}"); + Console.ResetColor(); + } + } + + private static void GuardarDatosLectura(string resultado, string x, string y, string angle) + { + try + { + // Paso 1: Escribir en la carpeta local del .exe + string localLecturaPath = "Lectura.txt"; + string localCopiaPath = "Lectura_Copia.txt"; + string[] lineas = new string[] { resultado, x, y, angle }; + + File.WriteAllLines(localCopiaPath, lineas); + + if (File.Exists(localLecturaPath)) + { + File.Delete(localLecturaPath); + Thread.Sleep(100); + } + + File.Move(localCopiaPath, localLecturaPath); + Console.WriteLine("[SISTEMA] Lectura.txt actualizado localmente."); + + // Paso 2: Copiar al configDirectory + Thread.Sleep(100); + string configCopiaPath = Path.Combine(_configDirectory, "Lectura_Copia.txt"); + File.Copy(localLecturaPath, configCopiaPath, true); + + if (File.Exists(_lecturaDataPath)) + { + File.Delete(_lecturaDataPath); + Thread.Sleep(100); + } + + File.Move(configCopiaPath, _lecturaDataPath); + Console.WriteLine("[SISTEMA] Lectura.txt copiado a configDirectory."); + } + catch (Exception ex) + { + Console.ForegroundColor = ConsoleColor.Red; + Console.WriteLine($"[ERROR ARCHIVO DATA] No se pudo guardar: {ex.Message}"); + Console.ResetColor(); + } + } +} \ No newline at end of file diff --git a/LecturaDM/ResultLectura.txt b/LecturaDM/ResultLectura.txt new file mode 100644 index 0000000..c227083 --- /dev/null +++ b/LecturaDM/ResultLectura.txt @@ -0,0 +1 @@ +0 \ No newline at end of file