Commit f551821f authored by 潘栩锋's avatar 潘栩锋 🚴

优化 GComm 线程安全

parent e4483cf2
......@@ -21,7 +21,7 @@ namespace GeneralGommunication
/// </summary>
public abstract class Dev7E:IDev7E
{
protected Logger logger = NLog.LogManager.GetCurrentClassLogger();
public Logger logger = NLog.LogManager.GetCurrentClassLogger();
public event PropertyChangedEventHandler PropertyChanged;
......@@ -43,14 +43,11 @@ namespace GeneralGommunication
/// <summary>
/// 有数据需要发送
/// </summary>
public event SendMsgEventHander SendMsgEvent;
public event SendDataEventHander SendMsgEvent;
/// <summary>
/// 对于全部 有返回的函数调用,都使用Dispatcher,使线程同步
/// </summary>
public Dispatcher Dispatcher;
List<byte> currPack = new List<byte>();
......@@ -79,22 +76,32 @@ namespace GeneralGommunication
/// </summary>
protected int PrefixIndex { get; set; } = 1;
/// <summary>
/// 对于全部 有返回的函数调用,都使用Dispatcher,使线程同步
/// </summary>
Dispatcher dispatcher;
DispatcherTimer timerTimeOut;//等待回复超时
public Dev7E()
{
Transactions = new List<COMMREQ_TransactionBase>();
stopwatch_timeOut = new Stopwatch();
timerTimeOut = new DispatcherTimer();
timerTimeOut.Interval = TimeSpan.FromSeconds(0.5);
timerTimeOut.Tick += TimerTimeOut_Tick;
timerTimeOut.Start();
}
#region 测量
#endregion
/// <summary>
/// 发送指令的超时判断
/// </summary>
public void OnPoll_TimeOut()
private void TimerTimeOut_Tick(object sender, EventArgs e)
{
//TODO 要处理 TimeOut / ParseFuncPack / GetSendMsg 线性同步问题
if (!IsConnected)
......@@ -117,17 +124,14 @@ namespace GeneralGommunication
if (retryCnt >= 3)
{
//已经重试了3次,放弃
IsConnected = false;
currTran = null;
//清空 指令队列
Transactions.Clear();
ResetMsg();
return;
}
else
{
//再发一次指令
SendMsgEvent?.Invoke(this);
byte[] msg = GetSendMsg();
SendMsgEvent?.Invoke(this,msg);
}
}
......@@ -389,9 +393,9 @@ namespace GeneralGommunication
//调用回调
if (tran.asyncDelegate != null)
{
if (Dispatcher != null)//线程同步执行
if (dispatcher != null)//线程同步执行
{
Dispatcher.BeginInvoke(tran.asyncDelegate, tran.asyncContext, retData);
dispatcher.BeginInvoke(tran.asyncDelegate, tran.asyncContext, retData);
}
else
{
......@@ -408,7 +412,8 @@ namespace GeneralGommunication
if (Transactions.Count() > 0)
{
//队列还有需要发送的指令,通知外部获取指令发送
SendMsgEvent?.Invoke(this);
byte[] msg = GetSendMsg();
SendMsgEvent?.Invoke(this,msg);
}
return true;
......@@ -492,9 +497,9 @@ namespace GeneralGommunication
//调用回调
if (tran.asyncDelegate != null)
{
if (Dispatcher != null)//线程同步执行
if (dispatcher != null)//线程同步执行
{
Dispatcher.BeginInvoke(tran.asyncDelegate, tran.asyncContext, retData);
dispatcher.BeginInvoke(tran.asyncDelegate, tran.asyncContext, retData);
}
else
{
......@@ -507,9 +512,9 @@ namespace GeneralGommunication
//完成, 全部回复
if (_tran.asyncDelegate != null)
{
if (Dispatcher != null)//线程同步执行
if (dispatcher != null)//线程同步执行
{
Dispatcher.BeginInvoke(_tran.asyncDelegate, _tran.asyncContext, _tran);
dispatcher.BeginInvoke(_tran.asyncDelegate, _tran.asyncContext, _tran);
}
else
{
......@@ -526,7 +531,8 @@ namespace GeneralGommunication
if (Transactions.Count() > 0)
{
//队列还有需要发送的指令,通知外部获取指令发送
SendMsgEvent?.Invoke(this);
byte[] msg = GetSendMsg();
SendMsgEvent?.Invoke(this,msg);
}
return true;
......@@ -587,7 +593,8 @@ namespace GeneralGommunication
if (currTran == null)
{
//当前没有指令正在发送
SendMsgEvent?.Invoke(this);
byte[] msg = GetSendMsg();
SendMsgEvent?.Invoke(this,msg);
}
}
}
......@@ -628,7 +635,9 @@ namespace GeneralGommunication
if (currTran == null)
{
//当前没有指令正在发送
SendMsgEvent?.Invoke(this);
byte[] msg = GetSendMsg();
SendMsgEvent?.Invoke(this, msg);
}
}
}
......

using NLog;
using System;
using System.Collections.Generic;
using System.ComponentModel;
......@@ -12,6 +13,7 @@ namespace GeneralGommunication
{
public class GComm_SerialPort : IGeneralComm
{
public Logger logger;// = NLog.LogManager.GetCurrentClassLogger();
/// <summary>
/// 串口号
/// </summary>
......@@ -68,6 +70,7 @@ namespace GeneralGommunication
{
var buffer = buf.ToArray();
sp.Write(buffer, 0, buffer.Length);
logger?.Debug($"serial W len={buffer.Length}");
ErrMsg = null;
}
catch (Exception e)
......@@ -183,6 +186,7 @@ namespace GeneralGommunication
return;
byte[] recBuf = new byte[bytesToRead];
sp.Read(recBuf, 0, bytesToRead);
logger?.Debug($"serial R len={bytesToRead}");
DataReceived?.Invoke(this, recBuf);
}
......
This diff is collapsed.
......@@ -51,14 +51,17 @@
<Compile Include="GComm_TcpClient.cs" />
<Compile Include="IDev7E.cs" />
<Compile Include="IGeneralComm.cs" />
<Compile Include="IModbusAsciiAsync.cs" />
<Compile Include="IModbusBase.cs" />
<Compile Include="ModbusAscii.cs" />
<Compile Include="ModbusAsciiAsync.cs" />
<Compile Include="ModbusAsciiAsyncConnector.cs" />
<Compile Include="ModbusRtuServer.cs" />
<Compile Include="ModbusAsciiServer.cs" />
<Compile Include="ModbusRtuAsync.cs" />
<Compile Include="ModbusRtu.cs" />
<Compile Include="ModbusServer.cs" />
<Compile Include="Modbus_Transaction.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Protocol7ECommon.cs" />
<Compile Include="ProtocolModbusCommon.cs" />
......
......@@ -9,9 +9,10 @@ namespace GeneralGommunication
{
public interface IDev7E : INotifyPropertyChanged
{
#region 测量通讯速度
/// <summary>
/// 通讯速度测量模块
/// </summary>
CommSpeedMeasuring Csm { get; }
#endregion
/// <summary>
/// 包出错次数
......@@ -27,13 +28,9 @@ namespace GeneralGommunication
/// <summary>
/// 有数据需要发送
/// </summary>
event SendMsgEventHander SendMsgEvent;
event SendDataEventHander SendMsgEvent;
#region 模块运行接口
/// <summary>
/// 超时判断,长时间收不到数据,会触发,0.5s调用一次
/// </summary>
void OnPoll_TimeOut();
/// <summary>
/// 在接收事件中调用;
......@@ -41,12 +38,6 @@ namespace GeneralGommunication
/// </summary>
/// <param name="recBuf"></param>
void RecMsg(byte[] recBuf);
/// <summary>
/// 获取 发送队列 第1条msg
/// </summary>
/// <returns></returns>
byte[] GetSendMsg();
/// <summary>
/// 复位全部状态,通常由于通讯模块检测到连接断开导致的
......@@ -68,6 +59,11 @@ namespace GeneralGommunication
/// <param name="retData"></param>
public delegate void CallBackHandler(object asyncContext, object retData);
public class CallBackHandlerContext
{
public CallBackHandler asyncDelegate;
public object asyncContext;
}
public class CallBackAttribute : Attribute
{
......@@ -149,10 +145,28 @@ namespace GeneralGommunication
var c = (byte)command;
bytes.Add(c);
}
else if (command is UInt16)
{
var c = (UInt16)command;
var bs = BitConverter.GetBytes(c);
bytes.AddRange(bs);
}
else if (command is UInt32)
{
var c = (UInt32)command;
var bs = BitConverter.GetBytes(c);
bytes.AddRange(bs);
}
else if (command is int)
{
var c = (int)command;
bytes.Add((byte)c);
var bs = BitConverter.GetBytes(c);
bytes.AddRange(bs);
}
else if (command is byte[])
{
var c = (byte[])command;
bytes.AddRange(c);
}
else
{
......
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Threading;
using static GeneralGommunication.Modbus_Transaction;
namespace GeneralGommunication
{
public interface IModbusAsciiAsync : INotifyPropertyChanged
{
/// <summary>
/// 通讯速度测量模块
/// </summary>
CommSpeedMeasuring Csm { get; }
/// <summary>
/// 包出错次数
/// </summary>
int ErrCnt { get; }
/// <summary>
/// 有数据需要发送
/// </summary>
event SendDataEventHander SendMsgEvent;
/// <summary>
/// 设备连接状态改变
/// </summary>
event DeviceConnectEventHander DeviceConnectEvent;
/// <summary>
/// 通讯中
/// </summary>
bool IsBusy();
/// <summary>
/// 检查发生列表是否包含某条指令
/// </summary>
/// <param name="deviceNo"></param>
/// <param name="desription"></param>
/// <returns></returns>
bool Contain(int deviceNo, string desription);
/// <summary>
/// 设备是否连接成功
/// </summary>
/// <param name="deviceNo"></param>
/// <returns></returns>
bool IsConnected(byte deviceNo);
/// <summary>
/// 接收回调调用
/// </summary>
/// <param name="recBuf"></param>
void RecMsg(byte[] recBuf);
/// <summary>
/// 复位全部状态,通常由于通讯模块检测到连接断开导致的
/// </summary>
void ResetMsg();
/// <summary>
/// 添加 通讯任务
/// </summary>
/// <param name="tran"></param>
void AddTran(Modbus_Transaction tran);
/// <summary>
/// 读多个Holding REGs
/// </summary>
/// <param name="deviceNo"></param>
/// <param name="addr"></param>
/// <param name="cnt"></param>
/// <param name="desription"></param>
/// <param name="parseU16FuncPack"></param>
/// <param name="asyncDelegate"></param>
/// <param name="asyncContext"></param>
/// <returns></returns>
Modbus_Transaction Do_03(int deviceNo, int addr, int cnt,
string desription,
ParseU16FuncPackHandler parseU16FuncPack,
CallBackHandler asyncDelegate, object asyncContext);
/// <summary>
/// 读多个Input REGs
/// </summary>
/// <param name="deviceNo"></param>
/// <param name="addr"></param>
/// <param name="cnt"></param>
/// <param name="desription"></param>
/// <param name="parseU16FuncPack"></param>
/// <param name="asyncDelegate"></param>
/// <param name="asyncContext"></param>
/// <returns></returns>
Modbus_Transaction Do_04(int deviceNo, int addr, int cnt,
string desription,
ParseU16FuncPackHandler parseU16FuncPack,
CallBackHandler asyncDelegate, object asyncContext);
/// <summary>
/// 写单个 Holding REG
/// </summary>
/// <param name="deviceNo"></param>
/// <param name="addr"></param>
/// <param name="cnt"></param>
/// <param name="desription"></param>
/// <param name="asyncDelegate"></param>
/// <param name="asyncContext"></param>
/// <returns></returns>
Modbus_Transaction Do_06(int deviceNo, int addr, UInt16 value,
string desription,
CallBackHandler asyncDelegate, object asyncContext);
/// <summary>
/// 写多个 Holding REG
/// </summary>
/// <param name="deviceNo"></param>
/// <param name="addr"></param>
/// <param name="cnt"></param>
/// <param name="desription"></param>
/// <param name="asyncDelegate"></param>
/// <param name="asyncContext"></param>
/// <returns></returns>
Modbus_Transaction Do_10(int deviceNo, int addr, IEnumerable<UInt16> datas,
string desription,
CallBackHandler asyncDelegate, object asyncContext);
/// <summary>
/// <para>任务内部转为发送的字节</para>
/// <para>用于自定义指令</para>
/// </summary>
/// <param name="tran"></param>
void ToSendBuf(Modbus_Transaction tran);
}
}
This diff is collapsed.
using Newtonsoft.Json;
using NLog;
using System;
using System.ComponentModel;
using System.IO;
using System.Windows.Threading;
namespace GeneralGommunication
{
public class ModbusAsciiAsyncConnector : INotifyPropertyChanged
{
public Logger comm_logger;
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// AD盒地址, 当为 TCP通讯时,为 192.168.251.200:20020;
/// 当为 串口通讯时, 为 COM6
/// </summary>
public string Addr { get; set; } = "192.168.251.60:1502";
/// <summary>
/// 连接成功
/// </summary>
public bool IsConnected { get; private set; }
public ModbusAsciiAsync Modbus => modbus;
IGeneralComm comm;
ModbusAsciiAsync modbus;
public ModbusAsciiAsyncConnector()
{
modbus = new ModbusAsciiAsync();
}
public ModbusAsciiAsyncConnector(string filePath):this()
{
this.filePath = filePath;
}
public void Init()
{
//启动速度测量
modbus.Csm.StartMeasure();
//注册modbus发送动作,把数据通过 comm模块发送出去
modbus.SendMsgEvent += (s, msg) =>
{
comm?.Write(msg);
};
}
/// <summary>
/// 断开连接
/// </summary>
public void Disconnect()
{
if (comm != null)
{
comm.Stop();
//只要comm.Stop() IsConnected 就会为 False, 就会触发 modbus.AllDeviceDisconnect();
}
}
/// <summary>
/// 连接
/// </summary>
public void Connect()
{
Connect(Addr);
}
/// <summary>
/// 连接 addr
/// </summary>
/// <param name="addr"></param>
public void Connect(string addr)
{
Addr = addr;
if (comm == null)
{
createComm();
}
else
{
comm.Stop();
//只要comm.Stop() IsConnected 就会为 False, 就会触发 modbus.AllDeviceDisconnect();
if ((Addr.ToLower().StartsWith("com") && (comm is GComm_SerialPort)) ||
(!Addr.ToLower().StartsWith("com") && (comm is GComm_TcpClient)))
{
//不用重建
}
else
{
disposeComm();
createComm();
}
}
comm.Addr = addr;
comm.Start();
}
void createComm()
{
if (Addr.ToLower().StartsWith("com"))
{
var _comm = new GComm_SerialPort();
_comm.Init(new System.IO.Ports.SerialPort()
{
BaudRate = 19200,
DataBits = 8,
Parity = System.IO.Ports.Parity.None,
StopBits = System.IO.Ports.StopBits.One
});
_comm.logger = comm_logger;
comm = _comm;
}
else
{
var _comm = new GComm_TcpClient();
_comm.logger = comm_logger;
comm = _comm;
}
comm.DataReceived += Comm_DataReceived;
comm.PropertyChanged += Comm_PropertyChanged;
IsConnected = comm.IsConnected;
}
private void Comm_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(comm.IsConnected))
{
IsConnected = comm.IsConnected;
if (!IsConnected) {
modbus.ResetMsg();
}
}
}
void disposeComm()
{
comm.DataReceived -= Comm_DataReceived;
comm.PropertyChanged -= Comm_PropertyChanged;
IsConnected = false;
}
private void Comm_DataReceived(IGeneralComm sender, byte[] buf)
{
modbus.RecMsg(buf);
}
/// <summary>
/// 重连
/// </summary>
public void ReConnect()
{
Connect();
}
string filePath = "modbusAscii.json";
/// <summary>
/// 参数保存
/// </summary>
public void Save()
{
ModbusAsciiAsyncConnectorJsonDb.Save(filePath, this);
}
public bool Load()
{
return ModbusAsciiAsyncConnectorJsonDb.Load(filePath, this);
}
}
class ModbusAsciiAsyncConnectorJsonDb
{
public static void Save(string jsonDbPath, ModbusAsciiAsyncConnector src)
{
if (string.IsNullOrEmpty(jsonDbPath))
return;
ModbusAsciiAsyncConnectorJsonDb jsonDb = new ModbusAsciiAsyncConnectorJsonDb()
{
Addr = src.Addr,
};
try
{
File.WriteAllText(jsonDbPath, JsonConvert.SerializeObject(jsonDb, Formatting.Indented));
}
catch
{
//异常,没有json 编码失败
}
}
public static bool Load(string jsonDbPath, ModbusAsciiAsyncConnector src)
{
if (string.IsNullOrEmpty(jsonDbPath))
return false;
try
{
if (File.Exists(jsonDbPath))
{
string json = File.ReadAllText(jsonDbPath);
var jsonDb = JsonConvert.DeserializeObject<ModbusAsciiAsyncConnectorJsonDb>(json);
src.Addr = jsonDb.Addr;
return true;
}
}
catch
{
//异常,没有json 解码失败
}
return false;
}
public string Addr { get; set; } = "192.168.251.60:1502";
}
}
......@@ -36,7 +36,7 @@ namespace GeneralGommunication
/// <summary>
/// 有数据需要发送
/// </summary>
public event SendMsgEventHander SendMsgEvent;
public event SendDataEventHander SendMsgEvent;
/// <summary>
/// 对于全部 有返回的函数调用,都使用Dispatcher,使线程同步
......@@ -147,7 +147,8 @@ namespace GeneralGommunication
retryCnt = 0;
if (Transactions.Count() != 0) //还要其它需要发送
{
SendMsgEvent?.Invoke(this);
byte[] msg = GetSendMsg();
SendMsgEvent?.Invoke(this,msg);
}
return;
}
......@@ -156,9 +157,10 @@ namespace GeneralGommunication
//重新把指令放回队列
Transactions.Insert(0, currTran);
currTran = null;
//再发一次指令
SendMsgEvent?.Invoke(this);
byte[] msg = GetSendMsg();
SendMsgEvent?.Invoke(this, msg);
}
}
......@@ -184,7 +186,7 @@ namespace GeneralGommunication
/// 获取 发送队列 第1条msg
/// </summary>
/// <returns></returns>
public byte[] GetSendMsg()
byte[] GetSendMsg()
{
//TODO 要处理 TimeOut / ParseFuncPack / GetSendMsg 线性同步问题
......@@ -371,7 +373,8 @@ namespace GeneralGommunication
if (Transactions.Count() > 0)
{
//队列还有需要发送的指令,通知外部获取指令发送
SendMsgEvent?.Invoke(this);
byte[] msg = GetSendMsg();
SendMsgEvent?.Invoke(this,msg);
}
}
......@@ -382,7 +385,8 @@ namespace GeneralGommunication
if (currTran == null)
{
//当前没有指令正在发送
SendMsgEvent?.Invoke(this);
byte[] msg = GetSendMsg();
SendMsgEvent?.Invoke(this,msg);
}
}
......@@ -499,82 +503,5 @@ namespace GeneralGommunication
}
}
public class Modbus_Transaction
{
/// <summary>
/// 交易描述
/// </summary>
public string desription;
/// <summary>
/// 设备编号 0~255 0是广播
/// </summary>
public int deviceNo;
/// <summary>
/// modbus 功能号
/// </summary>
public byte func;
/// <summary>
/// 数据地址
/// </summary>
public int addr;
/// <summary>
/// 操作的寄存器数量
/// </summary>
public int cnt;
/// <summary>
/// 期待接收的数据量
/// </summary>
public int expRecBytes;
public List<byte> sendBuf = new List<byte>();
/// <summary>
/// 功能 的数据
/// </summary>
public List<byte> funcData = new List<byte>();
public delegate object ParseU16FuncPackHandler(List<UInt16> values);
/// <summary>
/// 数据回复处理
/// </summary>
public ParseU16FuncPackHandler parse16FuncPack;
public delegate object ParseBoolFuncPackHandler(List<bool> values);
/// <summary>
/// 数据回复处理
/// </summary>
public ParseBoolFuncPackHandler parseBoolFuncPack;
/// <summary>
/// 回复的数据,只用于调试而已
/// </summary>
public object retData;
/// <summary>
/// 回复 callback
/// </summary>
public CallBackHandler asyncDelegate;
/// <summary>
/// 上下文
/// </summary>
public object asyncContext;
}
public delegate void DeviceConnectEventHander(object sender, DeviceConnectEventArgs e);
public class DeviceConnectEventArgs:EventArgs
{
public int deviceNo;
public bool isConnected;
public string errMsg;
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GeneralGommunication
{
public class Modbus_Transaction
{
/// <summary>
/// 输出调试信息
/// </summary>
public bool EnableLog = true;
/// <summary>
/// 交易描述
/// </summary>
public string desription;
/// <summary>
/// 设备编号 0~255 0是广播
/// </summary>
public int deviceNo;
/// <summary>
/// modbus 功能号
/// </summary>
public byte func;
/// <summary>
/// 数据地址
/// </summary>
public int addr;
/// <summary>
/// 操作的寄存器数量
/// </summary>
public int cnt;
/// <summary>
/// 期待接收的数据量
/// </summary>
public int expRecBytes;
public List<byte> sendBuf = new List<byte>();
/// <summary>
/// 功能 的数据
/// </summary>
public List<byte> funcData = new List<byte>();
/// <summary>
/// u16 读取处理
/// </summary>
/// <param name="values"></param>
/// <returns></returns>
public delegate object ParseU16FuncPackHandler(List<UInt16> values);
/// <summary>
/// u16 数据回复处理
/// </summary>
public ParseU16FuncPackHandler parse16FuncPack;
/// <summary>
/// bool 读取处理
/// </summary>
/// <param name="values"></param>
/// <returns></returns>
public delegate object ParseBoolFuncPackHandler(List<bool> values);
/// <summary>
/// bool 数据回复处理
/// </summary>
public ParseBoolFuncPackHandler parseBoolFuncPack;
/// <summary>
/// 回复的数据,只用于调试而已
/// </summary>
public object retData;
/// <summary>
/// 回复 callback
/// </summary>
public CallBackHandler asyncDelegate;
/// <summary>
/// 上下文
/// </summary>
public object asyncContext;
}
public delegate void DeviceConnectEventHander(object sender, DeviceConnectEventArgs e);
public class DeviceConnectEventArgs : EventArgs
{
public int deviceNo;
public bool isConnected;
public string errMsg;
}
public delegate void SendDataEventHander(object sender, byte[] data);
}
......@@ -265,8 +265,15 @@ namespace GeneralGommunication
for (int i = 0; i < len / 2; i++)
{
string msg = System.Text.Encoding.ASCII.GetString(new byte[] { ascii.ElementAt(index + i * 2), ascii.ElementAt(index + i * 2 + 1) });
byte d = (byte)int.Parse(msg, System.Globalization.NumberStyles.HexNumber);
hex.Add(d);
if (int.TryParse(msg, System.Globalization.NumberStyles.HexNumber, null, out int d))
{
hex.Add((byte)d);
}
else {
hex.Add(0);
}
}
return hex.ToArray();
......
......@@ -18,6 +18,7 @@
<SolidColorBrush x:Key="Brushes.Text.White" Color="White"/>
<SolidColorBrush x:Key="Brushes.Text.Gray" Color="#FFC3C3C3"/>
<SolidColorBrush x:Key="Brushes.Text.Black" Color="Black"/>
<!--随机颜色-->
<x:Array x:Key="Brushes.Random" Type="SolidColorBrush">
<SolidColorBrush>#2195f2</SolidColorBrush>
......
......@@ -19,7 +19,6 @@
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="FontFamily" Value="Microsoft Sans Serif"/>
<Setter Property="FontSize" Value="12"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="Margin" Value="3,0"/>
</Style>
<Style TargetType="TextBlock" x:Key="Styles.Module.Text.ItemValue">
......
......@@ -15,10 +15,11 @@ namespace FlyADBase
{
public partial class FlyAd2021B2 : IFlyADClient
{
protected Logger logger = NLog.LogManager.GetCurrentClassLogger();
public Logger logger = NLog.LogManager.GetCurrentClassLogger();
#region MARKNO
const int MARKNO_SET_SAVE = 4;
const int MARKNO_PARAM_APPLY = 5;
#endregion
#region INotifyPropertyChanged 成员
......@@ -317,17 +318,12 @@ namespace FlyADBase
core = new FlyAd2021B2Core();
core.logger = logger;
core.Csm.StartMeasure();
//注册AD2021版的发送动作,把数据通过 comm模块发送出去
core.SendMsgEvent += (s) =>
core.SendMsgEvent += (s,msg) =>
{
byte[] msg = core.GetSendMsg();
if (msg == null)
return;
//if(logger.IsDebugEnabled)
// logger.Debug($"W {msg.ToString_Bytes2HexAndAscii()}");
comm?.Write(msg);
};
......@@ -355,16 +351,10 @@ namespace FlyADBase
//避免推送太快,全部推送事件统一周期处理
PollModule.Current.Poll_Config(onPoll_PushEvent, TimeSpan.FromSeconds(0.1));
PollModule.Current.Poll_Config(core.OnPoll_TimeOut, TimeSpan.FromSeconds(0.5));
Misc.BindingOperations.SetBinding(core, nameof(core.IsConnected), this, nameof(IsConnected));
Misc.BindingOperations.SetBinding(isReadyContext, nameof(isReadyContext.IsReady), this, nameof(IsReady));
this.PropertyChanged += FlyAd2021_PropertyChanged;
......@@ -379,7 +369,7 @@ namespace FlyADBase
if (Surplus > 0)
{
Surplus--;
core.AddAccess(null, null);
//TODO
}
}
}, TimeSpan.FromMinutes(60));
......@@ -516,6 +506,9 @@ namespace FlyADBase
ConnectCnt++;
AfterConnected();
}
else {
isReadyContext.Reset();
}
return;
}
......@@ -525,25 +518,36 @@ namespace FlyADBase
if (e.PropertyName == nameof(PosOffset))
{
core.SetSysParam_Zero(PosOffset, null, null);
FObjBase.PollModule.Current.Poll_JustOnce(SetSysParamApply, this, MARKNO_PARAM_APPLY);
}
else if (e.PropertyName == nameof(JogVelocity))
{
core.SetSysParam_Jog(JogVelocity, null, null);
FObjBase.PollModule.Current.Poll_JustOnce(SetSysParamApply, this, MARKNO_PARAM_APPLY);
}
else if (e.PropertyName == nameof(MotorType))
{
core.SetSysParam_MotorType(MotorType, null, null);
FObjBase.PollModule.Current.Poll_JustOnce(SetSysParamApply, this, MARKNO_PARAM_APPLY);
}
else if (e.PropertyName == nameof(Ratio01))
{
core.SetSysParam_Ratio01(Ratio01, null, null);
FObjBase.PollModule.Current.Poll_JustOnce(SetSysParamApply, this, MARKNO_PARAM_APPLY);
}
else if (e.PropertyName == nameof(Ratio02))
{
core.SetSysParam_Ratio02(Ratio02, null, null);
FObjBase.PollModule.Current.Poll_JustOnce(SetSysParamApply, this, MARKNO_PARAM_APPLY);
}
}
/// <summary>
/// 参数保存
/// </summary>
void SetSysParamApply()
{
core.SetSysParam_Apply(null, null);
}
void _core_PushRunResultEvent(PushRunResultEventArgs e)
{
......@@ -690,6 +694,7 @@ namespace FlyADBase
core.SetSysParam_Ratio02(Ratio02, null, null);
core.SetSysParam_Zero(PosOffset, null, null);
core.SetSysParam_Jog(JogVelocity, null, null);
core.SetSysParam_Apply(null, null);
//});
//NotifyPropertyChanged(nameof(MotorType));
//NotifyPropertyChanged(nameof(Ratio01));
......@@ -718,25 +723,7 @@ namespace FlyADBase
}
void GetAccess()
{
core.GetAccess((asyncContext, _retData) =>
{
PollModule.Current.Dispatcher.BeginInvoke(new Action<object>((retData) =>
{
GetAccess_Response reponse = (GetAccess_Response)retData;
AreaStatus = reponse.status;
AreaRet = reponse.ret;
Array.Copy(reponse.code, Code, reponse.code.Length);
Code[6] = 0x06;
NotifyPropertyChanged(nameof(Code));
Surplus = reponse.surplus;
Array.Copy(reponse.access, Access, reponse.access.Length);
NotifyPropertyChanged(nameof(Access));
}), _retData);
}, null);
//TODO
}
......@@ -814,22 +801,42 @@ namespace FlyADBase
var _comm = new GComm_SerialPort();
_comm.Init(new System.IO.Ports.SerialPort()
{
BaudRate = 115200*2,
BaudRate = 115200 * 2,
DataBits = 8,
Parity = System.IO.Ports.Parity.None,
StopBits = System.IO.Ports.StopBits.One
});
//_comm.logger = logger;
comm = _comm;
}
else
comm = new GComm_TcpClient();
comm.DataReceived += (sendor, msg) =>
{
//core.logger.Debug($"R {core.bytes2hex(msg)}");
core.RecMsg(msg);
};
var _comm = new GComm_TcpClient();
//_comm.logger = logger;
comm = _comm;
}
comm.DataReceived += Comm_DataReceived;
comm.PropertyChanged += Comm_PropertyChanged;
core.ResetMsg();
}
void disposeComm()
{
comm.DataReceived -= Comm_DataReceived;
comm.PropertyChanged -= Comm_PropertyChanged;
core.ResetMsg();
}
private void Comm_DataReceived(IGeneralComm sender, byte[] msg)
{
core.RecMsg(msg);
}
private void Comm_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(comm.IsConnected))
{
core.ResetMsg();
}
}
/// <summary>
/// 连接 addr
/// </summary>
......@@ -844,6 +851,7 @@ namespace FlyADBase
else
{
comm.Stop();
//只要comm.Stop() IsConnected 就会为 False
if ((Addr.ToLower().StartsWith("com") && (comm is GComm_SerialPort)) ||
(!Addr.ToLower().StartsWith("com") && (comm is GComm_TcpClient)))
......@@ -852,6 +860,7 @@ namespace FlyADBase
}
else
{
disposeComm();
createComm();
}
}
......@@ -884,24 +893,6 @@ namespace FlyADBase
}, null);
}
#region 运动参数
/// <summary>
/// 设置 运动参数
/// </summary>
/// <param name="posOfGrid">脉冲/grid</param>
/// <param name="motortype">电机类型</param>
/// <param name="ratio01">脉冲比例 分母(电机脉冲)</param>
/// <param name="ratio02">脉冲比例 分子(编码器脉冲)</param>
public void SetSysParam(UInt16 posOfGrid, MOTORTYPE motortype, UInt16 ratio01, UInt16 ratio02)
{
core.SetSysParam_MotorType(motortype, null, null);
core.SetSysParam_Ratio01(ratio01, null, null);
core.SetSysParam_Ratio02(ratio02, null, null);
}
#endregion
#region 速度参数
/// <summary>
/// 设置速度参数
......@@ -940,33 +931,6 @@ namespace FlyADBase
}
#endregion
#region 密码
/// <summary>
/// 输入系统授权码
/// </summary>
/// <param name="access">系统授权码access[8]</param>
public void SetAccess(byte[] access)
{
core.CheckAccessCode(access, (asyncContext, retData) =>
{
//AreaRet = (AREA_ERR)retData;
GetAccess();
}, null);
}
/// <summary>
/// 初始化系统信息区
/// </summary>
public void InitArea()
{
core.InitArea((asyncContext, retData) =>
{
GetAccess();
}, null);
}
#endregion
#region 运行动作
......
......@@ -12,12 +12,6 @@ namespace FlyADBase
public partial class FlyAd2021B2 : IFlyADClientAdv
{
#region IFlyADClientAdv property
/// <summary>
/// 通过脉冲计算速度,不使用AD盒的输出
/// </summary>
[Obsolete("已经无效,必须通过电脑计算速度")]
public bool IsCalSpeed { get; set; } = true;
/// <summary>
/// grid数据平滑
/// </summary>
......
......@@ -86,25 +86,21 @@ namespace FlyADBase
/// </summary>
/// <param name="mask"></param>
/// <param name="enable"></param>
void SetOutput(UInt16 mask, UInt16 enable);
void SetOutput(UInt16 mask, UInt16 enable);
#region 运动参数
/// <summary>
/// 设置 运动参数
/// 脉冲/grid, 最大1000个grid
/// </summary>
/// <param name="posOfGrid">脉冲/grid</param>
/// <param name="motortype">电机类型</param>
/// <param name="ratio01">脉冲比例 分母(电机脉冲)</param>
/// <param name="ratio02">脉冲比例 分子(编码器脉冲)</param>
//void SetSysParam(UInt16 posOfGrid, MOTORTYPE motortype, UInt16 ratio01, UInt16 ratio02);
UInt16 PosOfGrid { set; get; }
#region 运动参数
/// <summary>
/// 电机类型
/// </summary>
MOTORTYPE MotorType { set; get; }
/// <summary>
/// 脉冲/grid, 最大1000个grid
/// </summary>
UInt16 PosOfGrid { set; get; }
/// <summary>
/// 脉冲比例 分母(电机脉冲)
/// </summary>
......@@ -114,16 +110,16 @@ namespace FlyADBase
/// </summary>
UInt16 Ratio02 { get; set; }
#endregion
/// <summary>
/// 脉冲平移(0位处脉冲值)
/// </summary>
Int16 PosOffset { set; get; }
/// <summary>
/// 手动速度 pps
/// </summary>
UInt32 JogVelocity { set; get; }
#endregion
#region 速度参数
/// <summary>
......@@ -168,39 +164,6 @@ namespace FlyADBase
#endregion
#region 密码
/// <summary>
/// 使用码区状态
/// </summary>
AREA_STATUS AreaStatus { get; }
/// <summary>
/// 使用码区出错码
/// </summary>
AREA_ERR AreaRet { get; }
/// <summary>
/// 序列码byte[6]
/// </summary>
byte[] Code { get; }
/// <summary>
/// 系统剩余时间
/// </summary>
int Surplus { get; }
/// <summary>
/// 系统授权码access[8]
/// </summary>
byte[] Access { get; }
/// <summary>
/// 输入系统授权码
/// </summary>
/// <param name="access">系统授权码access[8]</param>
void SetAccess(byte[] access);
/// <summary>
/// 初始化系统信息区
/// </summary>
void InitArea();
#endregion
/// <summary>
/// timegrid 事件; 版本1: 1.28s 一次; 版本2: 0.2s一次,
......
......@@ -8,51 +8,8 @@ namespace FlyADBase.Inc
/// AD盒2021版.B2 , 核心模块
/// 实现AD盒2021版.B2 基本接口
/// </summary>
public interface IFlyAd2021B2Core : INotifyPropertyChanged
public interface IFlyAd2021B2Core : IDev7E
{
/// <summary>
/// 包出错次数
/// </summary>
int ErrCnt { get; }
/// <summary>
/// 连接成功;
/// 当命令多次发送失败,IsConnected = false
/// </summary>
bool IsConnected { get; }
#region 模块运行接口
/// <summary>
/// 超时判断,长时间收不到数据,会触发,0.5s调用一次
/// </summary>
void OnPoll_TimeOut();
/// <summary>
/// 在接收事件中调用;
/// 全部接收事件 及 超时事件也是在这里触发
/// </summary>
/// <param name="recBuf"></param>
void RecMsg(byte[] recBuf);
/// <summary>
/// 获取 发送队列 第1条msg
/// </summary>
/// <returns></returns>
byte[] GetSendMsg();
/// <summary>
/// 有数据需要发送
/// </summary>
/// <param name="sender"></param>
event SendMsgEventHander SendMsgEvent;
/// <summary>
/// 复位全部状态,通常由于通讯模块检测到连接断开导致的
/// </summary>
void ResetMsg();
#endregion
#region AD 功能
/// <summary>
/// 数据推送事件
......@@ -138,37 +95,6 @@ namespace FlyADBase.Inc
[CallBack(typeof(UInt32))]
void GetSysTick(CallBackHandler asyncDelegate, object asyncContext);
/// <summary>
/// 初始化系统信息区
/// </summary>
/// <param name="asyncDelegate"></param>
/// <param name="asyncContext"></param>
[CallBack(typeof(bool))]
void InitArea(CallBackHandler asyncDelegate, object asyncContext);
/// <summary>
/// 输入系统授权码
/// </summary>
/// <param name="access"></param>
/// <param name="asyncDelegate"></param>
/// <param name="asyncContext"></param>
[CallBack(typeof(AREA_ERR))]
void CheckAccessCode(byte[] access, CallBackHandler asyncDelegate, object asyncContext);
/// <summary>
/// 获取系统授权信息
/// </summary>
/// <param name="asyncDelegate"></param>
/// <param name="asyncContext"></param>
[CallBack(typeof(GetAccess_Response))]
void GetAccess(CallBackHandler asyncDelegate, object asyncContext);
/// <summary>
/// 系统运行时间+1
/// </summary>
/// <param name="asyncDelegate"></param>
/// <param name="asyncContext"></param>
void AddAccess(CallBackHandler asyncDelegate, object asyncContext);
#endregion
#region GetSysParam 读运行参数
......@@ -199,6 +125,8 @@ namespace FlyADBase.Inc
void SetSysParam_Zero(Int16 zero, CallBackHandler asyncDelegate, object asyncContext);
void SetSysParam_Jog(UInt32 jog, CallBackHandler asyncDelegate, object asyncContext);
void SetSysParam_Apply(CallBackHandler asyncDelegate, object asyncContext);
#endregion
#endregion
}
......
......@@ -495,7 +495,13 @@ namespace FlyADBase
public int pos;
public int pos2;
public UInt16 istatus;
public int GetPos(int no)
{
if (no == 1)
return pos;
else
return pos2;
}
public override string ToString()
{
return $"ad={ad} | ad2={ad2} | p={pos} | p2={pos2} | i={istatus:X4}";
......@@ -640,14 +646,7 @@ namespace FlyADBase
var beginPoint = dataPool[begin_idx];
var endPoint = dataPool[end_idx];
if (posNo == 1)
{
return (endPoint.pos - beginPoint.pos) / ((end_idx - begin_idx) / 60000.0);
}
else
{
return (endPoint.pos2 - beginPoint.pos2) / ((end_idx - begin_idx) / 60000.0);
}
return (endPoint.GetPos(posNo) - beginPoint.GetPos(posNo)) / ((end_idx - begin_idx) / 60000.0);
}
/// <summary>
......@@ -669,14 +668,7 @@ namespace FlyADBase
idx = dataPool.Count() - 1;
var point = dataPool[idx];
if (posNo == 1)
{
return point.pos;
}
else
{
return point.pos2;
}
return point.GetPos(posNo);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment