462 lines
14 KiB
C#
462 lines
14 KiB
C#
using Aurora;
|
|
using Aurora.Api;
|
|
using AuroraLaser.Amplitude.Satsuma;
|
|
using AuroraLaser.Coherent.Arm;
|
|
using Hermes;
|
|
using MathNet.Numerics.Distributions;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using System.Windows;
|
|
|
|
namespace AuroraLaser.Coherent.Compact
|
|
{
|
|
// Compact 시리즈가 아닌, Coherent 사 제품을 공통으로 묶을 수 있을까?
|
|
public class LaserDeviceCompact : Device, ILaserDeviceCoherent
|
|
{
|
|
protected readonly Logger Log;
|
|
|
|
private LaserCompactMiniSerialConn _laserCompactMiniSerialConn; // 공통 인터페이스
|
|
public LaserCompactMiniConfig Config { get; set; }
|
|
|
|
protected const Int16 FAIL = -1;
|
|
public int Index { get; set; }
|
|
|
|
//----- For Simul
|
|
double _powerPerc;
|
|
Random _randomInt;
|
|
Normal _randomValue;
|
|
const double magForGaussian = 5.0;
|
|
//===========================
|
|
|
|
#region 생성자
|
|
public LaserDeviceCompact(string deviceId, int laserIndex = 0)
|
|
{
|
|
DeviceId = deviceId;
|
|
CommType = CommunicationType.Serial;
|
|
Type = DeviceType.Laser;
|
|
|
|
Index = laserIndex;
|
|
Log = new Logger("Compact_" + deviceId);
|
|
}
|
|
#endregion
|
|
|
|
#region 활성화/비활성화
|
|
protected override int DoActivate(IDeviceConfig config)
|
|
{
|
|
Config = config as LaserCompactMiniConfig;
|
|
return ActivateDevice();
|
|
|
|
//_rawConfig = config as LaserCompactMiniConfig;
|
|
|
|
//_laserCompactMiniSerialConn = new LaserCompactMiniSerialConn(DeviceId, IsSimul);
|
|
//var result = _laserCompactMiniSerialConn.Connect(_rawConfig);
|
|
//if (IsSimul == false) {
|
|
// if (result == E1.OK) { // 통신 연결 성공
|
|
// if (_laserCompactMiniSerialConn.NeedConfigSave) { // 시리얼넘버의 최초 write 발생 시, config 저장 필요
|
|
// Application.Current.AuroraEnv().DeviceManager.SaveDeviceConfig(DeviceId); // Config 저장
|
|
// // SN 가 변경되었다는 이벤트 publish
|
|
// EventPublisher.Publish(new EventMessage("LaserCompactMini", LaserEvent.EVENT_ID_SerialNumberUpdate));
|
|
|
|
// // reset
|
|
// _laserCompactMiniSerialConn.NeedConfigSave = false;
|
|
// Log.I($"Serial number ({_rawConfig.SerialNumber}) is saved");
|
|
// }
|
|
|
|
// Log.I($"Activated Laser : {DeviceId}");
|
|
// } else { Log.E($"Activate Laser : {DeviceId} Fail"); }
|
|
//} else { // 시뮬
|
|
// _randomInt = new Random();
|
|
// _randomValue = new Normal(0.0, 0.1);
|
|
//}
|
|
//return result;
|
|
}
|
|
|
|
protected override int DoDeactivate()
|
|
{
|
|
return DeactivateDevice();
|
|
|
|
//Log.I($"Deactivate Laser : {DeviceId}");
|
|
|
|
//if (IsSimul == false) {
|
|
// return _laserCompactMiniSerialConn.Disconnect();
|
|
//}
|
|
|
|
//return E1.OK;
|
|
}
|
|
#endregion
|
|
|
|
public int ActivateDevice()
|
|
{
|
|
_laserCompactMiniSerialConn = new LaserCompactMiniSerialConn(DeviceId, IsSimul);
|
|
var result = _laserCompactMiniSerialConn.Connect(Config);
|
|
if (IsSimul == false) {
|
|
if (result == E1.OK) { // 통신 연결 성공
|
|
if (_laserCompactMiniSerialConn.NeedConfigSave) { // 시리얼넘버의 최초 write 발생 시, config 저장 필요
|
|
Application.Current.AuroraEnv().DeviceManager.SaveDeviceConfig(DeviceId); // Config 저장
|
|
// SN 가 변경되었다는 이벤트 publish
|
|
EventPublisher.Publish(new EventMessage("LaserCompactMini", LaserEvent.EVENT_ID_SerialNumberUpdate));
|
|
|
|
// reset
|
|
_laserCompactMiniSerialConn.NeedConfigSave = false;
|
|
Log.I($"Serial number ({Config.SerialNumber}) is saved");
|
|
}
|
|
|
|
Log.I($"Activated Laser : {DeviceId}");
|
|
} else { Log.E($"Activate Laser : {DeviceId} Fail"); }
|
|
} else { // 시뮬
|
|
_randomInt = new Random();
|
|
_randomValue = new Normal(0.0, 0.1);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public int DeactivateDevice()
|
|
{
|
|
Log.I($"Deactivate Laser : {DeviceId}");
|
|
|
|
if (IsSimul == false) {
|
|
return _laserCompactMiniSerialConn.Disconnect();
|
|
}
|
|
|
|
return E1.OK;
|
|
}
|
|
|
|
#region 통신 상태
|
|
public int Reconnect()
|
|
{
|
|
if (Monitor.TryEnter(_alarmLockReconnectObj) && (IsCommError || !_laserCompactMiniSerialConn.IsConnected())) {
|
|
if (_laserCompactMiniSerialConn.Reconnect() == E1.OK) {
|
|
ClearAlarm(CreateEigenAlarmCode(99));
|
|
ClearAlarm(CreateEigenAlarmCode(98));
|
|
return E1.OK;
|
|
}
|
|
return E1.NETWORK;
|
|
}
|
|
return E1.NETWORK;
|
|
}
|
|
|
|
public bool IsConnected()
|
|
{
|
|
if (!IsActivated) {
|
|
return false;
|
|
}
|
|
|
|
IsCommError = !_laserCompactMiniSerialConn.IsConnected();
|
|
return IsCommError == false;
|
|
}
|
|
|
|
// 알람용인데, 흠 전체적인 그림을 봐야겠는데....
|
|
public bool IsNetworkError()
|
|
{
|
|
if (_laserCompactMiniSerialConn == null) {
|
|
Log.E($"{DeviceId} is null");
|
|
return true;
|
|
} else {
|
|
IsCommError = _laserCompactMiniSerialConn.IsNetworkError || !_laserCompactMiniSerialConn.IsConnected();
|
|
if (IsCommError) {
|
|
if (!_laserCompactMiniSerialConn.IsConnected()) {
|
|
AddAlarm(CreateEigenAlarmCode(98)); // Eigen 단어가 어색한데....장치니까 Device 는 어떨까?
|
|
} else {
|
|
AddAlarm(CreateEigenAlarmCode(99));
|
|
}
|
|
}
|
|
return IsCommError;
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
|
|
// 이 구조체들이 공용화가 어디까지 될까?? Compact 시리즈 모델이 추가되면 수정여부 재검토
|
|
public STRUCT_STATUS_REGISTER GetLaserStatusInfo()
|
|
{
|
|
return _laserCompactMiniSerialConn.GetLaserStatusInfo();
|
|
}
|
|
|
|
public STRUCT_LASER_MODE_REGISTER GetLaserModeInfo()
|
|
{
|
|
return _laserCompactMiniSerialConn.GetLaserModeInfo();
|
|
}
|
|
|
|
public STRUCT_ERROR_REGISTER GetLaserErrMsgInfo()
|
|
{
|
|
return _laserCompactMiniSerialConn.GetLaserErrMsgInfo();
|
|
}
|
|
|
|
#region 레이저 관련, 통신 R/W API 포함
|
|
public bool IsLaserError()
|
|
{
|
|
bool result = _laserCompactMiniSerialConn.IsLaserError;
|
|
if (result) {
|
|
var statusInfo = GetLaserStatusInfo();
|
|
if (statusInfo.bErrorStatus) { AddAlarm(CreateEigenAlarmCode(10)); }
|
|
if (statusInfo.bFatalError) { AddAlarm(CreateEigenAlarmCode(11)); }
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public void ErrorReset()
|
|
{
|
|
_laserCompactMiniSerialConn.ErrorReset();
|
|
ClearAlarm(new int[2] { CreateEigenAlarmCode(10), CreateEigenAlarmCode(11) });
|
|
}
|
|
|
|
public int SetOutputPower(double powerPerc)
|
|
{
|
|
_powerPerc = powerPerc;
|
|
if (IsSimul == false) {
|
|
return _laserCompactMiniSerialConn.SetOutputPower(powerPerc) ? E1.OK : FAIL;
|
|
}
|
|
|
|
return E1.OK;
|
|
}
|
|
|
|
#region Power calibration
|
|
public int LoadLaserCalibrationData()
|
|
{
|
|
// Aurora Config Json reload
|
|
Application.Current.AuroraEnv().DeviceManager.LoadDeviceConfig(DeviceId);
|
|
_laserCompactMiniSerialConn.LoadLaserCalibrationData();
|
|
return E1.OK;
|
|
}
|
|
|
|
public List<(double perc, double watt)> GetPowerCalData()
|
|
{
|
|
return _laserCompactMiniSerialConn?.GetPowerCalData();
|
|
}
|
|
public double Watt2Power(double watt)
|
|
{
|
|
return _laserCompactMiniSerialConn.Watt2Power(watt);
|
|
}
|
|
|
|
public double Watt2Power(double watt, eModelType calibType)
|
|
{
|
|
return _laserCompactMiniSerialConn.Watt2Power(watt, calibType);
|
|
}
|
|
|
|
// 오직 시뮬에서만 필요
|
|
public double Power2Watt(double dPowerPerc)
|
|
{
|
|
if (IsSimul) {
|
|
return _laserCompactMiniSerialConn.Power2Watt(dPowerPerc);
|
|
} else {
|
|
Log.W("Only for Sim mode");
|
|
return 0.0;
|
|
}
|
|
}
|
|
public void SetLaserPowerCalibMethod(string powerCalibMethod)
|
|
{
|
|
_laserCompactMiniSerialConn?.SetLaserPowerCalibMethod(powerCalibMethod);
|
|
}
|
|
|
|
public string GetLaserPowerCalibMethod()
|
|
{
|
|
return _laserCompactMiniSerialConn?.GetLaserPowerCalibMethod();
|
|
}
|
|
#endregion
|
|
|
|
public void Update()
|
|
{
|
|
if (!IsActivated) {
|
|
return;
|
|
}
|
|
|
|
if (IsSimul == false) {
|
|
_laserCompactMiniSerialConn.Update();
|
|
} else { // 시뮬
|
|
// 1. 레이저 Internal Set Power 업데이트
|
|
int iPow = (int)(Math.Round(_powerPerc, 1) * 10); // [0, 1000]
|
|
var l_compactMiniRegister = (_laserCompactMiniSerialConn as LaserCompactMiniSerialConn).m_Register;
|
|
l_compactMiniRegister.m_stStatus_Regster.PowerValue = iPow + (int)(Math.Round(_randomValue.Sample() * magForGaussian, 1) * 10.0); // 가우시안 노이즈 추가
|
|
|
|
// 2. 온도 시뮬레이션
|
|
l_compactMiniRegister.m_stStatus_Regster.Temp = _randomInt.Next(0, 51); // [0, 50]
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region Alarm
|
|
private const int _alarmPrefix = 32; // TYPE 값 기준으로 하는게 어떨까?
|
|
private object _alarmObject = new object();
|
|
private readonly object _alarmLockReconnectObj = new object();
|
|
|
|
public override void ClearAlarms()
|
|
{
|
|
if (IsActivated) {
|
|
lock (_alarmObject) {
|
|
var list = GetAlarmList().ToArray();
|
|
foreach (var alarmCode in list) {
|
|
switch (alarmCode % 100) {
|
|
case 10:
|
|
case 11:
|
|
ErrorReset();
|
|
break;
|
|
case 98:
|
|
case 99:
|
|
Reconnect();
|
|
break;
|
|
default:
|
|
ClearAlarm(alarmCode);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
base.ClearAlarms();
|
|
}
|
|
}
|
|
|
|
private int CreateEigenAlarmCode(int alarmCode)
|
|
{
|
|
return _alarmPrefix * 1000 + Index * 100 + alarmCode;
|
|
}
|
|
#endregion
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// Laser Interface 추가
|
|
|
|
// All LaserDevice 에서 선택하여 Device 가 생성될 때 사용되며, All LaserDevice 가 Activated 일 때만 true 가 됨.
|
|
public bool IsActivated_InAllLaserDevice = false;
|
|
private bool CanCallLaserFunction()
|
|
{
|
|
if (IsActivated_InAllLaserDevice == false && IsActivated == false) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public int LaserOn()
|
|
{
|
|
// TODO: 구현 필요
|
|
return 1;
|
|
}
|
|
|
|
public int LaserOff()
|
|
{
|
|
// TODO: 구현 필요
|
|
return 1;
|
|
}
|
|
|
|
public int PilotLaserOn()
|
|
{
|
|
// TODO: 구현 필요
|
|
return 1;
|
|
}
|
|
|
|
public int PilotLaserOff()
|
|
{
|
|
// TODO: 구현 필요
|
|
return 1;
|
|
}
|
|
|
|
public bool GetPilotLaserStatus()
|
|
{
|
|
// TODO: 구현 필요
|
|
return true;
|
|
}
|
|
|
|
public bool GetLaserReady()
|
|
{
|
|
// TODO: 구현 필요
|
|
return true;
|
|
}
|
|
|
|
public bool GetPilotLaserSetBitStatus()
|
|
{
|
|
// TODO: 구현 필요
|
|
return true;
|
|
}
|
|
|
|
public bool GetConnected()
|
|
{
|
|
// TODO: 구현 필요
|
|
return true;
|
|
}
|
|
|
|
public int SetData(int nTarget, int value)
|
|
{
|
|
// TODO: 구현 필요
|
|
return 1;
|
|
}
|
|
|
|
public int ResetLaser()
|
|
{
|
|
// TODO: 구현 필요
|
|
return E1.OK;
|
|
}
|
|
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();
|
|
}
|
|
}
|
|
}
|