462 lines
16 KiB
C#
462 lines
16 KiB
C#
using Aurora.Api;
|
|
using Aurora.Api.Devices;
|
|
using Aurora.Util.HislogPlus;
|
|
using Hermes;
|
|
using PropertyTools.DataAnnotations;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Data;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Text.RegularExpressions;
|
|
using System.Threading.Tasks;
|
|
using System.Windows.Input;
|
|
using static AuroraHeightSensor.HeightSensor;
|
|
|
|
namespace AuroraHeightSensor.Keyence
|
|
{
|
|
public enum ILResponseType
|
|
{
|
|
Write = 0,
|
|
Read = 1,
|
|
|
|
}
|
|
public enum ILCommandType
|
|
{
|
|
//데이터 번호 1 ~ 28까지는 무조건 Write만 가능하고 설정 데이터를 +000000001로 해야 한다.
|
|
CurrentReadValue = 0, //0은 없지만 데이터 측정 시에 대해서 쓰기 위해 생성
|
|
ZeroOffsetRequest = 1,
|
|
ZeroOffsetClearRequest = 2,
|
|
ResetRequest = 3,
|
|
ElevationDifferenceCountFilter = 28,
|
|
ZeroOffsetResult = 54, //Read만 가능
|
|
ResetResult = 55, //Read만 가능
|
|
ZeroShiftSave = 152 //Read, Write 둘 다 가능
|
|
}
|
|
|
|
public static class ILAmpNo
|
|
{
|
|
//2개를 사용중이며 CH No에 따른 제품 번호를 정의 한다.
|
|
public const string IL1000_1 = "01";
|
|
public const string IL1000_2 = "02";
|
|
public const string IL1000_3 = "03";
|
|
public const string IL1050 = "04";
|
|
}
|
|
|
|
public class HeightSensorIL : SocketConn, IHeightSensor
|
|
{
|
|
|
|
private readonly Dictionary<int, string> ErrorMessages = new Dictionary<int, string>()
|
|
{
|
|
{ 009, "입력된 데이터가 유효 범위 밖입니다." },
|
|
{ 012, "동작 명령이 실행 불가능한 상태입니다." },
|
|
{ 014, "이 주소는 쓰기 금지 또는 쓰기할 수 없는 상태입니다." },
|
|
{ 016, "이 데이터 번호는 읽기 금지 또는 읽기가 불가능한 상태입니다." },
|
|
{ 020, "데이터 번호가 유효 범위 밖입니다." },
|
|
{ 022, "앰프 번호가 유효 범위 밖입니다." },
|
|
{ 031, "지정된 앰프 번호, 데이터 번호에 대한 읽기/쓰기에 센서가 대응하지 않습니다. 현재의 모드로는 쓰기할 수 없습니다." },
|
|
{ 254, "시스템 에러 상태입니다. 기동 시간을 대기하거나 재기동이 필요할 수 있습니다." },
|
|
{ 255, "커맨드 포맷이 바르지 않습니다." }
|
|
};
|
|
|
|
private readonly Dictionary<string, string> MeasureState = new Dictionary<string, string>()
|
|
{
|
|
{ "+100000000", "측정 데이터 에러" },
|
|
{ "+099999999", "측정 데이터 오버 레인지(센서 앰프의 표시가 FFFF)" },
|
|
{ "-099999999", "측정 데이터 언더 레인지(센서 앰프의 표시가 -FFFF)" },
|
|
{ "-099999998", "측정 데이터 무효 상태(센서 앰프의 표시가 ----)" }
|
|
};
|
|
|
|
private const string ReadCmd = "SR";
|
|
private const string WriteCmd = "SW";
|
|
private const string MeasureAllCmd = "M0\r\n";
|
|
private string _ampNo = "01"; // [DL 유닛 경우, 00] // [기본 유닛 경우, 01..15 최대 15개까지 가능]
|
|
private ILCommandType _sendCommand;
|
|
|
|
private object _lock = new object();
|
|
public HeightSensorIL(string deviceId, bool isSimul = false, SocketProtocol type = SocketProtocol.TCP, Action<bool> commErr = null) : base(deviceId, isSimul, type, commErr)
|
|
{
|
|
}
|
|
|
|
public int Activate(IConnConfig Config)
|
|
{
|
|
return Connect(Config as SocketConnConfig);
|
|
}
|
|
|
|
public bool CheckConnected()
|
|
{
|
|
return IsConnected();
|
|
}
|
|
|
|
public int Deactivate()
|
|
{
|
|
return Close();
|
|
}
|
|
|
|
public int Measure(eChannel channel, out double value)
|
|
{
|
|
value = double.NaN;
|
|
|
|
switch (channel) {
|
|
case eChannel.CH0:
|
|
_ampNo = ILAmpNo.IL1000_1;
|
|
break;
|
|
case eChannel.CH1:
|
|
_ampNo = ILAmpNo.IL1000_2;
|
|
break;
|
|
case eChannel.CH2:
|
|
_ampNo = ILAmpNo.IL1000_3;
|
|
break;
|
|
case eChannel.CH3:
|
|
_ampNo = ILAmpNo.IL1050;
|
|
break;
|
|
default:
|
|
_ampNo = ILAmpNo.IL1000_1;
|
|
break;
|
|
}
|
|
|
|
byte[] receive = new byte[64];
|
|
lock (_lock) {
|
|
var command = MakeCommand(_ampNo, ILCommandType.CurrentReadValue, "0", 1);
|
|
if (SendAndRecieve(command, out receive, 2000) != E1.OK) {
|
|
Log.I($"[Fail] : Measure Request >> {command}");
|
|
return E1.NETWORK;
|
|
}
|
|
Task.Delay(100);
|
|
if (!ParseResponse(Encoding.ASCII.GetString(receive), ILCommandType.CurrentReadValue))
|
|
return E2.UNKNOWN;
|
|
}
|
|
return E1.OK;
|
|
}
|
|
|
|
|
|
public int MeasureAll(out List<double> Sensorvalue)
|
|
{
|
|
Sensorvalue = null;
|
|
byte[] receive = new byte[64];
|
|
lock (_lock) {
|
|
if (SendAndRecieve(MeasureAllCmd, out receive) != E1.OK) {
|
|
Log.I($"[Fail] : {MeasureAllCmd}");
|
|
return E1.OK;
|
|
}
|
|
|
|
if (!ParseResponse(Encoding.ASCII.GetString(receive), out Sensorvalue))
|
|
return E1.OK;
|
|
}
|
|
|
|
return E1.OK;
|
|
}
|
|
|
|
public int SetLed(bool isOn)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
public int SetZero(eChannel channel, bool isSet = true)
|
|
{
|
|
return E1.OK;
|
|
}
|
|
|
|
public int StartStopAutoTransmit(bool isOn, ICommand callback)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
public int SetZeroShiftSave(eChannel channel)
|
|
{
|
|
byte[] receive = new byte[64];
|
|
lock (_lock) {
|
|
|
|
switch (channel) {
|
|
case eChannel.CH0:
|
|
_ampNo = ILAmpNo.IL1000_1;
|
|
break;
|
|
case eChannel.CH1:
|
|
_ampNo = ILAmpNo.IL1000_2;
|
|
break;
|
|
case eChannel.CH2:
|
|
_ampNo = ILAmpNo.IL1000_3;
|
|
break;
|
|
case eChannel.CH3:
|
|
_ampNo = ILAmpNo.IL1050;
|
|
break;
|
|
default:
|
|
_ampNo = ILAmpNo.IL1000_1;
|
|
break;
|
|
}
|
|
|
|
var command = MakeCommand(_ampNo, ILCommandType.ZeroShiftSave, "+000000001", 0);
|
|
if (SendAndRecieve(command, out receive, 1000) != E1.OK) {
|
|
Log.I($"[Fail] : Zero Request >> {command}");
|
|
return E1.NETWORK;
|
|
}
|
|
Task.Delay(100);
|
|
if (!ParseResponse(Encoding.ASCII.GetString(receive), ILCommandType.ZeroShiftSave))
|
|
return E2.UNKNOWN;
|
|
}
|
|
return E1.OK;
|
|
}
|
|
|
|
public int SetZeroShift(eChannel channel)
|
|
{
|
|
byte[] receive = new byte[64];
|
|
lock (_lock) {
|
|
|
|
switch (channel) {
|
|
case eChannel.CH0:
|
|
_ampNo = ILAmpNo.IL1000_1;
|
|
break;
|
|
case eChannel.CH1:
|
|
_ampNo = ILAmpNo.IL1000_2;
|
|
break;
|
|
case eChannel.CH2:
|
|
_ampNo = ILAmpNo.IL1000_3;
|
|
break;
|
|
case eChannel.CH3:
|
|
_ampNo = ILAmpNo.IL1050;
|
|
break;
|
|
default:
|
|
_ampNo = ILAmpNo.IL1000_1;
|
|
break;
|
|
}
|
|
|
|
SetZeroShiftSave(channel);
|
|
Task.Delay(100);
|
|
|
|
var command = MakeCommand(_ampNo, ILCommandType.ZeroOffsetRequest, "+000000001", 0);
|
|
if (SendAndRecieve(command, out receive, 1000) != E1.OK) {
|
|
Log.I($"[Fail] : Zero Request >> {command}");
|
|
return E1.NETWORK;
|
|
}
|
|
Task.Delay(100);
|
|
if (!ParseResponse(Encoding.ASCII.GetString(receive), ILCommandType.ZeroOffsetRequest))
|
|
return E2.UNKNOWN;
|
|
|
|
command = MakeCommand(_ampNo, ILCommandType.ZeroOffsetResult, "0", 1);
|
|
if (SendAndRecieve(command, out receive, 1000) != E1.OK) {
|
|
Log.I($"[Fail] : Zero Result >> {command}");
|
|
return E1.NETWORK;
|
|
}
|
|
Task.Delay(100);
|
|
if (!ParseResponse(Encoding.ASCII.GetString(receive), ILCommandType.ZeroOffsetResult))
|
|
return E2.UNKNOWN;
|
|
}
|
|
return E1.OK;
|
|
}
|
|
|
|
public int SetZeroShiftReset(eChannel channel)
|
|
{
|
|
byte[] receive = new byte[64];
|
|
lock (_lock) {
|
|
|
|
switch (channel) {
|
|
case eChannel.CH0:
|
|
_ampNo = ILAmpNo.IL1000_1;
|
|
break;
|
|
case eChannel.CH1:
|
|
_ampNo = ILAmpNo.IL1000_2;
|
|
break;
|
|
case eChannel.CH2:
|
|
_ampNo = ILAmpNo.IL1000_3;
|
|
break;
|
|
case eChannel.CH3:
|
|
_ampNo = ILAmpNo.IL1050;
|
|
break;
|
|
default:
|
|
_ampNo = ILAmpNo.IL1000_1;
|
|
break;
|
|
}
|
|
|
|
var command = MakeCommand(_ampNo, ILCommandType.ZeroOffsetClearRequest, "+000000001", 0);
|
|
if (SendAndRecieve(command, out receive, 1000) != E1.OK) {
|
|
Log.I($"[Fail] : ZeroReset Request >> {command}");
|
|
return E1.NETWORK;
|
|
}
|
|
Task.Delay(100);
|
|
if (!ParseResponse(Encoding.ASCII.GetString(receive), ILCommandType.ZeroOffsetClearRequest))
|
|
return E2.UNKNOWN;
|
|
|
|
command = MakeCommand(_ampNo, ILCommandType.ZeroOffsetResult, "0", 1);
|
|
if (SendAndRecieve(command, out receive, 1000) != E1.OK) {
|
|
Log.I($"[Fail] : ZeroReset Result >> {command}");
|
|
return E1.NETWORK;
|
|
}
|
|
Task.Delay(100);
|
|
if (!ParseResponse(Encoding.ASCII.GetString(receive), ILCommandType.ZeroOffsetResult))
|
|
return E2.UNKNOWN;
|
|
}
|
|
return E1.OK;
|
|
}
|
|
|
|
public int Reset(eChannel channel)
|
|
{
|
|
byte[] receive = new byte[64];
|
|
lock (_lock) {
|
|
|
|
switch (channel) {
|
|
case eChannel.CH0:
|
|
_ampNo = ILAmpNo.IL1000_1;
|
|
break;
|
|
case eChannel.CH1:
|
|
_ampNo = ILAmpNo.IL1000_2;
|
|
break;
|
|
case eChannel.CH2:
|
|
_ampNo = ILAmpNo.IL1000_3;
|
|
break;
|
|
case eChannel.CH3:
|
|
_ampNo = ILAmpNo.IL1050;
|
|
break;
|
|
default:
|
|
_ampNo = ILAmpNo.IL1000_1;
|
|
break;
|
|
}
|
|
|
|
var command = MakeCommand(_ampNo, ILCommandType.ResetRequest, "+000000001", 0);
|
|
if (SendAndRecieve(command, out receive, 1000) != E1.OK) {
|
|
Log.I($"[Fail] : Reset Request >> {command}");
|
|
return E1.NETWORK;
|
|
}
|
|
Task.Delay(100);
|
|
if (!ParseResponse(Encoding.ASCII.GetString(receive), ILCommandType.ResetRequest))
|
|
return E2.UNKNOWN;
|
|
|
|
command = MakeCommand(_ampNo, ILCommandType.ResetResult, "0", 1);
|
|
if (SendAndRecieve(command, out receive, 1000) != E1.OK) {
|
|
Log.I($"[Fail] : Reset Result >> {command}");
|
|
return E1.NETWORK;
|
|
}
|
|
Task.Delay(100);
|
|
if (!ParseResponse(Encoding.ASCII.GetString(receive), ILCommandType.ResetResult))
|
|
return E2.UNKNOWN;
|
|
}
|
|
return E1.OK;
|
|
}
|
|
|
|
public bool ParseResponse(string response, ILCommandType cmd)
|
|
{
|
|
if(string.IsNullOrEmpty(response))
|
|
return false;
|
|
|
|
// Command 확인
|
|
if (_sendCommand != cmd)
|
|
return false;
|
|
|
|
// 정상 종료가 확인
|
|
//if (CheckResponse(response) != ILResponseType.NormalComplete)
|
|
// return false;
|
|
|
|
// 에러 확인 (ER,**,ddd\r\n)
|
|
if (CheckErrorResponse(response))
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
public bool ParseResponse(string response, ILCommandType cmd, out double value)
|
|
{
|
|
value = double.NaN;
|
|
|
|
if (ParseResponse(response, cmd))
|
|
return false;
|
|
|
|
value = CheckValueResponse(response);
|
|
return true;
|
|
}
|
|
|
|
public bool ParseResponse(string response, out List<double> values)
|
|
{
|
|
values = null;
|
|
// 정상 종료가 확인
|
|
//if (CheckResponse(response) != ILResponseType.NormalComplete)
|
|
// return false;
|
|
|
|
// 애러 확인
|
|
if (CheckErrorResponse(response))
|
|
return false;
|
|
|
|
values = CheckValuesResponse(response);
|
|
return true;
|
|
}
|
|
|
|
private ILResponseType CheckResponse(string response)
|
|
{
|
|
//if (response.Contains("+000000000"))
|
|
// return ILResponseType.Running;
|
|
|
|
//if (response.Contains("+000000002"))
|
|
// return ILResponseType.AbnormalComplete;
|
|
|
|
//return ILResponseType.NormalComplete;
|
|
return 0;
|
|
}
|
|
|
|
private bool CheckErrorResponse(string response)
|
|
{
|
|
try {
|
|
var errorMatch = Regex.Match(response, @"ER,[A-Z]+,?(\d{3})");
|
|
if (errorMatch.Success) {
|
|
int errorCode = int.Parse(errorMatch.Groups[1].Value);
|
|
if (ErrorMessages.TryGetValue(errorCode, out string message)) {
|
|
Log.I($"[에러 {errorCode}] {message}");
|
|
}
|
|
return true;
|
|
}
|
|
} catch (Exception ex) {
|
|
Log.I($"Exception : {ex.Message}");
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private double CheckValueResponse(string response)
|
|
{
|
|
try {
|
|
var match = Regex.Match(response, @"[\+\-]\d{9}");
|
|
if (match.Success) {
|
|
var value = Convert.ToDouble(match.Value) / 1000;
|
|
Log.I($"Height Measure : {value}");
|
|
return value;
|
|
}
|
|
} catch (Exception ex) {
|
|
Log.I($"Exception : {ex.Message}");
|
|
}
|
|
|
|
return double.NaN;
|
|
}
|
|
private List<double> CheckValuesResponse(string response)
|
|
{
|
|
try {
|
|
List<double> list = new List<double>();
|
|
string[] parts = response.Split(',');
|
|
for (int i = 1; i < parts.Length; i++) // 0번째는 "M0"
|
|
{
|
|
string value = parts[i].Replace("\r", "").Replace("\n", "").Trim();
|
|
list.Add(Convert.ToDouble(value) / 1000);
|
|
}
|
|
return list;
|
|
} catch (Exception ex) {
|
|
Log.I($"Exception : {ex.Message}");
|
|
}
|
|
|
|
return null;
|
|
}
|
|
public string MakeCommand(string ampNo, ILCommandType command, string sendValue, int attribute)
|
|
{
|
|
string ret;
|
|
if(command == ILCommandType.CurrentReadValue){
|
|
ret = "M0";
|
|
}
|
|
else if(attribute == 0){ //0이면 Write
|
|
ret = ($"{WriteCmd},{ampNo},{(int)command:000},{sendValue}");
|
|
}
|
|
else{
|
|
ret = ($"{ReadCmd},{ampNo},{(int)command:000}");
|
|
}
|
|
|
|
ret += "\r\n";
|
|
|
|
_sendCommand = command;
|
|
return ret;
|
|
}
|
|
}
|
|
}
|