2026-01-26 18:56:53 +09:00

1395 lines
63 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using Aurora.Api.Devices;
using Hermes;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace AuroraLaser.IPG.YLS
{
public class LaserYLSSocketConn : SocketConn
{
public bool IsEmissionReady { get; set; }
public bool HasAlarm { get; set; }
private bool _IsSimul;
private int _Status;
private double _OperatingPower;
private double _RepetitionRate = 0.0;
internal bool IsCommError => IsConnected();
private readonly object _sendLock = new object();
#region IPG YLS Enumerator Definitions
public enum eFunctionCommand
{
GetLaserID = 1, // The command requests laser identification data
GetNetworkSettings = 2, // Command requests laser network settings
SetIpSettings = 3, // Command defines laser network address.
SetCommandTimeout = 4, // Set communication timeout. If there is no command during that time, the current connection will be closed. Default value – 5000 ms
GetCriticalErrorCounter = 5, // The command returns the counter of Critical Errors.
GetLongRunningOperationsState = 6, // The command returns the status off all long-running operations in the laser.
LockControl = 10, // The command locks controls on the Control page in LaserNet and for this protocol on other sockets (connections)
UnlockControl = 11, // The command unlocks controls on the Control page in LaserNet and for this protocol on other sockets (connections)
GetLaserStaticParameters = 2000, // Request static parameters structure from the laser
GetLaserData = 2001, // Request dynamic (current) parameters structure from the laser , 매우 중요.
GetTimeData = 2002, // Request time from the laser
SetCurrentTime = 2003, // Set time in the laser
SetAutoSwitchOff = 2004, // Set time for auto switch off the laser
GetPowerSuppliesStaticParameters = 2010, // Request static parameters structure of laser power supplies
GetPowerSupplyData = 2011, // Request dynamic (current) parameters structure of the power supply
GetPowerSupplyParameters = 2012, // Request static parameters structure of the power supply
GetExtOpticsStaticParameters = 2020, // Request static parameters structure of Beamswitch or Beamcoupler
GetBeamSwitchData = 2021, // Request dynamical (current) parameters structure of Beamswitch
GetFFCouplerData = 2022, // Request dynamical (current) parameters structure of Fiber-Fiber Coupler
GetChillerStaticParameters = 2030, // Request static parameters structure of the chiller
GetChillerData = 2031, // Request dynamic (current) parameters structure of the chiller
GetDewPointData = 2032, // Request dynamical (cuurent) parameters structure of dew point sensor
GetFieldbusStaticParameters = 2040, // Request static parameters structure of Fieldbus controller
GetFieldbusControllerParameters = 2041, // Request parameters structure of the given Fieldbus controller
GetFieldbusData = 2042, // Request dynamical (current) parameters structure of Fieldbus controller
SetFieldbusParameters = 2043, // Set common parameters structure for Fieldbus
SetFieldbusSlotParameters = 2044, // Set common parameters structure for Fieldbus
SetFieldbusSlotSpecificParameters = 2045, // Set specific parameters for Fieldbus
GetPulsedStaticParameters = 2050, // Request static parameters structure of pulsed operational modes (lasers of type QCW, QCW+, Pulsed)
GetPulsedData = 2051, // Request dynamical (current) parameters structure of pulsed operational modes (lasers of type QCW, QCW+, Pulsed, HPP, AMB-QCW)
GetAuxUserInterfaceStaticParameters = 2060, // Request static parameters structure of User Interface
GetAuxUserInterfaceData = 2061, // Request dynamic (current) parameters structure of User Interface
GetLaserProgram = 2070, // Request the laser program
SetLaserProgram = 2071, // Set to the laser program
GetQcwLaserProgram = 2052, // Request the Qcw laser program
SetQcwLaserProgram = 2053, // Set to the Qcw laser program
DownloadQcwPulsedLibrary = 2054, // Set to the laser Qcw Pulsed Library
SetAccessLevel = 2080, // The command set access level
GetEventsFromFile = 2090, // The request of stored events from internal file for the synchronization at start of connection session. This command can be sent one time per session only. After this command all new events should be read by command GetNewEvents
GetNewEvents = 2091, // The request of new events list from the last call of this command
GetPulseGeneratorParameters = 2092, // Request static parameters structure of pulse generator
GetPulseGeneratorData = 2093, // Request dynamical (current) parameters structure of pulse generator
SetPulseGeneratorParameter = 2520, // The command set pulse generator parameter
GetLaserModuleData = 2300, // Request dynamic (current) parameters structure of the laser module
GetXY2Data = 2400, // Request parameters structure of XY2-100 Interface
DownloadNewConfiguration = 2600, // The command download HPLP file with new configuration and/or new firmware into the laser
// Control Commands , See the manual : Access Permission
PowerSupply = 2500, // The command is switching on/off the main power supply of the laser: (= 0 – switching off) (= 1 – switching on)
SetCurrent = 2501, // The command set pump current
SetPower = 2502, // The command set output power
Emission = 2503, // The command is switching on/off the emission: (= 0 – switching off) (= 0x155 – switching on)
GuideLaser = 2504, // The command is switching on/off guide lasers:
// Parameter1: the optical channel number or 0 – the mian guide laser
// Parameter2: (= 0 – switching off) (= 1 – switching on)
SetOpticalChannel = 2505, // The command set optical channel (0 – home-position)
Reset = 2506, // The command reset non-critical errors
ResetCriticalError = 2507, // The command reset critical errors. Parameter is the string got from IPG Service.
AnalogCtrl = 2508, // The command is switching on/off the analogue control: (= 0 – switching off) (= 1 – switching on)
ModulationCtrl = 2509, // The command is switching on/off the external control (modulation input): (= 0 – switching off) (= 1 – switching on)
SetRiseTime = 2510, // The command set rise time for the program 0
SetFallTime = 2511, // The command set fall time for the program 0
StartProgram = 2512, // The command start of the laser program
StopProgram = 2513, // The command interrupt the running laser program
SetPulsedMode = 2514, // The command is switching on/off the pulsed (QCW) mode of the laser:
// bit 0 – switching on/off – the pulsed mode; For HPP lasers switch on/off HPP mode;
// bit 1 – switching on/off – the single short submode for the pulsed mode;
// bit 2 – switching on/off – the gate submode for the pulsed mode
SetFrequency = 2515, // The command set frequency for the pulsed mode
SetPulsedWidth = 2516, // The command set pulse width for the pulsed mode
DisableModules = 2517, // The command disables selected modules for working in “single module mode”. 0 – enable all working modules.
SetSideSpotPower = 2521, // The command set output power for the side spots of the Brazing lasers. For AMB lasers the command set output power for the central and ring cores. Parameter1: Power1 (W) , Parameter2: Power2 (W)
EnablePowerSensorAdjustment = 2522, // The command enabled/disabled adjustment of power sensor option: 1 – enable , 0 – disable
AdjustPowerSensor = 2523, // The command adjust power sensor if power sensor adjustment option is activated
EnableOutputPowerTune = 2524, // The command enabled/disabled output power tune option: 1 – enable, 0 – disable
TuneOutputPower = 2525, // The command tune output power if output power tune option is activated.
SetAMBCurrents = 2526, // The command set pump currents for the central and ring cores in AMB2 lasers. Parameter1: Central Current , Parameter2: Ring Current
SetPulsedModeCh2 = 2527, // Similar to SetPulsedMode (2514) command for the second channel.
SetFrequencyCh2 = 2528, // Similar to SetFrequency (2515) command for the second channel.
SetPulsedWidthCh2 = 2529, // Similar to SetPulsedWidth (2516) command for the second channel.
SetXY2Control = 2530 // The command set control word on XY2-100 Interface
}
// Table 5.1: Laser Types, GetLaserData → LaserType
enum eLaserType
{
MultiMode = 0,
SingleMode,
Reserved,
SingleModeHPLaser,
HighBrightnessMultiMode
}
//private static class MaskingData
//{
// // enum 으로 선언하면 맨마지막 항목인 FirmwareIsUpdatding 이 signed 로 처리되어서 overflow 가능성있음
// public const UInt32 LaserEmissionSlowSignal = 0x00000001; // Emission of the laser is on (slow signal from laser modules)
// public const UInt32 LaserModulationMode = 0x00000002;
// public const UInt32 MainGuideLaser = 0x00000004;
// public const UInt32 LaserReady = 0x00000008;
// public const UInt32 RearDoorOpen = 0x00000010;
// public const UInt32 FrontDoorOpen = 0x00000020;
// public const UInt32 LaserAnalogControl = 0x00000040;
// public const UInt32 LaserEmissionEnable = 0x00000080;
// public const UInt32 LaserHardwiringActive = 0x00000100;
// public const UInt32 Reserved1 = 0x00000200;
// public const UInt32 ChillerReady = 0x00000400;
// public const UInt32 SWControlDisabledRequired = 0x00000800;
// public const UInt32 MainPowerSupplyOn = 0x00001000;
// public const UInt32 ErrorOccurred = 0x00002000;
// public const UInt32 BeamSwitchReady = 0x00004000;
// public const UInt32 IPGServiceMode = 0x00008000;
// public const UInt32 LaserProgramActived = 0x00010000;
// public const UInt32 LaserProgramInterrupted = 0x00020000;
// public const UInt32 LaserProgramEnded = 0x00040000;
// public const UInt32 LaserPermission_BeamSwitchHighLevel = 0x00080000;
// public const UInt32 LaserEnable_BeamSwitchHighLevel = 0x00100000;
// public const UInt32 TestKeyInRobotPosition = 0x00200000;
// public const UInt32 LaserAssignedbyRobot = 0x00400000; // The laser is assigned by robot via hardwiring or fieldbus interface
// public const UInt32 LaserEmissionFastSignal = 0x00800000; // Emission of the laser is on (fast signal from detector in the combiner unit)
// public const UInt32 SignalRestoreDefaultSetting = 0x01000000; // The signal from hardware button for restore default settings (now it used only for restoration of IP settings in the laser)
// public const UInt32 SignalInitialization = 0x02000000; // The signal about initialization (restart) of main microcontroller in the laser
// public const UInt32 CanResetCriticalError = 0x04000000; // The laser can "reset critical errors" in the laser by command "reset"
// public const UInt32 QCWMode = 0x08000000;
// public const UInt32 ShutdownState = 0x10000000;
// public const UInt32 InverseShutdownState = 0x20000000; // 중요!. Inversion of bit 28. If this bit same as bit 28 – all information from the laser is inadequate
// public const UInt32 StandbyState = 0x40000000;
// public const UInt32 FirmwareIsUpdatding = 0x80000000;
//}
#region GetLaserData = 2001, Structure Info
// State1
const string LaserEmissionSlowSignal = "LaserEmissionSlowSignal";
const string LaserModulationMode = "LaserModulationMode";
const string MainGuideLaser = "MainGuideLaser";
const string LaserReady = "LaserReady";
const string RearDoorOpen = "RearDoorOpen";
const string FrontDoorOpen = "FrontDoorOpen";
const string LaserAnalogControll = "LaserAnalogControll";
const string LaserEmissionEnable = "LaserEmissionEnable";
const string LaserHardwiringActive = "LaserHardwiringActive";
const string Reserved1 = "Reserved1";
const string ChillerReady = "ChillerReady";
const string SWControlDisabledRequired = "SWControlDisabledRequired";
const string MainPowerSupplyOn = "MainPowerSupplyOn";
const string ErrorOccurred = "ErrorOccurred";
const string BeamSwitchReady = "BeamSwitchReady";
const string IPGServiceMode = "IPGServiceMode";
const string LaserProgramActived = "LaserProgramActived";
const string LaserProgramInterrupted = "LaserProgramInterrupted";
const string LaserProgramEnded = "LaserProgramEnded";
const string LaserPermission_BeamSwitchHighLevel = "LaserPermission_BeamSwitchHighLevel";
const string LaserEnable_BeamSwitchHighLevel = "LaserEnable_BeamSwitchHighLevel";
const string TestKeyInRobotPosition = "TestKeyInRobotPosition";
const string LaserAssignedbyRobot = "LaserAssignedbyRobot";
const string LaserEmissionFastSignal = "LaserEmissionFastSignal";
const string SignalRestoreDefaultSetting = "SignalRestoreDefaultSetting";
const string SignalInitialization = "SignalInitialization";
const string CanResetCriticalError = "CanResetCriticalError";
const string QCWMode = "QCWMode";
const string ShutdownState = "ShutdownState";
const string InverseShutdownState = "InverseShutdownState";
const string StandbyState = "StandbyState";
const string FirmwareIsUpdatding = "FirmwareIsUpdatding";
private Dictionary<string, UInt32> LaserStatusMaskMap = new Dictionary<string, UInt32>
{
{ LaserEmissionSlowSignal, 0x00000001},
{ LaserModulationMode, 0x00000002},
{ MainGuideLaser, 0x00000004},
{ LaserReady, 0x00000008},
{ RearDoorOpen, 0x00000010},
{ FrontDoorOpen, 0x00000020},
{ LaserAnalogControll, 0x00000040},
{ LaserEmissionEnable, 0x00000080},
{ LaserHardwiringActive, 0x00000100},
{ Reserved1, 0x00000200},
{ ChillerReady, 0x00000400},
{ SWControlDisabledRequired, 0x00000800},
{ MainPowerSupplyOn, 0x00001000},
{ ErrorOccurred, 0x00002000},
{ BeamSwitchReady, 0x00004000},
{ IPGServiceMode, 0x00008000},
{ LaserProgramActived, 0x00010000},
{ LaserProgramInterrupted, 0x00020000},
{ LaserProgramEnded, 0x00040000},
{ LaserPermission_BeamSwitchHighLevel, 0x00080000},
{ LaserEnable_BeamSwitchHighLevel, 0x00100000},
{ TestKeyInRobotPosition, 0x00200000},
{ LaserAssignedbyRobot, 0x00400000},
{ LaserEmissionFastSignal, 0x00800000},
{ SignalRestoreDefaultSetting, 0x01000000},
{ SignalInitialization, 0x02000000},
{ CanResetCriticalError, 0x04000000},
{ QCWMode, 0x08000000},
{ ShutdownState, 0x10000000},
{ InverseShutdownState, 0x20000000},
{ StandbyState, 0x40000000},
{ FirmwareIsUpdatding, 0x80000000},
};
// State2 는 생략
// Alarm1 Code
const string Alarm1_laserFiberInterlock = "laserFiberInterlock";
const string Alarm1_laserOverheating = "laserOverheating";
const string Alarm1_HighBackReflection = "HighBackReflection";
const string Alarm1_HighLevelSignalPhotoDiode1 = "HighLevelSignalPhotoDiode1";
const string Alarm1_HighLevelSignalPhotoDiode2 = "HighLevelSignalPhotoDiode2";
const string Alarm1_LaserModuleFailed = "LaserModuleFailed";
const string Alarm1_EStop = "EStop";
const string Alarm1_ElectronicOverheating = "ElectronicOverheating";
const string Alarm1_LowWaterFlowFeedingFiber = "LowWaterFlowFeedingFiber";
const string Alarm1_LowWaterFlowProcessFiberIn = "LowWaterFlowProcessFiberIn";
const string Alarm1_LowWaterFlowProcessFiberOut = "LowWaterFlowProcessFiberOut";
const string Alarm1_LowWaterFlowLaser = "LowWaterFlowLaser";
const string Alarm1_SignalLampErrorOnLaser = "SignalLampErrorOnLaser";
const string Alarm1_CombinerFailed = "CombinerFailed";
const string Alarm1_UnExpectedPumpCurrent = "UnExpectedPumpCurrent";
const string Alarm1_InitializationError = "InitializationError";
const string Alarm1_UnExpectedGroundLeakage = "UnExpectedGroundLeakage";
const string Alarm1_UnConnectedLaserModuleExist = "UnConnectedLaserModuleExist";
const string Alarm1_PowerSupplyErrorOfLaserModuleExist = "PowerSupplyErrorOfLaserModuleExist";
const string Alarm1_ChillerError = "ChillerError";
const string Alarm1_WaterInLaser = "WaterInLaser";
const string Alarm1_CriticalErrorLaser = "CriticalErrorLaser"; // Critical error in the laser (Call for service)
const string Alarm1_FeedingFiberInitialError = "FeedingFiberInitialError"; // Feeding Fiber initial diagnostic procedure finished unsuccessfully
const string Alarm1_ChillerParameterOutofRange = "ChillerParameterOutofRange";
const string Alarm1_PowerSupplyAlarmExist = "PowerSupplyAlarmExist";
const string Alarm1_EStopButtonPressed = "EStopButtonPressed";
const string Alarm1_ACPowerProblem = "ACPowerProblem";
const string Alarm1_ExternalSafetyLoopOpen = "ExternalSafetyLoopOpen";
private Dictionary<string, UInt32> LaserAlarmMaskMap1 = new Dictionary<string, UInt32>
{
{ Alarm1_laserFiberInterlock, 0x00000001},
{ Alarm1_laserOverheating, 0x00000002},
{ Alarm1_HighBackReflection, 0x00000004},
{ Alarm1_HighLevelSignalPhotoDiode1, 0x00000008},
{ Alarm1_HighLevelSignalPhotoDiode2, 0x00000010},
{ Alarm1_LaserModuleFailed, 0x00000020},
{ Alarm1_EStop, 0x00000040},
{ Alarm1_ElectronicOverheating, 0x00000080},
{ Alarm1_LowWaterFlowFeedingFiber, 0x00000100},
{ Alarm1_LowWaterFlowProcessFiberIn, 0x00000200},
{ Alarm1_LowWaterFlowProcessFiberOut, 0x00000400},
//{ Reserved, 0x00000800},
//{ Reserved, 0x00001000},
//{ Reserved, 0x00002000},
//{ Reserved, 0x00004000},
{ Alarm1_LowWaterFlowLaser, 0x00008000},
{ Alarm1_SignalLampErrorOnLaser, 0x00010000},
{ Alarm1_CombinerFailed, 0x00020000},
{ Alarm1_UnExpectedPumpCurrent, 0x00040000},
{ Alarm1_InitializationError, 0x00080000},
{ Alarm1_UnExpectedGroundLeakage, 0x00100000},
{ Alarm1_UnConnectedLaserModuleExist, 0x00200000},
{ Alarm1_PowerSupplyErrorOfLaserModuleExist, 0x00400000},
{ Alarm1_ChillerError, 0x00800000},
{ Alarm1_WaterInLaser, 0x01000000},
{ Alarm1_CriticalErrorLaser, 0x02000000},
{ Alarm1_FeedingFiberInitialError, 0x04000000},
{ Alarm1_ChillerParameterOutofRange, 0x08000000},
{ Alarm1_PowerSupplyAlarmExist, 0x10000000},
{ Alarm1_EStopButtonPressed, 0x20000000},
{ Alarm1_ACPowerProblem, 0x40000000},
{ Alarm1_ExternalSafetyLoopOpen, 0x80000000},
};
// Alarm2 Code
private const string Alarm2_OutputPowerAboveAverage = "Alarm2_OutputPowerAboveAverage";
private const string Alarm2_InvalidLaserNumber = "Alarm2_InvalidLaserNumber";
private const string Alarm2_AutoSwitchOff = "Alarm2_AutoSwitchOff";
private const string Alarm2_AuxIOAlarm = "Alarm2_AuxIOAlarm";
private const string Alarm2_SpliceBoxAlarm = "Alarm2_SpliceBoxAlarm";
private const string Alarm2_InvalidOpticalPath = "Alarm2_InvalidOpticalPath";
private const string Alarm2_PowerSupplyOverheat = "Alarm2_PowerSupplyOverheat";
private const string Alarm2_TemperatureTooLow = "Alarm2_TemperatureTooLow";
private const string Alarm2_PulseTooLong = "Alarm2_PulseTooLong";
private const string Alarm2_PulseDutyCycleTooHigh = "Alarm2_PulseDutyCycleTooHigh";
private const string Alarm2_OpticalCableDamaged = "Alarm2_OpticalCableDamaged";
private const string Alarm2_ExternalError = "Alarm2_ExternalError";
private const string Alarm2_DewPointTooHigh = "Alarm2_DewPointTooHigh";
private const string Alarm2_PulseEnergyTooHigh = "Alarm2_PulseEnergyTooHigh";
private const string Alarm2_BSChannelError = "Alarm2_BSChannelError";
private const string Alarm2_ExternalLaserEnableReset = "Alarm2_ExternalLaserEnableReset";
private const string Alarm2_BeamSwitchDoorDelayTooLong = "Alarm2_BeamSwitchDoorDelayTooLong";
private const string Alarm2_MaintenanceNotDoneInTime = "Alarm2_MaintenanceNotDoneInTime";
private const string Alarm2_BackReflectionComparator = "Alarm2_BackReflectionComparator";
private const string Alarm2_PulseTooShort = "Alarm2_PulseTooShort";
private const string Alarm2_DischargeCircuitBroken = "Alarm2_DischargeCircuitBroken";
private const string Alarm2_SafetyPLCNoData = "Alarm2_SafetyPLCNoData";
private const string Alarm2_ModuleNoInputVoltage = "Alarm2_ModuleNoInputVoltage";
private const string Alarm2_PowerNotSwitchedOn = "Alarm2_PowerNotSwitchedOn";
private const string Alarm2_CombinerOverheat = "Alarm2_CombinerOverheat";
private const string Alarm2_NoEmissionDetected = "Alarm2_NoEmissionDetected";
private const string Alarm2_EnvironmentSensorAlarm = "Alarm2_EnvironmentSensorAlarm";
private Dictionary<string, UInt32> LaserAlarmMaskMap2 = new Dictionary<string, UInt32>
{
{ Alarm2_OutputPowerAboveAverage, 0x00000001 },
{ Alarm2_InvalidLaserNumber, 0x00000002 },
{ Alarm2_AutoSwitchOff, 0x00000004 },
{ Alarm2_AuxIOAlarm, 0x00000008 },
{ Alarm2_SpliceBoxAlarm, 0x00000010 },
{ Alarm2_InvalidOpticalPath, 0x00000020 },
{ Alarm2_PowerSupplyOverheat, 0x00000040 },
{ Alarm2_TemperatureTooLow, 0x00000080 },
{ Alarm2_PulseTooLong, 0x00000100 },
{ Alarm2_PulseDutyCycleTooHigh, 0x00000200 },
{ Alarm2_OpticalCableDamaged, 0x00000400 },
{ Alarm2_ExternalError, 0x00000800 },
{ Alarm2_DewPointTooHigh, 0x00001000 },
{ Alarm2_PulseEnergyTooHigh, 0x00002000 },
{ Alarm2_BSChannelError, 0x00004000 },
{ Alarm2_ExternalLaserEnableReset, 0x00008000 },
{ Alarm2_BeamSwitchDoorDelayTooLong, 0x00010000 },
{ Alarm2_MaintenanceNotDoneInTime, 0x00020000 },
{ Alarm2_BackReflectionComparator, 0x00040000 },
{ Alarm2_PulseTooShort, 0x00080000 },
{ Alarm2_DischargeCircuitBroken, 0x00100000 },
{ Alarm2_SafetyPLCNoData, 0x00200000 },
{ Alarm2_ModuleNoInputVoltage, 0x00400000 },
{ Alarm2_PowerNotSwitchedOn, 0x00800000 },
{ Alarm2_CombinerOverheat, 0x01000000 },
{ Alarm2_NoEmissionDetected, 0x02000000 },
{ Alarm2_EnvironmentSensorAlarm, 0x04000000 },
// 0x08000000 ~ 0x80000000 은 Reserved
};
// Warning Code
private const string Warning1_LaserPowerNotSwitchedOn = "Warning1_LaserPowerNotSwitchedOn";
private const string Warning1_ReservedModuleOn = "Warning1_ReservedModuleOn";
private const string Warning1_ModuleNearOverheat = "Warning1_ModuleNearOverheat";
private const string Warning1_ChillerTempWarning = "Warning1_ChillerTempWarning";
private const string Warning1_ModuleUnconnected = "Warning1_ModuleUnconnected";
private const string Warning1_OutputPowerNearThreshold = "Warning1_OutputPowerNearThreshold";
private const string Warning1_DischargeSensorWarning = "Warning1_DischargeSensorWarning";
private const string Warning1_AuxIOWarning = "Warning1_AuxIOWarning";
private const string Warning1_ActiveModuleReduced = "Warning1_ActiveModuleReduced";
private const string Warning1_AvgModuleTempNearThreshold = "Warning1_AvgModuleTempNearThreshold";
private const string Warning1_OutputPowerOutOfSpec = "Warning1_OutputPowerOutOfSpec";
private const string Warning1_FiberCodingCommLost = "Warning1_FiberCodingCommLost";
private const string Warning1_CurrentSourceError = "Warning1_CurrentSourceError";
private const string Warning1_PumpDiodeError = "Warning1_PumpDiodeError";
private const string Warning1_DewPointNearThreshold = "Warning1_DewPointNearThreshold";
private const string Warning1_AirConditionerError = "Warning1_AirConditionerError";
private const string Warning1_DewPointCommLost = "Warning1_DewPointCommLost";
private const string Warning1_ModuleNoPowerSupply = "Warning1_ModuleNoPowerSupply";
private const string Warning1_FFBDWarning = "Warning1_FFBDWarning";
private const string Warning1_FFWaterLow = "Warning1_FFWaterLow";
private const string Warning1_PulseGenCommLost = "Warning1_PulseGenCommLost";
private const string Warning1_MaintenanceRequired = "Warning1_MaintenanceRequired";
private const string Warning1_QCWShortPulseAlarmDisabled = "Warning1_QCWShortPulseAlarmDisabled";
private const string Warning1_CombinerAlmostOverheat = "Warning1_CombinerAlmostOverheat";
private const string Warning1_EmissionNotDetected = "Warning1_EmissionNotDetected";
private const string Warning1_SDCardFailure = "Warning1_SDCardFailure";
private const string Warning1_LowWaterFlowLaser = "Warning1_LowWaterFlowLaser";
private const string Warning1_LowWaterFlowFF = "Warning1_LowWaterFlowFF";
private const string Warning1_LowWaterFlowPFI = "Warning1_LowWaterFlowPFI";
private const string Warning1_LowWaterFlowPFO = "Warning1_LowWaterFlowPFO";
private Dictionary<string, UInt32> LaserWarningMaskMap = new Dictionary<string, UInt32>
{
{ Warning1_LaserPowerNotSwitchedOn, 0x00000001 },
{ Warning1_ReservedModuleOn, 0x00000002 },
{ Warning1_ModuleNearOverheat, 0x00000004 },
{ Warning1_ChillerTempWarning, 0x00000008 },
{ Warning1_ModuleUnconnected, 0x00000010 },
{ Warning1_OutputPowerNearThreshold, 0x00000020 },
{ Warning1_DischargeSensorWarning, 0x00000040 },
{ Warning1_AuxIOWarning, 0x00000080 },
{ Warning1_ActiveModuleReduced, 0x00000100 },
{ Warning1_AvgModuleTempNearThreshold, 0x00000200 },
{ Warning1_OutputPowerOutOfSpec, 0x00000400 },
{ Warning1_FiberCodingCommLost, 0x00000800 },
{ Warning1_CurrentSourceError, 0x00001000 },
{ Warning1_PumpDiodeError, 0x00002000 },
{ Warning1_DewPointNearThreshold, 0x00004000 },
{ Warning1_AirConditionerError, 0x00008000 },
{ Warning1_DewPointCommLost, 0x00010000 },
{ Warning1_ModuleNoPowerSupply, 0x00020000 },
{ Warning1_FFBDWarning, 0x00040000 },
{ Warning1_FFWaterLow, 0x00080000 },
{ Warning1_PulseGenCommLost, 0x00100000 },
{ Warning1_MaintenanceRequired, 0x00200000 },
{ Warning1_QCWShortPulseAlarmDisabled, 0x00400000 },
{ Warning1_CombinerAlmostOverheat, 0x00800000 },
{ Warning1_EmissionNotDetected, 0x01000000 },
{ Warning1_SDCardFailure, 0x02000000 },
{ Warning1_LowWaterFlowLaser, 0x10000000 },
{ Warning1_LowWaterFlowFF, 0x20000000 },
{ Warning1_LowWaterFlowPFI, 0x40000000 },
{ Warning1_LowWaterFlowPFO, 0x80000000 },
};
#endregion
#endregion
STRUCT_LASER_DATA stLaserData;
Dictionary<string, bool> LaserDataMap { get; set; }
Dictionary<string, bool> LaserAlarmMap1 { get; set; }
Dictionary<string, bool> LaserAlarmMap2 { get; set; }
Dictionary<string, bool> LaserWarningMap { get; set; }
Thread m_threadUpdateLaserStatus = null;
private bool bPilotLaserOnCmd;
private bool bLaserEmissionReadyOnCmd;
public LaserYLSSocketConn(string deviceid, bool isSimul) : base(deviceid, isSimul)
{
_IsSimul = isSimul;
bPilotLaserOnCmd = false;
if (LaserDataMap == null || LaserDataMap.Count < 1) {
InitLaserDataMapInfo();
}
}
public int Open(SocketConnConfig Config)
{
if (_IsSimul) {
return E1.OK;
}
int nRet = Connect(Config);
if (nRet == E1.OK) {
SetAccessLevel(100);
Thread.Sleep(100);
m_threadUpdateLaserStatus = new Thread(new ThreadStart(UpdateLaserStatus));
m_threadUpdateLaserStatus.Start();
}
if (LockControl(false)) {
LockControl(true);
}
return E1.OK;
}
public void DisConnect()
{
if (_IsSimul) {
return;
}
if (IsConnected()) {
// 동작중인것을 정지시키는 코드는 여기에
// update 하는 thread 정지
if (m_threadUpdateLaserStatus != null) {
m_threadUpdateLaserStatus.Join(500);
m_threadUpdateLaserStatus.Abort();
}
if (LockControl(true)) {
LockControl(false);
}
Close();
}
}
public int LaserOn()
{
if (_IsSimul) {
bLaserEmissionReadyOnCmd = true;
return E1.OK;
}
STRUCT_COMMAND_RESPONSE stResponse = new STRUCT_COMMAND_RESPONSE();
int nRet = SendNReceive(eFunctionCommand.AnalogCtrl, BitConverter.GetBytes((ushort)1), out stResponse);
if (nRet != E1.OK || stResponse.nExecutionCode != 0) {
return E2.ABORTED;
}
Thread.Sleep(500);
nRet = SetEmission(true);
if (nRet != E1.OK) {
return E2.ABORTED;
}
Thread.Sleep(500);
nRet = SendNReceive(eFunctionCommand.StartProgram, BitConverter.GetBytes((ushort)0), out stResponse);
if (nRet != E1.OK || stResponse.nExecutionCode != 0) {
return E2.ABORTED;
}
bLaserEmissionReadyOnCmd = true;
return E1.OK;
}
public int LaserOff()
{
if (_IsSimul) {
bLaserEmissionReadyOnCmd = false;
return E1.OK;
}
STRUCT_COMMAND_RESPONSE stResponse = new STRUCT_COMMAND_RESPONSE();
int nRet = SendNReceive(eFunctionCommand.StopProgram, BitConverter.GetBytes((ushort)0), out stResponse);
if (nRet != E1.OK || stResponse.nExecutionCode != 0) {
return E2.ABORTED;
}
Thread.Sleep(500);
nRet = SetEmission(false);
if (nRet != E1.OK) {
return E2.ABORTED;
}
Thread.Sleep(500);
nRet = SendNReceive(eFunctionCommand.AnalogCtrl, BitConverter.GetBytes((ushort)0), out stResponse);
if (nRet != E1.OK || stResponse.nExecutionCode != 0) {
return E2.ABORTED;
}
bLaserEmissionReadyOnCmd = false;
return E1.OK;
}
public int ExternalControlOn()
{
if (_IsSimul) {
return E1.OK;
}
STRUCT_COMMAND_RESPONSE stResponse = new STRUCT_COMMAND_RESPONSE();
int nRet = SendNReceive(eFunctionCommand.ModulationCtrl, BitConverter.GetBytes((ushort)1), out stResponse);
if (nRet != E1.OK || stResponse.nExecutionCode != 0) {
return E2.ABORTED;
}
return E1.OK;
}
public int ExternalControlOFF()
{
if (_IsSimul) {
return E1.OK;
}
STRUCT_COMMAND_RESPONSE stResponse = new STRUCT_COMMAND_RESPONSE();
int nRet = SendNReceive(eFunctionCommand.ModulationCtrl, BitConverter.GetBytes((ushort)0), out stResponse);
if (nRet != E1.OK || stResponse.nExecutionCode != 0) {
return E2.ABORTED;
}
return E1.OK;
}
public int PilotLaserOn()
{
if (_IsSimul) {
bPilotLaserOnCmd = true;
return E1.OK;
}
STRUCTUREA Cmd = new STRUCTUREA { Parameter1 = 0, Parameter2 = 1 };
STRUCT_COMMAND_RESPONSE stResponse = new STRUCT_COMMAND_RESPONSE();
byte[] data = StructureAToByte(Cmd);
int nRet = SendNReceive(eFunctionCommand.GuideLaser, data, out stResponse);
bPilotLaserOnCmd = true;
return nRet;
}
public int PilotLaserOff()
{
if (_IsSimul) {
bPilotLaserOnCmd = false;
return E1.OK;
}
STRUCTUREA Cmd = new STRUCTUREA { Parameter1 = 0, Parameter2 = 0 };
STRUCT_COMMAND_RESPONSE stResponse = new STRUCT_COMMAND_RESPONSE();
byte[] data = StructureAToByte(Cmd);
int nRet = SendNReceive(eFunctionCommand.GuideLaser, data, out stResponse);
bPilotLaserOnCmd = false;
return nRet;
}
public bool GetConnected()
{
return IsConnected();
}
public int SetData(int nTarget, int value)
{
// nTarget 이 eSetCommand 로 들어와야지 쓸수있다.
// interlock 을 어떻게 할것인지는 고민이 필요하다.
if (nTarget < 0 || nTarget > 65) {
return E2.ABORTED;
}
return E1.OK;
//return SendCommand((eSetCommand)nTarget, value) ? E1.OK : E2.ABORTED;
}
public string GetData(int nTarget)
{
// nTarget 이 eReadCommand 로 들어와야지 쓸수있다.
// interlock 을 어떻게 할것인지는 고민이 필요하다.
if (nTarget < 0 || nTarget > 96) {
return E2.INTERNAL_ERROR.ToString();
}
return "";
//return bret ? outvalue.ToString() : E2.INTERNAL_ERROR.ToString();
}
private void InitLaserDataMapInfo()
{
if (LaserDataMap == null)
LaserDataMap = new Dictionary<string, bool>();
else
LaserDataMap.Clear();
foreach (var item in LaserStatusMaskMap) {
LaserDataMap.Add(item.Key, false);
}
}
private bool CalLaserStateData(UInt32 nData, UInt32 nMask)
{
// nMask 가 OR 연산해서 들어왔을때는?
return ((nData & nMask) == 0) ? false : true;
}
private bool CheckValidationLaserData(UInt32 nData)
{
bool bShutdown = ((nData & LaserStatusMaskMap[ShutdownState]) == 0) ? false : true;
bool bInvShutdown = ((nData & LaserStatusMaskMap[InverseShutdownState]) == 0) ? false : true;
return bShutdown == !bInvShutdown;
}
private bool GetLaserData(out STRUCT_LASER_DATA LaserData)
{
// sturcture 를 새로 만들어서 쓸때는 이거 호출
LaserData = new STRUCT_LASER_DATA();
if (_IsSimul) {
return true;
}
byte[] arrSend = null;
STRUCT_COMMAND_RESPONSE stReceive = new STRUCT_COMMAND_RESPONSE();
int nRet = SendNReceive(eFunctionCommand.GetLaserData, arrSend, out stReceive);
if (nRet == E1.OK) {
LaserData = BytesToObject<STRUCT_LASER_DATA>(stReceive.nData);
return true;
} else
return false;
}
private void GetLaserAllStatus()
{
// LaserDataMap 에 전부 넣어주는 함수
// 한번에 여러개 읽어올때 통신을 한번만 하는 용도로 사용
if (_IsSimul)
return;
if (LaserDataMap == null || LaserDataMap.Count < 1)
InitLaserDataMapInfo();
if (GetLaserData(out stLaserData) && CheckValidationLaserData(stLaserData.Status1)) {
foreach (var key in LaserStatusMaskMap.Keys) {
LaserDataMap[key] = CalLaserStateData(stLaserData.Status1, LaserStatusMaskMap[key]);
}
UpdateLaserAlarms();
}
}
private void UpdateLaserAlarms()
{
if (_IsSimul)
return;
if (LaserAlarmMap1 == null)
LaserAlarmMap1 = new Dictionary<string, bool>();
if (LaserAlarmMap2 == null)
LaserAlarmMap2 = new Dictionary<string, bool>();
if (LaserWarningMap == null)
LaserWarningMap = new Dictionary<string, bool>();
foreach (var key in LaserAlarmMaskMap1.Keys) {
LaserAlarmMap1[key] = CalLaserStateData(stLaserData.Alarm1, LaserAlarmMaskMap1[key]);
}
foreach (var key in LaserAlarmMaskMap2.Keys) {
LaserAlarmMap2[key] = CalLaserStateData(stLaserData.Alarm2, LaserAlarmMaskMap2[key]);
}
foreach (var key in LaserWarningMaskMap.Keys) {
UInt32 mergedWarnings = stLaserData.Warning1 | stLaserData.Warning2;
LaserWarningMap[key] = CalLaserStateData(mergedWarnings, LaserWarningMaskMap[key]);
}
}
private void UpdateLaserStatus()
{
int UpdateTimeInterval = 300; // 300ms
while (GetConnected()) {
try {
GetLaserAllStatus();
} catch {
Thread.Sleep(1000);
continue;
}
Thread.Sleep(UpdateTimeInterval);
}
}
public int SetEmission(bool bOn)
{
if (_IsSimul) {
bLaserEmissionReadyOnCmd = true;
return E1.OK;
}
STRUCT_COMMAND_RESPONSE stResponse = new STRUCT_COMMAND_RESPONSE();
//The command is switching on/off the emission:
//= 0 – switching off
//= 0x155 – switching on
UInt16 emissionValue = 0;
if (bOn) {
emissionValue = 0x0155;
} else {
emissionValue = 0;
}
int nRet = SendNReceive(eFunctionCommand.Emission, BitConverter.GetBytes((ushort)emissionValue), out stResponse);
if (nRet != E1.OK || stResponse.nExecutionCode != 0) {
return E2.ABORTED;
}
return E1.OK;
}
public bool GetInitCommunication()
{
if (_IsSimul)
return false;
if (LaserDataMap == null)
return false;
return LaserDataMap[SignalInitialization];
}
public bool GetEmissionStatus()
{
if (_IsSimul)
return false;
if (LaserDataMap == null)
return false;
return LaserDataMap[LaserEmissionEnable];
}
public bool GetLaserReady()
{
if (LaserDataMap == null) {
return false;
}
return LaserDataMap[LaserReady];
}
public bool GetLaserPowerOn()
{
if (LaserDataMap == null)
return false;
return LaserDataMap[MainPowerSupplyOn];
}
public bool GetRearDoorClose()
{
if (LaserDataMap == null)
return true;
return !LaserDataMap[RearDoorOpen];
}
public bool GetFrontDoorClose()
{
if (LaserDataMap == null)
return true;
return !LaserDataMap[FrontDoorOpen];
}
public bool GetAnalogCtrl()
{
if (LaserDataMap == null)
return false;
return LaserDataMap[LaserAnalogControll];
}
public bool GetExternalCtrl()
{
if (LaserDataMap == null)
return false;
return LaserDataMap[LaserAssignedbyRobot]; //테스트 필요
}
public bool GetInternalCtrlDisable()
{
if (LaserDataMap == null)
return false;
return LaserDataMap[SWControlDisabledRequired];
}
public bool GetLaserError()
{
// code 는 bit 연산해서 확인 가능함
bool AlarmOccured1 = stLaserData.Alarm1 == 0 ? false : true;
bool AlarmOccured2 = stLaserData.Alarm2 == 0 ? false : true;
return AlarmOccured1 || AlarmOccured2;
}
public bool GetWariningStatus()
{
// code 는 bit 연산해서 확인 가능함
bool WarningOccured1 = stLaserData.Warning1 == 0 ? false : true;
bool WarningOccured2 = stLaserData.Warning2 == 0 ? false : true;
return WarningOccured1 || WarningOccured2;
}
public bool GetLaserAssigned()
{
if (LaserDataMap == null)
return true;
return LaserDataMap[LaserAssignedbyRobot];
}
// MAINS_STATUS, ERROR_STATUS 는 위에 있음
public bool GetPilotLaserStatus()
{
if (LaserDataMap == null) {
return false;
}
return LaserDataMap[MainGuideLaser];
}
public string GetControlMode()
{
if (LaserDataMap == null) return "Unknown";
bool analogControl = LaserDataMap[LaserAnalogControll];
bool swControlDisabled = LaserDataMap[SWControlDisabledRequired];
if (analogControl)
return "Analog Control";
else if (swControlDisabled)
//return "Remote (External)";
return "REMOTE";
else
//return "Local (Software)";
return "LOCAL";
}
public double GetILD()
{
return stLaserData.SetILD * 0.01;
}
public uint GetPower()
{
return stLaserData.OutputPower;
}
public double GetTemperatureMean()
{
return stLaserData.TemperatureMean * 0.1;
}
public double GetTemperatureMin()
{
return stLaserData.TemperatureMin * 0.1;
}
public double GetTemperatureMax()
{
return stLaserData.TemperatureMax * 0.1;
}
public ushort GetModuleTemperatureMax()
{
return (ushort)stLaserData.nModuleMaxTemp;
}
public ushort GetModuleTemperatureMin()
{
return (ushort)stLaserData.nModuleMinTemp;
}
public double GetEmissionRiseTime()
{
return stLaserData.RiseTime * 0.1; // Emission 켜진 시간, 단위 ms
}
public double GetEmissionFallTime()
{
return stLaserData.FallTime * 0.1; // Emission 꺼진 시간, 단위 ms
}
public string GetPowerCenter()
{
// LaserData 에 power 는 1개만 있음. (SetPower 항목)
// Center 와 Ring 은 Current , Voltage 로 나뉘어져 있는데, 두개를 받아서 곱해야하는지 애매함.
double PowerCenter = stLaserData.SetPower;
return "";
}
public string GetPowerRing()
{
// 업데이트 예정
return "";
}
#region Set 명령 나간 bit 를 모니터링
public bool GetStartLaserSetBitStatus()
{
if (LaserDataMap == null) return false;
return LaserDataMap[LaserReady]; //LaserReady or Emiision On ??
}
public bool GetLaserStartSetBitStatus()
{
if (LaserDataMap == null) return false;
return LaserDataMap[LaserEmissionEnable]; //LaserReady or Emiision On ??
}
public bool GetPilotLaserSetBitStatus()
{
if (LaserDataMap == null) return false;
return LaserDataMap[MainGuideLaser];
}
public bool GetLaserResetSetBitStatus()
{
if (LaserDataMap == null) return false;
return LaserDataMap[CanResetCriticalError];
}
public bool GetControlModeSetStatus()
{
if (LaserDataMap == null) return false;
return LaserDataMap[SWControlDisabledRequired];
}
public int ResetLaser()
{
STRUCT_COMMAND_RESPONSE stResponse = new STRUCT_COMMAND_RESPONSE();
int nRet = SendNReceive(eFunctionCommand.Reset, null, out stResponse);
if (nRet != E1.OK) {
return E2.ABORTED;
}
if (stResponse.nExecutionCode != 0) {
return E2.ABORTED;
}
return E1.OK;
}
public bool GetProgramInterrupted()
{
if (LaserDataMap == null) return false;
return LaserDataMap[LaserProgramInterrupted];
}
public bool GetProgramActived()
{
if (LaserDataMap == null) return false;
return LaserDataMap[LaserProgramActived];
}
public bool GetEStop()
{
if (LaserAlarmMap1 == null) return false;
return LaserAlarmMap1[Alarm1_EStop] || LaserAlarmMap1[Alarm1_EStopButtonPressed];
}
public bool GetLaserOverheatingAlarm()
{
if (LaserAlarmMap1 == null) return false;
return LaserAlarmMap1[Alarm1_laserOverheating];
}
public bool GetFeedingFierInterlockAlarm()
{
if (LaserAlarmMap1 == null) return false;
return LaserAlarmMap1[Alarm1_LowWaterFlowFeedingFiber];
}
public bool GetHighBackreflectionAlarm()
{
if (LaserAlarmMap1 == null) return false;
return LaserAlarmMap1[Alarm1_HighBackReflection];
}
public bool GetLaserModuleAlarm()
{
if (LaserAlarmMap1 == null) return false;
return LaserAlarmMap1[Alarm1_LaserModuleFailed];
}
public bool GetLaserModuleDisconnectedAlarm()
{
if (LaserAlarmMap1 == null) return false;
return LaserAlarmMap1[Alarm1_UnConnectedLaserModuleExist];
}
public bool GetCombinerAlarm()
{
if (LaserAlarmMap1 == null) return false;
return LaserAlarmMap1[Alarm1_CombinerFailed];
}
public bool GetWaterInLaserAlarm()
{
if (LaserAlarmMap1 == null) return false;
return LaserAlarmMap1[Alarm1_WaterInLaser];
}
public bool GetPowerSupplyAlarm()
{
if (LaserAlarmMap1 == null) return false;
return LaserAlarmMap1[Alarm1_PowerSupplyAlarmExist];
}
public bool GetUnexpectedPumpCurrentAlarm()
{
if (LaserAlarmMap1 == null) return false;
return LaserAlarmMap1[Alarm1_UnExpectedPumpCurrent];
}
public bool GetFiberCouplerPhotodiode1Alarm()
{
if (LaserAlarmMap1 == null) return false;
return LaserAlarmMap1[Alarm1_HighLevelSignalPhotoDiode1];
}
public bool GetFiberCouplerPhotodiode2Alarm()
{
if (LaserAlarmMap1 == null) return false;
return LaserAlarmMap1[Alarm1_HighLevelSignalPhotoDiode2];
}
public bool LockControl(bool bLock)
{
STRUCT_COMMAND_RESPONSE response;
int result = 0;
if (bLock) {
result = SendNReceive(eFunctionCommand.LockControl, null, out response);
} else {
result = SendNReceive(eFunctionCommand.UnlockControl, null, out response);
}
if (response.nExecutionCode != 0) {
return false;
} else
return true;
}
public int SetAccessLevel(ushort level)
{
//Parameter1 : Version, Parameter3 : Access Level, Parameter3 : Password
// level: 0 = Monitor, 1 = Operator, 2 = Engineer, 100 = Supervisor
var Cmd = new STRUCTURE_ACCESS_LEVEL_DATA { Version = 1, AccessLevel = level };
Cmd.SetPassword("");
byte[] DataBytes = StructureAccessLevelToByte(Cmd);
STRUCT_COMMAND_RESPONSE response;
int result = SendNReceive(eFunctionCommand.SetAccessLevel, DataBytes, out response);
if (response.nExecutionCode == 0)
return E1.OK;
else
return E2.ABORTED;
}
public List<string> Alarm1String()
{
List<string> Alarm1List = new List<string>();
if (LaserAlarmMap1 == null) {
return Alarm1List;
}
foreach (var key in LaserAlarmMaskMap1.Keys) {
if (LaserAlarmMap1[key]) {
Alarm1List.Add(key);
}
}
return Alarm1List;
}
public List<string> Alarm2String()
{
List<string> Alarm2List = new List<string>();
if (LaserAlarmMap2 == null) {
return Alarm2List;
}
foreach (var key in LaserAlarmMaskMap2.Keys) {
if (LaserAlarmMap2[key]) {
Alarm2List.Add(key);
}
}
return Alarm2List;
}
public List<string> StatusString()
{
List<string> StatusList = new List<string>();
if (LaserDataMap == null) {
return StatusList;
}
foreach (var key in LaserStatusMaskMap.Keys) {
if (LaserDataMap[key]) {
StatusList.Add(key);
}
}
return StatusList;
}
#endregion
#region TCP/IP Functions
private UInt16 GetCrc16(byte[] data, int length)
{
UInt16 crc = 0x0000;
for (int i = 0; i < length; i++) {
crc ^= data[i];
for (int j = 0; j < 8; j++) {
if ((crc & 0x0001) != 0)
crc = (UInt16)((crc >> 1) ^ 0xA001);
else
crc >>= 1;
}
}
return crc;
}
private byte[] StructToBytes_WithoutCRC(STRUCT_COMMAND_REQUEST_HEADER header, byte[] data)
{
int headerSize = Marshal.SizeOf(typeof(STRUCT_COMMAND_REQUEST_HEADER));
int dataSize = data?.Length ?? 0;
byte[] result = new byte[headerSize + dataSize];
IntPtr ptr = Marshal.AllocHGlobal(headerSize);
Marshal.StructureToPtr(header, ptr, false);
Marshal.Copy(ptr, result, 0, headerSize);
Marshal.FreeHGlobal(ptr);
if (dataSize > 0)
Array.Copy(data, 0, result, headerSize, dataSize);
return result;
}
private byte[] StructToBytes_WithCRC(STRUCT_COMMAND_REQUEST_HEADER header, byte[] data)
{
byte[] withoutCrc = StructToBytes_WithoutCRC(header, data);
UInt16 crc = GetCrc16(withoutCrc, withoutCrc.Length);
byte[] fullPacket = new byte[withoutCrc.Length + 2];
Array.Copy(withoutCrc, 0, fullPacket, 0, withoutCrc.Length);
BitConverter.GetBytes(crc).CopyTo(fullPacket, withoutCrc.Length);
return fullPacket;
}
//private int SendNReceive(eFunctionCommand eSetCommand, byte[] nData, out STRUCT_COMMAND_RESPONSE stReceive)
//{
// //if (nData == null)
// // nData = new byte[2048];
// STRUCT_COMMAND_REQUEST stCommand = new STRUCT_COMMAND_REQUEST(nData);
// stCommand.nCommandCode = (UInt16)eSetCommand;
// stCommand.nReserve = (UInt16)0;
// if(nData == null)
// stCommand.nDataSize = (UInt32)0;
// else
// stCommand.nDataSize = (UInt32)nData.Length;
// byte[] btCommand = StructToBytes(stCommand);
// stCommand.nCheckSum = GenerateCheckSum(btCommand, nData.Length + 7);
// btCommand = StructToBytes(stCommand);
// byte[] btReceive = new byte[2048];
// SendAndRecieve(btCommand, out btReceive);
// if (btReceive == null)
// {
// stReceive = new STRUCT_COMMAND_RESPONSE();
// return E1.ARGUMENT;
// }
// stReceive = BytesToStruct(btReceive);
// return E1.OK;
//}
private int SendNReceive(eFunctionCommand eSetCommand, byte[] nData, out STRUCT_COMMAND_RESPONSE stReceive)
{
lock (_sendLock) {
byte[] packet = CreateCommandPacket(eSetCommand, nData);
byte[] received;
int ret = SendAndRecieve(packet, out received);
if (ret != E1.OK || received == null || received.Length < 10) {
stReceive = default;
return E2.ABORTED;
}
stReceive = BytesToStruct(received);
return E1.OK;
}
}
private byte[] CreateCommandPacket(eFunctionCommand command, byte[] data)
{
STRUCT_COMMAND_REQUEST_HEADER header = new STRUCT_COMMAND_REQUEST_HEADER {
nCommandCode = (UInt16)command,
nReserve = 0,
nDataSize = (UInt32)(data?.Length ?? 0)
};
int headerSize = Marshal.SizeOf(header);
int dataSize = (int)header.nDataSize;
byte[] buffer = new byte[headerSize + dataSize];
IntPtr ptr = Marshal.AllocHGlobal(headerSize);
Marshal.StructureToPtr(header, ptr, false);
Marshal.Copy(ptr, buffer, 0, headerSize);
Marshal.FreeHGlobal(ptr);
if (dataSize > 0)
Array.Copy(data, 0, buffer, headerSize, dataSize);
UInt16 crc = GetCrc16(buffer, buffer.Length);
byte[] fullPacket = new byte[buffer.Length + 2];
Array.Copy(buffer, fullPacket, buffer.Length);
BitConverter.GetBytes(crc).CopyTo(fullPacket, buffer.Length);
return fullPacket;
}
private byte[] StructToBytes(STRUCT_COMMAND_REQUEST obj)
{
int datasize = Convert.ToInt32(obj.nDataSize + 10);
IntPtr buff = Marshal.AllocHGlobal(datasize);
Marshal.StructureToPtr(obj, buff, false);
byte[] data = new byte[datasize];
Marshal.Copy(buff, data, 0, datasize);
Marshal.FreeHGlobal(buff);
return data;
}
//private STRUCT_COMMAND_RESPONSE BytesToStruct(byte[] data)
//{
// IntPtr ptr = Marshal.AllocHGlobal(data.Length);
// if(data.Length < 10) return default(STRUCT_COMMAND_RESPONSE);
// Marshal.Copy(data, 0, ptr, data.Length);
// var obj = (STRUCT_COMMAND_RESPONSE_NODATA)Marshal.PtrToStructure(ptr, typeof(STRUCT_COMMAND_RESPONSE_NODATA));
// Marshal.FreeHGlobal(ptr);
// if (Marshal.SizeOf(obj) != data.Length)
// {
// return default(STRUCT_COMMAND_RESPONSE);
// }
// return default(STRUCT_COMMAND_RESPONSE);
//}
public STRUCT_COMMAND_RESPONSE BytesToStruct(byte[] buffer)
{
STRUCT_COMMAND_RESPONSE response = new STRUCT_COMMAND_RESPONSE();
if (buffer == null || buffer.Length < 10)
return default;
UInt16 receivedCrc = BitConverter.ToUInt16(buffer, buffer.Length - 2);
UInt16 calcCrc = GetCrc16(buffer, buffer.Length - 2);
if (receivedCrc != calcCrc) {
return default;
}
int headerSize = Marshal.SizeOf(typeof(STRUCT_COMMAND_RESPONSE_HEADER));
IntPtr ptr = Marshal.AllocHGlobal(headerSize);
Marshal.Copy(buffer, 0, ptr, headerSize);
var header = (STRUCT_COMMAND_RESPONSE_HEADER)Marshal.PtrToStructure(ptr, typeof(STRUCT_COMMAND_RESPONSE_HEADER));
Marshal.FreeHGlobal(ptr);
response.nAnswerCode = header.nAnswerCode;
response.nExecutionCode = header.nExecutionCode;
response.nDataSize = header.nDataSize;
if (response.nDataSize > 0) {
response.nData = new byte[response.nDataSize];
Array.Copy(buffer, headerSize, response.nData, 0, response.nDataSize);
} else {
response.nData = new byte[0];
}
response.nCheckSum = receivedCrc;
return response;
}
private UInt16 GenerateCheckSum(byte[] data, int nSize)
{
UInt16 sum = 0;
if (data.Length < nSize) return 0;
for (int i = 0; i < nSize; i++) {
sum += (UInt16)data[i];
}
return sum;
}
private byte[] StructureAToByte(STRUCTUREA stA)
{
byte[] bytes = new byte[4]; // StructureA 는 4Byte
IntPtr buff = Marshal.AllocHGlobal(4);
Marshal.StructureToPtr(stA, buff, true);
Marshal.Copy(buff, bytes, 0, 4);
Marshal.FreeHGlobal(buff);
return bytes;
}
public static byte[] StructureAccessLevelToByte(STRUCTURE_ACCESS_LEVEL_DATA data)
{
byte[] buffer = new byte[14];
Array.Copy(BitConverter.GetBytes(data.Version), 0, buffer, 0, 2);
Array.Copy(BitConverter.GetBytes(data.AccessLevel), 0, buffer, 2, 2);
Array.Copy(data.Password, 0, buffer, 4, 10);
return buffer;
}
private T BytesToObject<T>(byte[] data)
{
IntPtr ptr = Marshal.AllocHGlobal(data.Length);
Marshal.Copy(data, 0, ptr, data.Length);
var obj = (T)Marshal.PtrToStructure(ptr, typeof(T));
Marshal.FreeHGlobal(ptr);
if (Marshal.SizeOf(obj) != data.Length) {
return default(T);
}
return obj;
}
#endregion
public static object GetPropertyValue(object obj, string propertyName)
{
if (obj == null)
throw new ArgumentNullException(nameof(obj));
if (string.IsNullOrEmpty(propertyName))
throw new ArgumentNullException(nameof(propertyName));
Type type = obj.GetType();
PropertyInfo propertyInfo = type.GetProperty(propertyName);
if (propertyInfo == null)
throw new ArgumentException($"Property '{propertyName}' not found on type '{type.FullName}'");
return propertyInfo.GetValue(obj);
}
}
}