#define ENABLE_MULTI_TRANS
using AutoMapper;
using FlyADBase.Inc;
using FObjBase;
using GeneralGommunication;
using Newtonsoft.Json;
using NLog;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Linq;
namespace FlyADBase
{
public partial class FlyAd2021B2 : IFlyADClient
{
public Logger logger = NLog.LogManager.GetCurrentClassLogger();
#region MARKNO
const int MARKNO_SET_SAVE = 4;
const int MARKNO_PARAM_APPLY = 5;
#endregion
#region INotifyPropertyChanged 成员
protected void NotifyPropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
#endregion
#region IFlyADClient property
///
/// 连接成功
///
public bool IsConnected { get; private set; }
///
/// 重连次数
///
public int ConnectCnt { get; private set; }
///
/// 已经从AD盒获取全部当前数据
///
public bool IsReady { get; private set; }
///
/// 通过判断systick,判断AD盒是否发生重启;
/// BeResetTime为上一次被复位时间, 此为 电脑的时间
///
public DateTime BeResetTime { get; private set; }
///
/// 只要connect成功,获取systick被复位,都会从AD盒设备读取参数;
/// 否则, 设置参数 到 AD盒
///
public bool IsReadParamFromDev { get; set; }
#endregion
#region IFlyAD property
///
/// AD盒地址, 当为 TCP通讯时,为 192.168.251.200:20020;
/// 当为 串口通讯时, 为 COM6
///
public string Addr { get; set; } = "192.168.251.10:20006";
///
/// 从flyad7 获取 的systick 转换的时间
///
public DateTime Now { get; private set; }
///
/// AD盒版本号 版本1 没有systick;版本2 有systick;
/// 通过通讯读取
///
public int Version { get; } = 2021;
///
/// 硬件版本,设置的!!!
///
public int HardwareVersion { get; set; } = 2021;
///
/// 脉冲
///
public int Position { get; private set; }
///
/// 速度 pps
///
public int Speed { get; private set; }
///
/// 纵向脉冲,也叫主轴脉冲
///
public int Position2 { get; private set; }
///
/// 纵向速度
///
public int Speed2 { get; private set; }
///
/// 1000ms从AD卡获取(或推送)1个AD值。此AD值只用于调试,定点
///
public int AD { get; private set; }
///
/// 1000ms从AD卡获取(或推送)1个AD值。此AD值只用于调试,定点
///
public int AD2 { get; private set; }
///
/// AD值最大值 ,恒定返回65535
///
public int ADMax => 0xFFFF;
///
/// 输入口状态,只有12位有效
///
public UInt16 IStatus { get; private set; } = 0xffff;
///
/// 输出口状态,只有4位有效
///
public UInt16 OStatus { get; private set; } = 0xffff;
///
/// 电机类型
///
public MOTORTYPE MotorType { get; set; } = MOTORTYPE.SERVO;
///
/// 脉冲/grid, 最大1000个grid
///
private UInt16 posofgrid = 10;
///
/// 脉冲/grid, 最大1000个grid
///
public UInt16 PosOfGrid
{
get { return posofgrid; }
set
{
if (value < 1)
value = 1;
if (posofgrid != value)
posofgrid = value;
}
}
///
/// 脉冲比例 分母(电机脉冲)
///
public UInt16 Ratio01 { get; set; } = 4;
///
/// 脉冲比例 分子(编码器脉冲)
///
public UInt16 Ratio02 { get; set; } = 1;
///
/// 脉冲平移(0位处脉冲值)
///
public Int16 PosOffset { set; get; }
///
/// 手动速度 pps
///
public UInt32 JogVelocity { get; set; } = 5000;
///
/// runto 速度 pps
///
public UInt32 Velocity { get; private set; } = 8000;
///
/// 开始速度 pps
///
public UInt32 SVelocity { get; private set; } = 200;
///
/// 加速时间 ms
///
public UInt32 ATime { get; private set; } = 300;
///
/// 减速时间 ms
///
public UInt32 DTime { get; private set; } = 200;
///
/// 归0 第1段速 pps
///
public UInt32 HVelocity1 { get; private set; } = 4000;
///
/// 归0 第2段速 pps
///
public UInt32 HVelocity2 { get; private set; } = 500;
///
/// 使用码区状态
///
public AREA_STATUS AreaStatus { get; private set; }
///
/// 使用码区出错码
///
public AREA_ERR AreaRet { get; private set; }
///
/// 序列码byte[6], AD盒只需要 6个byte,但flysecute 软件需要 7byte, code[6]=0x06
///
public byte[] Code { get; private set; } = new byte[7];
///
/// 系统剩余时间
///
public int Surplus { get; private set; } = 10000;
///
/// 系统授权码access[8]
///
public byte[] Access { get; private set; } = new byte[8];
///
/// 当前运行指令
///
public DRIVE_MAN_ORDER DriveOrder { get; set; } = DRIVE_MAN_ORDER.IDLE;
///
/// 之前运行动作的状态
///
public DRIVE_MAN_STATUS DriveStatus { get; set; } = DRIVE_MAN_STATUS.STOP;
///
/// timegrid 事件; 大约0.1s更新一次
/// ad值不会被机架修正
///
public event TimeGridEventHandler TimeGridEvent;
///
/// runto 中,每经过1个grid 推送数据
///
public event MiniGridEventHandler MiniGridEvent;
///
/// 输入状态改变事件
///
public event IStatusChangedEventHandler IStatusChangedEvent;
///
/// 指令状态改变事件
///
public event DriveStatusChangedEventHandler DriveStatusChangedEvent;
///
/// 脉冲1改变事件
///
public event PositionChangedEventHandler PositionChangedEvent;
///
/// 脉冲2改变事件
///
public event PositionChangedEventHandler Position2ChangedEvent;
#endregion
IsReadyContext isReadyContext = new IsReadyContext();
SysTickContext sysTickContext = new SysTickContext();
CalSpeed calSpeed = new CalSpeed();
public FlyAd2021B2Core Core => core;
IGeneralComm comm;
FlyAd2021B2Core core;
///
/// 不设置服务器
///
bool bShieldSetValueEx;
///
/// 最后一次动作时间
///
DateTime orderGetRunResultTime;
DateTime orderGetEnc1Time;
DateTime orderGetEnc2Time;
DateTime orderGetInTime;
static string[] propertyName_save;
List pushEventArgs = new List();
string defaultPath = "flyad.json";
string jsonDbPath;
static FlyAd2021B2()
{
propertyName_save = FlyAd2021JsonDb.GetMemberNames();
}
public FlyAd2021B2()
{
constructor();
advConstructor();
}
void constructor()
{
Now = DateTime.Now;
sysTickContext.BeReseted += () => BeResetTime = DateTime.Now;
core = new FlyAd2021B2Core();
core.logger = logger;
core.Csm.StartMeasure();
//注册AD2021版的发送动作,把数据通过 comm模块发送出去
core.SendMsgEvent += (s,msg) =>
{
comm?.Write(msg);
};
core.PushDataEvent += (sender, e) =>
{
//这个线程非主线程, 数据接收完,应该快速返回。
//事件触发,都放在主线程操作。
//要有线程锁!!!!!
lock (pushEventArgs)
{
pushEventArgs.Add(e);
}
};
core.PushRunResultEvent += (sender, e) =>
{
//这个线程非主线程, 数据接收完,应该快速返回。
//事件触发,都放在主线程操作。
lock (pushEventArgs)
{
pushEventArgs.Add(e);
}
};
//避免推送太快,全部推送事件统一周期处理
PollModule.Current.Poll_Config(onPoll_PushEvent, TimeSpan.FromSeconds(0.1));
Misc.BindingOperations.SetBinding(core, nameof(core.IsConnected), this, nameof(IsConnected));
Misc.BindingOperations.SetBinding(isReadyContext, nameof(isReadyContext.IsReady), this, nameof(IsReady));
this.PropertyChanged += FlyAd2021_PropertyChanged;
//每隔一个小时,改变剩下时间
PollModule.Current.Poll_Config(() =>
{
if (!IsConnected)
return;
if (Surplus < 60000)
{
if (Surplus > 0)
{
Surplus--;
//TODO
}
}
}, TimeSpan.FromMinutes(60));
//1分钟,脉冲都没改变, 发送一次获取
PollModule.Current.Poll_Config(() =>
{
if (!IsConnected)
return;
if (Now - mTimeGridAdvHelper.positionChangedTime > TimeSpan.FromSeconds(60))
{
if (Now - orderGetEnc1Time > TimeSpan.FromSeconds(60))
GetEnc1();
}
if (Now - mTimeGridAdvHelper.position2ChangedTime > TimeSpan.FromSeconds(60))
{
if (Now - orderGetEnc2Time > TimeSpan.FromSeconds(60))
GetEnc2();
}
if (Now - mTimeGridAdvHelper.istatusChangedTime > TimeSpan.FromSeconds(60))
{
if (Now - orderGetInTime > TimeSpan.FromSeconds(60))
GetIn();
}
}, TimeSpan.FromSeconds(1));
//更新线速度
PollModule.Current.Poll_Config(() =>
{
if (calSpeed.Cal(Now, out int speed1, out int speed2))
{
Speed = speed1;
Speed2 = speed2;
}
}, TimeSpan.FromSeconds(0.5));
//当状态为Running时,且每秒脉冲没变,需要 查 当前的状态, 也许Stop状态少推送了
PollModule.Current.Poll_Config(() =>
{
if (!IsConnected)
return;
if (DriveStatus != DRIVE_MAN_STATUS.RUNNING)
return;
if (Now - mTimeGridAdvHelper.positionChangedTime > TimeSpan.FromSeconds(3))
{
//3秒内脉冲没改变
if (Now - orderGetRunResultTime >= TimeSpan.FromSeconds(3))//每3秒检查一次
{
GetRunResult();
}
}
}, TimeSpan.FromSeconds(1));
}
void GetRunResult()
{
orderGetRunResultTime = Now;
//不需要处理回复数据。 它会作为事件被处理
core.GetRunResult(null, null);
}
void GetEnc1()
{
orderGetEnc1Time = Now;
core.GetEnc1((asyncContext, _retData) =>
{
PollModule.Current.Dispatcher.BeginInvoke(new Action