using BPA.Message;
using BPA.Message.Enum;
using BPASmartClient.Helper;
using BPASmartClient.Message;
using BPASmartClient.Model;
using BPASmartClient.Peripheral;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.ObjectModel;
using BPASmartClient.Model.单片机;
using BPASmartClient.EventBus;
namespace BPASmartClient.Device
{
///
/// 设备基类
///
public abstract class BaseDevice : IDevice
{
public BaseDevice()
{
}
#region 属性
///
/// 订单物料信息
///
public OrderMaterialDelivery orderMaterialDelivery { get; set; } = new OrderMaterialDelivery();
///
/// 配方数据信息
///
public RecipeBoms recipeBoms { get; set; } = new RecipeBoms();
///
/// 设备ID
///
public int DeviceId { get; set; }
///
/// 设备所有状态
///
public DeviceStatus Status { get; set; } = new DeviceStatus();
///
/// 设备名称
///
public string Name { get; set; }
///
/// 当前订单数量
///
protected int OrderCount { get; set; }
///
/// 设备初始化中
///
protected bool Initing { get; set; }
///
/// 设备类型
///
public abstract DeviceClientType DeviceType { get; }
///
/// 是否忙碌
///
public bool IsBusy { get; protected set; }
///
/// 是否健康
///
public bool IsHealth { get; protected set; }
///
/// 设备运行日志
///
public List Log { get; set; } = new List();
///
/// 设备运行告警与错误
///
public List Error { get; set; } = new List();
///
/// 设备变量监控
///
public ObservableCollection variableMonitors { get; set; } = new ObservableCollection();
///
/// 外设状态,硬件设备数据
///
protected ConcurrentDictionary peripheralStatus = new ConcurrentDictionary();
protected
///
/// 外设设备集合
///
private List peripherals;
///
/// <炒锅>:<外设状态,硬件设备数据>的键值对
///
protected Dictionary> dicPort2peripheralStatus = new Dictionary>();
public Action AddErrorAction { get; set; }
public Action DeleteErrorAction { get; set; }
public List alarms { get; set; } = new List();
public IAlarm InterfaceAlarm { get; set; }
public AlarmHelper alarmHelper { get; set; } = new AlarmHelper();
public IStatus InterfaceStatus { get; set; }
#endregion
///
/// 写控制
///
///
///
public void WriteControl(string address, object value)
{
if (peripherals != null)
{
for (int i = 0; i < peripherals.Count; i++)
{
peripherals.ElementAt(i).WriteData(address, value);
}
}
}
///
/// 多设备分开写控制
///
///
///
public void WriteControlExact(string address, object value,int i)
{
if (peripherals != null)
{
if (peripherals.Count > i)
{
peripherals.ElementAt(i).WriteData(address, value);
}
}
}
///
/// 设备过程日志显示
///
///
public void DeviceProcessLogShow(string info)
{
Log.Insert(0, new { Time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), Type = "流程", Text = info });
MessageLog.GetInstance.DeviceProcessLogShow(DeviceId.ToString(), info);
if (Log.Count > 100) { Log.RemoveAt(Log.Count - 1); }
}
public void Initliaze()
{
}
public void Initliaze(List peripherals)
{
peripherals.ForEach(p =>
{
p.DeviceId = this.DeviceId;
p.Init();
});
this.peripherals = peripherals;
}
public virtual void StartMain()
{
ThreadManage.GetInstance().StartLong(new Action(() =>
{
int i = 0;
foreach (var peripheral in peripherals)
{
string TypeName = peripheral.GetType().FullName.Replace("BPASmartClient.", "");
Status.Update($"{TypeName}.IsConnected", peripheral.IsConnected);
Status.Update($"{TypeName}.IsWork", peripheral.IsWork);
//做为炒锅与状态字典的新数据
ConcurrentDictionary newPeripheralStatus = new ConcurrentDictionary();
foreach (var key in peripheral.GetAllStatus().Keys)
{
peripheralStatus[key] = peripheral.GetAllStatus()[key];
//新的硬件设备数据存储
newPeripheralStatus[key] = peripheral.GetAllStatus()[key];
if (TypeName != "PLC.PLCMachine")
{
Status.Update($"{TypeName}.{key}", peripheral.GetAllStatus()[key]);
}
}
if(dicPort2peripheralStatus.ContainsKey(i))
{
dicPort2peripheralStatus[i] = newPeripheralStatus;
}
else
{
//将存储的新硬件设备数据放入字典中,i是作为炒锅编号。
dicPort2peripheralStatus.Add(i, newPeripheralStatus);
}
i++;
}
if (AddErrorAction != null && DeleteErrorAction != null)
{
foreach (var item in Status.GetStatusT())
{
if (item.Name == "Warning" || item.Name == "Fault")
{
if (item.Status != "无故障" && item.Status != "无警告" && item.Status != "未发生故障")
{
var res = Error?.FirstOrDefault(p => p.GetType().GetProperty("Text").GetValue(p).ToString() == item.Ms);
if (res == null)
{
object obj = new
{
Time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
Type = item.Name == "Warning" ? "警告" : "故障",
Text = item.Ms
};
Error.Add(obj);
AddErrorAction?.Invoke(DeviceId, obj);
}
}
else
{
var res = Error?.FirstOrDefault(p => p.GetType().GetProperty("Text").GetValue(p).ToString().Contains(item.id));
if (res != null)
{
Error.Remove(res);
DeleteErrorAction?.Invoke(DeviceId, res);
}
}
}
}
}
Thread.Sleep(100);
}), $"GetAllStatus:{DeviceId}");
DoMain();
SimOrder();
GetGvlStatus();
InitResetTask();
InitTask();
}
private void ResetStatus()
{
this.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).ToList().ForEach(item =>
{
var res = item.FieldType.GetInterfaces();
if (res != null)
{
foreach (var faces in res)
{
if (faces.Name == "IStatus") InterfaceStatus = item.GetValue(this) as IStatus;
}
}
});
}
private void GetGvlStatus()
{
this.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).ToList().ForEach(item =>
{
var res = item.FieldType.GetInterfaces();
if (res != null)
{
foreach (var faces in res)
{
if (faces.Name == "IStatus")
{
InterfaceStatus = item.GetValue(this) as IStatus;
GetMonitorData(InterfaceStatus);
}
else if (faces.Name == "IAlarm")
{
InterfaceAlarm = item.GetValue(this) as IAlarm;
alarmHelper.AddAction += new Action((s) =>
{
var res = alarmHelper.Alarms.FirstOrDefault(p => p.Info == s);
if (res != null)
{
object obj = new
{
Time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
Type = res.Grade,
Text = res.Info
};
Error.Insert(0, obj);
AddErrorAction?.Invoke(DeviceId, obj);
}
});
alarmHelper.RemoveAction += new Action((s) =>
{
var res = Error.FirstOrDefault(p => p.GetType().GetProperty("Text").GetValue(p).ToString() == s);
if (res != null && Error.Contains(res))
{
Error.Remove(res);
DeleteErrorAction?.Invoke(DeviceId, res);
}
});
ThreadManage.GetInstance().StartLong(new Action(() =>
{
AlarmMonitoring();
Thread.Sleep(500);
}), $"报警检测监控:{DeviceId}");
}
}
}
});
}
///
/// 报警监控
///
///
///
private void AlarmMonitoring()
{
if (InterfaceAlarm == null) return;
foreach (var item in InterfaceAlarm.GetType().GetProperties())
{
var res = item.GetValue(InterfaceAlarm);
if (res != null && res is bool blen)
{
if (item.CustomAttributes.Count() > 0 && item.CustomAttributes.ElementAt(0)?.ConstructorArguments.Count() > 0)
{
var info = item.GetCustomAttribute().AlarmInfo;
if (info != null) alarmHelper.EdgeAlarm(blen, $"{info.ToString()}-{DeviceId}");
}
}
}
}
private void InitResetTask()
{
#region 复位程序
ThreadManage.GetInstance().StartLong(new Action(() =>
{
if (RTrig.GetInstance($"ResetProgram:{DeviceId}").Start(Initing))
{
ThreadManage.GetInstance().StopTask($"MainTask:{DeviceId}", new Action(() =>
{
ThreadManage.GetInstance().StopTask($"ReadData:{DeviceId}", new Action(() =>
{
ThreadManage.GetInstance().StopTask($"GvlStatusMonitor:{DeviceId}", new Action(() =>
{
ResetProgram();
ResetStatus();
InitTask();
}));
}));
}));
}
Thread.Sleep(10);
}), $"ResetProgram:{DeviceId}");
#endregion
}
private void InitTask()
{
#region 数据读取
ThreadManage.GetInstance().StartLong(new Action(() =>
{
ReadData();
Thread.Sleep(10);
}), $"ReadData:{DeviceId}",true);
#endregion
#region 任务流程
ThreadManage.GetInstance().StartLong(new Action(() =>
{
MainTask();
Thread.Sleep(10);
}), $"MainTask:{DeviceId}", true);
#endregion
#region 设备状态监控
ThreadManage.GetInstance().StartLong(new Action(() =>
{
UpdateValue(InterfaceStatus);
Thread.Sleep(1000);
}), $"GvlStatusMonitor:{DeviceId}");
#endregion
}
///
/// 获取监控信息
///
private void GetMonitorData(IStatus status)
{
if (status == null) return;
foreach (var item in status.GetType().GetProperties())
{
if (item.CustomAttributes.Count() > 0)
{
var attributeName = item.CustomAttributes.FirstOrDefault(p => p.AttributeType.Name == "VariableMonitorAttribute");
if (attributeName == null) return;
var plcadd = item.GetCustomAttribute()?.PLCAddress;
var modadd = item.GetCustomAttribute()?.ModbusTcpAddress;
var notes = item.GetCustomAttribute()?.Notes;
if (item.PropertyType?.BaseType?.Name == "Array")
{
if (plcadd?.Length > 0)
{
var arrayRes = item.GetValue(status, null);
if (arrayRes != null && arrayRes is Array arr)
{
for (int i = 0; i < arr.Length; i++)
{
var res = variableMonitors.FirstOrDefault(p => p.VarName == $"{item.Name}_{i + 1}");
if (res == null)
{
string[] plc = plcadd?.Substring(1).Split('.');
string TempPlcAddress = string.Empty;
if (plc?.Length == 2)
{
int add = int.Parse(plc[1]);
int firstAdd = int.Parse(plc[0]);
if (add >= 0 && add < 7)
{
add += i;
}
else if (add >= 7)
{
add = 0;
firstAdd++;
}
plc[0] = firstAdd.ToString();
plc[1] = add.ToString();
TempPlcAddress = $"M{plc[0]}.{plc[1]}";
}
variableMonitors.Add(new VariableMonitor()
{
Id = variableMonitors.Count,
VarName = $"{item.Name}_{i + 1}",
Notes = $"{notes}_{i + 1}",
ModbusTcpAddress = $"{int.Parse(modadd) + i}",
PLCAddress = TempPlcAddress,
});
}
}
}
}
else
{
var arrayRes = item.GetValue(status, null);
if (arrayRes != null && arrayRes is Array arr)
{
for (int i = 0; i < arr.Length; i++)
{
var res = variableMonitors.FirstOrDefault(p => p.VarName == $"{item.Name}_{i + 1}");
if (res == null)
{
variableMonitors.Add(new VariableMonitor()
{
Id = variableMonitors.Count,
VarName = $"{item.Name}_{i + 1}",
Notes = $"{notes}_{i + 1}",
});
}
}
}
}
}
else
{
var res = variableMonitors.FirstOrDefault(p => p.VarName == item.Name);
if (res == null)
{
variableMonitors.Add(new VariableMonitor()
{
Id = variableMonitors.Count,
VarName = item.Name,
Notes = notes,
ModbusTcpAddress = modadd,
PLCAddress = plcadd,
});
}
}
}
}
}
///
/// 更新数据
///
///
public void UpdateValue(IStatus status)
{
if (status == null) return;
foreach (var item in status.GetType().GetProperties())
{
if (item.CustomAttributes.Count() > 0)
{
if (item.PropertyType?.BaseType?.Name == "Array")
{
var arrayRes = item.GetValue(status);
if (arrayRes != null && arrayRes is Array arr)
{
for (int i = 0; i < arr.Length; i++)
{
int index = Array.FindIndex(variableMonitors.ToArray(), p => p.VarName == $"{item.Name}_{i + 1}");
if (index >= 0 && index < variableMonitors.Count)
{
variableMonitors.ElementAt(index).CurrentValue = arr.GetValue(i)?.ToString();
}
}
}
}
else
{
int index = Array.FindIndex(variableMonitors.ToArray(), p => p.VarName == item.Name);
if (index >= 0 && index < variableMonitors.Count)
{
variableMonitors.ElementAt(index).CurrentValue = item.GetValue(status)?.ToString();
}
}
}
}
}
public abstract void DoMain();
public abstract void Stop();
///
/// 数据读取
///
public abstract void ReadData();
///
/// 主流程控制
///
public abstract void MainTask();
///
/// 复位程序
///
public abstract void ResetProgram();
///
/// 模拟订单
///
public abstract void SimOrder();
public object GetError()
{
return new { data = Error };
}
public object GetLog()
{
return new { data = Log };
}
public object GetVariableMonitor()
{
return new { data = variableMonitors };
}
///
/// 获取某个对象中的属性值
///
///
///
///
public object GetPropertyValue(object info, string field)
{
if (info == null) return null;
Type t = info.GetType();
IEnumerable property = from pi in t.GetProperties() where pi.Name.ToLower() == field.ToLower() select pi;
return property.First().GetValue(info, null);
}
}
}