using FlyAd2021.Inc; using FlyADBase; using NLog; using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace FlyAd2021 { public class FlyAd2021Core : IFlyAd2021Core { Logger logger = NLog.LogManager.GetCurrentClassLogger(); public event PropertyChangedEventHandler PropertyChanged; #region 测量速度 public bool IsMeasuring { get; private set; } /// <summary> /// 通讯速度 byte/s /// </summary> public double CommSpeed { get; private set; } /// <summary> /// 传输速度 单位 pack/s /// </summary> public double PackSpeed { get; private set; } #endregion /// <summary> /// 包出错次数 /// </summary> public int ErrCnt { get; private set; } /// <summary> /// 连接成功; /// 当命令多次发送失败,IsConnected = false /// </summary> public bool IsConnected { get; private set; } /// <summary> /// 有数据需要发送 /// </summary> public event SendMsgEventHander SendMsgEvent; /// <summary> /// 数据推送事件 /// </summary> public event PushDataEventHandler PushDataEvent; /// <summary> /// 运行状态推送事件 /// </summary> public event PushRunResultEventHandler PushRunResultEvent; List<byte> currPack = new List<byte>(); int packCnt = 0; int recCnt = 0; Stopwatch stopwatch = new Stopwatch(); CancellationTokenSource cancellationTokenSource; /// <summary> /// 全部指令类别 /// </summary> Dictionary<COMMREQ_Type,COMMREQ> COMMREQs; /// <summary> /// 指令队列,必须等上1条指令回复了,才能发下条指令 /// </summary> List<COMMREQ_Transaction> Transactions; /// <summary> /// 当前正在等待回复的指令 /// </summary> COMMREQ_Transaction currTran; /// <summary> /// currTran 发送后,开始计时 /// </summary> Stopwatch stopwatch_timeOut; /// <summary> /// currTran 重发次数 /// </summary> int retryCnt = 0; COMMREQ COMMREQ_RN; public FlyAd2021Core() { //COMMREQ_RN 作为事件,会触发一次,作为指令,也会回复一次 COMMREQ_RN = new COMMREQ(COMMREQ_Type.RN, 5, (pack, dataIdx) => { DRIVE_MAN_STATUS result = (DRIVE_MAN_STATUS)pack[dataIdx]; dataIdx += 1; UInt32 serial = BitConverter.ToUInt32(pack, dataIdx); dataIdx += 4; return new GetRunResult_Reponse() { result = result, serial = serial }; }); var _COMMREQs = new List<COMMREQ> { COMMREQ_RN, #region IOComm IO指令 new COMMREQ(COMMREQ_Type.IGI,2,(pack,dataIdx)=>BitConverter.ToUInt16(pack, dataIdx)), new COMMREQ(COMMREQ_Type.IGO,2,(pack,dataIdx)=>BitConverter.ToUInt16(pack, dataIdx)), new COMMREQ(COMMREQ_Type.IGP0,4,(pack,dataIdx)=>BitConverter.ToInt32(pack, dataIdx)), new COMMREQ(COMMREQ_Type.IGP1,4,(pack,dataIdx)=>BitConverter.ToInt32(pack, dataIdx)), new COMMREQ(COMMREQ_Type.IGPA,8,(pack,dataIdx)=>{ int pos1 = BitConverter.ToInt32(pack, dataIdx); dataIdx += 4; int pos2 = BitConverter.ToInt32(pack, dataIdx); dataIdx += 4; return new GetEncAll_Reponse() { pos1 = pos1, pos2 = pos2 }; }), new COMMREQ(COMMREQ_Type.ISO), #endregion #region RunComm 运行指令 SetRunParam new COMMREQ(COMMREQ_Type.RPV), new COMMREQ(COMMREQ_Type.RPS), new COMMREQ(COMMREQ_Type.RPU), new COMMREQ(COMMREQ_Type.RPD), new COMMREQ(COMMREQ_Type.RP1), new COMMREQ(COMMREQ_Type.RP2), #endregion #region RunComm 运行指令 GetRunParam new COMMREQ(COMMREQ_Type.RpV,4,(pack,dataIdx)=>BitConverter.ToUInt32(pack, dataIdx)), new COMMREQ(COMMREQ_Type.RpS,4,(pack,dataIdx)=>BitConverter.ToUInt32(pack, dataIdx)), new COMMREQ(COMMREQ_Type.RpU,4,(pack,dataIdx)=>BitConverter.ToUInt32(pack, dataIdx)), new COMMREQ(COMMREQ_Type.RpD,4,(pack,dataIdx)=>BitConverter.ToUInt32(pack, dataIdx)), new COMMREQ(COMMREQ_Type.Rp1,4,(pack,dataIdx)=>BitConverter.ToUInt32(pack, dataIdx)), new COMMREQ(COMMREQ_Type.Rp2,4,(pack,dataIdx)=>BitConverter.ToUInt32(pack, dataIdx)), #endregion #region RunComm 运行指令 new COMMREQ(COMMREQ_Type.RR), new COMMREQ(COMMREQ_Type.RO), new COMMREQ(COMMREQ_Type.RF), new COMMREQ(COMMREQ_Type.RB), new COMMREQ(COMMREQ_Type.RS), new COMMREQ(COMMREQ_Type.RT), #endregion #region 同步运行指令 new COMMREQ(COMMREQ_Type.RD0x80,new byte[]{ (byte)'R', (byte)'D',0x80}), new COMMREQ(COMMREQ_Type.RD0x81,new byte[]{ (byte)'R', (byte)'D',0x81}), new COMMREQ(COMMREQ_Type.RD0x02,new byte[]{ (byte)'R', (byte)'D',0x02}), new COMMREQ(COMMREQ_Type.RD0x03,new byte[]{ (byte)'R', (byte)'D',0x03}), new COMMREQ(COMMREQ_Type.RD0x04,new byte[]{ (byte)'R', (byte)'D',0x04}), new COMMREQ(COMMREQ_Type.RD0xE0,new byte[]{ (byte)'R', (byte)'D',0xE0}), new COMMREQ(COMMREQ_Type.RD0xE1,new byte[]{ (byte)'R', (byte)'D',0xE1}), new COMMREQ(COMMREQ_Type.RD0xE2,new byte[]{ (byte)'R', (byte)'D',0xE3}), new COMMREQ(COMMREQ_Type.RGD,2), #endregion #region SysParamComm 系统参数指令 new COMMREQ(COMMREQ_Type.ST,4,(pack,dataIdx)=>BitConverter.ToInt32(pack, dataIdx)), new COMMREQ(COMMREQ_Type.SI0,1,(pack,dataIdx)=> pack[dataIdx] == (byte)'O'), new COMMREQ(COMMREQ_Type.SA,2,(pack,dataIdx)=>{ short ret = BitConverter.ToInt16(pack, dataIdx); if(ret == 0) return AREA_ERR.NO_ERR; else if(ret == -105) return AREA_ERR.DUP_ACCESS; else// if(ret == -101) return AREA_ERR.ERR_ACCESS; }), new COMMREQ(COMMREQ_Type.Sa,18,(pack,dataIdx)=>{ GetAccess_Reponse reponse = new GetAccess_Reponse(); int idx = dataIdx; reponse.status = (AREA_STATUS)pack[idx]; idx++; reponse.ret = (AREA_ERR)pack[idx]; idx++; Array.Copy(pack, idx, reponse.code, 0, 6); idx += 6; reponse.surplus = BitConverter.ToUInt16(pack, idx); idx += 2; Array.Copy(pack, idx, reponse.access, 0, 8); idx += 8; return reponse; }), new COMMREQ(COMMREQ_Type.S1), #endregion #region GetSysParam 读运行参数 new COMMREQ(COMMREQ_Type.SpM,1,(pack,dataIdx)=>{ byte motorType = pack[dataIdx]; motorType &= 3; return (MOTORTYPE)motorType; }), new COMMREQ(COMMREQ_Type.Spm,2,(pack,dataIdx)=>BitConverter.ToUInt16(pack, dataIdx)), new COMMREQ(COMMREQ_Type.SpE,2,(pack,dataIdx)=>BitConverter.ToUInt16(pack, dataIdx)), new COMMREQ(COMMREQ_Type.SpZ,2,(pack,dataIdx)=>BitConverter.ToInt16(pack, dataIdx)), new COMMREQ(COMMREQ_Type.SpJ,4,(pack,dataIdx)=>BitConverter.ToUInt32(pack, dataIdx)), #endregion #region SetSysParam 读运行参数 new COMMREQ(COMMREQ_Type.SPM), new COMMREQ(COMMREQ_Type.SPm), new COMMREQ(COMMREQ_Type.SPE), new COMMREQ(COMMREQ_Type.SPZ), new COMMREQ(COMMREQ_Type.SPJ), #endregion }; COMMREQs = new Dictionary<COMMREQ_Type, COMMREQ>(); foreach (var commreq in _COMMREQs) { COMMREQs.Add(commreq.CType, commreq); } Transactions = new List<COMMREQ_Transaction>(); stopwatch_timeOut = new Stopwatch(); } #region 测量 public void StartMeasure() { if (IsMeasuring) return; IsMeasuring = true; cancellationTokenSource = new CancellationTokenSource(); //启动线程,测量速度 Task.Factory.StartNew(MeasureTask, cancellationTokenSource.Token); } public void StopMeasure() { cancellationTokenSource.Cancel(); //停止线程 IsMeasuring = false; } async void MeasureTask() { stopwatch.Start(); while (!cancellationTokenSource.IsCancellationRequested) { if (stopwatch.Elapsed > TimeSpan.FromSeconds(1)) { //1秒均值 CommSpeed = recCnt / stopwatch.Elapsed.TotalSeconds; PackSpeed = packCnt / stopwatch.Elapsed.TotalSeconds; recCnt = 0; packCnt = 0; stopwatch.Restart(); } await Task.Delay(100); } stopwatch.Stop(); } #endregion /// <summary> /// 发送指令的超时判断 /// </summary> public void OnPoll_TimeOut() { //TODO 要处理 TimeOut / ParseFuncPack / GetSendMsg 线性同步问题 if (!IsConnected) return; if (currTran == null) return;//没有指令 if (!stopwatch_timeOut.IsRunning) return;//还没开始发送 if (stopwatch_timeOut.Elapsed < TimeSpan.FromSeconds(1)) return;//发送到现在,还没到1秒,继续等 //大于1秒也没回复,异常 //重试3次 retryCnt++; stopwatch_timeOut.Stop();//停止,等下次发送 if (retryCnt >= 3) { //已经重试了3次,放弃 IsConnected = false; currTran = null; //清空 指令队列 Transactions.Clear(); return; } else { //再发一次指令 SendMsgEvent?.Invoke(this); } } public void RecMsg(byte[] recBuf) { IsConnected = true; for (int i = 0; i < recBuf.Count(); i++) { if (recBuf[i] == 0x7e) { //找到头了 //结束之前的包 if (currPack.Count > 0) { var pack = currPack.ToArray(); ParsePack(pack); currPack.Clear(); packCnt++; } } currPack.Add(recBuf[i]); } //OnPoll_TimeOut(); } /// <summary> /// 获取 发送队列 第1条msg /// </summary> /// <returns></returns> public byte[] GetSendMsg() { //TODO 要处理 TimeOut / ParseFuncPack / GetSendMsg 线性同步问题 if (currTran == null) { //当前没有指令正在发送 if (Transactions.Count() == 0)//队列没有需要发送的指令 return null; currTran = Transactions.First(); retryCnt = 0; Transactions.RemoveAt(0); } else { //发送出去中,等待回复 if (stopwatch_timeOut.IsRunning) return null;//已经发送了,计时器都启动了 } //找出 COMMREQ var commReq = COMMREQs[currTran.ctype]; List<byte> pack = new List<byte>(); pack.AddRange(commReq.Prefix); if (currTran.datas != null) pack.AddRange(currTran.datas); if(currTran.datasObj==null) logger.Debug($"REQ {commReq.CType}"); else logger.Debug($"REQ {commReq.CType} {Newtonsoft.Json.JsonConvert.SerializeObject(currTran.datasObj)}"); //获取需要发送出去的数据 var buf = GetSendPack(pack).ToArray(); //开始计时 stopwatch_timeOut.Restart(); return buf; } /// <summary> /// 复位全部状态,通常由于通讯模块检测到连接断开导致的 /// </summary> public void ResetMsg() { currTran = null; stopwatch_timeOut.Stop(); recCnt = 0; IsConnected = false; Transactions.Clear(); } /// 包解析 /// </summary> void ParsePack(byte[] pack) { //第0个肯定是7E if (pack.Count() == 1) { //只有一个 7E return; } //转义数据 if (!ProtocolCommon.Pdu2Data(pack, out List<byte> datas)) { //异常 return; } pack = datas.ToArray(); //解析后的 datas 没有了 帧包装 7E byte crc8 = Misc.CRC.CRC8(pack, 0, pack.Count() - 1); if (pack.Last() != crc8) { //CRC8 出错 ErrCnt++; return; } byte B0 = pack[0]; bool PT = Misc.MyBase.CHECKBIT(B0, 7); if (!PT) { ParseDataPack(pack); } else { ParseFuncPack(pack); } } void ParseDataPack(byte[] pack) { PushDataEventArgs eventArgs = new PushDataEventArgs(); int ReponseLen = 4; if (ReponseLen > pack.Count()) { //失败,指令长度不对!! ErrCnt++; return; } byte systick = pack[0]; Misc.MyBase.CLEARBIT(ref systick, 7); eventArgs.SysTick = systick; byte B1 = pack[1]; bool hasIn = Misc.MyBase.CHECKBIT(B1, 7); bool hasENC1 = Misc.MyBase.CHECKBIT(B1, 6); bool hasENC2 = Misc.MyBase.CHECKBIT(B1, 5); bool hasOut = Misc.MyBase.CHECKBIT(B1, 4); var buf = pack; int index = 2; eventArgs.AD = BitConverter.ToUInt16(buf, index); index += 2; if (hasENC1) { ReponseLen += 2; if (ReponseLen > pack.Count()) { //失败,指令长度不对!! ErrCnt++; return; } eventArgs.ENC1 = BitConverter.ToUInt16(buf, index); index += 2; } if (hasENC2) { ReponseLen += 2; if (ReponseLen > pack.Count()) { //失败,指令长度不对!! ErrCnt++; return; } eventArgs.ENC2 = BitConverter.ToUInt16(buf, index); index += 2; } if (hasIn) { ReponseLen += 4; if (ReponseLen > pack.Count()) { //失败,指令长度不对!! ErrCnt++; return; } eventArgs.In = BitConverter.ToUInt16(buf, index); index += 2; eventArgs.InChange = BitConverter.ToUInt16(buf, index); index += 2; } if (hasOut) { ReponseLen += 2; if (ReponseLen > pack.Count()) { //失败,指令长度不对!! ErrCnt++; return; } eventArgs.Out = BitConverter.ToUInt16(buf, index); index += 2; } PushDataEvent?.Invoke(this, eventArgs); } void ParseFuncPack_PushRunResultEvent(byte[] pack) { PushRunResultEventArgs eventArgs = new PushRunResultEventArgs(); var retData = COMMREQ_RN.ParseFuncPack(pack, 1 + COMMREQ_RN.Prefix.Count()) as GetRunResult_Reponse; eventArgs.Status = retData.result; eventArgs.Serial = retData.serial; logger.Debug($"REQ RN {Newtonsoft.Json.JsonConvert.SerializeObject(retData)}"); byte systick = pack[0]; Misc.MyBase.CLEARBIT(ref systick, 7); eventArgs.SysTick = systick; PushRunResultEvent?.Invoke(this, eventArgs); } /// <summary> /// 功能包解析 /// </summary> /// <param name="datas"></param> void ParseFuncPack(byte[] pack) { //TODO 要处理 TimeOut / ParseFuncPack / GetSendMsg 线性同步问题 //优先处理 PushRunResultEvent 事件 if (IsMatch(COMMREQ_RN, pack)) { //还有B0 if (COMMREQ_RN.ReponseLen+1 > pack.Count()) { //失败,指令长度不对!! ErrCnt++; return; } ParseFuncPack_PushRunResultEvent(pack); } if (currTran == null) { //没有请求。。。 return; } var commReq = COMMREQs[currTran.ctype]; if (!IsMatch(commReq, pack)) { logger.Error($"ACK expect:{commReq.CType} ,but reponse: {Newtonsoft.Json.JsonConvert.SerializeObject(pack)}"); //回复对不上请求 return; } //还有B0 if (commReq.ReponseLen+1 > pack.Count()) { //失败,指令长度不对!! ErrCnt++; return; } //处理指令 //还有B0 object retData = null; if (commReq.ParseFuncPack != null)//解析回复数据 retData = commReq.ParseFuncPack(pack, commReq.Prefix.Count() + 1); if (retData == null) logger.Debug($"ACK {commReq.CType}"); else logger.Debug($"ACK {commReq.CType} {Newtonsoft.Json.JsonConvert.SerializeObject(retData)}"); //有很多指令是没有回复数据的, 回调只是通知 指令已经执行了而已 //调用回调 currTran.asyncDelegate?.Invoke(currTran.asyncContext, retData); stopwatch_timeOut.Stop(); currTran = null; if (Transactions.Count() > 0) { //队列还有需要发送的指令 SendMsgEvent?.Invoke(this); } } bool IsMatch(COMMREQ commreq, byte[] datas) { //datas[0] 是B0, 不应该用于判断 if (datas.Count() < commreq.Prefix.Length+1) return false; for (int i = 0; i < commreq.Prefix.Length; i++) { if (commreq.Prefix[i] != datas[1+i]) { return false; } } return true; } /// <summary> /// 数据发送,不需要包含开头的7E /// </summary> /// <param name="datas"></param> List<byte> GetSendPack(List<byte> datas) { datas.Insert(0, 0x80);//插入B0 //需要在后面添加CRC8 byte crc8 = Misc.CRC.CRC8(datas, 0, datas.Count); datas.Add(crc8); ProtocolCommon.Data2Pdu(datas, out List<byte> pack); pack.Add(0x7E);//一定要加0x7E return pack; } void AddTran(COMMREQ_Transaction tran) { //放入 交易队列 Transactions.Add(tran); if (currTran == null) { //当前没有指令正在发送 SendMsgEvent?.Invoke(this); } } #region IOComm IO指令 /// <summary> /// 获取输入口状态 /// </summary> /// <param name="asyncDelegate"></param> /// <param name="asyncContext"></param> [CallBack(typeof(UInt16))] public void GetIn(CallBackHandler asyncDelegate, object asyncContext) { //放入 交易队列 AddTran( new COMMREQ_Transaction() { ctype = COMMREQ_Type.IGI, asyncDelegate = asyncDelegate, asyncContext = asyncContext }); } /// <summary> /// 获取输出口状态 /// </summary> /// <param name="asyncDelegate"></param> /// <param name="asyncContext"></param> [CallBack(typeof(UInt16))] public void GetOut(CallBackHandler asyncDelegate, object asyncContext) { //放入 交易队列 AddTran( new COMMREQ_Transaction() { ctype = COMMREQ_Type.IGO, asyncDelegate = asyncDelegate, asyncContext = asyncContext }); } [CallBack(typeof(Int32))] public void GetEnc1(CallBackHandler asyncDelegate, object asyncContext) { //放入 交易队列 AddTran( new COMMREQ_Transaction() { ctype = COMMREQ_Type.IGP0, asyncDelegate = asyncDelegate, asyncContext = asyncContext }); } [CallBack(typeof(Int32))] public void GetEnc2(CallBackHandler asyncDelegate, object asyncContext) { //放入 交易队列 AddTran( new COMMREQ_Transaction() { ctype = COMMREQ_Type.IGP1, asyncDelegate = asyncDelegate, asyncContext = asyncContext }); } [CallBack(typeof(GetEncAll_Reponse))] public void GetEncAll(CallBackHandler asyncDelegate, object asyncContext) { //放入 交易队列 AddTran( new COMMREQ_Transaction() { ctype = COMMREQ_Type.IGPA, asyncDelegate = asyncDelegate, asyncContext = asyncContext }); } public void SetOutPorts(UInt16 mask, UInt16 value, CallBackHandler asyncDelegate, object asyncContext) { List<byte> datas = new List<byte>(); datas.AddRange(BitConverter.GetBytes(mask)); datas.AddRange(BitConverter.GetBytes(value)); //放入 交易队列 AddTran( new COMMREQ_Transaction() { ctype = COMMREQ_Type.ISO, asyncDelegate = asyncDelegate, asyncContext = asyncContext, datas = datas.ToArray(), datasObj = new { mask, value } }); } #endregion #region RunComm 运行指令 SetRunParam public void SetRunParam_V(UInt32 velocity, CallBackHandler asyncDelegate, object asyncContext) { //放入 交易队列 AddTran( new COMMREQ_Transaction() { ctype = COMMREQ_Type.RPV, asyncDelegate = asyncDelegate, asyncContext = asyncContext, datas = BitConverter.GetBytes(velocity), datasObj = velocity }); } public void SetRunParam_SV(UInt32 sv, CallBackHandler asyncDelegate, object asyncContext) { //放入 交易队列 AddTran( new COMMREQ_Transaction() { ctype = COMMREQ_Type.RPS, asyncDelegate = asyncDelegate, asyncContext = asyncContext, datas = BitConverter.GetBytes(sv), datasObj = sv }); } public void SetRunParam_AccTime(UInt32 accTime, CallBackHandler asyncDelegate, object asyncContext) { //放入 交易队列 AddTran( new COMMREQ_Transaction() { ctype = COMMREQ_Type.RPU, asyncDelegate = asyncDelegate, asyncContext = asyncContext, datas = BitConverter.GetBytes(accTime), datasObj = accTime }); } public void SetRunParam_DecTime(UInt32 decTime, CallBackHandler asyncDelegate, object asyncContext) { //放入 交易队列 AddTran( new COMMREQ_Transaction() { ctype = COMMREQ_Type.RPD, asyncDelegate = asyncDelegate, asyncContext = asyncContext, datas = BitConverter.GetBytes(decTime), datasObj = decTime }); } public void SetRunParam_HSpd1(UInt32 homespd1, CallBackHandler asyncDelegate, object asyncContext) { //放入 交易队列 AddTran( new COMMREQ_Transaction() { ctype = COMMREQ_Type.RP1, asyncDelegate = asyncDelegate, asyncContext = asyncContext, datas = BitConverter.GetBytes(homespd1), datasObj = homespd1, }); } public void SetRunParam_HSpd2(UInt32 homespd2, CallBackHandler asyncDelegate, object asyncContext) { //放入 交易队列 AddTran( new COMMREQ_Transaction() { ctype = COMMREQ_Type.RP2, asyncDelegate = asyncDelegate, asyncContext = asyncContext, datas = BitConverter.GetBytes(homespd2), datasObj = homespd2 }); } #endregion #region RunComm 运行指令 GetRunParam public void GetRunParam_V(CallBackHandler asyncDelegate, object asyncContext) { //放入 交易队列 AddTran( new COMMREQ_Transaction() { ctype = COMMREQ_Type.RpV, asyncDelegate = asyncDelegate, asyncContext = asyncContext }); } public void GetRunParam_SV(CallBackHandler asyncDelegate, object asyncContext) { //放入 交易队列 AddTran( new COMMREQ_Transaction() { ctype = COMMREQ_Type.RpS, asyncDelegate = asyncDelegate, asyncContext = asyncContext }); } public void GetRunParam_AccTime(CallBackHandler asyncDelegate, object asyncContext) { //放入 交易队列 AddTran( new COMMREQ_Transaction() { ctype = COMMREQ_Type.RpU, asyncDelegate = asyncDelegate, asyncContext = asyncContext }); } public void GetRunParam_DecTime(CallBackHandler asyncDelegate, object asyncContext) { //放入 交易队列 AddTran( new COMMREQ_Transaction() { ctype = COMMREQ_Type.RpD, asyncDelegate = asyncDelegate, asyncContext = asyncContext }); } public void GetRunParam_HSpd1(CallBackHandler asyncDelegate, object asyncContext) { //放入 交易队列 AddTran( new COMMREQ_Transaction() { ctype = COMMREQ_Type.Rp1, asyncDelegate = asyncDelegate, asyncContext = asyncContext }); } public void GetRunParam_HSpd2(CallBackHandler asyncDelegate, object asyncContext) { //放入 交易队列 AddTran( new COMMREQ_Transaction() { ctype = COMMREQ_Type.Rp2, asyncDelegate = asyncDelegate, asyncContext = asyncContext }); } #endregion #region RunComm 运行指令 public void GetRunResult(CallBackHandler asyncDelegate, object asyncContext) { { //放入 交易队列 AddTran( new COMMREQ_Transaction() { ctype = COMMREQ_Type.RN, asyncDelegate = asyncDelegate, asyncContext = asyncContext }); } } public void Forw(Int32 serial, CallBackHandler asyncDelegate, object asyncContext) { //放入 交易队列 AddTran( new COMMREQ_Transaction() { ctype = COMMREQ_Type.RF, asyncDelegate = asyncDelegate, asyncContext = asyncContext, datas = BitConverter.GetBytes(serial), datasObj = serial }); } public void Backw(Int32 serial, CallBackHandler asyncDelegate, object asyncContext) { //放入 交易队列 AddTran( new COMMREQ_Transaction() { ctype = COMMREQ_Type.RB, asyncDelegate = asyncDelegate, asyncContext = asyncContext, datas = BitConverter.GetBytes(serial), datasObj = serial }); } public void Org(Int32 serial, CallBackHandler asyncDelegate, object asyncContext) { //放入 交易队列 AddTran( new COMMREQ_Transaction() { ctype = COMMREQ_Type.RO, asyncDelegate = asyncDelegate, asyncContext = asyncContext, datas = BitConverter.GetBytes(serial), datasObj = serial }); } public void RunTo(int targetPos, Int32 serial, CallBackHandler asyncDelegate, object asyncContext) { List<byte> datas = new List<byte>(); datas.Add((byte)'P'); datas.AddRange(BitConverter.GetBytes(targetPos)); datas.AddRange(BitConverter.GetBytes(serial)); //放入 交易队列 AddTran( new COMMREQ_Transaction() { ctype = COMMREQ_Type.RR, asyncDelegate = asyncDelegate, asyncContext = asyncContext, datas = datas.ToArray(), datasObj = new { targetPos, serial } }); } public void Stop(CallBackHandler asyncDelegate, object asyncContext) { //放入 交易队列 AddTran( new COMMREQ_Transaction() { ctype = COMMREQ_Type.RS, asyncDelegate = asyncDelegate, asyncContext = asyncContext }); } public void EStop(CallBackHandler asyncDelegate, object asyncContext) { //放入 交易队列 AddTran( new COMMREQ_Transaction() { ctype = COMMREQ_Type.RT, asyncDelegate = asyncDelegate, asyncContext = asyncContext }); } #endregion #region 同步运行指令 public void SyncRun_SetHShift(int hShift, CallBackHandler asyncDelegate, object asyncContext) { //放入 交易队列 AddTran( new COMMREQ_Transaction() { ctype = COMMREQ_Type.RD0x80, asyncDelegate = asyncDelegate, asyncContext = asyncContext, datas = BitConverter.GetBytes(hShift), datasObj = hShift }); } public void SyncRun_SetVShift(int vShift, CallBackHandler asyncDelegate, object asyncContext) { //放入 交易队列 AddTran( new COMMREQ_Transaction() { ctype = COMMREQ_Type.RD0x81, asyncDelegate = asyncDelegate, asyncContext = asyncContext, datas = BitConverter.GetBytes(vShift), datasObj = vShift }); } public void SyncRun_Start(CallBackHandler asyncDelegate, object asyncContext) { //放入 交易队列 AddTran( new COMMREQ_Transaction() { ctype = COMMREQ_Type.RD0x02, asyncDelegate = asyncDelegate, asyncContext = asyncContext }); } public void SyncRun_Stop(CallBackHandler asyncDelegate, object asyncContext) { //放入 交易队列 AddTran( new COMMREQ_Transaction() { ctype = COMMREQ_Type.RD0x03, asyncDelegate = asyncDelegate, asyncContext = asyncContext }); } public void SyncRun_Clear(CallBackHandler asyncDelegate, object asyncContext) { //放入 交易队列 AddTran( new COMMREQ_Transaction() { ctype = COMMREQ_Type.RD0x04, asyncDelegate = asyncDelegate, asyncContext = asyncContext }); } /// <summary> /// 同步扫描至; /// D+0xE0+开始主轴位置+结束主轴位置+结束横向脉冲位置(逻辑位置)+命令识标号(4B) /// </summary> /// <param name="pos2_begin"></param> /// <param name="pos2_end"></param> /// <param name="pos1lc"></param> /// <param name="serial"></param> public void SyncRun_RunAtLC(int pos2_begin, int pos2_end, int pos1lc, UInt32 serial, CallBackHandler asyncDelegate, object asyncContext) { List<byte> datas = new List<byte>(); datas.AddRange(BitConverter.GetBytes(pos2_begin)); datas.AddRange(BitConverter.GetBytes(pos2_end)); datas.AddRange(BitConverter.GetBytes(pos1lc)); datas.AddRange(BitConverter.GetBytes(serial)); //放入 交易队列 AddTran( new COMMREQ_Transaction() { ctype = COMMREQ_Type.RD0xE0, asyncDelegate = asyncDelegate, asyncContext = asyncContext, datas = datas.ToArray(), datasObj = new { pos2_begin, pos2_end, pos1lc, serial } }); } /// <summary> /// 位于队列头时运行,归零; /// D+0xE1+命令识标号(4B) /// </summary> /// <param name="marker"></param> public void SyncRun_Origin(UInt32 serial, CallBackHandler asyncDelegate, object asyncContext) { //放入 交易队列 AddTran( new COMMREQ_Transaction() { ctype = COMMREQ_Type.RD0xE1, asyncDelegate = asyncDelegate, asyncContext = asyncContext, datas = BitConverter.GetBytes(serial), datasObj = serial }); } /// <summary> /// 位于队列头时运行,以速度运行至物理位置; /// D+0xE2+横向脉冲位置(4B:int32,物理位置)+速度(4B:int32)+命令识标号(4B) /// </summary> /// <param name="pos1"></param> /// <param name="velocity"></param> /// <param name="serial"></param> public void SyncRun_RunTo(int pos1, UInt32 velocity, UInt32 serial, CallBackHandler asyncDelegate, object asyncContext) { List<byte> datas = new List<byte>(); datas.AddRange(BitConverter.GetBytes(pos1)); datas.AddRange(BitConverter.GetBytes(velocity)); datas.AddRange(BitConverter.GetBytes(serial)); //放入 交易队列 AddTran( new COMMREQ_Transaction() { ctype = COMMREQ_Type.RD0xE2, asyncDelegate = asyncDelegate, asyncContext = asyncContext, datas = datas.ToArray(), datasObj = new { pos1, velocity, serial } }); } /// <summary> /// 位于队列头时运行,以速度运行至逻辑位置; /// D+0xE3+横向脉冲位置(4B:int32,逻辑位置)+速度(4B:int32)+命令识标号(4B) /// </summary> /// <param name="pos1lc"></param> /// <param name="velocity"></param> /// <param name="hasDataGrid"></param> /// <param name="marker"></param> public void SyncRun_RunToLC(int pos1lc, UInt32 velocity, UInt32 serial, CallBackHandler asyncDelegate, object asyncContext) { List<byte> datas = new List<byte>(); datas.AddRange(BitConverter.GetBytes(pos1lc)); datas.AddRange(BitConverter.GetBytes(velocity)); datas.AddRange(BitConverter.GetBytes(serial)); //放入 交易队列 AddTran( new COMMREQ_Transaction() { ctype = COMMREQ_Type.RD0xE3, asyncDelegate = asyncDelegate, asyncContext = asyncContext, datas = datas.ToArray(), datasObj = new { pos1lc, velocity, serial } }); } /// <summary> /// 获取队列长度 /// </summary> /// <param name="asyncDelegate"></param> /// <param name="asyncContext"></param> public void SyncRun_GetListCount(CallBackHandler asyncDelegate, object asyncContext) { //放入 交易队列 AddTran( new COMMREQ_Transaction() { ctype = COMMREQ_Type.RGD, asyncDelegate = asyncDelegate, asyncContext = asyncContext }); } #endregion #region SysParamComm 系统参数指令 /// <summary> /// 获取系统当前Tick /// </summary> [CallBack(typeof(UInt32))] public void GetSysTick(CallBackHandler asyncDelegate, object asyncContext) { //放入 交易队列 AddTran( new COMMREQ_Transaction() { ctype = COMMREQ_Type.ST, asyncDelegate = asyncDelegate, asyncContext = asyncContext }); } /// <summary> /// 初始化系统信息区 /// </summary> /// <param name="asyncDelegate"></param> /// <param name="asyncContext"></param> [CallBack(typeof(bool))] public void InitArea(CallBackHandler asyncDelegate, object asyncContext) { string password = "@flymeasure!"; List<byte> datas = new List<byte>(); datas.AddRange(password.Select(p => (byte)p)); //放入 交易队列 AddTran( new COMMREQ_Transaction() { ctype = COMMREQ_Type.SI0, asyncDelegate = asyncDelegate, asyncContext = asyncContext, datas = datas.ToArray(), datasObj = new { password } }); } /// <summary> /// 输入系统授权码 /// </summary> /// <param name="access"></param> /// <param name="asyncDelegate"></param> /// <param name="asyncContext"></param> [CallBack(typeof(AREA_ERR))] public void CheckAccessCode(byte[] access, CallBackHandler asyncDelegate, object asyncContext) { //放入 交易队列 AddTran( new COMMREQ_Transaction() { ctype = COMMREQ_Type.SA, asyncDelegate = asyncDelegate, asyncContext = asyncContext, datas = access, datasObj = access }); } /// <summary> /// 获取系统授权信息 /// </summary> /// <param name="asyncDelegate"></param> /// <param name="asyncContext"></param> [CallBack(typeof(GetAccess_Reponse))] public void GetAccess(CallBackHandler asyncDelegate, object asyncContext) { //放入 交易队列 AddTran( new COMMREQ_Transaction() { ctype = COMMREQ_Type.Sa, asyncDelegate = asyncDelegate, asyncContext = asyncContext }); } /// <summary> /// 系统运行时间+1 /// </summary> /// <param name="asyncDelegate"></param> /// <param name="asyncContext"></param> public void AddAccess(CallBackHandler asyncDelegate, object asyncContext) { //放入 交易队列 AddTran( new COMMREQ_Transaction() { ctype = COMMREQ_Type.S1, asyncDelegate = asyncDelegate, asyncContext = asyncContext }); } #endregion #region GetSysParam 读运行参数 [CallBack(typeof(MOTORTYPE))] public void GetSysParam_MotorType(CallBackHandler asyncDelegate, object asyncContext) { //放入 交易队列 AddTran( new COMMREQ_Transaction() { ctype = COMMREQ_Type.SpM, asyncDelegate = asyncDelegate, asyncContext = asyncContext }); } [CallBack(typeof(UInt16))] public void GetSysParam_Ratio01(CallBackHandler asyncDelegate, object asyncContext) { //放入 交易队列 AddTran( new COMMREQ_Transaction() { ctype = COMMREQ_Type.Spm, asyncDelegate = asyncDelegate, asyncContext = asyncContext }); } [CallBack(typeof(UInt16))] public void GetSysParam_Ratio02(CallBackHandler asyncDelegate, object asyncContext) { //放入 交易队列 AddTran( new COMMREQ_Transaction() { ctype = COMMREQ_Type.SpE, asyncDelegate = asyncDelegate, asyncContext = asyncContext }); } [CallBack(typeof(Int16))] public void GetSysParam_Zero(CallBackHandler asyncDelegate, object asyncContext) { //放入 交易队列 AddTran( new COMMREQ_Transaction() { ctype = COMMREQ_Type.SpZ, asyncDelegate = asyncDelegate, asyncContext = asyncContext }); } [CallBack(typeof(UInt32))] public void GetSysParam_Jog(CallBackHandler asyncDelegate, object asyncContext) { //放入 交易队列 AddTran( new COMMREQ_Transaction() { ctype = COMMREQ_Type.SpJ, asyncDelegate = asyncDelegate, asyncContext = asyncContext }); } #endregion #region SetSysParam 设置运行参数 public void SetSysParam_MotorType(MOTORTYPE motorType, CallBackHandler asyncDelegate, object asyncContext) { byte request = (byte)motorType; Misc.MyBase.SIGNBIT(ref request, 5); //放入 交易队列 AddTran( new COMMREQ_Transaction() { ctype = COMMREQ_Type.SPM, asyncDelegate = asyncDelegate, asyncContext = asyncContext, datas = new byte[] { request }, datasObj = motorType }); } public void SetSysParam_Ratio01(UInt16 ratio01, CallBackHandler asyncDelegate, object asyncContext) { //放入 交易队列 AddTran( new COMMREQ_Transaction() { ctype = COMMREQ_Type.SPm, asyncDelegate = asyncDelegate, asyncContext = asyncContext, datas = BitConverter.GetBytes(ratio01), datasObj = ratio01 }); } public void SetSysParam_Ratio02(UInt16 ratio02, CallBackHandler asyncDelegate, object asyncContext) { //放入 交易队列 AddTran( new COMMREQ_Transaction() { ctype = COMMREQ_Type.SPE, asyncDelegate = asyncDelegate, asyncContext = asyncContext, datas = BitConverter.GetBytes(ratio02), datasObj = ratio02 }); } public void SetSysParam_Zero(Int16 zero, CallBackHandler asyncDelegate, object asyncContext) { //放入 交易队列 AddTran( new COMMREQ_Transaction() { ctype = COMMREQ_Type.SPZ, asyncDelegate = asyncDelegate, asyncContext = asyncContext, datas = BitConverter.GetBytes(zero), datasObj = zero }); } public void SetSysParam_Jog(UInt32 jog, CallBackHandler asyncDelegate, object asyncContext) { //放入 交易队列 AddTran( new COMMREQ_Transaction() { ctype = COMMREQ_Type.SPJ, asyncDelegate = asyncDelegate, asyncContext = asyncContext, datas = BitConverter.GetBytes(jog), datasObj = jog }); } #endregion } /// <summary> /// 通知指令 /// </summary> class COMMREQ { public COMMREQ_Type CType; /// <summary> /// 指令 前缀 /// </summary> public byte[] Prefix; public string PrefixString { get { StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < Prefix.Count(); i++) { stringBuilder.Append((char)Prefix[i]); } return stringBuilder.ToString(); } } /// <summary> /// 回复数据 总长度,含前序 /// </summary> public int ReponseLen; public delegate object ParseFuncPackHandler(byte[] pack, int dataIdx); public ParseFuncPackHandler ParseFuncPack; public COMMREQ(COMMREQ_Type ctype) { CType = ctype; string prefixString = CType.ToString(); Prefix = new byte[prefixString.Count()]; this.Prefix = prefixString.Select(p => (byte)p).ToArray(); this.ReponseLen = Prefix.Length; } public COMMREQ(COMMREQ_Type ctype, int reponseLen) { CType = ctype; string prefixString = CType.ToString(); Prefix = new byte[prefixString.Count()]; this.Prefix = prefixString.Select(p => (byte)p).ToArray(); this.ReponseLen = reponseLen; } public COMMREQ(COMMREQ_Type ctype, int dataLen, ParseFuncPackHandler parseFuncPack) { CType = ctype; string prefixString = CType.ToString(); Prefix = new byte[prefixString.Count()]; this.Prefix = prefixString.Select(p => (byte)p).ToArray(); this.ParseFuncPack = parseFuncPack; this.ReponseLen = Prefix.Count() + dataLen; } public COMMREQ(COMMREQ_Type ctype, string prefix, int reponseLen, ParseFuncPackHandler parseFuncPack) { CType = ctype; Prefix = new byte[prefix.Count()]; this.Prefix = prefix.Select(p => (byte)p).ToArray(); this.ParseFuncPack = parseFuncPack; this.ReponseLen = reponseLen; } public COMMREQ(COMMREQ_Type ctype, byte[] prefixs, int reponseLen, ParseFuncPackHandler parseFuncPack) { CType = ctype; this.Prefix = prefixs; this.ParseFuncPack = parseFuncPack; this.ReponseLen = reponseLen; } public COMMREQ(COMMREQ_Type ctype, byte[] prefixs) { CType = ctype; this.Prefix = prefixs; this.ReponseLen = prefixs.Length; } } enum COMMREQ_Type { #region IOComm IO指令 IGI, IGO, IGP0, IGP1, IGPA, ISO, #endregion #region RunComm 运行指令 SetRunParam RPV, RPS, RPU, RPD, RP1, RP2, #endregion #region RunComm 运行指令 GetRunParam RpV, RpS, RpU, RpD, Rp1, Rp2, #endregion #region RunComm 运行指令 RF, RB, RO, RR, RS, RT, RN, #endregion #region D,同步运行指令 RD0x80, RD0x81, RD0x02, RD0x03, RD0x04, RD0xE0, RD0xE1, RD0xE2, RD0xE3, RGD, #endregion #region SysParamComm 系统参数指令 ST, SI0, SA, Sa, S1, #endregion #region GetSysParam 读运行参数 SpM, Spm, SpE, SpZ, SpJ, #endregion #region SetSysParam 设置运行参数 SPM, SPm, SPE, SPZ, SPJ, #endregion } class COMMREQ_Transaction { /// <summary> /// 请求的前缀 /// </summary> public COMMREQ_Type ctype; /// <summary> /// 回复 callback /// </summary> public CallBackHandler asyncDelegate; /// <summary> /// 上下文 /// </summary> public object asyncContext; /// <summary> /// 数据 /// </summary> public byte[] datas; /// <summary> /// 数据的object 表达,只用于调试而已 /// </summary> public object datasObj; } }