using System;
using System.Collections.Concurrent;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading;
using PaintDotNet.Base.SettingModel;
namespace StageController
{
public class M3HController : AxisController
{
#region Com Connection
private SerialPort m_serialPort;
private string m_portName;
private int m_baudRate;
#endregion
public override bool IsMoving => StateX > 1 || StateY > 1 || StateZ > 1;
///
/// 等待平台停稳
///
public override void WaitMoveDone()
{
// Console.WriteLine(string.Format("{0} {1} {2}", StateX, StateY, StateZ));
do Thread.Sleep(30);
while (IsMoving && IsOpen);
Thread.Sleep(100);
}
public M3HController() : base()
{
m_cmdQueueM = new ConcurrentQueue();
CommandBase.AddReceivedHandle(typeof(CommandAllPosition), new Action(PositionUpdate));
CommandBase.AddReceivedHandle(typeof(CommandVersion), new Action(VersionUpdate));
}
public override object LoadingStageModel
{
set
{
var m_loadingStageModel = value as LoadingStageModel;
m_portName = m_loadingStageModel.BaseSetPort;
m_baudRate = m_loadingStageModel.BaseSetBps;
base.LoadingStageModel = value;
m_workSpeedXY = m_loadingStageModel.items[m_loadingStageModel.WorkSpeedSelect].LSpeed;
m_workSpeedZ = m_loadingStageModel.items[m_loadingStageModel.WorkSpeedSelect].ZSpeed;
}
}
#region Open Close
///
/// 平台是否正常开启
///
public override bool IsOpen
{
get => m_running;
}
public override string Version { get; internal set; }
// TODO: 此函数测试期间使用
public override string Open()
{
try
{
if (!m_running)
Open(m_portName, m_baudRate, Parity.None, 8, StopBits.One);
return "";
}
catch (Exception ex)
{
return ex.Message;
}
}
public override void Open(string portName, int baudRate, Parity parity, int dataBits, StopBits stopBits)
{
if (m_serialPort == null || !m_serialPort.IsOpen)
{
m_serialPort = new SerialPort(portName, baudRate, parity, dataBits, stopBits);
m_serialPort.Encoding = Encoding.ASCII;
m_serialPort.ReadTimeout = 500;
m_serialPort.DataReceived += new SerialDataReceivedEventHandler(SerialPort_DataReceived);
m_serialPort.Open();
var cmd = new CommandGlobal(M3H.ControlType.F);
cmd.Send();
Thread.Sleep(100);
if (cmd.State == 1)
throw new Exception("Connection Failed!");
CommandBase.SerialPort = m_serialPort;
}
if (!m_running)
{
m_cmdQueueM = new ConcurrentQueue();
m_curCommand = null;
base.Open();
ResetParameter();
}
}
public override void Close()
{
if (IsOpen)
{
FreeStage();
FreeZ();
_closing = true;
}
}
#endregion
// 接收串口返回数据
private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
if (!m_running) return;
string recvData = ((SerialPort)sender).ReadExisting();
m_curCommand.Receive(recvData);
}
#region Command Runtime
private CommandBase m_curCommand = null;
///
/// 发送试错次数
///
private int m_retryCount = 3;
protected override void Process()
{
base.Process();
#region 执行当前指令
if (m_curCommand != null)
{
switch (m_curCommand.State)
{
case -1: //error:停止当前运动控制服务.
if (m_curCommand.SendCount > m_retryCount) CommandError();
m_curCommand.Send();
return;
case 1: //等待平台应答
if (m_curCommand.IsTimeout)
{
if (_timeoutTimes > 1)
CommandTimeout();
m_curCommand = null;
_timeoutTimes++;
}
break;
case 2: //完成应答处理
m_curCommand = null; _timeoutTimes = 0;
break;
case 0: //初始值, 此处不应该出现0的情况
CommandError();
break;
default:
break;
}
}
#endregion
#region 开始一个新指令,
if (m_curCommand == null)
{
if (m_cmdQueueM.IsEmpty && _closing)
{
m_running = false;
_closing = false;
return;
}
if (m_cmdQueueM.IsEmpty || !m_cmdQueueM.TryDequeue(out m_curCommand))
{ // 空闲时间刷新位置
//m_curCommand = new CommandAllPosition();
}
if (m_curCommand != null && !m_curCommand.Send())
{ //指令发送失败
CommandError();
}
}
#endregion
}
protected override void CommandError()
{
Dispose();
base.CommandError();
}
private void Dispose()
{
m_running = false;
m_serialPort.Close();
m_curCommand = null;
m_currentMoveflow?.Stop();
}
int _timeoutTimes = 0;
protected override void CommandTimeout()
{
Dispose();
base.CommandTimeout();
}
public override void RefreshPosition()
{
if (m_cmdQueueM.Any(e => e is CommandAllPosition))
return;
AddCommand(new CommandAllPosition());
}
private void VersionUpdate(CommandBase cmd)
{
Version = (cmd as CommandVersion).Version;
}
#endregion
#region Moveflow
private bool IsSimulation = false;
///
/// 平台中心位置
///
protected override int _centerX => 106500;
///
/// 平台中心位置
///
protected override int _centerY => 73500;
///
/// 正边界
///
const int LIMIT_P = (int)Border.F;
private bool _closing;
///
/// 开始中心移动流程
///
public override void ToCenter()
{
if (IsSimulation) return;
base.ToCenter();
}
protected override void ClearPosXY()
{
base.ClearPosXY();
AddCommand(new CommandAllPosition());
}
///
/// 开始复位流程
///
public override void ResetStage(Action actDone)
{
if (IsSimulation)//模拟模式
{
ClearPosXY();
actDone();
return;
}
new System.Threading.Tasks.Task(new Action(() =>
{
while (m_cmdQueueM.Count > 0)
{
Thread.Sleep(100);
}
StartResetStage(actDone);
})).Start();
}
private void StartResetStage(Action actDone)
{
var mf = StartMoveflow();
mf.Add(() =>
{
_LockStage();
},
null
);
mf.Add(() =>
{
this.Slide(AxisType.X, false);
this.Slide(AxisType.Y, false);
},
() =>
{
RefreshPosition();
return IsLimitXY();// m_AxisX.Limit == LIMIT_N && m_AxisY.Limit == LIMIT_N;
});
mf.Add(() =>
{
ClearPosXY();
},
null);
mf.Start();
mf.OnMoveflowDone += actDone;
m_currentMoveflow = mf;
}
public override void ZScan(double start, double steplen, int times, Action shoot, Action package, Action actDone)
{
if (IsSimulation)//模拟模式
return;
base.ZScan(start, steplen, times, shoot, package, actDone);
}
#endregion
#region Speed
int m_workSpeedXY;
int m_workSpeedZ;
public override void SetWorkspeedXY()
{
SetSpeedXY(m_workSpeedXY);
SetSpeedZ(m_workSpeedZ);
}
#endregion
public void ResetParameter()
{
AddCommand(new CommandAllPosition());
AddCommand(new CommandParameter() { AxisSelect = 'x' });
AddCommand(new CommandParameter() { AxisSelect = 'y' });
// AddCommand(new CommandParameter() { AxisSelect = 'z', LockOrFree = 'F' }); // z轴参数下发不识别
AddCommand(new CommandVersion());
}
///
/// 拼图模式
///
public override void SetMergeMode(bool isMerge)
{
if (isMerge)
AddCommand(new CommandGlobal(M3H.ControlType.P));
else
AddCommand(new CommandGlobal(M3H.ControlType.Q));
}
///
/// 启用/禁用摇杆
///
/// 摇杆可用
public override void SetRockerEnabel(bool isAvailable)
{
}
}
}