|
- using BPA.Message;
- using BPA.Message.Enum;
- 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 BPA.Models;
- using BPA.Helper;
-
- namespace BPASmartClient.Device
- {
- /// <summary>
- /// 设备基类
- /// </summary>
- public abstract class BaseDevice : IDevice
- {
- public BaseDevice()
- {
- }
-
- #region 属性
- /// <summary>
- /// 订单物料信息
- /// </summary>
- public OrderMaterialDelivery orderMaterialDelivery { get; set; } = new OrderMaterialDelivery();
-
- /// <summary>
- /// 配方数据信息
- /// </summary>
- public RecipeBoms recipeBoms { get; set; } = new RecipeBoms();
-
- /// <summary>
- /// 设备ID
- /// </summary>
- public int DeviceId { get; set; }
-
- /// <summary>
- /// 设备所有状态
- /// </summary>
- public DeviceStatus Status { get; set; } = new DeviceStatus();
-
- /// <summary>
- /// 设备名称
- /// </summary>
- public string Name { get; set; }
-
- /// <summary>
- /// 当前订单数量
- /// </summary>
- protected int OrderCount { get; set; }
-
- /// <summary>
- /// 设备初始化中
- /// </summary>
- protected bool Initing { get; set; }
-
- /// <summary>
- /// 设备类型
- /// </summary>
- public abstract DeviceClientType DeviceType { get; }
-
- /// <summary>
- /// 是否忙碌
- /// </summary>
- public bool IsBusy { get; protected set; }
-
- /// <summary>
- /// 是否健康
- /// </summary>
- public bool IsHealth { get; protected set; }
-
- /// <summary>
- /// 设备运行日志
- /// </summary>
- public List<object> Log { get; set; } = new List<object>();
-
- /// <summary>
- /// 设备运行告警与错误
- /// </summary>
- public List<object> Error { get; set; } = new List<object>();
-
- /// <summary>
- /// mork_F暂用余量列表
- /// </summary>
- public List<BatchingInfo> BatchingInfos { get; set; } = new List<BatchingInfo>();
-
- /// <summary>
- /// 设备变量监控
- /// </summary>
- public ObservableCollection<VariableMonitor> variableMonitors { get; set; } = new ObservableCollection<VariableMonitor>();
-
- /// <summary>
- /// 外设状态,硬件设备数据
- /// </summary>
- protected ConcurrentDictionary<string, object> peripheralStatus = new ConcurrentDictionary<string, object>();
-
- protected
-
- /// <summary>
- /// 外设设备集合
- /// </summary>
- private List<IPeripheral> peripherals;
-
- /// <summary>
- /// <炒锅>:<外设状态,硬件设备数据>的键值对
- /// </summary>
- protected Dictionary<int, ConcurrentDictionary<string, object>> dicPort2peripheralStatus = new Dictionary<int, ConcurrentDictionary<string, object>>();
-
- public Action<int, object> AddErrorAction { get; set; }
- public Action<int, object> DeleteErrorAction { get; set; }
- public List<BPASmartClient.Model.Alarm> alarms { get; set; } = new List<BPASmartClient.Model.Alarm>();
- public IAlarm InterfaceAlarm { get; set; }
- public AlarmHelper alarmHelper { get; set; } = new AlarmHelper();
- public IStatus InterfaceStatus { get; set; }
- public ObservableCollection<Variable> variables { get; set; } = new ObservableCollection<Variable>();
-
- #endregion
-
- /// <summary>
- /// 写控制
- /// </summary>
- /// <param name="address"></param>
- /// <param name="value"></param>
- public void WriteControl(string address, object value)
- {
- if (peripherals != null)
- {
- for (int i = 0; i < peripherals.Count; i++)
- {
- peripherals.ElementAt(i).WriteData(address, value);
- }
- }
- }
- /// <summary>
- /// 多设备分开写控制
- /// </summary>
- /// <param name="address"></param>
- /// <param name="value"></param>
- public void WriteControlExact(string address, object value, int i)
- {
- if (peripherals != null)
- {
- if (peripherals.Count > i)
- {
- peripherals.ElementAt(i).WriteData(address, value);
- }
- }
- }
-
-
- /// <summary>
- /// 设备过程日志显示
- /// </summary>
- /// <param name="info"></param>
- public void DeviceProcessLogShow(string info)
- {
- Log.Insert(0, new { Time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff"), 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<IPeripheral> peripherals)
- {
- peripherals.ForEach(p =>
- {
- p.DeviceId = this.DeviceId;
-
- p.Init();
- });
- this.peripherals = peripherals;
- }
-
- public virtual void StartMain()
- {
- TaskManage.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<string, object> newPeripheralStatus = new ConcurrentDictionary<string, object>();
- 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<string>((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<string>((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);
- }
- });
- TaskManage.GetInstance.StartLong(new Action(() =>
- {
- AlarmMonitoring();
- Thread.Sleep(500);
- }), $"报警检测监控:{DeviceId}");
- }
- }
- }
- });
- }
-
- /// <summary>
- /// 报警监控
- /// </summary>
- /// <param name="alarm"></param>
- /// <param name="alarmHelper"></param>
- 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<AlarmAttribute>().AlarmInfo;
- if (info != null) alarmHelper.EdgeAlarm(blen, $"{info.ToString()}-{DeviceId}");
- }
- }
- }
- }
-
- private void InitResetTask()
- {
- #region 复位程序
- TaskManage.GetInstance.StartLong(new Action(() =>
- {
- if (RTrig.GetInstance($"ResetProgram:{DeviceId}").Start(Initing))
- {
- DeviceProcessLogShow("启动初始化");
- //记录监控数据
- DeviceProcessLogShow($"监控数据:【 {variableMonitors.ToJSON()} 】");
-
- TaskManage.GetInstance.StopTask($"MainTask:{DeviceId}", new Action(() =>
- {
- TaskManage.GetInstance.StopTask($"ReadData:{DeviceId}", new Action(() =>
- {
- TaskManage.GetInstance.StopTask($"GvlStatusMonitor:{DeviceId}", new Action(() =>
- {
- ActionManage.GetInstance.Send("ClearOrders");
- ResetProgram();
- ResetStatus();
- InitTask();
- }));
- }));
- }));
- }
- Thread.Sleep(10);
- }), $"ResetProgram:{DeviceId}");
- #endregion
- }
-
- private void InitTask()
- {
- #region 数据读取
- TaskManage.GetInstance.StartLong(new Action(() =>
- {
- ReadData();
- Thread.Sleep(10);
- }), $"ReadData:{DeviceId}", true);
- #endregion
-
- #region 任务流程
- TaskManage.GetInstance.StartLong(new Action(() =>
- {
- MainTask();
- Thread.Sleep(10);
- }), $"MainTask:{DeviceId}", true);
- #endregion
-
- #region 设备状态监控
- TaskManage.GetInstance.StartLong(new Action(() =>
- {
- UpdateValue(InterfaceStatus);
- Thread.Sleep(1000);
- }), $"GvlStatusMonitor:{DeviceId}");
- #endregion
- }
-
- /// <summary>
- /// 获取监控信息
- /// </summary>
- private void GetMonitorData(IStatus status)
- {
- if (status == null) return;
- List<VariableMonitor> vm = new List<VariableMonitor>();
- 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<VariableMonitorAttribute>()?.PLCAddress;
- var modadd = item.GetCustomAttribute<VariableMonitorAttribute>()?.ModbusTcpAddress;
- var notes = item.GetCustomAttribute<VariableMonitorAttribute>()?.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 = vm.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]}";
- }
-
- vm.Add(new VariableMonitor()
- {
- Id = vm.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 = vm.FirstOrDefault(p => p.VarName == $"{item.Name}_{i + 1}");
- if (res == null)
- {
- vm.Add(new VariableMonitor()
- {
- Id = vm.Count,
- VarName = $"{item.Name}_{i + 1}",
- Notes = $"{notes}_{i + 1}",
-
- });
- }
- }
- }
- }
- }
- else
- {
- var res = vm.FirstOrDefault(p => p.VarName == item.Name);
- if (res == null)
- {
- vm.Add(new VariableMonitor()
- {
- Id = vm.Count,
- VarName = item.Name,
- Notes = notes,
- ModbusTcpAddress = modadd,
- PLCAddress = plcadd,
-
- });
- }
- }
-
- }
- }
-
- //监控列表排序
- //vm.OrderBy(p => p.VarName).ToList().ForEach(item => { variableMonitors.Add(item); });
- vm.ForEach(item => { variableMonitors.Add(item); });
-
- }
-
- /// <summary>
- /// 更新数据
- /// </summary>
- /// <param name="status"></param>
- 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();
-
- /// <summary>
- /// 数据读取
- /// </summary>
- public abstract void ReadData();
- /// <summary>
- /// 主流程控制
- /// </summary>
- public abstract void MainTask();
- /// <summary>
- /// 复位程序
- /// </summary>
- public abstract void ResetProgram();
-
- /// <summary>
- /// 模拟订单
- /// </summary>
- 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 };
- }
-
- /// <summary>
- /// 获取某个对象中的属性值
- /// </summary>
- /// <param name="info"></param>
- /// <param name="field"></param>
- /// <returns></returns>
- public object GetPropertyValue(object info, string field)
- {
- if (info == null) return null;
- Type t = info.GetType();
- IEnumerable<System.Reflection.PropertyInfo> property = from pi in t.GetProperties() where pi.Name.ToLower() == field.ToLower() select pi;
- return property.First().GetValue(info, null);
- }
-
- }
- }
|