315 lines
11 KiB
C#
315 lines
11 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 IXHResponseType
|
|
{
|
|
Running = 0,
|
|
NormalComplete = 1,
|
|
AbnormalComplete = 2,
|
|
}
|
|
public enum IXHCommandType
|
|
{
|
|
ZeroOffsetRequest = 1,
|
|
ZeroOffsetClearRequest = 2,
|
|
ResetRequest = 3,
|
|
ZeroOffsetResult = 54,
|
|
ResetResult = 55,
|
|
|
|
ProgramSwitchRequest = 163, // Write [0~31]
|
|
ProgramSwitchResult = 164, // Read [ResponseType]
|
|
// 설정 읽기 시나리오
|
|
ReadSettingRequest = 165, // R/W [0~32]
|
|
ReadSettingResult = 166, // Read [ResponseType]
|
|
ReadSettingValue = 167, // Read [-999.99 ~ 999.99]
|
|
// 설정 쓰기 시나리오
|
|
WriteSettingValue = 168, // Write [-999.99 ~ 999.99]
|
|
WriteSettingRequest = 169, // Write [0~32]
|
|
WriteSettingResult = 170, // Read [ResponseType]
|
|
// 측정 시나리오
|
|
ReadMeasurementRequest = 171, // Write [0~18]
|
|
ReadMeasurementResult = 172, // Read [ResponseType]
|
|
ReadMeasurementValue = 173 // Read [-999.99 ~ 999.99]
|
|
}
|
|
|
|
public class HeightSensorIXH : SocketConn, IHeightSensor
|
|
{
|
|
|
|
private readonly Dictionary<int, string> ErrorMessages = new Dictionary<int, string>()
|
|
{
|
|
{ 9, "입력된 데이터가 유효 범위 밖입니다." },
|
|
{ 12, "동작 명령이 실행 불가능한 상태입니다." },
|
|
{ 14, "이 주소는 쓰기 금지 또는 쓰기할 수 없는 상태입니다." },
|
|
{ 16, "이 데이터 번호는 읽기 금지 또는 읽기가 불가능한 상태입니다." },
|
|
{ 20, "데이터 번호가 유효 범위 밖입니다." },
|
|
{ 22, "앰프 번호가 유효 범위 밖입니다." },
|
|
{ 31, "지정된 앰프 번호, 데이터 번호에 대한 읽기/쓰기에 센서가 대응하지 않습니다. 현재의 모드로는 쓰기할 수 없습니다." },
|
|
{ 254, "시스템 에러 상태입니다. 기동 시간을 대기하거나 재기동이 필요할 수 있습니다." },
|
|
{ 255, "커맨드 포맷이 바르지 않습니다." }
|
|
};
|
|
|
|
private const string ReadCmd = "SR";
|
|
private const string WriteCmd = "SW";
|
|
private const string MeasureAllCmd = "M0\r\n";
|
|
private string _ampNo = "01"; // [DL 유닛 경우, 00] // [기본 유닛 경우, 01] // [증설 유닛 경우, 04]
|
|
private IXHCommandType _sendCommand;
|
|
|
|
private object _lock = new object();
|
|
public HeightSensorIXH(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;
|
|
|
|
byte[] receive = new byte[64];
|
|
lock (_lock) {
|
|
var command = MakeCommand(_ampNo, IXHCommandType.ReadMeasurementRequest, $"+00000000{(int)channel}");
|
|
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), IXHCommandType.ReadMeasurementRequest))
|
|
return E2.UNKNOWN;
|
|
|
|
command = MakeCommand(_ampNo, IXHCommandType.ReadMeasurementResult);
|
|
if (SendAndRecieve(command, out receive, 1000) != E1.OK) {
|
|
Log.I($"[Fail] : Measure Result >> {command}");
|
|
return E1.NETWORK;
|
|
}
|
|
Task.Delay(100);
|
|
if (!ParseResponse(Encoding.ASCII.GetString(receive), IXHCommandType.ReadMeasurementResult))
|
|
return E2.UNKNOWN;
|
|
|
|
command = MakeCommand(_ampNo, IXHCommandType.ReadMeasurementValue);
|
|
if (SendAndRecieve(command, out receive, 1000) != E1.OK) {
|
|
Log.I($"[Fail] : Measure Value >> {command}");
|
|
return E1.NETWORK;
|
|
}
|
|
Task.Delay(100);
|
|
if (!ParseResponse(Encoding.ASCII.GetString(receive), IXHCommandType.ReadMeasurementResult, out value))
|
|
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)
|
|
{
|
|
byte[] receive = new byte[64];
|
|
lock(_lock) {
|
|
var Set = isSet ? "1" : "0";
|
|
var command = MakeCommand(_ampNo, IXHCommandType.ZeroOffsetRequest, $"+00000000{Set}");
|
|
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), IXHCommandType.ZeroOffsetRequest))
|
|
return E2.UNKNOWN;
|
|
|
|
command = MakeCommand(_ampNo, IXHCommandType.ZeroOffsetResult);
|
|
if(SendAndRecieve(command, out receive, 1000) != E1.OK) {
|
|
Log.I($"[Fail] : Measure Request >> {command}");
|
|
return E1.NETWORK;
|
|
}
|
|
Task.Delay(100);
|
|
if (!ParseResponse(Encoding.ASCII.GetString(receive), IXHCommandType.ZeroOffsetResult))
|
|
return E2.UNKNOWN;
|
|
}
|
|
|
|
return E1.OK;
|
|
}
|
|
public int SetZeroShift(eChannel channel)
|
|
{
|
|
return E1.OK;
|
|
}
|
|
|
|
public int SetZeroShiftReset(eChannel channel)
|
|
{
|
|
return E1.OK;
|
|
}
|
|
|
|
public int StartStopAutoTransmit(bool isOn, ICommand callback)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
public int Reset(eChannel channel)
|
|
{
|
|
return E1.OK;
|
|
}
|
|
|
|
public bool ParseResponse(string response, IXHCommandType cmd)
|
|
{
|
|
if(string.IsNullOrEmpty(response))
|
|
return false;
|
|
|
|
// Command 확인
|
|
if (_sendCommand != cmd)
|
|
return false;
|
|
|
|
// 정상 종료가 확인
|
|
if (CheckResponse(response) != IXHResponseType.NormalComplete)
|
|
return false;
|
|
|
|
// 애러 확인 (ER,**,ddd\r\n)
|
|
if (CheckErrorResponse(response))
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
public bool ParseResponse(string response, IXHCommandType 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) != IXHResponseType.NormalComplete)
|
|
return false;
|
|
|
|
// 애러 확인
|
|
if (CheckErrorResponse(response))
|
|
return false;
|
|
|
|
values = CheckValuesResponse(response);
|
|
return true;
|
|
}
|
|
|
|
private IXHResponseType CheckResponse(string response)
|
|
{
|
|
if (response.Contains("+000000000"))
|
|
return IXHResponseType.Running;
|
|
|
|
if (response.Contains("+000000002"))
|
|
return IXHResponseType.AbnormalComplete;
|
|
|
|
return IXHResponseType.NormalComplete;
|
|
}
|
|
|
|
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, IXHCommandType command, string sendValue = null)
|
|
{
|
|
string ret;
|
|
if(sendValue != null)
|
|
ret = ($"{WriteCmd},{ampNo},{(int)command:000},{sendValue}");
|
|
else
|
|
ret = ($"{ReadCmd},{ampNo},{(int)command:000}");
|
|
|
|
ret += "\r\n";
|
|
|
|
_sendCommand = command;
|
|
return ret;
|
|
}
|
|
}
|
|
}
|