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 _ObservableReceiveString = new Subject(); public IObservable 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(OnForcedCloseEvent); ErrorEvent += new EventHandler(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 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(); 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; } } }