using Aurora.Api; using Aurora.Api.Devices; using AuroraLaser.Trumpf.TruDisk; using Hermes; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace AuroraLaser.Trumpf.TruPulseNano { public partial class LaserDeviceTruPulseNano : Device, ILaserDeviceTrumpf { private const int TimeOut = 3000; private string _deviceId; public LaserTruPulseNanoConfig Config { get; set; } private SocketConn _socketConn; public LaserDeviceTruPulseNano(string deviceId) { _deviceId = deviceId; _socketConn = new SocketConn(deviceId, IsSimul); } protected override int DoActivate(IDeviceConfig config) { Config = config as LaserTruPulseNanoConfig; return ActivateDevice(); //if (IsSimul) { // return E1.OK; //} //var socketconfig = config.ConnConfig as SocketConnConfig; //return _socketConn.Connect(socketconfig); } protected override int DoDeactivate() { return DeactivateDevice(); //if (IsSimul) { // return E1.OK; //} //var res = _socketConn.Close(); //return res; } public int ActivateDevice() { if (IsSimul) { return E1.OK; } var socketconfig = Config.ConnConfig as SocketConnConfig; return _socketConn.Connect(socketconfig); } public int DeactivateDevice() { if (IsSimul) { return E1.OK; } var res = _socketConn.Close(); return res; } public Task SendandReceiveAsync(byte[] bytearray) { return Task.Run(() => SendandReceive(bytearray)); } public byte[] SendandReceive(byte[] bytearray) { if (IsSimul) { return bytearray; } byte[] result = null; var res = _socketConn.SendAndRecieve(bytearray, out result, 3000); return result; } public byte[] CreateCommandPacket(TrupulseNanoCommand command, string[] arguments) { if (!CommandArguments.TryGetValue(command, out var argInfo)) { throw new ArgumentException("Invalid command"); } var argTypes = argInfo.ArgumentTypes; // arguments가 null이면 빈 배열로 처리 if (arguments == null) arguments = new string[0]; // ArgumentTypes가 null(즉, 인자가 필요 없는 명령어)이면 arguments 없이 패킷 생성 if (argTypes == null) { byte[] packet = new byte[6]; packet[0] = 0x1B; // Start byte packet[1] = 2; // Number of command bytes (명령어만 2바이트) packet[2] = 0x09; // Command start byte packet[3] = (byte)command; packet[4] = 0x0D; // Stop byte packet[5] = CalculateChecksum(packet); return packet; } // argument 개수 체크: 둘 다 0이면 허용 if (argTypes.Length != arguments.Length) { if (argTypes.Length == 0 && (arguments.Length == 0 || (arguments.Length == 1 && string.IsNullOrEmpty(arguments[0])))) { // 인자가 필요 없는 명령어, arguments가 빈 배열 또는 [""]인 경우 허용 } else { throw new ArgumentException("Argument count mismatch"); } } var argList = new List(); for (int i = 0; i < argTypes.Length; i++) { string arg = arguments[i]; Type t = argTypes[i]; if (t == typeof(byte)) { if (byte.TryParse(arg, out byte b)) { argList.Add(b); } else { argList.Add(0); } } else if (t == typeof(UInt16) || t == typeof(ushort)) { ushort us = 0; ushort.TryParse(arg, out us); var bytes = BitConverter.GetBytes(us); Array.Reverse(bytes); // Big Endian argList.AddRange(bytes); } else if (t == typeof(UInt32) || t == typeof(uint)) { uint ui = 0; uint.TryParse(arg, out ui); var bytes = BitConverter.GetBytes(ui); Array.Reverse(bytes); // Big Endian argList.AddRange(bytes); } else { argList.Add(0); } } byte[] packetWithArgs = new byte[argList.Count + 6]; packetWithArgs[0] = 0x1B; // Start byte packetWithArgs[1] = (byte)(argList.Count + 2); // Number of command bytes packetWithArgs[2] = 0x09; // Command start byte packetWithArgs[3] = (byte)command; if (argList.Count > 0) { Array.Copy(argList.ToArray(), 0, packetWithArgs, 4, argList.Count); } packetWithArgs[packetWithArgs.Length - 2] = 0x0D; // Stop byte packetWithArgs[packetWithArgs.Length - 1] = CalculateChecksum(packetWithArgs); return packetWithArgs; } #region Processing Received Message private byte CalculateChecksum(byte[] packet) { byte checksum = 0; for (int i = 0; i < packet.Length - 1; i++) { checksum += packet[i]; } return checksum; } public bool IsValidResponse(byte[] responsePacket) { if (responsePacket.Length < 6) { return false; } byte startByte = responsePacket[0]; byte commandnumber = responsePacket[1]; byte stopByte = responsePacket[responsePacket.Length - 2]; byte checksum = responsePacket[responsePacket.Length - 1]; if (startByte != 0x1B || stopByte != 0x0D) { return false; } if (commandnumber != (responsePacket.Length - 4)) { return false; } byte calculatedChecksum = CalculateChecksum(responsePacket); if (checksum != calculatedChecksum) { return false; } return true; } public (byte commandNumber, byte[] arguments, string error) ParseResponse(byte[] responsePacket) { if (!IsValidResponse(responsePacket)) { return ((byte)0x00, null, "Invalid response packet."); } byte responseProtocolCommandByte = responsePacket[2]; byte responseValue = responsePacket[3]; byte commandNumber = responsePacket[4]; if (responseProtocolCommandByte == 0x00) { string errorMessage = Enum.GetName(typeof(ResponseCheck), responseValue) ?? "UnknownError"; return (commandNumber, null, errorMessage); } if (commandNumber == 0) { byte commandcheck = responsePacket[5]; string errorMessage = Enum.GetName(typeof(CommandCheck), commandcheck) ?? "UnknownCommandError"; return (commandNumber, null, errorMessage); } if (responseProtocolCommandByte == 0x09 && responseValue == 0) { // Command transferred to Laser correctly int argumentCount = responsePacket.Length - 7; byte[] arguments = new byte[argumentCount]; Array.Copy(responsePacket, 5, arguments, 0, argumentCount); return (commandNumber, arguments, null); } return (commandNumber, null, "Unknown response error"); } public object[] ParseArguments(TrupulseNanoCommand command, byte[] arguments) { if (!ResponseArguments.TryGetValue(command, out var respInfo) || respInfo.ArgumentTypes == null) { return new object[0]; } var result = new List(); int argCount = respInfo.ArgumentCount; var types = respInfo.ArgumentTypes; if (argCount == -1) { // 가변 개수, 타입 하나 반복 var type = types[0]; int size = GetTypeSize(type); int count = arguments.Length / size; for (int i = 0; i < count; i++) { result.Add(ParseSingle(arguments, i * size, type)); } } else { int offset = 0; for (int i = 0; i < types.Length && offset < arguments.Length; i++) { var type = types[i]; int size = GetTypeSize(type); if (offset + size > arguments.Length) { break; } result.Add(ParseSingle(arguments, offset, type)); offset += size; } } return result.ToArray(); } private int GetTypeSize(Type type) { if (type == typeof(byte) || type == typeof(char)) { return 1; } if (type == typeof(UInt16) || type == typeof(ushort)) { return 2; } if (type == typeof(UInt32) || type == typeof(uint)) { return 4; } return 1; } private object ParseSingle(byte[] data, int offset, Type type) { if (type == typeof(byte)) { return data[offset]; } if (type == typeof(UInt16) || type == typeof(ushort)) { return (UInt16)((data[offset] << 8) | data[offset + 1]); // Big Endian } if (type == typeof(UInt32) || type == typeof(uint)) { return (UInt32)((data[offset] << 24) | (data[offset + 1] << 16) | (data[offset + 2] << 8) | data[offset + 3]); // Big Endian } if (type == typeof(char)) { return (char)data[offset]; } return data[offset]; } #endregion /////////////////////////////////////////////////////////// // Laser Interface 추가 // All LaserDevice 에서 선택하여 Device 가 생성될 때 사용되며, All LaserDevice 가 Activated 일 때만 true 가 됨. public bool IsActivated_InAllLaserDevice = false; private bool CanCallLaserFunction() { throw new NotImplementedException(); } public int LaserOn() { throw new NotImplementedException(); } public int LaserOff() { throw new NotImplementedException(); } public int PilotLaserOn() { throw new NotImplementedException(); } public int PilotLaserOff() { throw new NotImplementedException(); } public bool GetPilotLaserStatus() { throw new NotImplementedException(); } public bool GetLaserReady() { throw new NotImplementedException(); } public bool GetPilotLaserSetBitStatus() { throw new NotImplementedException(); } public bool GetConnected() { throw new NotImplementedException(); } public int SetData(int nTarget, int value) { throw new NotImplementedException(); } public int ResetLaser() { throw new NotImplementedException(); } public string GetControlMode() { throw new NotImplementedException(); } public bool GetControlModeSetStatus() { throw new NotImplementedException(); } public bool GetEmissionStatus() { throw new NotImplementedException(); } public bool GetEStop() { throw new NotImplementedException(); } public bool GetInitCommunication() { throw new NotImplementedException(); } public bool GetLaserError() { throw new NotImplementedException(); } public bool GetLaserResetSetBitStatus() { throw new NotImplementedException(); } public bool GetLaserStartSetBitStatus() { throw new NotImplementedException(); } public string GetPowerCenter() { throw new NotImplementedException(); } public string GetPowerRing() { throw new NotImplementedException(); } public bool GetStartLaserSetBitStatus() { throw new NotImplementedException(); } public bool GetWarningStatus() { throw new NotImplementedException(); } public bool GetLaserInterlock() { throw new NotImplementedException(); } } }