377 lines
12 KiB
C#
377 lines
12 KiB
C#
using Aurora.Api;
|
|
using Aurora.Api.DataType;
|
|
using Aurora.Api.Devices;
|
|
using Hermes;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.Linq;
|
|
using System.Reactive.Linq;
|
|
using System.Reactive.Subjects;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using System.Windows.Input;
|
|
using System.Windows.Interop;
|
|
using static AuroraHeightSensor.HeightSensor;
|
|
|
|
namespace AuroraHeightSensor.Keyence
|
|
{
|
|
internal class HeightSensorCL3000 : SocketConn, IHeightSensor
|
|
{
|
|
private const int TIME_OUT = 3000;
|
|
enum eCommand
|
|
{
|
|
R0, // 모드 변경 : 측정 모드로 이행
|
|
MS, // 측정값 출력(단일)
|
|
LC, // 발광 제어 : LED On / Off
|
|
ZS, // 오토 제로 ON/OFF(단일) : Zero Set
|
|
ER,
|
|
NS, // 자동 송신 시작
|
|
ND, // 자동 송신 데이터 수신 (추정)
|
|
NT // 자동 송신 중지
|
|
}
|
|
|
|
enum eAckField
|
|
{
|
|
CMD = 0,
|
|
DATA
|
|
}
|
|
|
|
enum eNakField
|
|
{
|
|
ER = 0,
|
|
CMD,
|
|
CODE
|
|
}
|
|
|
|
internal enum eErrorCode : int
|
|
{
|
|
None = 0,
|
|
Timeout = 72, // Timeout Error
|
|
Command = 73, // Command Error
|
|
UndefinedCommand = 74, // Undefined Command Error
|
|
Status = 81, // Status Error
|
|
ParameterNumber = 82, // Parameter Number Error
|
|
ParameterRange = 83, // Parameter Range Error
|
|
CommonSpecific = 84, // Command Specific Error
|
|
}
|
|
|
|
private byte[] _ByteReceivePacket;
|
|
private string _ReceiveString;
|
|
|
|
private object Lock = new object();
|
|
private Subject<string> _ObservableReceiveString = new Subject<string>();
|
|
public IObservable<string> ObservableReceiveString;
|
|
private const int TimeOut = 3000;
|
|
Logger LOG = new Logger("HeightSensor");
|
|
|
|
internal bool _IsCommError = false;
|
|
internal eErrorCode _LastError;
|
|
bool _IsSimul = false;
|
|
public bool IsCommError { get; set; }
|
|
private double _HeightValue; public double HeightValue { get => _HeightValue; set => _HeightValue = value; }
|
|
|
|
internal HeightSensorCL3000(string deviceId, bool isSimul = false) : base(deviceId, isSimul)
|
|
{
|
|
//ObservableReceiveString = _ObservableReceiveString.AsObservable();
|
|
_IsSimul = isSimul;
|
|
CloseEvent += new EventHandler<string>(OnForcedCloseEvent);
|
|
ErrorEvent += new EventHandler<Exception>(OnExceptionEvent);
|
|
}
|
|
|
|
public bool CheckConnected()
|
|
{
|
|
//return !_IsCommError;
|
|
return !IsCommError;
|
|
}
|
|
|
|
//public int Connect(IConnConfig config)
|
|
//{
|
|
// IsCommError = false;
|
|
// return Connect(config as SocketConnConfig); // Socket comm
|
|
//}
|
|
|
|
public int Activate(IConnConfig config)
|
|
{
|
|
IsCommError = false;
|
|
_IsAutoTransmitOn = false;
|
|
|
|
return Connect(config as SocketConnConfig);
|
|
}
|
|
|
|
protected override void OnReceive(object arg1, AsyncSocketReceiveEventArgs args)
|
|
{
|
|
|
|
if (_IsAutoTransmitOn) {
|
|
//Log.I("OnReceive : " + args.ReceiveData.ToString());
|
|
// Handling Data
|
|
|
|
//var parsingData = Parse(eCommand.ND, args.ReceiveData, out double value);
|
|
//var test = BitConverter.ToString(args.ReceiveData).Replace("-", "");
|
|
//var test = Encoding.Default.GetString(args.ReceiveData).Skip(8 + 4).Take(4).ToString();
|
|
if (Parse(eCommand.ND, args.ReceiveData) == E1.OK) {
|
|
double value = (double)BitConverter.ToInt32(args.ReceiveData.ToArray().Skip(8).Take(6).ToArray(), 0) / 10000;
|
|
Log.V("Parsed Value : " + value.ToString("F3"));
|
|
_HeightValue = value;
|
|
OnMeasured.Execute(value);
|
|
}
|
|
}
|
|
}
|
|
|
|
public int Deactivate()
|
|
{
|
|
_IsAutoTransmitOn = false;
|
|
|
|
return Close();
|
|
}
|
|
|
|
private void SetReceiveString()
|
|
{
|
|
_ReceiveString = ConvertByteToString(_ByteReceivePacket);
|
|
_ByteReceivePacket = null;
|
|
_ObservableReceiveString.OnNext(_ReceiveString);
|
|
}
|
|
|
|
//public int Disconnect()
|
|
//{
|
|
// if ((bool)IsConnected()) {
|
|
// return Close();
|
|
// }
|
|
// _IsCommError = false;
|
|
// IsCommError = false;
|
|
// return E1.OK;
|
|
//}
|
|
|
|
|
|
private void OnForcedCloseEvent(object sender, string e)
|
|
{
|
|
_IsCommError = true;
|
|
}
|
|
|
|
private void OnExceptionEvent(object sender, Exception e)
|
|
{
|
|
_IsCommError = true;
|
|
}
|
|
|
|
public int ChangeWriteMode()
|
|
{
|
|
string msg = CreatePacket(eCommand.R0);
|
|
if (SendAndRecieve(msg, out byte[] recieveData, TIME_OUT) == E1.OK) {
|
|
Log.E($"CmdWriteModeChange Error");
|
|
return E2.INTERNAL_ERROR;
|
|
}
|
|
|
|
return Parse(eCommand.R0, recieveData);
|
|
}
|
|
|
|
public int SetLed(bool isOn)
|
|
{
|
|
string msg = CreatePacket(eCommand.LC, isOn);
|
|
if (SendAndRecieve(msg, out byte[] recieveData, TIME_OUT) != E1.OK) {
|
|
Log.E($"LedOn Error");
|
|
return E2.INTERNAL_ERROR;
|
|
}
|
|
|
|
return Parse(eCommand.LC, recieveData);
|
|
}
|
|
|
|
public int Measure(eChannel channel, out double value)
|
|
{
|
|
if (_IsAutoTransmitOn) {
|
|
value = _HeightValue;
|
|
return E1.OK;
|
|
} else {
|
|
value = 0;
|
|
string msg = CreatePacket(channel, eCommand.MS);
|
|
if (SendAndRecieve(msg, out byte[] recieveData, TIME_OUT) != E1.OK) {
|
|
return E2.INTERNAL_ERROR;
|
|
}
|
|
|
|
return Parse(eCommand.MS, recieveData, out value);
|
|
}
|
|
}
|
|
|
|
public int MeasureAll(out List<double > SensorValue)
|
|
{
|
|
SensorValue = null;
|
|
return E1.OK;
|
|
}
|
|
|
|
public int SetZero(eChannel channel, bool isSet = true)
|
|
{
|
|
string msg = CreatePacket(channel, eCommand.ZS, isSet);
|
|
if (SendAndRecieve(msg, out byte[] recieveData, TIME_OUT) == E1.OK) {
|
|
Log.E($"Set Zero Error. Set Value = {isSet}");
|
|
return E2.INTERNAL_ERROR;
|
|
}
|
|
|
|
return Parse(eCommand.ZS, recieveData);
|
|
}
|
|
|
|
ICommand OnMeasured = null;
|
|
public int StartStopAutoTransmit(bool isOn, ICommand callback, eChannel channel = eChannel.CH0)
|
|
{
|
|
if (isOn) {
|
|
OnMeasured = callback;
|
|
return StartAutoTransmit(channel);
|
|
} else {
|
|
return StopAutoTransmit(channel);
|
|
}
|
|
}
|
|
|
|
bool _IsAutoTransmitOn = false;
|
|
public int StartAutoTransmit(eChannel channel)
|
|
{
|
|
var mode = eAutoTrasmitMode.ValueOnly;
|
|
string msg = CreatePacketAutoTransmitStart(channel, eCommand.NS, mode);
|
|
Log.V("Send msg : " + msg);
|
|
if (SendAndRecieve(msg, out byte[] recieveData, TIME_OUT) != E1.OK) {
|
|
Log.E($"Start Auto Transmit Error. Set Value = {mode.ToString()}");
|
|
return E2.INTERNAL_ERROR;
|
|
}
|
|
|
|
var ret = Parse(eCommand.NS, recieveData);
|
|
if (ret == E1.OK) {
|
|
_IsAutoTransmitOn = true;
|
|
} else {
|
|
Log.E("Failed to Start Auto Transmit : " + ret);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
public int StopAutoTransmit(eChannel channel)
|
|
{
|
|
string msg = CreatePacket(eCommand.NT);
|
|
if (SendAndRecieve(msg, out byte[] recieveData, TIME_OUT) != E1.OK) {
|
|
Log.E($"Stop Auto Transmit Error");
|
|
return E2.INTERNAL_ERROR;
|
|
}
|
|
|
|
var ret = Parse(eCommand.NT, recieveData);
|
|
if (ret != E1.OK) {
|
|
Log.E("Failed to Stop Auto Transmit : " + ret);
|
|
}
|
|
_IsAutoTransmitOn = false;
|
|
|
|
return ret;
|
|
}
|
|
|
|
public enum eAutoTrasmitMode
|
|
{
|
|
ValueOnly = 0,
|
|
ValueResult,
|
|
ValueJudge,
|
|
ValueResultJudge,
|
|
CountValue,
|
|
CountValueResult,
|
|
CountValuejudge,
|
|
CountValueResultJudge,
|
|
}
|
|
|
|
private string CreatePacketAutoTransmitStart(eChannel channel, eCommand command, eAutoTrasmitMode mode)
|
|
=> $"{command},{(int)mode},10000000\r"; //
|
|
|
|
private string CreatePacket(eChannel channel, eCommand command, bool isOn)
|
|
=> $"{command},{(isOn ? 1 : 0)},{(int)channel + 1}\r";
|
|
private string CreatePacket(eChannel channel, eCommand command)
|
|
=> $"{command},0,{(int)channel + 1}\r";
|
|
private string CreatePacket(eCommand command, bool isOn)
|
|
=> $"{command},{(isOn ? 1 : 0)}\r";
|
|
private string CreatePacket(eCommand command)
|
|
=> $"{command}\r";
|
|
|
|
private int Parse(eCommand command, byte[] receiveData)
|
|
=> Parse(command, receiveData, out double result);
|
|
|
|
private int Parse(eCommand command, byte[] recieveData, out double result)
|
|
{
|
|
result = 0;
|
|
if (recieveData == null) {
|
|
return E2.UNAVAILABLE; ;
|
|
}
|
|
var response = Encoding.Default.GetString(recieveData);
|
|
Log.V("Recv msg : " + response);
|
|
|
|
string[] splits = response.Split(',');
|
|
if (splits.Length < 1) {
|
|
return E2.UNAVAILABLE;
|
|
}
|
|
|
|
var cmdStr = splits[(int)eAckField.CMD]?.Substring(0, 2);
|
|
if (!Enum.IsDefined(typeof(eCommand), cmdStr)) {
|
|
Log.E($"Response Command Error : {cmdStr}");
|
|
return E2.UNKNOWN;
|
|
}
|
|
|
|
if (cmdStr == eCommand.ER.ToString()) {
|
|
if (!int.TryParse(splits[(int)eNakField.CODE], out int errorCode)) {
|
|
var errorList = Enum.GetValues(typeof(eErrorCode)).Cast<int>();
|
|
if (errorList.Contains(errorCode)) {
|
|
Log.E($"Parse Error. Code : {(eErrorCode)errorCode}");
|
|
}
|
|
_LastError = (eErrorCode)errorCode;
|
|
}
|
|
return E2.INTERNAL_ERROR;
|
|
}
|
|
|
|
if (cmdStr != command.ToString()) {
|
|
if (_IsAutoTransmitOn) {
|
|
// continue
|
|
} else if (command == eCommand.NS && cmdStr == eCommand.NT.ToString()) {
|
|
Log.D($"Received {cmdStr} for Command : {cmdStr}");
|
|
return E1.OK;
|
|
} else if (command == eCommand.NS && cmdStr == eCommand.ND.ToString()) {
|
|
Log.E($"Send : {command}, Receive : {cmdStr}, But Continue (Data Received)");
|
|
return E1.OK;
|
|
} else {
|
|
Log.E($"Wrong response. Send : {command}, Receive : {cmdStr}");
|
|
return E2.UNAVAILABLE;
|
|
}
|
|
}
|
|
|
|
if (command == eCommand.MS) {
|
|
if (!double.TryParse(splits[(int)eAckField.DATA], out result)) {
|
|
Log.E($"Measure result parsed Error : {splits[(int)eAckField.DATA]}");
|
|
return E2.UNAVAILABLE;
|
|
}
|
|
} else if (command == eCommand.ND) {
|
|
// TODO: Implement
|
|
}
|
|
|
|
_IsCommError = false;
|
|
|
|
return E1.OK;
|
|
}
|
|
|
|
protected virtual byte[] ConvertStringToByte(string data)
|
|
{
|
|
return Encoding.Default.GetBytes(data);
|
|
}
|
|
|
|
protected string ConvertByteToString(byte[] data)
|
|
{
|
|
return Encoding.Default.GetString(data);
|
|
}
|
|
|
|
public int StartStopAutoTransmit(bool isOn, ICommand callback)
|
|
{
|
|
return StartStopAutoTransmit(isOn, callback, eChannel.CH0);
|
|
}
|
|
|
|
public int SetZeroShift(eChannel channel)
|
|
{
|
|
return E1.OK;
|
|
}
|
|
|
|
public int SetZeroShiftReset(eChannel channel)
|
|
{
|
|
return E1.OK;
|
|
}
|
|
public int Reset(eChannel channel)
|
|
{
|
|
return E1.OK;
|
|
}
|
|
}
|
|
}
|