2026-03-30 17:09:29 +09:00

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;
}
}
}