Files
ENIG/Emulator/AGVEmulator/DevPLC.cs
2025-05-26 11:00:23 +09:00

299 lines
11 KiB
C#

using System;
using static AGVEmulator.DevBMS;
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics.Contracts;
using arCtl;
using System.Xml.Schema;
using System.Drawing;
namespace AGVEmulator
{
class DevPLC : AR.Dev.RS232
{
byte runtime = 0;
public enum eCommand : byte
{
LOAD = 0, //EEPROM 불러오기
SAVE, //EEPROM 저장
RESET, //초기화
PINGCHK,
SET_PINMODE, //PINMODE 설정
SET_DOUTPUT, //디지털출력설정(포트번호,값[1,0])
SET_AOUTPUT, //아날로그출력설정(포트GET_SETTING = 50, //셋팅값 요청
SET_FLAG,
SET_EEPROM,
SET_MANUALSPEED,
GET_SETTING = 50,
GUIDE_MOT = 90, //가이드커버(양쪽) 0=멈춤,1=UP,2=DN 아스키코드표 90=Z
SET_EEP_DIREV,
};
public enum DOName
{
PINO_GUIDEMOTOR_LDIR,
PINO_GUIDEMOTOR_LRUN,
PINO_GUIDEMOTOR_RDIR,
PINO_GUIDEMOTOR_RRUN,
PINO_EMPTY_26,
PINO_EMPTY_27,
PINO_EMPTY_28,
PINO_EMPTY_29,
}
public enum DIName
{
PINI_EMG,
PINI_BTN_1,
PINI_BTN_2,
PINI_BTN_3,
PINI_BTN_4,
PINI_OVERLOADL,
PINI_OVERLOADR,
PINI_EMPTY_36,
PINI_EMPTY_37,
PINI_EMPTY_38,
PINI_BTN_ZUP,
PINI_BTN_ZDN,
PINI_LIMIT_LU,
PINI_LIMIT_LD,
PINI_LIMIT_RU,
PINI_LIMIT_RD,
PINI_STOP,
}
public class ValueChangedArgs : EventArgs
{
public int Idx { get; set; }
public bool Value { get; set; }
public bool IsOut { get; set; }
public ValueChangedArgs(int idx, bool val, bool isOut)
{
this.Idx = idx;
this.Value = val;
this.IsOut = isOut;
}
}
public class RequestBatteryDataArgs : EventArgs
{
public UInt32 IOValue { get; set; }
public UInt32 FGValue { get; set; }
public RequestBatteryDataArgs()
{
this.IOValue = 0x00;
this.FGValue = 0xFF;
}
}
public event EventHandler<RequestBatteryDataArgs> RequestData;
public event EventHandler<ValueChangedArgs> ValueChanged;
public override bool ProcessRecvData(byte[] data)
{
//dd로 시작하고 34개의 데이터
// var sample = "DD 03 00 1B 0A 65 00 00 21 63 29 04 00 00 2C 92 00 00 00 00 00 00 28 51 03 08 02 0B 69 0B 66 FC 9C 77";
// var barr = sample.Split(' ').ToList().Select(t => Convert.ToByte(t, 16)).ToArray();
var datalne = data[2];
byte[] buffer = new byte[datalen];
Array.Copy(data, 3, buffer, 0, buffer.Length);
var cmd = (eCommand)buffer[0];
if (cmd == eCommand.GUIDE_MOT)
{
var p1 = (char)buffer[1];
var p2 = (char)buffer[2];
switch (p1)
{
case 'A': //all
if (p2 == 'P')
{
ValueChanged?.Invoke(this, new ValueChangedArgs((int)DOName.PINO_GUIDEMOTOR_LRUN, true, true));
ValueChanged?.Invoke(this, new ValueChangedArgs((int)DOName.PINO_GUIDEMOTOR_RRUN, true, true));
ValueChanged?.Invoke(this, new ValueChangedArgs((int)DOName.PINO_GUIDEMOTOR_LDIR, true, true));
ValueChanged?.Invoke(this, new ValueChangedArgs((int)DOName.PINO_GUIDEMOTOR_RDIR, true, true));
}
else if (p2 == 'N')
{
ValueChanged?.Invoke(this, new ValueChangedArgs((int)DOName.PINO_GUIDEMOTOR_LRUN, true, true));
ValueChanged?.Invoke(this, new ValueChangedArgs((int)DOName.PINO_GUIDEMOTOR_RRUN, true, true));
ValueChanged?.Invoke(this, new ValueChangedArgs((int)DOName.PINO_GUIDEMOTOR_LDIR, false, true));
ValueChanged?.Invoke(this, new ValueChangedArgs((int)DOName.PINO_GUIDEMOTOR_RDIR, false, true));
}
else if(p2 == 'S')
{
ValueChanged?.Invoke(this, new ValueChangedArgs((int)DOName.PINO_GUIDEMOTOR_LRUN, false, true));
ValueChanged?.Invoke(this, new ValueChangedArgs((int)DOName.PINO_GUIDEMOTOR_RRUN, false, true));
}
break;
case 'L':
if (p2 == 'P')
{
ValueChanged?.Invoke(this, new ValueChangedArgs((int)DOName.PINO_GUIDEMOTOR_LRUN, true, true));
ValueChanged?.Invoke(this, new ValueChangedArgs((int)DOName.PINO_GUIDEMOTOR_LDIR, true, true));
}
else if (p2 == 'N')
{
ValueChanged?.Invoke(this, new ValueChangedArgs((int)DOName.PINO_GUIDEMOTOR_LRUN, true, true));
ValueChanged?.Invoke(this, new ValueChangedArgs((int)DOName.PINO_GUIDEMOTOR_LDIR, false, true));
}
else if (p2 == 'S')
{
ValueChanged?.Invoke(this, new ValueChangedArgs((int)DOName.PINO_GUIDEMOTOR_LRUN, false, true));
}
break;
case 'R':
if (p2 == 'P')
{
ValueChanged?.Invoke(this, new ValueChangedArgs((int)DOName.PINO_GUIDEMOTOR_RRUN, true, true));
ValueChanged?.Invoke(this, new ValueChangedArgs((int)DOName.PINO_GUIDEMOTOR_RDIR, true, true));
}
else if (p2 == 'N')
{
ValueChanged?.Invoke(this, new ValueChangedArgs((int)DOName.PINO_GUIDEMOTOR_RRUN, true, true));
ValueChanged?.Invoke(this, new ValueChangedArgs((int)DOName.PINO_GUIDEMOTOR_RDIR, false, true));
}
else if (p2 == 'S')
{
ValueChanged?.Invoke(this, new ValueChangedArgs((int)DOName.PINO_GUIDEMOTOR_RRUN, false, true));
}
break;
}
}
return true;
}
public override void AutoSendData()
{
//if (_device.DtrEnable == false) return;
List<byte> barr = new List<byte>();
barr.Add((byte)'@');
barr.Add((byte)'@');
barr.Add(10);
barr.Add((byte)'I');
//입/출력포트 각 16접 데이터 입력
UInt32 iovalue = 0;
//플래그 각 16접 데이터 입력
UInt32 fgvalue = 0;
if (RequestData != null)
{
var p = new RequestBatteryDataArgs();
RequestData.Invoke(this, p);
iovalue = p.IOValue;
fgvalue = p.FGValue;
}
var arr_volt = BitConverter.GetBytes(iovalue).ToArray();
foreach (var b in arr_volt)
barr.Add(b);
arr_volt = BitConverter.GetBytes(fgvalue).ToArray();
foreach (var b in arr_volt)
barr.Add(b);
if (runtime < 255) runtime += 1;
else runtime = 0;
barr.Add(runtime);
//체크섬무시
barr.Add((byte)'*');
//barr.Add((byte)'*');
barr.Add(0x0D);
barr.Add(0x0A);
RaiseMessage(MessageType.Normal, "Tx:" + barr.ToArray().HexString());
WriteData(barr.ToArray());
}
bool findstx2 = false;
byte datalen = 0;
protected override bool CustomParser(byte[] buf, out byte[] remainBuffer)
{
//DD A5 03 00 FF FD 77 0D
//remainBuffer = new byte[] { };
List<byte> remain = new List<byte>();
bool retval = false;
foreach (var b in buf)
{
if (retval)
{
remain.Add(b);
continue;
}
if (findSTX == false)
{
if (b == '@')
{
tempBuffer.Clear();
tempBuffer.Add(b);
findSTX = true;
findstx2 = false;
datalen = 0;
}
}
else if (findstx2 == false)
{
if (b == '@')
{
tempBuffer.Add(b);
findstx2 = true;
datalen = 0;
}
else
{
tempBuffer.Clear();
findSTX = false;
findstx2 = false;
}
}
else if (datalen == 0)
{
tempBuffer.Add(b);
datalen = b;
}
else
{
//데이터길이가 만족한 상태
tempBuffer.Add(b);
var maxlen = datalen + 3 + 3;
if (tempBuffer.Count == maxlen)
{
if (tempBuffer[tempBuffer.Count - 1] == 0x0A && tempBuffer[tempBuffer.Count - 2] == 0x0D)
{
//무조건 맞는걸로 하자 체크섬은 체크하지 말자
retval = true;
}
}
else if (tempBuffer.Count > maxlen)
{
RaiseMessage(MessageType.Error, $"buffer over({maxlen})");
findstx2 = false;
findSTX = false;
datalen = 0;
tempBuffer.Clear();
}
}
}
remainBuffer = remain.ToArray();
return retval;
}
}
}