#define SPEED_BY_MySelf using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net; using System.ComponentModel; using FObjBase; using System.IO; using Misc; using System.Collections.ObjectModel; namespace FlyADBase { /// <summary> /// 执行顺序 /// 1. IFlyAD flyad = new FlyAD7();//加载速度参数,IP地址 /// 2. flyad.Connect();//flyad.Connect("192.168.251.10:20006"); /// 3. 当连接上,会设置推送,获取flyad7控制器里面所有数据,设置速度参数到控制器 /// </summary> public class FlyAD7 : FObj, IFlyADClient { #region MARKNO public const int MARKNO_SET_VELOCITY = 1; public const int MARKNO_SET_ZEROPOS = 2; public const int MARKNO_SET_SYSPARAM = 3; #endregion #region 成员变量 /// <summary> /// 不设置服务器 /// </summary> private bool bShieldSetValueEx = false; private DateTime dt_surplus = DateTime.MinValue; class DtAndBool { public bool bNeedGet; public DateTime dt; public void Clear() { bNeedGet = true; dt = DateTime.Now; } } DtAndBool driveman_wait = new DtAndBool(); DtAndBool pos_wait = new DtAndBool(); DtAndBool sysinfo_wait = new DtAndBool(); class SGrid { const int GRID_MAX_SIZE = 1000; int size; public int[][] data = new int[2][];//data[0]=forword, data[1]=backward public SGrid() { //清空所有数据 SetSize(GRID_MAX_SIZE); } public void SetSize(int size) { this.size = size; data[0] = new int[size]; data[1] = new int[size]; Clear(); } public void Clear() { //清空所有数据 for (int i = 0; i < size; i++) { data[0][i] = Misc.MyBase.NULL_VALUE; data[1][i] = Misc.MyBase.NULL_VALUE; } } } SGrid fGrid = new SGrid(); TCPCConn conn = null; #endregion #region IFlyADClient bool hascrc = false; public bool HasCRC { get { return hascrc; } set { if (hascrc != value) { hascrc = value; NotifyPropertyChanged("HasCRC"); } } } private int gridsmooth = 0; /// <summary> /// grid数据平滑 /// </summary> public int GridSmooth { get { return gridsmooth; } set { if (value < 0) value = 0; if (gridsmooth != value) { gridsmooth = value; NotifyPropertyChanged("GridSmooth"); } } } private int inbuflen = 0; public int InBufLen //1秒刷新一次 { get { return inbuflen; } protected set { if (inbuflen != value) { inbuflen = value; NotifyPropertyChanged("InBufLen"); } } } #endregion int noTGridCnt = 0;//没有收到timegrid的次数, 1秒加1次 const int ReConnectTGridMaxCnt = 3;//3次收不到timegrid, 重连 const double SpeedScale = 1000.0 / 620; public FlyAD7() { Now = DateTime.Now; Position = 0; Speed = 0; Position2 = 0; Speed2 = 0; AD = 0; IStatus = 0xffff; OStatus = 0xffff; MotorType = MOTORTYPE.VF0; PosOffset = 0; JogVelocity = 5000; PosOfGrid = 10; PosLen = 8900; Ratio01 = 4; Ratio02 = 1; Velocity = 8000; SVelocity = 200; ATime = 300; DTime = 300; HVelocity1 = 4000; HVelocity2 = 500; Marker = 0; Pos2Comp = 1; Pos1LCShift = 0; IsSync = false; fGrid.SetSize(PosLen / PosOfGrid); this.PropertyChanged += new PropertyChangedEventHandler(FlyAD7_PropertyChanged); PollModule.Current.Poll_Config(PollModule.POLL_CONFIG.ADD, new PollModule.PollHandler(OnPoll)); //3秒内收不到1个timegrid ,就会重连 PollModule.Current.Poll_Config(PollModule.POLL_CONFIG.ADD, () => { if (!IsConnected) { noTGridCnt = 0; } else { noTGridCnt++; if (noTGridCnt >= ReConnectTGridMaxCnt) { noTGridCnt = 0; ReConnect(); } } }, TimeSpan.FromSeconds(1)); #if SPEED_BY_MySelf //更新线速度 PollModule.Current.Poll_Config(PollModule.POLL_CONFIG.ADD, () => { if (pos1_last_for_speed != int.MinValue) { Speed = Position - pos1_last_for_speed; } pos1_last_for_speed = Position; if (pos2_last_for_speed != int.MinValue) { Speed2 = Position2 - pos2_last_for_speed; } pos2_last_for_speed = Position2; }, TimeSpan.FromSeconds(1)); #endif mCreateGridAdv.Init(this); } int pos1_last_for_speed = int.MinValue; int pos2_last_for_speed = int.MinValue; void FlyAD7_PropertyChanged(object sender, PropertyChangedEventArgs e) { if (e.PropertyName == "HasCRC") { if (conn != null) conn.HasCRC = HasCRC; } else if (e.PropertyName == "DriveStatus") { switch (DriveStatus) { case DRIVE_MAN_STATUS.STOP_MANUAL: case DRIVE_MAN_STATUS.STOP: case DRIVE_MAN_STATUS.LIMIT: IsFinish = true; break; case DRIVE_MAN_STATUS.RUNNING: IsFinish = false; break; } } else if ((e.PropertyName == "PosLen") || (e.PropertyName == "PosOfGrid")) { fGrid.SetSize(PosLen / PosOfGrid); } else if (e.PropertyName == "Marker") { //if (DriveOrder == DRIVE_MAN_ORDER.SYNC) { //同步运行中 //检测与哪个指令一致, //该指令置为 Doing, 前面的全部置为 Finish,并且删除 for (int i = 0; i < SyncOrders.Count(); i++) { if (SyncOrders[i].Marker == Marker) { SyncOrders[i].State = SyncOrderState.Doing; for (int j = 0; j < i; j++) { SyncOrders[0].State = SyncOrderState.Finish; SyncOrders.RemoveAt(0); } } } } } if (bShieldSetValueEx) return; if ((e.PropertyName == "Velocity") || (e.PropertyName == "SVelocity") || (e.PropertyName == "ATime") || (e.PropertyName == "DTime") || (e.PropertyName == "HVelocity1") || (e.PropertyName == "HVelocity2")) { FObjBase.PollModule.Current.Poll_JustOnce( delegate() { //TODO,不应该直接修改Velocity,SVelocity。。。。。。 //所以下面也不可能存在!!! SetPosParam(Velocity, SVelocity, ATime, DTime, HVelocity1, HVelocity2); }, this, MARKNO_SET_VELOCITY); } else if ((e.PropertyName == "PosOffset") || (e.PropertyName == "JogVelocity")) { FObjBase.PollModule.Current.Poll_JustOnce( delegate() { CurrObjSys.SetValueEx(conn, FLYAD7_OBJ_INTERFACE.SYS_DATA_INTERFACE.ID, ID, FLYAD7_OBJ_INTERFACE.SYS_DATA_INTERFACE.SET_ZERO_POS, new FLYAD7_OBJ_INTERFACE.SYS_DATA_INTERFACE.Pack_ZeroPos() { zero_pos = PosOffset, jog_velocity = JogVelocity }.ToBytes()); }, this, MARKNO_SET_ZEROPOS); } else if ((e.PropertyName == "MotorType") || (e.PropertyName == "PosOfGrid") || (e.PropertyName == "Ratio01") || (e.PropertyName == "Ratio02")) { FObjBase.PollModule.Current.Poll_JustOnce( delegate() { SetSysParam(PosOfGrid, MotorType, Ratio01, Ratio02); }, this, MARKNO_SET_SYSPARAM); } else if (e.PropertyName == "Pos1LCShift") { CurrObjSys.CallFunctionEx( conn, FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.ID, ID, FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.CALL_PXX, new FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.Pack_Pos1LCShift() { pos1_LCShift = Pos1LCShift }.ToBytes()); } else if (e.PropertyName == "Position2") { CurrObjSys.CallFunctionEx( conn, FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.ID, ID, FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.CALL_PXX, new FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.Pack_Pos2() { pos2 = Position2 }.ToBytes()); } else if (e.PropertyName == "Pos2Comp") { CurrObjSys.CallFunctionEx( conn, FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.ID, ID, FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.CALL_PXX, new FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.Pack_Pos2Comp() { comp = Pos2Comp }.ToBytes()); } } #region IFlyADClient public void Connect() { Connect(LocalEP); } public void Connect(IPEndPoint ep) { LocalEP = ep; if (conn != null) { if (!conn.RemoteEP.Equals(LocalEP)) { //断开之前的连接 CurrObjSys.Disconnect_to_Another_OBJSys(conn.RemoteEP, ID); } } conn = CurrObjSys.Connect_to_Another_OBJSys(LocalEP, ID); conn.HasCRC = HasCRC; } public void ReConnect() { if (conn != null) { //断开之前的连接 CurrObjSys.Disconnect_to_Another_OBJSys(conn.RemoteEP, ID); } conn = CurrObjSys.Connect_to_Another_OBJSys(LocalEP, ID); conn.HasCRC = HasCRC; } #endregion private void Init() { CurrObjSys.SenseConfigEx( conn, FLYAD7_OBJ_INTERFACE.PUSH_DATA_INTERFACE.ID, ID, Misc.MyBase.BIT(FLYAD7_OBJ_INTERFACE.PUSH_DATA_INTERFACE.PUSH_POS1) | Misc.MyBase.BIT(FLYAD7_OBJ_INTERFACE.PUSH_DATA_INTERFACE.PUSH_POS2) | Misc.MyBase.BIT(FLYAD7_OBJ_INTERFACE.PUSH_DATA_INTERFACE.PUSH_AD1) | Misc.MyBase.BIT(FLYAD7_OBJ_INTERFACE.PUSH_DATA_INTERFACE.PUSH_IO) | Misc.MyBase.BIT(FLYAD7_OBJ_INTERFACE.PUSH_DATA_INTERFACE.PUSH_TIMEGRID) | Misc.MyBase.BIT(FLYAD7_OBJ_INTERFACE.PUSH_DATA_INTERFACE.PUSH_GRID) | Misc.MyBase.BIT(FLYAD7_OBJ_INTERFACE.PUSH_DATA_INTERFACE.PUSH_STATUS) | Misc.MyBase.BIT(FLYAD7_OBJ_INTERFACE.PUSH_DATA_INTERFACE.PUSH_MINIGRID) , SENSE_CONFIG.ADD); UpdateParam(); //DRIVE_MAN CurrObjSys.GetValueEx( conn, FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.ID, ID, FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.GET_STATE); //FLYADC CurrObjSys.GetValueEx( conn, FLYAD7_OBJ_INTERFACE.FLYADC_OBJ_INTERFACE.ID, ID, FLYAD7_OBJ_INTERFACE.FLYADC_OBJ_INTERFACE.GET_POS1AD1); CurrObjSys.GetValueEx( conn, FLYAD7_OBJ_INTERFACE.FLYADC_OBJ_INTERFACE.ID, ID, FLYAD7_OBJ_INTERFACE.FLYADC_OBJ_INTERFACE.GET_POS2); //FLYIO CurrObjSys.GetValueEx( conn, FLYAD7_OBJ_INTERFACE.FLYIO_OBJ_INTERFACE.ID, ID, FLYAD7_OBJ_INTERFACE.FLYIO_OBJ_INTERFACE.GET_IO); NotifyPropertyChanged("Pos1LCShift"); NotifyPropertyChanged("Pos2Comp"); SyncPos2Clear(); SyncClear(); SyncEnd(); mSysTick.Reset(); mCreateGridAdv.Clear(); } #region FObj public override void ConnectNotify(IFConn from) { IsConnected = from.IsConnected; if (IsConnected) { ConnectCnt++; Init(); } else { DriveStatus = DRIVE_MAN_STATUS.STOP; } } public override void PushGetValue(IFConn from, uint srcid, ushort memid, byte[] infodata) { bShieldSetValueEx = true; switch (srcid) { case FLYAD7_OBJ_INTERFACE.FLYADC_OBJ_INTERFACE.ID: { switch (memid) { case FLYAD7_OBJ_INTERFACE.FLYADC_OBJ_INTERFACE.GET_POS1AD1: { FLYAD7_OBJ_INTERFACE.FLYADC_OBJ_INTERFACE.Pack_GetPos1AD1 pack = new FLYAD7_OBJ_INTERFACE.FLYADC_OBJ_INTERFACE.Pack_GetPos1AD1(); if (!pack.TryParse(infodata)) break; Position = pack.pos; mCreateGridAdv.AddPos_Default(Position, Now); if (CorrectADs != null) { int grid = Position / PosOfGrid; int[] d = new int[1]; d[0] = pack.ad; CorrectADs(Misc.DIRECTION.FIX, grid, d); pack.ad = d[0]; } AD = pack.ad; } break; case FLYAD7_OBJ_INTERFACE.FLYADC_OBJ_INTERFACE.GET_POS2: { FLYAD7_OBJ_INTERFACE.FLYADC_OBJ_INTERFACE.Pack_GetPos2 pack = new FLYAD7_OBJ_INTERFACE.FLYADC_OBJ_INTERFACE.Pack_GetPos2(); if (!pack.TryParse(infodata)) break; Position2 = pack.pos2; #if !SPEED_BY_MySelf Speed2 = (int)(pack.speed2 * SpeedScale); #endif } break; } } break; case FLYAD7_OBJ_INTERFACE.FLYIO_OBJ_INTERFACE.ID: { switch (memid) { case FLYAD7_OBJ_INTERFACE.FLYIO_OBJ_INTERFACE.GET_IO: { FLYAD7_OBJ_INTERFACE.FLYIO_OBJ_INTERFACE.Pack_GetIO pack = new FLYAD7_OBJ_INTERFACE.FLYIO_OBJ_INTERFACE.Pack_GetIO(); if (!pack.TryParse(infodata)) break; IStatus = pack.istatus; OStatus = pack.ostatus; mCreateGridAdv.AddIStatus_Default(IStatus,Position, Now); } break; } } break; case FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.ID: { switch (memid) { case FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.GET_DRIVEPARAM: { FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.Pack_DriveParam pack = new FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.Pack_DriveParam(); if (!pack.TryParse(infodata)) break; Velocity = pack.Velocity; SVelocity = pack.SV; ATime = pack.ATime; DTime = pack.DTime; HVelocity1 = pack.hspeed1; HVelocity2 = pack.hspeed2; } break; case FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.GET_STATE: { //TODO ????? FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.Pack_DriveState p = new FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.Pack_DriveState(); if (!p.TryParse(infodata)) break; DriveOrder = p.order;//TODO DriveStatus = p.status; Marker = p.marker; } break; } } break; case FLYAD7_OBJ_INTERFACE.SYS_DATA_INTERFACE.ID: { switch (memid) { case FLYAD7_OBJ_INTERFACE.SYS_DATA_INTERFACE.GET_IP: break; case FLYAD7_OBJ_INTERFACE.SYS_DATA_INTERFACE.GET_SYSPARAM: { FLYAD7_OBJ_INTERFACE.SYS_DATA_INTERFACE.Pack_SysParam pack = new FLYAD7_OBJ_INTERFACE.SYS_DATA_INTERFACE.Pack_SysParam(); if (!pack.TryParse(infodata)) break; PosOfGrid = pack.posOfGrid;//1个Grid=?脉冲数(2B) if ((pack.func_enable & 0x03) == 0x02) MotorType = MOTORTYPE.SERVO; else if ((pack.func_enable & 0x03) == 0x01) MotorType = MOTORTYPE.VF0; else MotorType = MOTORTYPE.NULL; Ratio01 = pack.ratio01; Ratio02 = pack.ratio02; } break; case FLYAD7_OBJ_INTERFACE.SYS_DATA_INTERFACE.GET_SYSINFO: { FLYAD7_OBJ_INTERFACE.SYS_DATA_INTERFACE.Pack_SysInfo pack = new FLYAD7_OBJ_INTERFACE.SYS_DATA_INTERFACE.Pack_SysInfo(); if (!pack.TryParse(infodata)) break; AreaStatus = pack.status; AreaRet = pack.ret; Array.Copy(pack.code, Code, pack.code.Length); Code[6] = 0x06; NotifyPropertyChanged("Code"); Surplus = pack.surplus; Array.Copy(pack.access, Access, pack.access.Length); NotifyPropertyChanged("Access"); } break; case FLYAD7_OBJ_INTERFACE.SYS_DATA_INTERFACE.GET_ZERO_POS: { FLYAD7_OBJ_INTERFACE.SYS_DATA_INTERFACE.Pack_ZeroPos pack = new FLYAD7_OBJ_INTERFACE.SYS_DATA_INTERFACE.Pack_ZeroPos(); if (!pack.TryParse(infodata)) break; PosOffset = pack.zero_pos; JogVelocity = pack.jog_velocity; } break; } } break; } bShieldSetValueEx = false; } /// <summary> /// systick 转 DateTime /// 不断把 从flyad7 获取的 systick 放入。 以每次systick 的差 加上 上一次 dt_1st, 得到时间。 /// 如: 当前 获得 systick1, 之前是 systick0, 所以 dt = dt_1st+ (systick1-systick0); dt_1st=dt; /// /// 第1个 dt_1st, 是 从 DateTime.Now. 获取的。 /// /// 不会管 当前DateTime.Now 与 dt 差多少。 所以如果 flyad7 时间比较慢,可能会出现 3天后, DateTime.Now 与 dt 差了 1个小时。 /// </summary> class TSysTick { Int32 systick_1st = 0; DateTime dt_1st = DateTime.MinValue; Int32 systick_last = 0; public void Reset() { dt_1st = DateTime.MinValue; } /// <summary> /// 输入从 flyad7 获取的 timemark, 转换为 本地 DateTime /// </summary> /// <param name="systick"></param> /// <returns></returns> public DateTime ToDateTime(int systick) { if (dt_1st == DateTime.MinValue) { dt_1st = DateTime.Now; systick_1st = systick; systick_last = systick; return dt_1st; } //记录与新的timemark 相差10秒,太大了,重新生成 timemark 与 dt 的关系 else if (Math.Abs(systick - systick_last) > 10000) { dt_1st = DateTime.Now; systick_1st = systick; systick_last = systick; return dt_1st; } else { int ms = systick - systick_1st; systick_last = systick; DateTime dt = dt_1st.AddMilliseconds(ms); systick_1st = systick; dt_1st = dt; return dt; } } } TSysTick mSysTick = new TSysTick(); public override void PushInfo(IFConn from, uint srcid, ushort infoid, byte[] infodata) { bShieldSetValueEx = true; switch (infoid) { case FLYAD7_OBJ_INTERFACE.PUSH_DATA_INTERFACE.PUSH_POS1: { FLYAD7_OBJ_INTERFACE.PUSH_DATA_INTERFACE.Pack_PushPos1_2 pack = new FLYAD7_OBJ_INTERFACE.PUSH_DATA_INTERFACE.Pack_PushPos1_2(); int version; if (!pack.TryParse_version(infodata,out version)) break; if(version == 1) { Position = pack.pos1; #if !SPEED_BY_MySelf Speed = (int)(pack.speed1 * SpeedScale); #endif mCreateGridAdv.AddPos(Position, DateTime.Now); } else if(version == 2) { Position = pack.pos1; #if !SPEED_BY_MySelf Speed = (int)(pack.speed1 * SpeedScale); #endif DateTime dt = mSysTick.ToDateTime(pack.systick); Now = dt; mCreateGridAdv.AddPos(Position, dt); } } break; case FLYAD7_OBJ_INTERFACE.PUSH_DATA_INTERFACE.PUSH_POS2: { FLYAD7_OBJ_INTERFACE.PUSH_DATA_INTERFACE.Pack_PushPos2_2 pack = new FLYAD7_OBJ_INTERFACE.PUSH_DATA_INTERFACE.Pack_PushPos2_2(); int version; if (!pack.TryParse_version(infodata,out version)) break; Position2 = pack.pos2; #if !SPEED_BY_MySelf Speed2 = (int)(pack.speed2 * SpeedScale); #endif } break; case FLYAD7_OBJ_INTERFACE.PUSH_DATA_INTERFACE.PUSH_AD1: { FLYAD7_OBJ_INTERFACE.PUSH_DATA_INTERFACE.Pack_PushAD1 pack = new FLYAD7_OBJ_INTERFACE.PUSH_DATA_INTERFACE.Pack_PushAD1(); if (!pack.TryParse(infodata)) break; if (CorrectADs != null) { int grid = Position / PosOfGrid; int[] d = new int[1]; d[0] = pack.AD; CorrectADs(Misc.DIRECTION.FIX, grid, d); pack.AD = d[0]; } AD = pack.AD; } break; case FLYAD7_OBJ_INTERFACE.PUSH_DATA_INTERFACE.PUSH_IO: { FLYAD7_OBJ_INTERFACE.PUSH_DATA_INTERFACE.Pack_PushIO_2 pack = new FLYAD7_OBJ_INTERFACE.PUSH_DATA_INTERFACE.Pack_PushIO_2(); int version; if (!pack.TryParse_version(infodata, out version)) break; if (version == 1) { UInt16 inchange = (UInt16)(IStatus ^ pack.istatus); IStatus = pack.istatus; OStatus = pack.ostatus; Now = DateTime.Now; mCreateGridAdv.AddIStatus(IStatus, Position, Now); if (IStatusChangedEvent != null) { IStatusChangedEvent( this, new IStatusChangedEventArgs( Now, IStatus, inchange, Position, Position2)); } } else if(version == 2) { IStatus = pack.istatus; OStatus = pack.ostatus; DateTime dt = mSysTick.ToDateTime(pack.systick); Now = dt; mCreateGridAdv.AddIStatus(IStatus,pack.pos1, Now); if (IStatusChangedEvent != null) { IStatusChangedEvent( this, new IStatusChangedEventArgs( dt, pack.istatus, pack.inChange, pack.pos1, pack.pos2)); } } } break; case FLYAD7_OBJ_INTERFACE.PUSH_DATA_INTERFACE.PUSH_AD2: break; case FLYAD7_OBJ_INTERFACE.PUSH_DATA_INTERFACE.PUSH_TIMEGRID: { int version; FLYAD7_OBJ_INTERFACE.PUSH_DATA_INTERFACE.Pack_PushTGrid_2 pack = new FLYAD7_OBJ_INTERFACE.PUSH_DATA_INTERFACE.Pack_PushTGrid_2(); if (!pack.TryParse_version(infodata, out version)) { break; } DateTime dt; int[] data; if (version == 1) { //怕数据发送出错 foreach (int d in pack.data) { if ((d >> 16) != 0) { //异常 goto _end_push_info; } } dt = DateTime.Now; } //else if (version == 2) { //怕数据发送出错 foreach (int d in pack.data) { if ((d >> 16) != 0) { //异常 goto _end_push_info; } } dt = mSysTick.ToDateTime(pack.systick); Now = dt; } data = pack.data; mCreateGridAdv.AddAD(data, dt - TimeSpan.FromMilliseconds(ADLag)); noTGridCnt = 0;//收到timegrid!!!!!!!!!!! { double ts_ms = 1.28; long ticks = (long)((ts_ms * data.Length) * TimeSpan.TicksPerMillisecond); dt = dt - TimeSpan.FromTicks(ticks); if (TimeGridEvent != null) { if (CorrectADs != null) { if (PosOfGrid > 0) { int grid = Position / PosOfGrid; int[] d = new int[1]; for (int i = 0; i < data.Count(); i++) { d[0] = data[i]; CorrectADs(Misc.DIRECTION.FIX, grid, d); data[i] = d[0]; } } } TimeGridEvent( this, new TimeGridEventArgs( dt, TimeSpan.FromTicks((long)(ts_ms * TimeSpan.TicksPerMillisecond)), data)); } } } break; case FLYAD7_OBJ_INTERFACE.PUSH_DATA_INTERFACE.PUSH_STATUS: { int version; FLYAD7_OBJ_INTERFACE.PUSH_DATA_INTERFACE.Pack_PushStatus_2 pack = new FLYAD7_OBJ_INTERFACE.PUSH_DATA_INTERFACE.Pack_PushStatus_2(); if (!pack.TryParse_version(infodata, out version)) break; if(version == 2) { DriveOrder = pack.order; DriveStatus = pack.status; Marker = pack.marker; DateTime dt = mSysTick.ToDateTime(pack.systick); Now = dt; } else if(version ==1) { DriveOrder = pack.order; DriveStatus = pack.status; } } break; case FLYAD7_OBJ_INTERFACE.PUSH_DATA_INTERFACE.PUSH_GRID: { int version; FLYAD7_OBJ_INTERFACE.PUSH_DATA_INTERFACE.Pack_PushGrid_2 pack = new FLYAD7_OBJ_INTERFACE.PUSH_DATA_INTERFACE.Pack_PushGrid_2(); if (!pack.TryParse_version(infodata,out version)) break; DateTime dt; int marker; if (version == 2) { dt = mSysTick.ToDateTime(pack.systick); marker = pack.marker; } else { dt = DateTime.Now; marker = Marker; } if (GridAdvEvent != null) { mCreateGridAdv.MarkGrid( pack.direction, pack.grid_start * PosOfGrid, pack.data.Length * PosOfGrid, marker, dt, (s, e) => { if (CorrectADs != null)//机架修正 { for (int i = 0; i < e.dt_data.Count(); i++) { int[] d = new int[]{e.dt_data[i].ad}; CorrectADs(e.direction, e.dt_data[i].pos / PosOfGrid, d); e.dt_data[i].ad = d[0]; } } GridAdvEvent(this, e); }); } mCreateGridAdv.NotifyGridIStatusEvent( pack.direction, pack.grid_start * PosOfGrid, pack.data.Length * PosOfGrid, marker, dt); { int index = 0; if (pack.direction == Misc.DIRECTION.BACKWARD) index = 1; if (pack.grid_start >= fGrid.data[index].Length) return; int grid_end = pack.data.Length + pack.grid_start - 1; if (grid_end >= fGrid.data[index].Length) grid_end = fGrid.data[index].Length - 1; int len = grid_end - pack.grid_start + 1; Array.Copy(pack.data, 0, fGrid.data[index], pack.grid_start, len); //清空其它数据 for (int i = 0; i < pack.grid_start; i++) { fGrid.data[index][i] = Misc.MyBase.NULL_VALUE; } for (int i = (grid_end + 1); i < fGrid.data[index].Length; i++) { fGrid.data[index][i] = Misc.MyBase.NULL_VALUE; } if (GridEvent != null) { if (CorrectADs != null) CorrectADs(pack.direction, pack.grid_start, pack.data); GridEvent(this, new MiniGridEventArgs() { direction = pack.direction, grid_start = pack.grid_start, posOfGrid = PosOfGrid, buf = pack.data, marker = marker }); } } } break; case FLYAD7_OBJ_INTERFACE.PUSH_DATA_INTERFACE.PUSH_MINIGRID: { FLYAD7_OBJ_INTERFACE.PUSH_DATA_INTERFACE.Pack_PushGrid pack = new FLYAD7_OBJ_INTERFACE.PUSH_DATA_INTERFACE.Pack_PushGrid(); if (!pack.TryParse(infodata)) break; int index = 0; if (pack.direction == Misc.DIRECTION.BACKWARD) index = 1; if (pack.grid_start >= fGrid.data[index].Length) break; int grid_end = pack.data.Length + pack.grid_start - 1; if (grid_end >= fGrid.data[index].Length) grid_end = fGrid.data[index].Length - 1; int len = grid_end - pack.grid_start + 1; Array.Copy(pack.data, 0, fGrid.data[index], pack.grid_start, len); //清空后面的数据 if (pack.direction == Misc.DIRECTION.BACKWARD) { for (int i = 0; i < pack.grid_start; i++) { fGrid.data[index][i] = Misc.MyBase.NULL_VALUE; } } else { for (int i = (grid_end + 1); i < fGrid.data[index].Length; i++) { fGrid.data[index][i] = Misc.MyBase.NULL_VALUE; } } if (CorrectADs != null) CorrectADs(pack.direction, pack.grid_start, pack.data); if (MiniGridEvent != null) { MiniGridEvent(this, new MiniGridEventArgs() { direction = pack.direction, grid_start = pack.grid_start, posOfGrid = PosOfGrid, buf = pack.data, marker = Marker }); } } break; } _end_push_info: bShieldSetValueEx = false; } #endregion /// <summary> /// 100ms 周期 /// </summary> private void OnPoll() { if (!IsConnected) return; DateTime now = DateTime.Now; if (Surplus != 65535) { if (dt_surplus != DateTime.MinValue) { dt_surplus = now - TimeSpan.FromMinutes(40);//再过20分钟,就会 执行 使用时间+1 } else if ((now - dt_surplus).TotalHours >= 1) //每隔一个小时 执行 使用时间+1 { dt_surplus = now; if (Surplus > 0) { Surplus--; CurrObjSys.CallFunctionEx(conn, FLYAD7_OBJ_INTERFACE.SYS_DATA_INTERFACE.ID, ID, FLYAD7_OBJ_INTERFACE.SYS_DATA_INTERFACE.CALL_SURPLUS_SUB, null); } } } if (sysinfo_wait.bNeedGet) { if ((now - sysinfo_wait.dt).TotalSeconds >= 1) { sysinfo_wait.bNeedGet = false; CurrObjSys.GetValueEx( conn, FLYAD7_OBJ_INTERFACE.SYS_DATA_INTERFACE.ID, ID, FLYAD7_OBJ_INTERFACE.SYS_DATA_INTERFACE.GET_SYSINFO); } } if (DriveStatus == DRIVE_MAN_STATUS.RUNNING) { //if (Position == TargetPos) //已经到达位置,问AD卡是不是? //{ // if ((now - driveman_wait.dt).TotalSeconds >= 1)//每次发送必须间隔1s // { // driveman_wait.Clear(); // CurrObjSys.GetValueEx( // conn, // FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.ID, // ID, // FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.GET_STATE); // } //} //else if ((now - driveman_wait.dt).TotalSeconds >= 3) { driveman_wait.Clear(); if (Position == last_position)//当前正在running,但脉冲在3秒内都没变化,问AD卡,现在什么情况。 { CurrObjSys.GetValueEx( conn, FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.ID, ID, FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.GET_STATE); } last_position = Position; } } } int last_position = int.MinValue; #region IFlyAD 成员 private bool isconnected; public bool IsConnected { get { return isconnected; } protected set { if (isconnected != value) { isconnected = value; NotifyPropertyChanged("IsConnected"); } } } private int connectcnt = 0; public int ConnectCnt { get { return connectcnt; } protected set { if (connectcnt != value) { connectcnt = value; NotifyPropertyChanged("ConnectCnt"); } } } #endregion #region INotifyPropertyChanged 成员 protected void NotifyPropertyChanged(string propertyName) { if (this.PropertyChanged != null) this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName)); } public event PropertyChangedEventHandler PropertyChanged; #endregion private int poslen=8900; public int PosLen { get { return poslen; } set { if (poslen != value) { poslen = value; NotifyPropertyChanged("PosLen"); } } } public void RuntoMin() { Runto(0); } public void RuntoMax() { Runto(PosLen); } #region IFlyAD 成员 private IPEndPoint localep = new IPEndPoint(IPAddress.Parse("192.168.251.10"), 20006); public IPEndPoint LocalEP { get { return localep; } set { if (value == null) return; if (!IPEndPoint.Equals(localep, value)) { localep = new IPEndPoint(value.Address, value.Port); NotifyPropertyChanged("LocalEP"); } } } private DateTime now; public DateTime Now { get { return now; } set { if (now != value) { now = value; NotifyPropertyChanged("Now"); } } } private int position; public int Position { get { return position; } set { if (position != value) { position = value; NotifyPropertyChanged("Position"); } } } private int speed; public int Speed { get { return speed; } set { if (speed != value) { speed = value; NotifyPropertyChanged("Speed"); } } } private int ad; public int AD { get { return ad; } set { if (ad != value) { ad = value; NotifyPropertyChanged("AD"); } } } public int ADMax { get { return 65535; } } private UInt16 uIStatus = 0xffff; public UInt16 IStatus { get { return uIStatus; } set { if (uIStatus != value) { uIStatus = value; NotifyPropertyChanged("IStatus"); } } } private UInt16 uOStatus; public UInt16 OStatus { get { return uOStatus; } set { if (uOStatus != value) { uOStatus = value; NotifyPropertyChanged("OStatus"); } } } public void SetOutputBit(int index, bool is1) { if (index > 4) return; if (index < 0) return; if (is1) { SetOutput( (UInt16)Misc.MyBase.BIT(index), (UInt16)Misc.MyBase.BIT(index)); } else { SetOutput( (UInt16)Misc.MyBase.BIT(index), (UInt16)~Misc.MyBase.BIT(index)); } } public void SetOutput(ushort mask, ushort enable) { CurrObjSys.CallFunctionEx( conn, FLYAD7_OBJ_INTERFACE.FLYIO_OBJ_INTERFACE.ID, ID, FLYAD7_OBJ_INTERFACE.FLYIO_OBJ_INTERFACE.CALL_OUTPORT, new FLYAD7_OBJ_INTERFACE.FLYIO_OBJ_INTERFACE.Pack_CallOutPort() { mask = mask, port = enable }.ToBytes()); } /// <summary> /// 更新参数 /// </summary> public void UpdateParam() { //OBJ_SYS_DATA CurrObjSys.GetValueEx( conn, FLYAD7_OBJ_INTERFACE.SYS_DATA_INTERFACE.ID, ID, FLYAD7_OBJ_INTERFACE.SYS_DATA_INTERFACE.GET_SYSPARAM); CurrObjSys.GetValueEx( conn, FLYAD7_OBJ_INTERFACE.SYS_DATA_INTERFACE.ID, ID, FLYAD7_OBJ_INTERFACE.SYS_DATA_INTERFACE.GET_ZERO_POS); CurrObjSys.GetValueEx( conn, FLYAD7_OBJ_INTERFACE.SYS_DATA_INTERFACE.ID, ID, FLYAD7_OBJ_INTERFACE.SYS_DATA_INTERFACE.GET_SYSINFO); //DRIVE_MAN CurrObjSys.GetValueEx( conn, FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.ID, ID, FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.GET_DRIVEPARAM); } #region 配置参数 /// <summary> /// 配置参数,请不要再用 /// </summary> /// <param name="posOfGrid"></param> /// <param name="motortype"></param> /// <param name="ratio01"></param> /// <param name="ratio02"></param> public void SetSysParam(UInt16 posOfGrid, MOTORTYPE motortype, UInt16 ratio01, UInt16 ratio02) { byte func_enable = 0x0e; if (motortype == MOTORTYPE.NULL) func_enable = 0x0e; else if (motortype == MOTORTYPE.SERVO) func_enable = 0x0e; else// if (motortype == MOTORTYPE.VF0) func_enable = 0x0d; CurrObjSys.SetValueEx( conn, FLYAD7_OBJ_INTERFACE.SYS_DATA_INTERFACE.ID, ID, FLYAD7_OBJ_INTERFACE.SYS_DATA_INTERFACE.SET_SYSPARAM, new FLYAD7_OBJ_INTERFACE.SYS_DATA_INTERFACE.Pack_SysParam() { posOfGrid = posOfGrid, ad1_interval = 1000, ad2_interval = 1000, push_interval = 100, func_setting = 0, func_enable = func_enable, ratio01 = ratio01, ratio02 = ratio02 }.ToBytes()); //CurrObjSys.GetValueEx( // conn, // FLYAD7_OBJ_INTERFACE.SYS_DATA_INTERFACE.ID, // ID, // 0x1234, // FLYAD7_OBJ_INTERFACE.SYS_DATA_INTERFACE.GET_SYSPARAM); } private MOTORTYPE motortype = MOTORTYPE.SERVO; public MOTORTYPE MotorType { get { return motortype; } set { if (motortype != value) { motortype = value; NotifyPropertyChanged("MotorType"); } } } private UInt16 posofgrid; /// <summary> /// // 单位 pulse/grid /// </summary> public UInt16 PosOfGrid { get { return posofgrid; } set { if (posofgrid != value) { posofgrid = value; NotifyPropertyChanged("PosOfGrid"); } } } private UInt16 ratio01; public UInt16 Ratio01 { get { return ratio01; } set { if (ratio01 != value) { ratio01 = value; NotifyPropertyChanged("Ratio01"); NotifyPropertyChanged("Speed1Scale"); } } } private UInt16 ratio02; public UInt16 Ratio02 { get { return ratio02; } set { if (ratio02 != value) { ratio02 = value; NotifyPropertyChanged("Ratio02"); NotifyPropertyChanged("Speed1Scale"); } } } /// <summary> /// Speed1 = Velocity * Speed1Scale /// </summary> public double Speed1Scale { get { return (double)Ratio02 / Ratio01; } } #endregion private Int16 posoffset; public Int16 PosOffset { get { return posoffset; } set { if (posoffset != value) { posoffset = value; NotifyPropertyChanged("PosOffset"); } } }//脉冲平移 private UInt32 jogvelocity; public UInt32 JogVelocity { get { return jogvelocity; } set { if (jogvelocity != value) { jogvelocity = value; NotifyPropertyChanged("JogVelocity"); } } } #region 速度 public void SetVelocity(UInt32 velocity) { SetPosParam(velocity, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff); } public void SetPosParam(UInt32 velocity, UInt32 sv, UInt32 atime, UInt32 dtime, UInt32 hspeed1, UInt32 hspeed2) { bShieldSetValueEx = true; if (velocity != 0xffffffff) Velocity = velocity; if (sv != 0xffffffff) SVelocity = sv; if (atime != 0xffffffff) ATime = atime; if (dtime != 0xffffffff) DTime = dtime; if (hspeed1 != 0xffffffff) HVelocity1 = hspeed1; if (hspeed2 != 0xffffffff) HVelocity2 = hspeed2; bShieldSetValueEx = false; CurrObjSys.SetValueEx( conn, FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.ID, ID, FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.SET_DRIVEPARAM, new FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.Pack_DriveParam() { Velocity = velocity, SV = sv, ATime = atime, DTime = dtime, hspeed1 = hspeed1, hspeed2 = hspeed2 }.ToBytes()); //CurrObjSys.GetValueEx( // conn, // FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.ID, // ID, // 0x1234, // FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.GET_DRIVEPARAM); } private UInt32 velocity; public UInt32 Velocity { get { return velocity; } set { if (velocity != value) { velocity = value; NotifyPropertyChanged("Velocity"); } } } private UInt32 svelocity; public UInt32 SVelocity { get { return svelocity; } set { if (svelocity != value) { svelocity = value; NotifyPropertyChanged("SVelocity"); } } } private UInt32 atime; public UInt32 ATime { get { return atime; } set { if (atime != value) { atime = value; NotifyPropertyChanged("ATime"); } } } private UInt32 dtime; public UInt32 DTime { get { return dtime; } set { if (dtime != value) { dtime = value; NotifyPropertyChanged("DTime"); } } } private UInt32 hvelocity1; public UInt32 HVelocity1 { get { return hvelocity1; } set { if (hvelocity1 != value) { hvelocity1 = value; NotifyPropertyChanged("HVelocity1"); } } } private UInt32 hvelocity2; public UInt32 HVelocity2 { get { return hvelocity2; } set { if (hvelocity2 != value) { hvelocity2 = value; NotifyPropertyChanged("HVelocity2"); } } } #endregion #region 密码 private AREA_STATUS areastatus; public AREA_STATUS AreaStatus { get { return areastatus; } set { if (areastatus != value) { areastatus = value; NotifyPropertyChanged("AreaStatus"); } } } private AREA_ERR arearet; public AREA_ERR AreaRet { get { return arearet; } set { if (arearet != value) { arearet = value; NotifyPropertyChanged("AreaRet"); } } } private byte[] code = new byte[7]; public byte[] Code { get { return code; } } private int surplus = 0xffff; /// <summary> /// //系统剩余时间 /// </summary> public int Surplus { get { return surplus; } set { if (surplus != value) { surplus = value; NotifyPropertyChanged("Surplus"); } } } private byte[] access = new byte[8]; public byte[] Access { get { return access; } }//access[8] /// <summary> /// 输入系统授权码 /// </summary> /// <param name="access"></param> public void SetAccess(byte[] access) { CurrObjSys.CallFunctionEx( conn, FLYAD7_OBJ_INTERFACE.SYS_DATA_INTERFACE.ID, ID, FLYAD7_OBJ_INTERFACE.SYS_DATA_INTERFACE.CALL_ACCESS, access); sysinfo_wait.bNeedGet = true; sysinfo_wait.dt = DateTime.Now; } /// <summary> /// 初始化系统信息区 /// </summary> public void InitArea() { CurrObjSys.CallFunctionEx( conn, FLYAD7_OBJ_INTERFACE.SYS_DATA_INTERFACE.ID, ID, FLYAD7_OBJ_INTERFACE.SYS_DATA_INTERFACE.CALL_INIT, new FLYAD7_OBJ_INTERFACE.SYS_DATA_INTERFACE.Pack_Init().ToBytes()); sysinfo_wait.bNeedGet = true; sysinfo_wait.dt = DateTime.Now; } #endregion #endregion #region IFlyAD 成员 public void GetGrid(Misc.DIRECTION direction, int grid_start, int grid_len, out int[] dat) { int index = 0; if (direction == Misc.DIRECTION.BACKWARD) index = 1; dat = new int[grid_len]; for (int i = 0; i < dat.Length; i++) { int grid_num = grid_start + i; if (grid_num >= fGrid.data[index].Length) break; if (GridSmooth > 0) { int sum = 0; int cnt = 0; for (int j = 0; j < (GridSmooth * 2 + 1); j++) { int idx = grid_num - GridSmooth + j; if(idx<0) continue; if(idx >= fGrid.data[index].Length) break; if (Misc.MyBase.ISVALIDATA(fGrid.data[index][idx])) { sum += fGrid.data[index][idx]; cnt++; } } if (cnt > 0) dat[i] = sum / cnt; else dat[i] = Misc.MyBase.NULL_VALUE; } else { dat[i] = fGrid.data[index][grid_num]; } } if (CorrectADs != null) CorrectADs(direction, grid_start, dat); return; } public void GetGrid(Misc.DIRECTION direction, out int[] dat) { GetGrid(direction, 0, fGrid.data[0].Length, out dat); } public event TimeGridEventHandler TimeGridEvent; public event MiniGridEventHandler MiniGridEvent; public event MiniGridEventHandler GridEvent; public event IStatusChangedEventHandler IStatusChangedEvent; public void Runto(int to) { Drive(DRIVE_MAN_ORDER.RUNTO, to); } public void Origin() { Drive(DRIVE_MAN_ORDER.ORIGIN); } public void Stop() { Drive(DRIVE_MAN_ORDER.STOP); } public void Backward() { Drive(DRIVE_MAN_ORDER.BACKWORD); } public void Forward() { Drive(DRIVE_MAN_ORDER.FORWORD); } private DRIVE_MAN_ORDER driveorder=DRIVE_MAN_ORDER.IDLE; public DRIVE_MAN_ORDER DriveOrder { get { return driveorder; } set { if (driveorder != value) { driveorder = value; NotifyPropertyChanged("DriveOrder"); } } } private DRIVE_MAN_STATUS drivestatus=DRIVE_MAN_STATUS.STOP; public DRIVE_MAN_STATUS DriveStatus { get { return drivestatus; } set { if (drivestatus != value) { drivestatus = value; NotifyPropertyChanged("DriveStatus"); } } } void Drive(DRIVE_MAN_ORDER order, object param) { switch (order) { case DRIVE_MAN_ORDER.RUNTO: { int TargetPos = (int)param; if (Position == TargetPos) { //已经到了位置!!!!!, FLYAD7 是没有动作,没有推送的!!! DriveStatus = DRIVE_MAN_STATUS.STOP; } else { DriveStatus = DRIVE_MAN_STATUS.RUNNING; CurrObjSys.CallFunctionEx( conn, FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.ID, ID, FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.CALL_PXX, new FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.Pack_CallRunto() { to = TargetPos }.ToBytes()); } } break; case DRIVE_MAN_ORDER.ORIGIN: case DRIVE_MAN_ORDER.BACKWORD: case DRIVE_MAN_ORDER.FORWORD: case DRIVE_MAN_ORDER.STOP: { DriveStatus = DRIVE_MAN_STATUS.RUNNING; CurrObjSys.CallFunctionEx( conn, FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.ID, ID, FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.CALL_PXX, new FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.Pack_CallPXX() { order = order }.ToBytes()); } break; case DRIVE_MAN_ORDER.SYNC: { if (param != null) { CurrObjSys.CallFunctionEx( conn, FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.ID, ID, FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.CALL_PXX, new FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.Pack_SyncBeginWithPos2() { pos2 = (int)param }.ToBytes()); } else { CurrObjSys.CallFunctionEx( conn, FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.ID, ID, FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.CALL_PXX, new FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.Pack_SyncBegin().ToBytes()); } } break; } driveman_wait.Clear(); } void Drive(DRIVE_MAN_ORDER order) { Drive(order, null); } private bool isfinish; public bool IsFinish { get { return isfinish; } set { if (isfinish != value) { isfinish = value; NotifyPropertyChanged("IsFinish"); } } } #endregion #region 同步 private Int32 marker; /// <summary> /// 同步用标示 /// </summary> public Int32 Marker { get { return marker; } protected set { if (marker != value) { marker = value; NotifyPropertyChanged("Marker"); } } } #region 横向脉冲 private int pos1lcshift=0; /// <summary> /// 逻辑横向脉冲偏移 Pos1 + Pos1LCShift = Pos1LC /// </summary> public int Pos1LCShift { get { return pos1lcshift; } set { if (pos1lcshift != value) { pos1lcshift = value; NotifyPropertyChanged("Pos1LCShift"); } } } #endregion #region 主轴脉冲 private int speed2=0; /// <summary> /// 纵向脉冲速度, pps, 1秒脉冲数 /// </summary> public int Speed2 { get { return speed2; } protected set { if (speed2 != value) { speed2 = value; NotifyPropertyChanged("Speed2"); } } } private int position2=0; /// <summary> /// 纵向脉冲,也叫主轴脉冲 /// </summary> public int Position2 { get { return position2; } set { if (position2 != value) { position2 = value; NotifyPropertyChanged("Position2"); } } } private int pos2shift=0; /// <summary> /// 纵向偏移 /// </summary> public void SetPos2Offset(int offset) { CurrObjSys.CallFunctionEx( conn, FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.ID, ID, FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.CALL_PXX, new FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.Pack_Pos2Shift() { pos2_shift = offset }.ToBytes()); } private float pos2comp=1; /// <summary> /// 纵向值补偿系数,补偿时,先乘除后加减 /// </summary> public float Pos2Comp { get { return pos2comp; } set { if (pos2comp != value) { pos2comp = value; NotifyPropertyChanged("Pos2Comp"); } } } /// <summary> /// 纵向同步事件,0-1事件 /// </summary> /// <param name="pos2"></param> public void SetPos2At01(int pos2,bool immediately) { CurrObjSys.CallFunctionEx( conn, FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.ID, ID, FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.CALL_PXX, new FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.Pack_Pos2_01() { pos2 = pos2, immediately = immediately }.ToBytes()); LastPos2At01 = pos2; } #endregion #region 同步控制 同步状态转换规则 /// <summary> /// 进入同步状态 /// </summary> /// <param name="pos2"></param> public void SyncBegin(int pos2) { Drive(DRIVE_MAN_ORDER.SYNC, pos2); IsSync = true; } /// <summary> /// 进入同步状态 /// </summary> public void SyncBegin() { Drive(DRIVE_MAN_ORDER.SYNC, null); IsSync = true; } /// <summary> /// 退出同步状态 /// </summary> public void SyncEnd() { CurrObjSys.CallFunctionEx( conn, FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.ID, ID, FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.CALL_PXX, new FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.Pack_SyncEnd().ToBytes()); IsSync = false; } /// <summary> /// 清空同步指令 /// </summary> public void SyncClear() { CurrObjSys.CallFunctionEx( conn, FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.ID, ID, FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.CALL_PXX, new FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.Pack_SyncClear().ToBytes()); SyncOrders.Clear(); } public void SyncPos2Clear() { CurrObjSys.CallFunctionEx( conn, FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.ID, ID, FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.CALL_PXX, new FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.Pack_SyncPos2Clear().ToBytes()); } #endregion #region 同步扫描 脚本指令 #region IFlyADClient 同步 private bool issync=false; public bool IsSync { get { return issync; } set { if (issync != value) { issync = value; NotifyPropertyChanged("IsSync"); } } } private int lastpos2at01 = 0; public int LastPos2At01 { get { return lastpos2at01; } protected set { if (lastpos2at01 != value) { lastpos2at01 = value; NotifyPropertyChanged("LastPos2At01"); } } } ObservableCollection<SyncOrder> syncorders = new ObservableCollection<SyncOrder>(); /// <summary> /// 同步列表,完成后,会删除 /// </summary> public ObservableCollection<SyncOrder> SyncOrders { get { return syncorders; } } #endregion //同步扫描至 //D+0xE0+开始主轴位置+结束主轴位置+结束横向脉冲位置(逻辑位置)+脉冲开关(1B)+命令识标号(4B) public void SyncRunAtLC(int pos2_begin, int pos2_end, int pos1lc, bool hasDataGrid, Int32 marker) { CurrObjSys.CallFunctionEx( conn, FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.ID, ID, FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.CALL_PXX, new FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.Pack_SyncRunAtLC() { pos2_begin = pos2_begin, pos2_end = pos2_end, pos1lc = pos1lc, hasDataGrid = hasDataGrid, marker = marker }.ToBytes()); SyncOrders.Add(new SyncOrder_SyncRunAtLC() { Pos2Begin = pos2_begin, Pos2End = pos2_end, Pos1LC = pos1lc, HasDataGrid = hasDataGrid, Marker = marker }); } //7.2 位于队列头时运行,归零 //D+0xE1+命令识标号(4B) public void SyncOrigin(Int32 marker) { CurrObjSys.CallFunctionEx( conn, FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.ID, ID, FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.CALL_PXX, new FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.Pack_SyncOrigin() { marker = marker }.ToBytes()); SyncOrders.Add(new SyncOrder_SyncOrigin() { Marker = marker }); } //7.3 位于队列头时运行,以速度运行至物理位置 //D+0xE2+横向脉冲位置(4B:int32,物理位置)+速度(4B:int32)+脉冲开关(1B)+命令识标号(4B) public void SyncRunTo(int pos1, UInt32 velocity, bool hasDataGrid, Int32 marker) { CurrObjSys.CallFunctionEx( conn, FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.ID, ID, FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.CALL_PXX, new FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.Pack_SyncRunto() { pos1 = pos1, velocity = velocity, hasDataGrid = hasDataGrid, marker = marker }.ToBytes()); SyncOrders.Add(new SyncOrder_SyncRunTo() { Pos1 = pos1, Velocity = velocity, HasDataGrid = hasDataGrid, Marker = marker }); } //7.3 位于队列头时运行,以速度运行至逻辑位置 //D+0xE3+横向脉冲位置(4B:int32,逻辑位置)+速度(4B:int32)+脉冲开关(1B)+命令识标号(4B) public void SyncRunToLC(int pos1lc, UInt32 velocity, bool hasDataGrid, Int32 marker) { CurrObjSys.CallFunctionEx( conn, FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.ID, ID, FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.CALL_PXX, new FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.Pack_SyncRuntoLC() { pos1 = pos1lc, velocity = velocity, hasDataGrid = hasDataGrid, marker = marker }.ToBytes()); SyncOrders.Add(new SyncOrder_SyncRunToLC() { Pos1 = pos1lc, Velocity = velocity, HasDataGrid = hasDataGrid, Marker = marker }); } //7.4 等待,ms //D+0xE4+毫秒数(4B:int32)+命令识标号(4B) public void SyncWait(int ms, Int32 marker) { CurrObjSys.CallFunctionEx( conn, FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.ID, ID, FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.CALL_PXX, new FLYAD7_OBJ_INTERFACE.DRIVE_MAN_INTERFACE.Pack_SyncWait() { ms = ms, marker = marker }.ToBytes()); SyncOrders.Add(new SyncOrder_SyncWait() { MS = ms, Marker = marker }); } #endregion #endregion public CorrectADsHandler CorrectADs { get; set; } #region 滞后处理 //一共有1.AD数据池(由timegrid提供) 1min //2.pos数据池(pos推送提供) 1min //4.当接收的grid事件数据。它有 (direction, grid_start,grid_len, systick ) //systick 就是结束的时间点。 当AD数据池出现了这个时间点 //pos数据池向前找。 pos 在 grid_start*posOfGrid 范围的数据。 //找到开始的systick 后,整合3个数据池的数据。 //5.最后代替 grid 推送出去。 int adlag = 0; /// <summary> /// ad滞后修正 单位ms /// </summary> public int ADLag { get { return adlag; } set { if (adlag != value) { adlag = value; NotifyPropertyChanged("ADLag"); } } } class CreateGridAdv { struct DataTimeUnit { public int data; public DateTime dt; public override string ToString() { return data.ToString() + " |" + dt.Ticks.ToString(); } } struct DataTimeUnit2 { public UInt16 istatus; public int pos; public DateTime dt; public override string ToString() { return pos.ToString()+"("+ istatus.ToString("X2") + ") |" + dt.ToString(); } } /// <summary> /// AD数据池时间间隔为1.28ms, 肯定最少有一个数据 /// </summary> RList<DataTimeUnit> ADPool = new RList<DataTimeUnit>(60000); /// <summary> /// pos 数据池, 肯定最少有一个数据 /// </summary> RList<DataTimeUnit> PosPool = new RList<DataTimeUnit>(60000); /// <summary> /// 输入端口 数据池, 肯定最少有一个数据 /// </summary> RList<DataTimeUnit2> IStatusPool = new RList<DataTimeUnit2>(60000); class GridData { public DIRECTION direction; public int pos_start; public int pos_len; public int marker; public DateTime time; public GridAdvEventHandler GridAdvFunc; } GridData mGridData = null; FlyAD7 flyad; public void Init(FlyAD7 flyad) { this.flyad = flyad; Clear(); } /// <summary> /// 添加ad数据,且判断数据量是否够触发事件 /// </summary> /// <param name="ads"></param> /// <param name="last_dt"></param> public void AddAD(int[] ads, DateTime last_dt) { //------------------------------------------------------------------------------------------ //AD数据添加 DateTime last_dt_last=DateTime.MinValue; if (ADPool.Count > 0) { last_dt_last = ADPool.Last().dt; } for (int i = 0; i < ads.Count(); i++) { DateTime dt; if (last_dt_last != DateTime.MinValue) { dt = last_dt - TimeSpan.FromTicks((long)(ads.Count()-i-1) * (last_dt - last_dt_last).Ticks / ads.Count()); } else { TimeSpan ts = TimeSpan.FromTicks((long)(TimeSpan.TicksPerMillisecond * (ads.Count() - 1 - i) * 1.28)); dt = last_dt - ts; } ADPool.RAdd(new DataTimeUnit() { data = ads[i], dt = dt }); } //------------------------------------------------------------------------------------------ //数据触发 if (mGridData != null) { if (last_dt >= mGridData.time)//够时间触发了!! { int start_idx; int end_idx; int start_pos; if (mGridData.direction == DIRECTION.FORWARD) { start_pos = mGridData.pos_start; } else { start_pos = mGridData.pos_start + mGridData.pos_len - 1; } GetIdxFromPosPool( start_pos,mGridData.time, out start_idx, out end_idx); List<GridAdvUnit> result = GetGridAdv(PosPool[start_idx].dt, mGridData.time); mGridData.GridAdvFunc(flyad, new GridAdvEventArgs() { direction = mGridData.direction, pos_start = mGridData.pos_start, pos_len = mGridData.pos_len, marker = mGridData.marker, dt_data = result }); mGridData = null; } } } public void AddPos(int pos, DateTime time) { if (PosPool.Count() > 0) { if (time < PosPool.Last().dt) { //异常 //把前面的都删除 PosPool.Clear(); } else if (time == PosPool.Last().dt) { return; } } PosPool.RAdd(new DataTimeUnit() { data = pos, dt = time }); } public void AddIStatus(UInt16 istatus, int pos, DateTime time) { if (IStatusPool.Count() > 0) { if (time < IStatusPool.Last().dt) { //异常 //把前面的都删除 IStatusPool.Clear(); } } IStatusPool.RAdd(new DataTimeUnit2() { istatus = istatus, pos=pos, dt = time }); //也添加到 PosPool AddPos(pos, time); } public void AddPos_Default(int pos, DateTime time) { if (PosPool.Count() == 0) { AddPos(pos, time); } } public void AddIStatus_Default(UInt16 istatus, int pos, DateTime time) { if (IStatusPool.Count() == 0) { AddIStatus(istatus, pos, time); } } public void Clear() { PosPool.Clear(); ADPool.Clear(); IStatusPool.Clear(); istatus_start_idx = -1; } /// <summary> /// 给定结束时间点,开始grid, 找到pos数据池 对应的开始序号 与 结束序号 /// </summary> /// <param name="start_pos">开始脉冲</param> /// <param name="endtime">结束时间点</param> /// <param name="start_idx">输出 pos数据池开始序号</param> /// <param name="end_idx">输出 pos数据池结束序号</param> /// <returns>false 发生在数据池前面, true成功获取</returns> bool GetIdxFromPosPool(int start_pos, DateTime endtime, out int start_idx, out int end_idx) { start_idx = -1; end_idx = -1; for (int i = 0; i < PosPool.Count(); i++) { int idx = PosPool.Count() - 1 - i; if (PosPool[idx].dt <= endtime) { //从这个点开始找 end_idx = idx; break; } } if (end_idx == -1) { //endtime 发生在过去很久以前 return false; } int pos_last = int.MinValue; int i_last = -1; for (int i = end_idx; i >= 0; i--) { int pos = PosPool[i].data; //if (pos == start_pos)//找到了!!!! //{ // pos_last = pos; // continue; //} if (pos_last == int.MinValue) { pos_last = pos; i_last = i; continue; } if (pos_last == pos) { continue; } if (Math.Abs(pos - start_pos) > Math.Abs(pos_last - start_pos)) { //越找越远, //上一个就是了 start_idx = i_last; return true; } else if (Math.Abs(pos - start_pos) == Math.Abs(pos_last - start_pos)) { //跨过了 start_idx = i_last; return true; } pos_last = pos; i_last = i; } //找完 start_idx = 0; return true; } /// <summary> /// 上一次查找istatus的序号 /// </summary> int istatus_start_idx = -1; /// <summary> /// 根据时间点,获取输入口状态 /// </summary> /// <param name="time"></param> /// <param name="start_idx">用于加快查找速度</param> /// <returns></returns> UInt16 GetIStatus(DateTime time) { int start_idx = istatus_start_idx; if (start_idx >= 0 && start_idx < IStatusPool.Count()) { for (int i = start_idx; i >= 0; i--) { int idx = i; if (time >= IStatusPool[idx].dt) { if (idx == start_idx)//有可能start_idx 位置 本来就在前面,看看后面再决定 { for (int j = start_idx + 1; j < IStatusPool.Count(); j++) { idx = j; if (time < IStatusPool[idx].dt) { //找到了 istatus_start_idx = idx - 1; return (UInt16)IStatusPool[istatus_start_idx].istatus; } } //找到最后 istatus_start_idx = idx; return (UInt16)IStatusPool[istatus_start_idx].istatus; } //找到 istatus_start_idx = idx; return (UInt16)IStatusPool[istatus_start_idx].istatus; } } } else { //没有以前的记录 //从列表的后面向前查找 for (int i = 0; i < IStatusPool.Count(); i++) { int idx = IStatusPool.Count() - 1 - i; if (time >= IStatusPool[idx].dt) { //找到 istatus_start_idx = idx; return (UInt16)IStatusPool[istatus_start_idx].istatus; } } } //在前面发生的!!! if (IStatusPool.Count() > 0) { istatus_start_idx = 0; return (UInt16)IStatusPool[istatus_start_idx].istatus; } else { //异常,一个数据都没有 istatus_start_idx = -1; return (UInt16)0xff; } } /// <summary> /// 根据时间点,获取输入口状态 /// </summary> /// <param name="time"></param> /// <param name="start_idx">用于加快查找速度</param> /// <returns></returns> UInt16 GetIStatus(DateTime time, out int istatus_idx) { UInt16 istatus = GetIStatus(time); istatus_idx = istatus_start_idx; return istatus; } /// <summary> /// 以 [idx,idx+1] 的比例, 给出 time 计算 pos /// </summary> /// <param name="time"></param> /// <param name="idx"></param> /// <returns></returns> int GetPos(DateTime time, int idx) { if (PosPool.Count() < 0) return int.MinValue; if (PosPool.Count() == 1) return PosPool[0].data; if (idx < 0) idx = 0; if (idx >= PosPool.Count()) idx = PosPool.Count() - 2; double d_pos = PosPool[idx].data - PosPool[idx + 1].data; TimeSpan ts = PosPool[idx].dt - PosPool[idx + 1].dt; double p = d_pos * (time - PosPool[idx + 1].dt).Ticks / ts.Ticks; return (int)(p + PosPool[idx + 1].data); } /// <summary> /// 获取时间对应的 位置点 /// </summary> /// <param name="dt"></param> /// <returns></returns> int GetPos(DateTime dt) { int index = -1; for (int i = 0; i < PosPool.Count(); i++)//从后面开始查找 { int idx = PosPool.Count() - 1 - i; if (PosPool[idx].dt <= dt) { //找到了 index = idx; break; } } if (index == PosPool.Count() - 1) { index = index -1; } else if(index == -1) { index = 0; } return GetPos(dt, index); } List<GridAdvUnit> GetGridAdv(DateTime start_dt, DateTime end_dt) { List<GridAdvUnit> result = new List<GridAdvUnit>(); for(int i=0;i<ADPool.Count();i++) { int idx = ADPool.Count()-1-i; if(ADPool[idx].dt<start_dt) { break; } else if(ADPool[idx].dt<=end_dt) { GridAdvUnit u = new GridAdvUnit(); u.dt = ADPool[idx].dt; u.ad = ADPool[idx].data; u.pos = GetPos(u.dt); u.istatus = GetIStatus(u.dt); result.Add(u); } } result.Reverse(); return result; } /// <summary> /// 记下grid /// </summary> /// <param name="direction">一幅grid数据 方向</param> /// <param name="pos_start">脉冲开始位置</param> /// <param name="pos_len">脉冲长度</param> /// <param name="marker">记录号</param> /// <param name="dt">时间点</param> /// <param name="func">当够数据,触发gridadv 回调</param> public void MarkGrid(DIRECTION direction, int pos_start, int pos_len, int marker, DateTime dt, GridAdvEventHandler func) { mGridData = new GridData() { direction = direction, pos_start = pos_start, pos_len = pos_len, marker = marker, time = dt, GridAdvFunc = func }; } #region 子功能,grid 的 istatus 变化 class gridistatuspush { public int istatus_no; public event GridIStatusEventHander GridIStatusEvent; public void Notify(object sender, GridIStatusEventArgs e) { if (GridIStatusEvent != null) { GridIStatusEvent.Invoke(sender, e); } } public bool IsNoEvent() { if (GridIStatusEvent == null) return true; else return false; } } List<gridistatuspush> mGridIStatusEventList = new List<gridistatuspush>(); /// <summary> /// 添加事件 /// </summary> /// <param name="istatus_no"></param> /// <param name="func"></param> public void GridIStatusEventAdd(int istatus_no, GridIStatusEventHander func) { var gs = from _g in mGridIStatusEventList where _g.istatus_no == istatus_no select _g; gridistatuspush g; if (gs.Count() > 0) { g = gs.First(); g.GridIStatusEvent += func; } else { g = new gridistatuspush() { istatus_no = istatus_no }; g.GridIStatusEvent += func; mGridIStatusEventList.Add(g); } } /// <summary> /// 删除事件 /// </summary> /// <param name="istatus_no"></param> /// <param name="func"></param> public void GridIStatusEventDel(int istatus_no, GridIStatusEventHander func) { var gs = from _g in mGridIStatusEventList where _g.istatus_no == istatus_no select _g; gridistatuspush g; if (gs.Count() > 0) { g = gs.First(); g.GridIStatusEvent -= func; if (g.IsNoEvent()) { mGridIStatusEventList.Remove(g); } } } /// <summary> /// 触发GridIStatusEvent事件 /// </summary> /// <param name="direction"></param> /// <param name="pos_start"></param> /// <param name="pos_len"></param> /// <param name="marker"></param> /// <param name="dt"></param> public void NotifyGridIStatusEvent(DIRECTION direction, int pos_start, int pos_len, int marker, DateTime dt) { if (mGridIStatusEventList.Count() <= 0) return; int start_idx; int end_idx; int start_pos; int end_pos; if (direction == DIRECTION.FORWARD) { start_pos = pos_start; end_pos = pos_start + pos_len - 1; } else { start_pos = pos_start + pos_len - 1; end_pos = pos_start; } bool ret = GetIdxFromPosPool( start_pos, dt, out start_idx, out end_idx); if (ret == false)//异常 return; DateTime start_dt = PosPool[start_idx].dt; DateTime end_dt = dt; foreach (gridistatuspush g in mGridIStatusEventList) { List<Range> data0; List<Range> data1; GetIStatusRange( g.istatus_no , start_dt, end_dt, direction, start_pos, end_pos, out data0, out data1); g.Notify(flyad, new GridIStatusEventArgs() { direction = direction, istatus_no = g.istatus_no, marker = marker, pos_start = pos_start, pos_len = pos_len, data_0 = data0, data_1 = data1 }); } } void GetIStatusRange( int istatus_no, DateTime start_dt, DateTime end_dt, DIRECTION direction, int start_pos, int end_pos, out List<Range> data0, out List<Range> data1) { data0 = new List<Range>(); data1 = new List<Range>(); istatus_start_idx = -1; int istatus_idx; UInt16 istatus = GetIStatus(start_dt, out istatus_idx); if (istatus_idx == -1)//异常,列表没有数据 { //全部都是1 if (direction == DIRECTION.FORWARD) data1.Add(new Range() { Begin = start_pos, End = end_pos }); else data1.Add(new Range() { Begin = end_pos, End = start_pos }); return; } bool istatus_no_b = Misc.MyBase.CHECKBIT(istatus, istatus_no - 1); Range r = new Range(); r.Begin = start_pos; for (int i = istatus_idx + 1; i < IStatusPool.Count(); i++) { istatus = IStatusPool[i].istatus; int pos = IStatusPool[i].pos; bool b = Misc.MyBase.CHECKBIT(istatus, istatus_no - 1); if (IStatusPool[i].dt >= end_dt) { //结束,这是最后!!! break; } else { if (b != istatus_no_b) { r.End = pos; if (istatus_no_b) data1.Add(r); else data0.Add(r); istatus_no_b = b; r = new Range(); r.Begin = pos; } } } r.End = end_pos; if (istatus_no_b) data1.Add(r); else data0.Add(r); if (direction == DIRECTION.FORWARD) { for (int i = 0; i < data0.Count(); i++) { data0[i].End -= 1; } for (int i = 0; i < data1.Count(); i++) { data1[i].End -= 1; } } else { for (int i = 0; i < data0.Count(); i++) { data0[i].End += 1; int t = data0[i].End; data0[i].End = data0[i].Begin; data0[i].Begin = t; } data0.Reverse(); for (int i = 0; i < data1.Count(); i++) { data1[i].End += 1; int t = data1[i].End; data1[i].End = data1[i].Begin; data1[i].Begin = t; } data1.Reverse(); } } #endregion } CreateGridAdv mCreateGridAdv = new CreateGridAdv(); public event GridAdvEventHandler GridAdvEvent; public static GridAdvUnit[] TimeUnit2PosUnit(Misc.DIRECTION direction, int pos_start, int pos_len, List<GridAdvUnit> dt_data) { GridAdvUnit[] pos_data = new GridAdvUnit[pos_len]; int ad_sum = 0; int ad_cnt = 0; int last_pos_idx = -1; DateTime st_dt = DateTime.MinValue; DateTime ed_dt = DateTime.MinValue; UInt16 istatus = 0xff; for (int i = 0; i < dt_data.Count(); i++) { int pos_idx = dt_data[i].pos - pos_start; if ((pos_idx < 0) || (pos_idx >= pos_len))//保存上一数据 { if (ad_cnt > 0) { GridAdvUnit u = new GridAdvUnit(); u.dt = st_dt.AddTicks((ed_dt - st_dt).Ticks / 2); u.ad = ad_sum / ad_cnt; u.pos = last_pos_idx + pos_start; u.istatus = istatus; pos_data[last_pos_idx] = u; } ad_sum = 0; ad_cnt = 0; istatus = 0xff; last_pos_idx = -1; st_dt = DateTime.MinValue; ed_dt = DateTime.MinValue; } else if (last_pos_idx == pos_idx)//还是同一个数据 { ad_sum += dt_data[i].ad; ad_cnt++; istatus &= dt_data[i].istatus; ed_dt = dt_data[i].dt; } else { if (last_pos_idx != -1)//保存上一个数据 { GridAdvUnit u = new GridAdvUnit(); u.dt = st_dt.AddTicks((ed_dt - st_dt).Ticks / 2); u.ad = ad_sum / ad_cnt; u.pos = last_pos_idx + pos_start; u.istatus = istatus; pos_data[last_pos_idx] = u; } last_pos_idx = pos_idx; st_dt = dt_data[i].dt; ed_dt = dt_data[i].dt; ad_sum = dt_data[i].ad; ad_cnt = 1; istatus = dt_data[i].istatus; } } if (last_pos_idx != -1)//保存上一个数据 { GridAdvUnit u = new GridAdvUnit(); u.dt = st_dt.AddTicks((ed_dt - st_dt).Ticks / 2); u.ad = ad_sum / ad_cnt; u.pos = last_pos_idx + pos_start; u.istatus = istatus; pos_data[last_pos_idx] = u; } return pos_data; } #endregion #region runto 推送 istatus 变化 public void GridIStatusEventAdd(int istatus_no, GridIStatusEventHander func) { mCreateGridAdv.GridIStatusEventAdd(istatus_no, func); } public void GridIStatusEventDel(int istatus_no, GridIStatusEventHander func) { mCreateGridAdv.GridIStatusEventDel(istatus_no, func); } #endregion } }