using FObjBase;
using Misc;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
namespace FlyADBase
{
public partial class FlyAD7 : IFlyADClientAdv
{
NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
///
/// 通过脉冲计算速度,不使用AD盒的输出
///
public bool IsCalSpeed { get; set; }// = true;
private int gridsmooth = 0;
///
/// grid数据平滑
///
public int GridSmooth
{
get { return gridsmooth; }
set
{
if (value < 0)
value = 0;
if (gridsmooth != value)
{
gridsmooth = value;
}
}
}
///
/// 机架总长
///
public int PosLen { get; set; } = 8900;
///
/// Speed1 = Velocity * Speed1Scale
///
public double Speed1Scale => (double)Ratio02 / Ratio01;
///
/// 动作完成
///
public bool IsFinish { get; set; }
int pos1_last_for_speed = int.MinValue;
int pos2_last_for_speed = int.MinValue;
Stopwatch sw_calSpeed = new Stopwatch();
void constructor2()
{
fGrid.SetSize(PosLen / PosOfGrid);
mTimeGridAdvHelper.Init();
this.PropertyChanged += FlyAD7_PropertyChanged1;
sw_calSpeed.Start();
//更新线速度
PollModule.Current.Poll_Config(PollModule.POLL_CONFIG.ADD,
() =>
{
//速度是错了,需要自己计算
double scale = 1000 / sw_calSpeed.ElapsedMilliseconds;
sw_calSpeed.Restart();
int speed = Speed;
int speed2 = Speed2;
if (pos1_last_for_speed != int.MinValue)
{
speed = (int)((Position - pos1_last_for_speed) * scale);
}
pos1_last_for_speed = Position;
if (pos2_last_for_speed != int.MinValue)
{
speed2 = (int)((Position2 - pos2_last_for_speed) * scale);
}
pos2_last_for_speed = Position2;
if (IsCalSpeed)
{
Speed = speed;
Speed2 = speed2;
}
}, TimeSpan.FromSeconds(1));
}
private void FlyAD7_PropertyChanged1(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
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);
}
}
}
}
}
}
void Init2()
{
mTimeGridAdvHelper.Clear();
preTimeGrid_start = DateTime.MinValue;
preTimeGrid_end = DateTime.MinValue;
}
///
/// Runto(0), 不同于 Backward
///
public void RuntoMin()
{
Runto(0);
}
///
/// Runto(PosLen), 不同于 Forward
///
public void RuntoMax()
{
Runto(PosLen);
}
///
/// 设置输出
///
///
///
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));
}
}
///
/// 正反转 grid数据 缓存区
///
class SGrid
{
public 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();
///
/// 从正反缓存区, 获取grid数据
///
/// 方向, 只有 正,反
/// grid 开始位置
/// grid 长度
/// grid 数据
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];
}
}
CorrectADs?.Invoke(direction, grid_start, dat);
return;
}
///
/// 从正反缓存区, 获取全部grid数据
///
/// 方向, 只有 正,反
/// grid 数据
public void GetGrid(Misc.DIRECTION direction, out int[] dat)
{
GetGrid(direction, 0, fGrid.data[0].Length, out dat);
}
///
/// 机架修正
///
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 推送出去。
///
/// ad滞后修正 单位ms
///
public int ADLag { get; set; }
public event TimeGridAdvEventHandler TimeGridAdvEvent;
TimeGridAdvHelper mTimeGridAdvHelper = new TimeGridAdvHelper();
///
/// 上一次接收到timegrid 的时间
///
DateTime preTimeGrid_start;
DateTime preTimeGrid_end;
#endregion
#region runto 推送 istatus 变化
public void GridIStatusEventAdd(int istatus_no, GridIStatusEventHander func)
{
mTimeGridAdvHelper.GridIStatusEventAdd(istatus_no, func);
}
public void GridIStatusEventDel(int istatus_no, GridIStatusEventHander func)
{
mTimeGridAdvHelper.GridIStatusEventDel(istatus_no, func);
}
#endregion
void advGetPos1AD1(int ad)
{
mTimeGridAdvHelper.AddPos_Default(Position, Now);
if (CorrectADs != null)
{
ad = CorrectAD(Position / PosOfGrid, ad);
}
AD = ad;
}
void advGetIo()
{
mTimeGridAdvHelper.AddIStatus_Default(IStatus, Position, Now);
}
void advPushPos1()
{
if (Version == 1)
{
mTimeGridAdvHelper.AddPos(Position, DateTime.Now);
}
else
{
mTimeGridAdvHelper.AddPos(Position, Now);
}
}
void advPushAd(int ad)
{
if (CorrectADs != null)
ad = CorrectAD(Position / PosOfGrid, ad);
AD = ad;
}
void advPushIo(int pos1)
{
mTimeGridAdvHelper.AddIStatus(IStatus, pos1, Now);
}
void advPushTimeGrid(DateTime dt, int[] data)
{
double ts_ms = 1.28;
long ticks = (long)((ts_ms * data.Length) * TimeSpan.TicksPerMillisecond);
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];
}
}
}
}
#region 高级 timegrid
//if (preTimeGrid_start != DateTime.MinValue)
//{
// if (TimeGridAdvEvent != null)
// {
// var gridAdvUnits = mTimeGridAdvHelper.GetGridAdv(preTimeGrid_start, preTimeGrid_end);
// if (CorrectADs != null)
// {
// foreach (var gridAdvUnit in gridAdvUnits)
// {
// gridAdvUnit.ad = CorrectAD(gridAdvUnit.pos / PosOfGrid, gridAdvUnit.ad);
// }
// }
// TimeGridAdvEvent(this, new TimeGridAdvEventArgs() { Data = gridAdvUnits });
// }
//}
mTimeGridAdvHelper.AddAD(data, dt - TimeSpan.FromMilliseconds(ADLag), ts_ms);
if (pushGridInfo != null)
{
if (TimeGridAdvEvent != null)
{
var gridAdvUnits = mTimeGridAdvHelper.GetTimeGridAdv(pushGridInfo.dt, pushGridInfo.direction, pushGridInfo.grid_start, pushGridInfo.grid_len, PosOfGrid);
if (CorrectADs != null)
{
foreach (var gridAdvUnit in gridAdvUnits)
{
gridAdvUnit.ad = CorrectAD(gridAdvUnit.pos / PosOfGrid, gridAdvUnit.ad);
}
}
TimeGridAdvEvent(this,
new TimeGridAdvEventArgs() {
Data = gridAdvUnits,
Marker = pushGridInfo.marker,
Direction = pushGridInfo.direction
});
}
pushGridInfo = null;
}
//preTimeGrid_start = dt;
//preTimeGrid_end = dt + TimeSpan.FromTicks(ticks);
#endregion
}
///
/// 转为 grid 数据
///
///
///
/// 测试功能,让ad值滞后
public void ToGrid(IEnumerable gridAdvUnits, out int[] dat, int adLag=0)
{
dat = mTimeGridAdvHelper.ToGrid(gridAdvUnits, PosOfGrid, SGrid.GRID_MAX_SIZE, adLag);
}
class PushGridInfo
{
public DateTime dt;
public int marker;
public DIRECTION direction;
public int grid_start;
public int grid_len;
}
PushGridInfo pushGridInfo=null;
void advPushGrid(DateTime dt, int marker, DIRECTION direction, int grid_start, int[] data)
{
mTimeGridAdvHelper.NotifyGridIStatusEvent(
direction, grid_start * PosOfGrid, data.Length * PosOfGrid, marker, dt, this);
int index = (direction == Misc.DIRECTION.BACKWARD) ? 1 : 0;
if (grid_start >= fGrid.data[index].Length)
return;
int grid_end = data.Length + grid_start - 1;
if (grid_end >= fGrid.data[index].Length)
grid_end = fGrid.data[index].Length - 1;
int len = grid_end - grid_start + 1;
Array.Copy(data, 0, fGrid.data[index], grid_start, len);
//清空其它数据
for (int i = 0; i < 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)
{
CorrectADs?.Invoke(direction, grid_start, data);
}
if (data.Length <= 1)
{
logger.Error("GRID 数据太少, 不触发 TimeGridAdv");
return;
}
pushGridInfo = new PushGridInfo()
{
dt = dt,
marker = marker,
direction = direction,
grid_start = grid_start,
grid_len = data.Length
};
}
void advPushMiniGrid(DIRECTION direction, int grid_start, int[] data)
{
int index = (direction == Misc.DIRECTION.BACKWARD) ? 1 : 0;
if (grid_start >= fGrid.data[index].Length)
return;
int grid_end = data.Length + grid_start - 1;
if (grid_end >= fGrid.data[index].Length)
grid_end = fGrid.data[index].Length - 1;
int len = grid_end - grid_start + 1;
Array.Copy(data, 0, fGrid.data[index], grid_start, len);
//清空后面的数据
if (direction == Misc.DIRECTION.BACKWARD)
{
for (int i = 0; i < 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;
}
}
CorrectADs?.Invoke(direction, grid_start, data);
}
int CorrectAD(int grid, int ad)
{
int[] d = new int[1];
d[0] = ad;
CorrectADs(Misc.DIRECTION.FIX, grid, d);
return d[0];
}
}
}