Browse Source

新增变量配置程序

master
pry 2 years ago
parent
commit
c7834bf2fe
45 changed files with 3476 additions and 1117 deletions
  1. +33
    -33
      HBLConsole.Business/Devices/MORKD.cs
  2. +617
    -617
      HBLConsole.Business/Devices/MORKS.cs
  3. +19
    -1
      HBLConsole.Business/MessageServer/Base.cs
  4. +19
    -16
      HBLConsole.Communication/ConnectHelper.cs
  5. +6
    -0
      HBLConsole.Communication/HBLConsole.Communication.csproj
  6. +32
    -6
      HBLConsole.Factory/SimpleFactory.cs
  7. +252
    -263
      HBLConsole.GVL/Device/MORKS.cs
  8. +1
    -0
      HBLConsole.GVL/GeneralConfig.cs
  9. +3
    -0
      HBLConsole.GVL/HBLConsole.GVL.csproj
  10. +1
    -1
      HBLConsole.Interface/IControl.cs
  11. +38
    -0
      HBLConsole.MORKD/Control_MORKD.cs
  12. +13
    -0
      HBLConsole.MORKD/GVL_MORKD.cs
  13. +13
    -0
      HBLConsole.MORKD/HBLConsole.MORKD.csproj
  14. +598
    -0
      HBLConsole.MORKS/Control_MORKS.cs
  15. +252
    -0
      HBLConsole.MORKS/GVL_MORKS.cs
  16. +24
    -0
      HBLConsole.MORKS/HBLConsole.MORKS.csproj
  17. +15
    -7
      HBLConsole.MainConsole/Main.cs
  18. +52
    -0
      HBLConsole.Model/AlarmSet.cs
  19. +55
    -0
      HBLConsole.Model/AnalogAlarmModel.cs
  20. +4
    -1
      HBLConsole.Model/CommunicationPar/CommunicationSet.cs
  21. +41
    -0
      HBLConsole.Model/DiscreteAlarmInfo.cs
  22. +17
    -0
      HBLConsole.Model/OrderLocInfo.cs
  23. +0
    -9
      HBLConsole.Model/ProcessData.cs
  24. +74
    -0
      HBLConsole.Model/PropBindInfo.cs
  25. +16
    -0
      HBLConsole.Model/SetPar.cs
  26. +12
    -4
      HBLConsole.Model/SimOrderData.cs
  27. +73
    -0
      HBLConsole.Model/VariableInfo.cs
  28. +81
    -0
      HBLConsole.Service/SqlHelper.cs
  29. +13
    -1
      HBLConsole.sln
  30. +1
    -1
      HBLConsole/App.xaml.cs
  31. +38
    -0
      HBLConsole/Converter/AlarmTypeTextConvert.cs
  32. +31
    -0
      HBLConsole/Converter/AnalogAlarmConvert.cs
  33. +31
    -0
      HBLConsole/Converter/DiscreteAlarmConvert.cs
  34. +39
    -0
      HBLConsole/Converter/IsEnableConvert.cs
  35. +34
    -0
      HBLConsole/Converter/TextDisplayConvert.cs
  36. +2
    -0
      HBLConsole/HBLConsole.csproj
  37. +18
    -0
      HBLConsole/View/DeviceManageView.xaml
  38. +2
    -1
      HBLConsole/View/MainView.xaml
  39. +177
    -9
      HBLConsole/View/ProcessMonitoringView.xaml
  40. +453
    -0
      HBLConsole/View/VariableConfig.xaml
  41. +44
    -0
      HBLConsole/View/VariableConfig.xaml.cs
  42. +20
    -116
      HBLConsole/ViewModel/DebugViewModel.cs
  43. +65
    -21
      HBLConsole/ViewModel/DeviceManageViewModel.cs
  44. +31
    -10
      HBLConsole/ViewModel/ProcessMonitoringViewModel.cs
  45. +116
    -0
      HBLConsole/ViewModel/VariableConfig.cs

+ 33
- 33
HBLConsole.Business/Devices/MORKD.cs View File

@@ -1,47 +1,47 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HBLConsole.Interface;
//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;
//using System.Threading.Tasks;
//using HBLConsole.Interface;

namespace HBLConsole.Business.Devices
{
public class MORKD : IControl
{
//namespace HBLConsole.Business.Devices
//{
// public class MORKD : IControl
// {

private volatile static MORKD _Instance;
public static MORKD GetInstance => _Instance ?? (_Instance = new MORKD());
private MORKD() { }
// private volatile static MORKD _Instance;
// public static MORKD GetInstance => _Instance ?? (_Instance = new MORKD());
// private MORKD() { }

public void DataParse<T>(T order)
{
// public void DataParse<T>(T order)
// {

}
// }

public void Init()
{
// public void Init()
// {

}
// }

public void Main()
{
// public void Main()
// {

}
// }

public void ReadData()
{
// public void ReadData()
// {

}
// }

public void SimOrder()
{
// public void SimOrder()
// {

}
// }

public void ConnectOk()
{
// public void ConnectOk()
// {

}
}
}
// }
// }
//}

+ 617
- 617
HBLConsole.Business/Devices/MORKS.cs
File diff suppressed because it is too large
View File


+ 19
- 1
HBLConsole.Business/MessageServer/Base.cs View File

@@ -11,6 +11,7 @@ using BPA.Message.Enum;
using HBLConsole.GVL;
using BPA.Utility;
using Newtonsoft.Json;
using HBLConsole.Communication;

namespace HBLConsole.Business.MessageServer
{
@@ -85,8 +86,25 @@ namespace HBLConsole.Business.MessageServer
if (recipeBomInfo is RecipeBoms recipeBom)
{
Json<BatchingInfoPar>.Data.recipeBoms = recipeBom;
MessageLog.GetInstance.Show("接收到辅料信息");
}

//写配方数据到PLC
List<ushort> recipeBoms = new List<ushort>();
foreach (var item in Json<BatchingInfoPar>.Data.recipeBoms.RecipeIds)
{
foreach (var rec in item.Recipes)
{
recipeBoms.Add((ushort)rec);
}
}
if (recipeBoms.Count > 0)
{
if (ModbusTcpHelper.GetInstance.Write(1100, WriteType.HoldingRegisters, recipeBoms.ToArray()))
{
MessageLog.GetInstance.Show("成功写入配方数据");
}
}
MessageLog.GetInstance.Show("接收到辅料信息");
}

/// <summary>


+ 19
- 16
HBLConsole.Communication/ConnectHelper.cs View File

@@ -20,24 +20,27 @@ namespace HBLConsole.Communication
Json<CommunicationPar>.Read();
foreach (var item in Json<CommunicationPar>.Data.communicationSets)
{
if (item.IsActive)
if (item.ClientDeviceType == GVL.GeneralConfig.DeviceType.ToString())
{
switch (item.deviceType)
if (item.IsActive)
{
case EDeviceType.Siemens:
break;
case EDeviceType.ModbusRtu:
break;
case EDeviceType.ModbusTcp:
if (item.Device is ModbusTcp modbus)
{
ModbusTcpHelper.GetInstance.ModbusTcpConnect(modbus.IP, modbus.PortNum);
}
break;
case EDeviceType.SerialPort:
break;
default:
break;
switch (item.deviceType)
{
case EDeviceType.Siemens:
break;
case EDeviceType.ModbusRtu:
break;
case EDeviceType.ModbusTcp:
if (item.Device is ModbusTcp modbus)
{
ModbusTcpHelper.GetInstance.ModbusTcpConnect(modbus.IP, modbus.PortNum);
}
break;
case EDeviceType.SerialPort:
break;
default:
break;
}
}
}
}


+ 6
- 0
HBLConsole.Communication/HBLConsole.Communication.csproj View File

@@ -16,4 +16,10 @@
<ProjectReference Include="..\HBLConsole.Service\HBLConsole.Service.csproj" />
</ItemGroup>

<ItemGroup>
<Reference Include="BPA.Message">
<HintPath>D:\BPACommon_output\net5.0\BPA.Message.dll</HintPath>
</Reference>
</ItemGroup>

</Project>

+ 32
- 6
HBLConsole.Factory/SimpleFactory.cs View File

@@ -63,28 +63,54 @@ namespace HBLConsole.Factory
Type type = Assembly.Load(NameSpace).GetType($"{NameSpace}.MessageServer.{DeviceType}");
if (type == null)
type = Assembly.Load(NameSpace).GetType($"{NameSpace}.MessageServer.Base");
return (AbstractMessageServer)Activator.CreateInstance(type);
return Activator.CreateInstance(type) as AbstractMessageServer;
}

IControl business;
/// <summary>
/// 设备初始化
/// </summary>
public void DeviceInit()
{
string NameSpace = "HBLConsole.Business";//Load 加载的是dll的名称,GetType获取的是全命名空间下的类
Type type = Assembly.Load(NameSpace).GetType($"{NameSpace}.Devices.{DeviceType}");
IControl business = (IControl)type?.GetProperty("GetInstance").GetValue(null);
//string NameSpace = "HBLConsole.Business";//Load 加载的是dll的名称,GetType获取的是全命名空间下的类
//Type type = Assembly.Load(NameSpace).GetType($"{NameSpace}.Devices.{DeviceType}");
//IControl business = (IControl)type?.GetProperty("GetInstance").GetValue(null);
//GetBatchingInfo();
//business?.Init();
//ActionManagerment.GetInstance.Register(new Action<object>((o) => { business?.DataParse(o); }), "DataParse");
//ActionManagerment.GetInstance.Register(new Action(() => { business?.ConnectOk(); }), "ConnectOk");
//ConnectHelper.GetInstance.Init();

string NameSpace = $"HBLConsole.{DeviceType}";//Load 加载的是dll的名称,GetType获取的是全命名空间下的类
Type type = Assembly.Load(NameSpace).GetType($"{NameSpace}.Control_{DeviceType}");
business = Activator.CreateInstance(type) as IControl;
//IControl business = (IControl)type?.GetProperty("GetInstance").GetValue(null);
GetBatchingInfo();
business?.Init();
ActionManagerment.GetInstance.Register(new Action<object>((o) => { business?.DataParse(o); }), "DataParse");
ActionManagerment.GetInstance.Register(new Action(() => { business?.ConnectOk(); }), "ConnectOk");
ActionManagerment.GetInstance.Register(new Action<object>((o) => { business?.SimOrder(o); }), "SimOrder");
ConnectHelper.GetInstance.Init();
}

public IGvl GetGvl()
{
Type type = Assembly.Load("HBLConsole.GVL").GetType($"HBLConsole.GVL.{DeviceType}");
return (IGvl)Activator.CreateInstance(type);
Type type = business?.GetType();
foreach (var item in type?.GetProperties())
{
var interfaces = item.PropertyType.GetInterfaces();
if (interfaces != null)
{
foreach (var inters in interfaces)
{
if (inters.Name.Equals("IGvl"))
{
return (type?.GetProperty(item.Name).GetValue(business, null)) as IGvl;
}
}
}
}
return default;
}
}
}

+ 252
- 263
HBLConsole.GVL/Device/MORKS.cs View File

@@ -1,263 +1,252 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HBLConsole.Interface;
using System.Collections.Concurrent;
using HBLConsole.Attributes;

namespace HBLConsole.GVL
{
/// <summary>
/// MORKS 设备数据
/// </summary>
public class MORKS : IGvl
{
/// <summary>
/// 机器人取面
/// PLC -> M0.3
/// ModbusTcp -> 323
/// </summary>
public bool RobotTakeNoodle { get; set; }

/// <summary>
/// 机器人出餐
/// PLC -> M0.4
/// ModbusTcp -> 324
/// </summary>
public bool RobotOutMeal { get; set; }

/// <summary>
/// 移动转台
/// PLC -> M0.5
/// ModbusTcp -> 325
/// </summary>
public bool MoveTurntable { get; set; }


#region 临时变量
/// <summary>
/// 允许运行
/// </summary>
[Circuit(new string[] { "机器人取面", "取碗控制" }, "允许运行")]
public bool AllowRun { get; set; }

/// <summary>
/// //机器人任务互锁信号
/// </summary>
[Circuit(new string[] { "机器人取面", "出面控制" }, "机器人互锁", new bool[] { true, false })]
public bool RobotTaskInterlock { get; set; }

/// <summary>
/// 取碗互锁信号
/// </summary>
[Circuit("取碗控制", "取碗互锁", true)]
public bool TakeBowlInterlock { get; set; }

/// <summary>
/// 取面互锁信号
/// </summary>
[Circuit(new string[] { "机器人取面", "出面控制" }, "取面互锁信号", new bool[] { true, true })]
public bool TakeNoodleInterlock { get; set; }

/// <summary>
/// 出面中
/// </summary>
[Circuit("机器人取面", "出面中", true)]
public bool OutNoodleing { get; set; }

/// <summary>
/// 允许取面
/// </summary>
[Circuit(new string[] { "转台控制", "机器人取面" }, "允许取面", new bool[] { true, false })]
public bool AllowTakeNoodle { get; set; }

/// <summary>
/// 转台互锁信号
/// </summary>
public bool TurntableInterlock { get; set; }
#endregion


/// <summary>
/// 初始化完成
/// PLC -> M100.0
/// ModbusTcp -> 1120
/// </summary>
[Circuit(new string[] { "允许运行", "转台控制", "转台控制" }, "初始化完成")]
public bool InitComplete { get; set; }

/// <summary>
/// 取碗机构空闲,True:忙碌,false:空闲
/// PLC -> M100.1
/// ModbusTcp -> 1121
/// </summary>
[Circuit("取碗控制", "取碗机构空闲", true)]
public bool TakeBowlIdle { get; set; }

/// <summary>
/// 温度到达,True:表示到达,false:未到达
/// PLC -> M100.2
/// ModbusTcp -> 1122
/// </summary>
[Circuit("允许运行", "温度到达")]
public bool TemperatureReached { get; set; }

/// <summary>
/// 允许到面,配料完成
/// PLC -> M100.3
/// ModbusTcp -> 1123
/// </summary>
[Circuit("出面控制", "允许到面")]
public bool AllowFallNoodle { get; set; }

/// <summary>
/// 机器人取面完成
/// PLC -> M100.4
/// ModbusTcp -> 1124
/// </summary>
public bool RbTakeNoodleComplete { get; set; }

/// <summary>
/// 机器人倒面完成
/// PLC -> M100.5
/// ModbusTcp -> 1125
/// </summary>
public bool RbFallNoodleComplete { get; set; }

/// <summary>
/// 机器人出餐完成,上报取餐完成
/// PLC -> M100.6
/// ModbusTcp -> 1126
/// </summary>
public bool RbOutMealComplete { get; set; }

/// <summary>
/// 机器人空闲
/// PLC -> M100.7
/// ModbusTcp -> 1127
/// </summary>
[Circuit(new string[] { "机器人取面", "出面控制" }, "机器人空闲")]
public bool RobotIdle { get; set; }

/// <summary>
/// 取餐口检测
/// PLC -> M101.0
/// ModbusTcp -> 1128
/// </summary>
[Circuit("出面控制", "取餐口检测", true)]
public bool TakeMealDetect { get; set; }

/// <summary>
/// 缺碗信号,false:缺碗,true:有碗
/// PLC -> M101.1
/// ModbusTcp -> 1129
/// </summary>
public bool MissingBowl { get; set; }

/// <summary>
/// 设备初始化中,执行中等于1,2秒后复位
/// PLC -> M101.2
/// ModbusTcp -> 1130
/// </summary>
public bool DeviceIniting { get; set; }

/// <summary>
/// 转台下限检测
/// PLC -> M101.3
/// ModbusTcp -> 1131
/// </summary>
[Circuit("转台控制", "转台下限检测有物料")]
public bool TurntableLowerLimit { get; set; }

/// <summary>
/// 缺碗信号 2
/// PLC -> M101.4
/// ModbusTcp -> 1132
/// </summary>
public bool MissingBowlSignal2 { get; set; }

/// <summary>
/// 转台上限检测
/// PLC -> M101.5
/// ModbusTcp -> 1133
/// </summary>
public bool TurntableUpLimit { get; set; }

/// <summary>
/// 转台移动到位
/// PLC -> M101.7
/// ModbusTcp -> 1135
/// </summary>
[Circuit(new string[] { "转台控制", "机器人取面" }, "转台移动到位")]
public bool TurntableMoveInPlace { get; set; }

/// <summary>
/// 煮面炉状态,True:忙碌,false:空闲
/// M102.0 - M102.5
/// 1136 - 1141
/// </summary>
public bool[] NoodleCookerStatus { get; set; } = new bool[6] { false, false, false, false, false, false };

/// <summary>
/// 煮面完成,上升后给信号
/// M103.0 - M103.5
/// 1144 - 1149
/// </summary>
public bool[] CookNoodlesComplete { get; set; } = new bool[6] { false, false, false, false, false, false };

/// <summary>
/// 配方编号
/// PLC -> VW0
/// ModbusTcp -> 100
/// </summary>
public ushort RecipeNumber { get; set; }

/// <summary>
/// 转台位置
/// PLC -> VW2
/// ModbusTcp -> 101
/// </summary>
public ushort TurntableLoc { get; set; }

/// <summary>
/// 到面至煮面炉位置
/// PLC -> VW4
/// ModbusTcp -> 102
/// </summary>
public ushort FallNoodleLoc { get; set; }

/// <summary>
/// 取面位置
/// PLC -> VW6
/// ModbusTcp -> 103
/// </summary>
public ushort TakeNoodleLoc { get; set; }

/// <summary>
/// 机器人取面位置队列
/// </summary>
[Circuit(new string[] { "转台控制", "机器人取面" }, "有机器人取面队列")]
public ConcurrentQueue<OrderLocInfo> RBTakeNoodleTask { get; set; } = new ConcurrentQueue<OrderLocInfo>();

/// <summary>
/// 出碗队列
/// </summary>
[Circuit("取碗控制", "有取碗队列数量")]
public ConcurrentQueue<OrderLocInfo> TakeBowlTask { get; set; } = new ConcurrentQueue<OrderLocInfo>();

}

public class OrderLocInfo
{
public string SuborderId { get; set; }
public ushort Loc { get; set; }
public ushort RecipeNumber { get; set; }
public int BatchingId { get; set; }
}




}
//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;
//using System.Threading.Tasks;
//using HBLConsole.Interface;
//using System.Collections.Concurrent;
//using HBLConsole.Attributes;
//using HBLConsole.Model;

//namespace HBLConsole.GVL
//{
// /// <summary>
// /// MORKS 设备数据
// /// </summary>
// public class MORKS : IGvl
// {
// /// <summary>
// /// 机器人取面
// /// PLC -> M0.3
// /// ModbusTcp -> 323
// /// </summary>
// public bool RobotTakeNoodle { get; set; }

// /// <summary>
// /// 机器人出餐
// /// PLC -> M0.4
// /// ModbusTcp -> 324
// /// </summary>
// public bool RobotOutMeal { get; set; }

// /// <summary>
// /// 移动转台
// /// PLC -> M0.5
// /// ModbusTcp -> 325
// /// </summary>
// public bool MoveTurntable { get; set; }


// #region 临时变量
// /// <summary>
// /// 允许运行
// /// </summary>
// [Circuit(new string[] { "机器人取面", "取碗控制" }, "允许运行")]
// public bool AllowRun { get; set; }

// /// <summary>
// /// //机器人任务互锁信号
// /// </summary>
// [Circuit(new string[] { "机器人取面", "出面控制" }, "机器人互锁", new bool[] { true, false })]
// public bool RobotTaskInterlock { get; set; }

// /// <summary>
// /// 取碗互锁信号
// /// </summary>
// [Circuit("取碗控制", "取碗互锁", true)]
// public bool TakeBowlInterlock { get; set; }

// /// <summary>
// /// 取面互锁信号
// /// </summary>
// [Circuit(new string[] { "机器人取面", "出面控制" }, "取面互锁信号", new bool[] { true, true })]
// public bool TakeNoodleInterlock { get; set; }

// /// <summary>
// /// 出面中
// /// </summary>
// [Circuit("机器人取面", "出面中", true)]
// public bool OutNoodleing { get; set; }

// /// <summary>
// /// 允许取面
// /// </summary>
// [Circuit(new string[] { "转台控制", "机器人取面" }, "允许取面", new bool[] { true, false })]
// public bool AllowTakeNoodle { get; set; }

// /// <summary>
// /// 转台互锁信号
// /// </summary>
// public bool TurntableInterlock { get; set; }
// #endregion


// /// <summary>
// /// 初始化完成
// /// PLC -> M100.0
// /// ModbusTcp -> 1120
// /// </summary>
// [Circuit(new string[] { "允许运行", "转台控制", "转台控制" }, "初始化完成")]
// public bool InitComplete { get; set; }

// /// <summary>
// /// 取碗机构空闲,True:忙碌,false:空闲
// /// PLC -> M100.1
// /// ModbusTcp -> 1121
// /// </summary>
// [Circuit("取碗控制", "取碗机构空闲", true)]
// public bool TakeBowlIdle { get; set; }

// /// <summary>
// /// 温度到达,True:表示到达,false:未到达
// /// PLC -> M100.2
// /// ModbusTcp -> 1122
// /// </summary>
// [Circuit("允许运行", "温度到达")]
// public bool TemperatureReached { get; set; }

// /// <summary>
// /// 允许到面,配料完成
// /// PLC -> M100.3
// /// ModbusTcp -> 1123
// /// </summary>
// [Circuit("出面控制", "允许到面")]
// public bool AllowFallNoodle { get; set; }

// /// <summary>
// /// 机器人取面完成
// /// PLC -> M100.4
// /// ModbusTcp -> 1124
// /// </summary>
// public bool RbTakeNoodleComplete { get; set; }

// /// <summary>
// /// 机器人倒面完成
// /// PLC -> M100.5
// /// ModbusTcp -> 1125
// /// </summary>
// public bool RbFallNoodleComplete { get; set; }

// /// <summary>
// /// 机器人出餐完成,上报取餐完成
// /// PLC -> M100.6
// /// ModbusTcp -> 1126
// /// </summary>
// public bool RbOutMealComplete { get; set; }

// /// <summary>
// /// 机器人空闲
// /// PLC -> M100.7
// /// ModbusTcp -> 1127
// /// </summary>
// [Circuit(new string[] { "机器人取面", "出面控制" }, "机器人空闲")]
// public bool RobotIdle { get; set; }

// /// <summary>
// /// 取餐口检测
// /// PLC -> M101.0
// /// ModbusTcp -> 1128
// /// </summary>
// [Circuit("出面控制", "取餐口检测", true)]
// public bool TakeMealDetect { get; set; }

// /// <summary>
// /// 缺碗信号,false:缺碗,true:有碗
// /// PLC -> M101.1
// /// ModbusTcp -> 1129
// /// </summary>
// public bool MissingBowl { get; set; }

// /// <summary>
// /// 设备初始化中,执行中等于1,2秒后复位
// /// PLC -> M101.2
// /// ModbusTcp -> 1130
// /// </summary>
// public bool DeviceIniting { get; set; }

// /// <summary>
// /// 转台下限检测
// /// PLC -> M101.3
// /// ModbusTcp -> 1131
// /// </summary>
// [Circuit("转台控制", "转台下限检测有物料")]
// public bool TurntableLowerLimit { get; set; }

// /// <summary>
// /// 缺碗信号 2
// /// PLC -> M101.4
// /// ModbusTcp -> 1132
// /// </summary>
// public bool MissingBowlSignal2 { get; set; }

// /// <summary>
// /// 转台上限检测
// /// PLC -> M101.5
// /// ModbusTcp -> 1133
// /// </summary>
// public bool TurntableUpLimit { get; set; }

// /// <summary>
// /// 转台移动到位
// /// PLC -> M101.7
// /// ModbusTcp -> 1135
// /// </summary>
// [Circuit(new string[] { "转台控制", "机器人取面" }, "转台移动到位")]
// public bool TurntableMoveInPlace { get; set; }

// /// <summary>
// /// 煮面炉状态,True:忙碌,false:空闲
// /// M102.0 - M102.5
// /// 1136 - 1141
// /// </summary>
// public bool[] NoodleCookerStatus { get; set; } = new bool[6] { false, false, false, false, false, false };

// /// <summary>
// /// 煮面完成,上升后给信号
// /// M103.0 - M103.5
// /// 1144 - 1149
// /// </summary>
// public bool[] CookNoodlesComplete { get; set; } = new bool[6] { false, false, false, false, false, false };

// /// <summary>
// /// 配方编号
// /// PLC -> VW0
// /// ModbusTcp -> 100
// /// </summary>
// public ushort RecipeNumber { get; set; }

// /// <summary>
// /// 转台位置
// /// PLC -> VW2
// /// ModbusTcp -> 101
// /// </summary>
// public ushort TurntableLoc { get; set; }

// /// <summary>
// /// 到面至煮面炉位置
// /// PLC -> VW4
// /// ModbusTcp -> 102
// /// </summary>
// public ushort FallNoodleLoc { get; set; }

// /// <summary>
// /// 取面位置
// /// PLC -> VW6
// /// ModbusTcp -> 103
// /// </summary>
// public ushort TakeNoodleLoc { get; set; }

// /// <summary>
// /// 机器人取面位置队列
// /// </summary>
// [Circuit(new string[] { "转台控制", "机器人取面" }, "有机器人取面队列")]
// public ConcurrentQueue<OrderLocInfo> RBTakeNoodleTask { get; set; } = new ConcurrentQueue<OrderLocInfo>();

// /// <summary>
// /// 出碗队列
// /// </summary>
// [Circuit("取碗控制", "有取碗队列数量")]
// public ConcurrentQueue<OrderLocInfo> TakeBowlTask { get; set; } = new ConcurrentQueue<OrderLocInfo>();

// }
//}

+ 1
- 0
HBLConsole.GVL/GeneralConfig.cs View File

@@ -5,6 +5,7 @@ using System.Text;
using System.Threading.Tasks;
using BPA.Message;
using BPA.Message.Enum;
using BPA.Models;

namespace HBLConsole.GVL
{


+ 3
- 0
HBLConsole.GVL/HBLConsole.GVL.csproj View File

@@ -22,6 +22,9 @@
<Reference Include="BPA.Message">
<HintPath>D:\BPACommon_output\net5.0\BPA.Message.dll</HintPath>
</Reference>
<Reference Include="BPA.Models">
<HintPath>D:\BPACommon_output\net5.0\BPA.Models.dll</HintPath>
</Reference>
<Reference Include="BPA.Utility">
<HintPath>D:\BPACommon_output\net5.0\BPA.Utility.dll</HintPath>
</Reference>


+ 1
- 1
HBLConsole.Interface/IControl.cs View File

@@ -11,7 +11,7 @@ namespace HBLConsole.Interface
void Main();
void Init();
void ReadData();
void SimOrder();
void SimOrder<T>(T simOrder);
void DataParse<T>(T order);
void ConnectOk();
}


+ 38
- 0
HBLConsole.MORKD/Control_MORKD.cs View File

@@ -0,0 +1,38 @@
using System;
using HBLConsole.Interface;

namespace HBLConsole.MORKD
{
public class Control_MORKD : IControl
{
public void ConnectOk()
{

}

public void DataParse<T>(T order)
{

}

public void Init()
{

}

public void Main()
{

}

public void ReadData()
{

}

public void SimOrder<T>(T simOrder)
{

}
}
}

+ 13
- 0
HBLConsole.MORKD/GVL_MORKD.cs View File

@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HBLConsole.Interface;

namespace HBLConsole.MORKD
{
public class GVL_MORKD : IGvl
{
}
}

+ 13
- 0
HBLConsole.MORKD/HBLConsole.MORKD.csproj View File

@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\HBLConsole.Attribute\HBLConsole.Attributes.csproj" />
<ProjectReference Include="..\HBLConsole.Communication\HBLConsole.Communication.csproj" />
<ProjectReference Include="..\HBLConsole.Factory\HBLConsole.Factory.csproj" />
</ItemGroup>

</Project>

+ 598
- 0
HBLConsole.MORKS/Control_MORKS.cs View File

@@ -0,0 +1,598 @@
//#define test
using BPA.Message;
using HBLConsole.Communication;
using HBLConsole.Factory;
using HBLConsole.Interface;
using HBLConsole.Model;
using HBLConsole.Service;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using BPA.Message.Enum;


namespace HBLConsole.MORKS
{
public class Control_MORKS : IControl
{
public GVL_MORKS mORKS { get; set; } = new GVL_MORKS();

public void Init()
{
Test();
ActionManagerment.GetInstance.Register(new Action(() => { DeviceInit(); }), "InitCommand");
}

public void ConnectOk()
{
//WriteRecipeBoms();
ReadData();
Main();
//ResetProgram();
MessageLog.GetInstance.Show("MORKS 设备初始化完成");
}

/// <summary>
/// 测试程序
/// </summary>
private void Test()
{
#if test
ThreadManagerment.GetInstance.StartLong(new Action(() =>
{
while (Json<MorkOrderPushPar>.GetInstance.Base.morkOrderPushes.Count > 0)
{
var result = Json<MorkOrderPushPar>.GetInstance.Base.morkOrderPushes.ElementAt(0);

SimpleFactory.GetInstance.OrderChanged(result.OrderPush.SuborderId, ORDER_STATUS.COOKING);
MessageLog.GetInstance.Show($"{result.OrderPush.GoodsName},{ORDER_STATUS.COOKING}");
Thread.Sleep(5000);

SimpleFactory.GetInstance.OrderChanged(result.OrderPush.SuborderId, ORDER_STATUS.COMPLETED_COOK);
MessageLog.GetInstance.Show($"{result.OrderPush.GoodsName},{ORDER_STATUS.COMPLETED_COOK}");
Thread.Sleep(5000);

SimpleFactory.GetInstance.OrderChanged(result.OrderPush.SuborderId, ORDER_STATUS.COMPLETED_TAKE);
MessageLog.GetInstance.Show($"{result.OrderPush.GoodsName},{ORDER_STATUS.COMPLETED_TAKE}");
Thread.Sleep(5000);

Json<MorkOrderPushPar>.GetInstance.Base.morkOrderPushes.RemoveAt(0);
}
Thread.Sleep(500);
}), "test");
#endif
}

private void Readbool(ushort startAddress, ushort len, Action<bool[]> action)
{
object result;
result = ModbusTcpHelper.GetInstance.Read(startAddress, ReadType.Coils, len);
if (result != null)
{
if (result is bool[] bools)
{
if (bools.Length == len)
{
action(bools);
}
}
}
}

/// <summary>
/// 复位程序
/// </summary>
private void ResetProgram()
{
ThreadManagerment.GetInstance.StartLong(new Action(() =>
{
if (RTrig.GetInstance("ResetProgram").Start(mORKS.DeviceIniting))
{
ThreadManagerment.GetInstance.StopTask("MainTask", new Action(() =>
{
mORKS.AllowRun = false;
TakeBowlId = string.Empty;
IngredientsCompleteId = string.Empty;
CookNodelId = new string[6] { string.Empty, string.Empty, string.Empty, string.Empty, string.Empty, string.Empty, };
mORKS.RobotTaskInterlock = false;
OutMealId = string.Empty;
mORKS.TakeBowlInterlock = false;
mORKS.TakeNoodleInterlock = false;
mORKS.OutNoodleing = false;
Main();
}));
}
Thread.Sleep(10);
}), "ResetProgram");
}

/// <summary>
/// 数据读取
/// </summary>
public void ReadData()
{
ThreadManagerment.GetInstance.StartLong(new Action(() =>
{
Readbool(323, 3, new Action<bool[]>((bools) =>
{
mORKS.RobotTakeNoodle = bools[0];
mORKS.RobotOutMeal = bools[1];
mORKS.MoveTurntable = bools[2];
}));

Readbool(1120, 16, new Action<bool[]>((bools) =>
{
mORKS.InitComplete = bools[0];
mORKS.TakeBowlIdle = bools[1];
mORKS.TemperatureReached = bools[2];
mORKS.AllowFallNoodle = bools[3];
mORKS.RbTakeNoodleComplete = bools[4];
mORKS.RbFallNoodleComplete = bools[5];
mORKS.RbOutMealComplete = bools[6];
mORKS.RobotIdle = bools[7];
mORKS.TakeMealDetect = bools[8];
mORKS.MissingBowl = bools[9];
mORKS.DeviceIniting = bools[10];
mORKS.TurntableLowerLimit = bools[11];
mORKS.MissingBowlSignal2 = bools[12];
mORKS.TurntableUpLimit = bools[13];
mORKS.TurntableMoveInPlace = bools[15];
}));

Readbool(1136, 6, new Action<bool[]>((bools) =>
{
for (int i = 0; i < 6; i++)
{
mORKS.NoodleCookerStatus[i] = bools[i];
}
}));

Readbool(1144, 6, new Action<bool[]>((bools) =>
{
for (int i = 0; i < 6; i++)
{
mORKS.CookNoodlesComplete[i] = bools[i];
}
}));

Thread.Sleep(500);
}), "ReadPLCData");
}

public void SimOrder<T>(T simOrder)
{
if (simOrder != null)
{
if (simOrder is SimOrderData simOrderData)
{
string subId = Guid.NewGuid().ToString();
mORKS.RBTakeNoodleTask.Enqueue(new OrderLocInfo() { Loc = simOrderData.NoodleLoc, SuborderId = subId });
mORKS.TakeBowlTask.Enqueue(new OrderLocInfo() { Loc = simOrderData.BowlLoc, SuborderId = subId });
MessageLog.GetInstance.Show($"添加订单:面条位置【{simOrderData.NoodleLoc}】,碗位置【{simOrderData.BowlLoc}】");
}
}
}

/// <summary>
/// 数据解析
/// </summary>
public void DataParse<T>(T order)
{
if (order is MorkOrderPush morkOrderPush)
{
foreach (var item in morkOrderPush.GoodBatchings)
{
var res = Json<BatchingInfoPar>.Data.orderMaterialDelivery.BatchingInfo.FirstOrDefault(p => p.BatchingId == item.BatchingId);
if (res != null)
{
if (ushort.TryParse(res.BatchingLoc, out ushort loc))
{
if (loc >= 1 && loc <= 5)
{
mORKS.RBTakeNoodleTask.Enqueue(new OrderLocInfo() { Loc = loc, SuborderId = morkOrderPush.SuborderId, BatchingId = res.BatchingId });
}
else if (loc >= 10 && loc <= 11)
{
int index = Array.FindIndex(Json<BatchingInfoPar>.Data.recipeBoms.RecipeIds.ToArray(), p => p.RecipeId == morkOrderPush.RecipeId);
index++;
mORKS.TakeBowlTask.Enqueue(new OrderLocInfo() { Loc = loc, SuborderId = morkOrderPush.SuborderId, RecipeNumber = (index >= 1 && index <= 10) ? (ushort)index : (ushort)0 });
}
}
}
}
}
}

#region 临时变量
/// <summary>
/// 取碗订单ID
/// </summary>
string TakeBowlId = string.Empty;

/// <summary>
/// 配料完成订单ID
/// </summary>
string IngredientsCompleteId = string.Empty;

/// <summary>
/// 煮面口对应的订单ID
/// </summary>
string[] CookNodelId = new string[6] { string.Empty, string.Empty, string.Empty, string.Empty, string.Empty, string.Empty, };

/// <summary>
/// 出餐订单ID
/// </summary>
string OutMealId = string.Empty;

/// <summary>
/// 转台位置轮询
/// </summary>
List<ushort> TurntableLoc = new List<ushort>();

#endregion

public void Main()
{
ThreadManagerment.GetInstance.StartLong(new Action(() =>
{
mORKS.AllowRun = mORKS.InitComplete && !mORKS.TemperatureReached;

TakeBowlTask();

TakeNoodleTask();

OutNoodleTask();

SingleDetect();

TurntableControl();

Thread.Sleep(100);

}), "MainTask");
}

/// <summary>
/// 取碗控制
/// </summary>
private void TakeBowlTask()
{
if (mORKS.AllowRun && mORKS.TakeBowlTask.Count > 0 && !mORKS.TakeBowlIdle && !mORKS.TakeBowlInterlock)
{
if (mORKS.TakeBowlTask.TryDequeue(out OrderLocInfo orderLocInfo))
{
TakeBowlId = orderLocInfo.SuborderId;
TakeBowlControl(orderLocInfo.Loc);
SetRecipeNumber(orderLocInfo.RecipeNumber);
SimpleFactory.GetInstance.OrderChanged(TakeBowlId, ORDER_STATUS.COOKING);
MessageLog.GetInstance.Show($"订单【{TakeBowlId}】执行取碗控制,位置:[{orderLocInfo.Loc}]");
}
mORKS.TakeBowlInterlock = true;
}
}

/// <summary>
/// 转台控制
/// </summary>
private void TurntableControl()
{
if (mORKS.TurntableMoveInPlace && mORKS.InitComplete && !mORKS.AllowTakeNoodle && mORKS.RBTakeNoodleTask.Count > 0)
{

if (mORKS.TurntableLowerLimit)
{
SetTurntableLoc(mORKS.RBTakeNoodleTask.ElementAt(0).Loc);
MoveTurntable();
mORKS.AllowTakeNoodle = true;
TurntableLoc.Clear();
MessageLog.GetInstance.Show("转台位置OK");
}
else
{

if (!mORKS.TurntableInterlock)
{
var result = Json<BatchingInfoPar>.Data.orderMaterialDelivery.BatchingInfo.Where(p => p.BatchingId == mORKS.RBTakeNoodleTask.ElementAt(0).BatchingId).ToList();
if (result != null)
{
foreach (var item in result)
{
if (ushort.TryParse(item.BatchingLoc, out ushort loc))
{
if (TurntableLoc.Contains(loc))
{
SetTurntableLoc(loc);
MoveTurntable();
mORKS.TurntableInterlock = true;
TurntableLoc.Add(loc);
return;
}
}
}
MessageLog.GetInstance.Show("转台位置缺少物料");
}
}
}
}
}

/// <summary>
/// 取面任务
/// </summary>
private void TakeNoodleTask()
{
//取面控制
if (mORKS.AllowRun && mORKS.RobotIdle && !mORKS.RobotTaskInterlock && mORKS.AllowTakeNoodle && mORKS.TurntableMoveInPlace && !mORKS.TakeNoodleInterlock && !mORKS.OutNoodleing && mORKS.RBTakeNoodleTask.Count > 0)
{
int loc = Array.FindIndex(mORKS.NoodleCookerStatus, p => p == false);//查找煮面炉空闲位置
if (loc >= 0 && loc <= 5)
{
if (mORKS.RBTakeNoodleTask.TryDequeue(out OrderLocInfo orderLocInfo))
{
//设置转台位置
SetTurntableLoc(orderLocInfo.Loc);
//设置倒面位置

CookNodelId[loc] = orderLocInfo.SuborderId;
SetFallNoodleLoc((ushort)(loc + 1));

//机器人开始取面
RobotTakeNoodle();
SimpleFactory.GetInstance.OrderChanged(orderLocInfo.SuborderId, ORDER_STATUS.COOKING);
MessageLog.GetInstance.Show($"订单【{orderLocInfo.SuborderId}】,转台:[{orderLocInfo}],煮面栏:[{loc + 1}]");
mORKS.TakeNoodleInterlock = true;
}
}

}
}

/// <summary>
/// 出餐控制
/// </summary>
private void OutNoodleTask()
{
if (mORKS.AllowFallNoodle && mORKS.RobotTaskInterlock && !mORKS.TakeNoodleInterlock && mORKS.RobotIdle && !mORKS.TakeMealDetect)
{
int loc = Array.FindIndex(CookNodelId, p => p == IngredientsCompleteId && p.Length > 0);
if (loc >= 0 && loc <= 5)
{
if (mORKS.CookNoodlesComplete[loc])
{
SetTakeNoodleLoc((ushort)(loc + 1));
RobotOutMeal();
CookNoodleStatusReset((ushort)(loc + 1));
ResetAllowFallNoodle();
OutMealId = IngredientsCompleteId;
IngredientsCompleteId = string.Empty;
CookNodelId[loc] = string.Empty;
MessageLog.GetInstance.Show($"{loc + 1}号位置出餐控制");
mORKS.OutNoodleing = true;
}
}
}
}

/// <summary>
/// 信号检测
/// </summary>
private void SingleDetect()
{
//允许倒面信号检测
if (RTrig.GetInstance("AllowFallNoodle").Start(mORKS.AllowFallNoodle))
{
IngredientsCompleteId = TakeBowlId;
TakeBowlId = string.Empty;
MessageLog.GetInstance.Show($"允许到面,{IngredientsCompleteId}");
mORKS.TakeBowlInterlock = false;
}

//出餐完成信号检测
if (RTrig.GetInstance("CompleteChange").Start(mORKS.RbOutMealComplete))
{
SimpleFactory.GetInstance.OrderChanged(OutMealId, ORDER_STATUS.COMPLETED_COOK);
MessageLog.GetInstance.Show($"订单【{OutMealId}】制作完成");
mORKS.OutNoodleing = false;
}

//取餐完成逻辑处理
if (DelayRTrig.GetInstance("CompleteChange1").Start(mORKS.RbOutMealComplete && !mORKS.TakeMealDetect, 2))
{
SimpleFactory.GetInstance.OrderChanged(OutMealId, ORDER_STATUS.COMPLETED_TAKE);
MessageLog.GetInstance.Show($"订单【{OutMealId}】取餐完成");
var RemoveItem = Json<MorkOrderPushPar>.Data.morkOrderPushes.FirstOrDefault(p => p.OrderPush.SuborderId == OutMealId);
if (RemoveItem != null)
{
Json<MorkOrderPushPar>.Data.morkOrderPushes.Remove(RemoveItem);
}
ResetCookComplete();
OutMealId = string.Empty;
}

//机器人取面完成信号检测
if (RTrig.GetInstance("TakeNoodleComplete").Start(mORKS.RbTakeNoodleComplete))
{
mORKS.TakeNoodleInterlock = false;
mORKS.AllowTakeNoodle = false;
MessageLog.GetInstance.Show("取面完成");
TakeNoodleCompleteReset();
}

//转台到位检测
if (RTrig.GetInstance("TurntableInPlace").Start(mORKS.TurntableMoveInPlace))
{
mORKS.TurntableInterlock = false;
}

int OutMealRequstCount = mORKS.CookNoodlesComplete.Where(p => p == true).ToList().Count;
int mlCount = mORKS.NoodleCookerStatus.Where(p => p == true).ToList().Count;
mORKS.RobotTaskInterlock = OutMealRequstCount > 0 && mORKS.AllowFallNoodle && (mlCount >= 2 || mORKS.RBTakeNoodleTask.Count == 0);
}


#region PLC 控制函数

/// <summary>
/// 写入配方数据到 PLC
/// </summary>
private void WriteRecipeBoms()
{
List<ushort> recipeBoms = new List<ushort>();
foreach (var item in Json<BatchingInfoPar>.Data.recipeBoms.RecipeIds)
{
foreach (var rec in item.Recipes)
{
recipeBoms.Add((ushort)rec);
}
}
if (recipeBoms.Count > 0)
{
if (ModbusTcpHelper.GetInstance.Write(1100, WriteType.HoldingRegisters, recipeBoms.ToArray()))
{
MessageLog.GetInstance.Show("成功写入配方数据");
}
}
}

/// <summary>
/// 转台移动
/// </summary>
private void MoveTurntable()
{
ModbusTcpHelper.GetInstance.Write(325, WriteType.Coils, true);
}

/// <summary>
/// 取面完成复位
/// </summary>
private void TakeNoodleCompleteReset()
{
ModbusTcpHelper.GetInstance.Write(1124, WriteType.Coils, false);
}

/// <summary>
/// 指定煮面口状态复位
/// </summary>
/// <param name="num"></param>
private void CookNoodleStatusReset(int num)
{
if (num >= 1 && num <= 6)
{
ushort addRess = (ushort)(1136 + num - 1);
ModbusTcpHelper.GetInstance.Write(addRess, WriteType.Coils, false);
MessageLog.GetInstance.Show($"{num}号煮面口占用复位");
}

}

/// <summary>
/// 写配方编号
/// </summary>
/// <param name="num"></param>
private void SetRecipeNumber(ushort num)
{
ModbusTcpHelper.GetInstance.Write(100, WriteType.HoldingRegisters, num);
}

/// <summary>
/// 设置转台位置
/// </summary>
/// <param name="loc"></param>
private void SetTurntableLoc(ushort loc)
{
ModbusTcpHelper.GetInstance.Write(101, WriteType.HoldingRegisters, loc);
}

/// <summary>
/// 设置倒面位置
/// </summary>
/// <param name="loc"></param>
private void SetFallNoodleLoc(ushort loc)
{
ModbusTcpHelper.GetInstance.Write(102, WriteType.HoldingRegisters, loc);
}

/// <summary>
/// 设置取面位置
/// </summary>
/// <param name="loc"></param>
private void SetTakeNoodleLoc(ushort loc)
{
ModbusTcpHelper.GetInstance.Write(103, WriteType.HoldingRegisters, loc);
}

/// <summary>
/// 取碗控制
/// </summary>
/// <param name="loc"></param>
private void TakeBowlControl(ushort loc)
{
if (loc == 10)
{
ModbusTcpHelper.GetInstance.Write(321, WriteType.Coils, true);
}
else if (loc == 11)
{
ModbusTcpHelper.GetInstance.Write(322, WriteType.Coils, true);
}
}

/// <summary>
/// 机器人取面
/// </summary>
private void RobotTakeNoodle()
{
ModbusTcpHelper.GetInstance.Write(323, WriteType.Coils, true);
}

/// <summary>
/// 机器人取餐
/// </summary>
private void RobotOutMeal()
{
ModbusTcpHelper.GetInstance.Write(324, WriteType.Coils, true);
var result = ModbusTcpHelper.GetInstance.Read(324, ReadType.Coils);
if (result is bool res)
while (!res)
{
ModbusTcpHelper.GetInstance.Write(324, WriteType.Coils, true);
}
}

/// <summary>
/// 制作完成信号复位
/// </summary>
private void ResetCookComplete()
{
ModbusTcpHelper.GetInstance.Write(1126, WriteType.Coils, false);
}

/// <summary>
/// 复位允许取面信号
/// </summary>
private void ResetAllowFallNoodle()
{
ModbusTcpHelper.GetInstance.Write(1123, WriteType.Coils, false);
}

/// <summary>
/// 设备初始化
/// </summary>
public async void DeviceInit()
{
ModbusTcpHelper.GetInstance.Write(320, WriteType.Coils, true);
await Task.Delay(1000);
ModbusTcpHelper.GetInstance.Write(320, WriteType.Coils, false);

}
#endregion



}

}


+ 252
- 0
HBLConsole.MORKS/GVL_MORKS.cs View File

@@ -0,0 +1,252 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HBLConsole.Interface;
using System.Collections.Concurrent;
using HBLConsole.Attributes;
using HBLConsole.Model;

namespace HBLConsole.MORKS
{
/// <summary>
/// MORKS 设备数据
/// </summary>
public class GVL_MORKS : IGvl
{
/// <summary>
/// 机器人取面
/// PLC -> M0.3
/// ModbusTcp -> 323
/// </summary>
public bool RobotTakeNoodle { get; set; }

/// <summary>
/// 机器人出餐
/// PLC -> M0.4
/// ModbusTcp -> 324
/// </summary>
public bool RobotOutMeal { get; set; }

/// <summary>
/// 移动转台
/// PLC -> M0.5
/// ModbusTcp -> 325
/// </summary>
public bool MoveTurntable { get; set; }


#region 临时变量
/// <summary>
/// 允许运行
/// </summary>
[Circuit(new string[] { "机器人取面", "取碗控制" }, "允许运行")]
public bool AllowRun { get; set; }

/// <summary>
/// //机器人任务互锁信号
/// </summary>
[Circuit(new string[] { "机器人取面", "出面控制" }, "机器人互锁", new bool[] { true, false })]
public bool RobotTaskInterlock { get; set; }

/// <summary>
/// 取碗互锁信号
/// </summary>
[Circuit("取碗控制", "取碗互锁", true)]
public bool TakeBowlInterlock { get; set; }

/// <summary>
/// 取面互锁信号
/// </summary>
[Circuit(new string[] { "机器人取面", "出面控制" }, "取面互锁信号", new bool[] { true, true })]
public bool TakeNoodleInterlock { get; set; }

/// <summary>
/// 出面中
/// </summary>
[Circuit("机器人取面", "出面中", true)]
public bool OutNoodleing { get; set; }

/// <summary>
/// 允许取面
/// </summary>
[Circuit(new string[] { "转台控制", "机器人取面" }, "允许取面", new bool[] { true, false })]
public bool AllowTakeNoodle { get; set; }

/// <summary>
/// 转台互锁信号
/// </summary>
public bool TurntableInterlock { get; set; }
#endregion


/// <summary>
/// 初始化完成
/// PLC -> M100.0
/// ModbusTcp -> 1120
/// </summary>
[Circuit(new string[] { "允许运行", "转台控制", "转台控制" }, "初始化完成")]
public bool InitComplete { get; set; }

/// <summary>
/// 取碗机构空闲,True:忙碌,false:空闲
/// PLC -> M100.1
/// ModbusTcp -> 1121
/// </summary>
[Circuit("取碗控制", "取碗机构空闲", true)]
public bool TakeBowlIdle { get; set; }

/// <summary>
/// 温度到达,True:表示到达,false:未到达
/// PLC -> M100.2
/// ModbusTcp -> 1122
/// </summary>
[Circuit("允许运行", "温度到达")]
public bool TemperatureReached { get; set; }

/// <summary>
/// 允许到面,配料完成
/// PLC -> M100.3
/// ModbusTcp -> 1123
/// </summary>
[Circuit("出面控制", "允许到面")]
public bool AllowFallNoodle { get; set; }

/// <summary>
/// 机器人取面完成
/// PLC -> M100.4
/// ModbusTcp -> 1124
/// </summary>
public bool RbTakeNoodleComplete { get; set; }

/// <summary>
/// 机器人倒面完成
/// PLC -> M100.5
/// ModbusTcp -> 1125
/// </summary>
public bool RbFallNoodleComplete { get; set; }

/// <summary>
/// 机器人出餐完成,上报取餐完成
/// PLC -> M100.6
/// ModbusTcp -> 1126
/// </summary>
public bool RbOutMealComplete { get; set; }

/// <summary>
/// 机器人空闲
/// PLC -> M100.7
/// ModbusTcp -> 1127
/// </summary>
[Circuit(new string[] { "机器人取面", "出面控制" }, "机器人空闲")]
public bool RobotIdle { get; set; }

/// <summary>
/// 取餐口检测
/// PLC -> M101.0
/// ModbusTcp -> 1128
/// </summary>
[Circuit("出面控制", "取餐口检测", true)]
public bool TakeMealDetect { get; set; }

/// <summary>
/// 缺碗信号,false:缺碗,true:有碗
/// PLC -> M101.1
/// ModbusTcp -> 1129
/// </summary>
public bool MissingBowl { get; set; }

/// <summary>
/// 设备初始化中,执行中等于1,2秒后复位
/// PLC -> M101.2
/// ModbusTcp -> 1130
/// </summary>
public bool DeviceIniting { get; set; }

/// <summary>
/// 转台下限检测
/// PLC -> M101.3
/// ModbusTcp -> 1131
/// </summary>
[Circuit("转台控制", "转台下限检测有物料")]
public bool TurntableLowerLimit { get; set; }

/// <summary>
/// 缺碗信号 2
/// PLC -> M101.4
/// ModbusTcp -> 1132
/// </summary>
public bool MissingBowlSignal2 { get; set; }

/// <summary>
/// 转台上限检测
/// PLC -> M101.5
/// ModbusTcp -> 1133
/// </summary>
public bool TurntableUpLimit { get; set; }

/// <summary>
/// 转台移动到位
/// PLC -> M101.7
/// ModbusTcp -> 1135
/// </summary>
[Circuit(new string[] { "转台控制", "机器人取面" }, "转台移动到位")]
public bool TurntableMoveInPlace { get; set; }

/// <summary>
/// 煮面炉状态,True:忙碌,false:空闲
/// M102.0 - M102.5
/// 1136 - 1141
/// </summary>
public bool[] NoodleCookerStatus { get; set; } = new bool[6] { false, false, false, false, false, false };

/// <summary>
/// 煮面完成,上升后给信号
/// M103.0 - M103.5
/// 1144 - 1149
/// </summary>
public bool[] CookNoodlesComplete { get; set; } = new bool[6] { false, false, false, false, false, false };

/// <summary>
/// 配方编号
/// PLC -> VW0
/// ModbusTcp -> 100
/// </summary>
public ushort RecipeNumber { get; set; }

/// <summary>
/// 转台位置
/// PLC -> VW2
/// ModbusTcp -> 101
/// </summary>
public ushort TurntableLoc { get; set; }

/// <summary>
/// 到面至煮面炉位置
/// PLC -> VW4
/// ModbusTcp -> 102
/// </summary>
public ushort FallNoodleLoc { get; set; }

/// <summary>
/// 取面位置
/// PLC -> VW6
/// ModbusTcp -> 103
/// </summary>
public ushort TakeNoodleLoc { get; set; }

/// <summary>
/// 机器人取面位置队列
/// </summary>
[Circuit(new string[] { "转台控制", "机器人取面" }, "有机器人取面队列")]
public ConcurrentQueue<OrderLocInfo> RBTakeNoodleTask { get; set; } = new ConcurrentQueue<OrderLocInfo>();

/// <summary>
/// 出碗队列
/// </summary>
[Circuit("取碗控制", "有取碗队列数量")]
public ConcurrentQueue<OrderLocInfo> TakeBowlTask { get; set; } = new ConcurrentQueue<OrderLocInfo>();

}
}

+ 24
- 0
HBLConsole.MORKS/HBLConsole.MORKS.csproj View File

@@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\HBLConsole.Attribute\HBLConsole.Attributes.csproj" />
<ProjectReference Include="..\HBLConsole.Communication\HBLConsole.Communication.csproj" />
<ProjectReference Include="..\HBLConsole.Factory\HBLConsole.Factory.csproj" />
<ProjectReference Include="..\HBLConsole.Interface\HBLConsole.Interface.csproj" />
<ProjectReference Include="..\HBLConsole.Model\HBLConsole.Model.csproj" />
</ItemGroup>

<ItemGroup>
<Reference Include="BPA.Message">
<HintPath>D:\BPACommon_output\net5.0\BPA.Message.dll</HintPath>
</Reference>
<Reference Include="BPA.Models">
<HintPath>D:\BPACommon_output\net5.0\BPA.Models.dll</HintPath>
</Reference>
</ItemGroup>

</Project>

+ 15
- 7
HBLConsole.MainConsole/Main.cs View File

@@ -10,6 +10,7 @@ using HBLConsole.Communication;
using BPA.Message;
using HBLConsole.Business;
using HBLConsole.Factory;
using BPA.Message.Enum;

namespace HBLConsole.MainConsole
{
@@ -24,14 +25,23 @@ namespace HBLConsole.MainConsole

public void DataInit()
{
Json<SetPar>.Read();
if (Enum.TryParse(Json<SetPar>.Data.ClientDeviceType, out DeviceClientType dct))
{
GeneralConfig.DeviceType = dct;
}
else { GeneralConfig.DeviceType = DeviceClientType.MORKS; }
Json<MorkOrderPushPar>.Read();
Json<BatchingInfoPar>.Read();
MessageLog.GetInstance.Show($"启动【{GeneralConfig.DeviceType}】设备");
}


public void DataSave()
{
Json<MorkOrderPushPar>.Save();
Json<BatchingInfoPar>.Save();
Json<SetPar>.Save();
TextHelper.GetInstance.SaveLogInfo(MessageLog.GetInstance.LogInfo, "LogInfo");
}

@@ -45,11 +55,11 @@ namespace HBLConsole.MainConsole
Topics.Add(TOPIC.GetInstance.GetOrderPushTopic(GeneralConfig.DeviceType, InternetInfo.ClientId));
Topics.Add(TOPIC.GetInstance.GetBusinessTopic(GeneralConfig.DeviceType, InternetInfo.ClientId));

SimpleFactory.GetInstance.DeviceInit();//设备初始化

//MQTT 连接成功
MqttHelper.GetInstance.ConnectOk = new Action(() =>
{
SimpleFactory.GetInstance.DeviceInit();//设备初始化

MqttHelper.GetInstance.MqttSubscriptionAsync(Topics.ToArray());//主题订阅

HeartbeatReport.GetInstance.Init();//心跳上报
@@ -67,11 +77,9 @@ namespace HBLConsole.MainConsole
MqttHelper.GetInstance.Reconnection = new Action(() => { MqttHelper.GetInstance.MqttSubscriptionAsync(Topics.ToArray()); });

//MQTT 连接
MqttHelper.GetInstance.MqttInitAsync(InternetInfo.MqttUserName,
InternetInfo.MqttPassword,
InternetInfo.MqttAddress,
InternetInfo.MqttPort,
DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss"));
MqttHelper.GetInstance.MqttInitAsync(InternetInfo.MqttUserName, InternetInfo.MqttPassword,
InternetInfo.MqttAddress, InternetInfo.MqttPort, DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss"));

}), "业务逻辑初始化");
}



+ 52
- 0
HBLConsole.Model/AlarmSet.cs View File

@@ -0,0 +1,52 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace HBLConsole.Model
{
[Table(nameof(AlarmSet))]
public class AlarmSet
{
public AlarmSet()
{
AnalogAlarmModels.Clear();
foreach (var item in Enum.GetNames(typeof(EAnalogAlarmType)))
{
AnalogAlarmModels.Add(new AnalogAlarmModel()
{
AlarmTag = item,
SortTag = (EAnalogAlarmType)Enum.Parse(typeof(EAnalogAlarmType), item)
});
}
}

[Key]
public int Id { get; set; }

/// <summary>
/// 模拟量报警信息
/// </summary>
public ObservableCollection<AnalogAlarmModel> AnalogAlarmModels { get; set; } = new ObservableCollection<AnalogAlarmModel>();

/// <summary>
/// 离散量报警信息
/// </summary>
public DiscreteAlarmInfo DiscreteAlarmInfoSet { get; set; } = new DiscreteAlarmInfo();

/// <summary>
/// 设置外键
/// </summary>
[ForeignKey("VariableInfoId")]
public int VariableInfoId { get; set; }

/// <summary>
/// 设置导航属性
/// </summary>
public VariableInfo VariableInfo { get; set; }
}
}

+ 55
- 0
HBLConsole.Model/AnalogAlarmModel.cs View File

@@ -0,0 +1,55 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace HBLConsole.Model
{
/// <summary>
/// 模拟量报警模块
/// </summary>
public class AnalogAlarmModel
{
[Key]
public int Id { get; set; }

/// <summary>
/// 设定报警值
/// </summary>
public int AlarmValue { get; set; } = 0;

/// <summary>
/// 是否启用该报警
/// </summary>
public bool IsEnable { get; set; }

/// <summary>
/// 报警信息
/// </summary>
public string AlarmInfo { get; set; }

/// <summary>
/// 报警标签
/// </summary>
public string AlarmTag { get; set; }

/// <summary>
/// 排序标签
/// </summary>
public EAnalogAlarmType SortTag { get; set; }

/// <summary>
/// 设置外键
/// </summary>
[ForeignKey("AlarmSetId")]
public int AlarmSetId { get; set; }

/// <summary>
/// 设置导航属性
/// </summary>
public AlarmSet AlarmSet { get; set; }
}
}

+ 4
- 1
HBLConsole.Model/CommunicationPar/CommunicationSet.cs View File

@@ -44,7 +44,10 @@ namespace HBLConsole.Model
public EDeviceType deviceType { get { return _mdeviceType; } set { _mdeviceType = value; OnPropertyChanged(); } }
private EDeviceType _mdeviceType;


/// <summary>
/// 客户端启动设备类型
/// </summary>
public string ClientDeviceType { get; set; }

public RelayCommand<object> RemoveCommand { get; set; }
}


+ 41
- 0
HBLConsole.Model/DiscreteAlarmInfo.cs View File

@@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace HBLConsole.Model
{
/// <summary>
/// 布尔量报警信息
/// </summary>
[Table(nameof(DiscreteAlarmInfo))]
public class DiscreteAlarmInfo
{
[Key]
public int Id { get; set; }

/// <summary>
/// 沿报警(上升沿,下降沿)
/// </summary>
public string TrigAlarm { get; set; }

/// <summary>
/// 报警信息
/// </summary>
public string AlarmInfo { get; set; }

/// <summary>
/// 设置外键
/// </summary>
[ForeignKey("AlarmSetId")]
public int AlarmSetId { get; set; }

/// <summary>
/// 设置导航属性
/// </summary>
public AlarmSet AlarmSet { get; set; }
}
}

+ 17
- 0
HBLConsole.Model/OrderLocInfo.cs View File

@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace HBLConsole.Model
{
public class OrderLocInfo
{
public string SuborderId { get; set; }
public ushort Loc { get; set; }
public ushort RecipeNumber { get; set; }
public int BatchingId { get; set; }

}
}

+ 0
- 9
HBLConsole.Model/ProcessData.cs View File

@@ -17,13 +17,4 @@ namespace HBLConsole.Model
public ConcurrentDictionary<string, List<Condition>> Conditions = new ConcurrentDictionary<string, List<Condition>>();

}

//public class Condition
//{
// public bool ConditionMet { get; set; }
// public string propertyIllustrate { get; set; }

// public string ToolTip { get; set; }
// public bool IsNot { get; set; }
//}
}

+ 74
- 0
HBLConsole.Model/PropBindInfo.cs View File

@@ -0,0 +1,74 @@
using Microsoft.Toolkit.Mvvm.Input;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace HBLConsole.Model
{
/// <summary>
/// 属性绑定信息
/// </summary>
public class PropBindInfo : VariableInfo
{
public PropBindInfo()
{
ComboBoxItemInit();
CancelCommand = new RelayCommand(() => { IsOpen = false; });
ConfirmCommand = new RelayCommand(() => { IsOpen = false; });
}

/// <summary>
/// 数据类型下拉列表
/// </summary>
public ObservableCollection<string> dataType { get; set; } = new ObservableCollection<string>();

/// <summary>
/// 报警类型下拉列表
/// </summary>
public ObservableCollection<string> alarmType { get; set; } = new ObservableCollection<string>();

/// <summary>
/// 报警设置窗离散量报警类型
/// </summary>
public ObservableCollection<string> PopupDiscreteAlarmType { get; set; } = new ObservableCollection<string>();

/// <summary>
/// 是否显示报警设置框
/// </summary>
public bool IsOpen { get { return _mIsOpen; } set { _mIsOpen = value; OnPropertyChanged(); } }
private bool _mIsOpen;

/// <summary>
/// 报警设置框取消操作
/// </summary>
public RelayCommand CancelCommand { get; set; }

/// <summary>
/// 报警设置框确认按钮
/// </summary>
public RelayCommand ConfirmCommand { get; set; }


/// <summary>
/// 下拉列表初始化
/// </summary>
private void ComboBoxItemInit()
{
dataType.Clear();
alarmType.Clear();
PopupDiscreteAlarmType.Clear();
string[] DataTypeNames = Enum.GetNames(typeof(EDataType));
foreach (var item in DataTypeNames) { dataType.Add(item); }

string[] AlarmTypeNames = Enum.GetNames(typeof(EAlarmType));
foreach (var item in AlarmTypeNames) { alarmType.Add(item); }

string[] PopupAlarmTypes = Enum.GetNames(typeof(EAlongTriggerType));
foreach (var item in PopupAlarmTypes) { PopupDiscreteAlarmType.Add(item); }
}
}
}

+ 16
- 0
HBLConsole.Model/SetPar.cs View File

@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace HBLConsole.Model
{
/// <summary>
/// 设置参数
/// </summary>
public class SetPar
{
public string ClientDeviceType { get; set; }
}
}

+ 12
- 4
HBLConsole.Model/SimOrderData.cs View File

@@ -8,9 +8,17 @@ namespace HBLConsole.Model
{
public class SimOrderData
{
public int NoodleLoc { get; set; }
public int BowlLoc { get; set; }
public bool NoodleIsEnableRandom { get; set; }
public bool BowlIsEnableRandom { get; set; }
/// <summary>
/// 面条位置(1 -- 5)
/// </summary>
public ushort NoodleLoc { get; set; }
/// <summary>
/// 碗位置(10 -- 11)
/// </summary>
public ushort BowlLoc { get; set; }
/// <summary>
/// 浇头位置 (6 -- 9)
/// </summary>
public ushort SoupLoc { get; set; }
}
}

+ 73
- 0
HBLConsole.Model/VariableInfo.cs View File

@@ -0,0 +1,73 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Toolkit.Mvvm.ComponentModel;
using Newtonsoft.Json;

namespace HBLConsole.Model
{
/// <summary>
/// 变量信息
/// </summary>
[Table(nameof(VariableInfo))]
public class VariableInfo : ObservableObject
{

[Key]
public int ID { get { return _mID; } set { _mID = value; OnPropertyChanged(); } }
private int _mID;

/// <summary>
/// 变量名
/// </summary>
public string VarName
{
get { return _mVarName; }
set
{
_mVarName = value;
OnPropertyChanged();

//if (DelegationNotifi.GetInstance.VarNameChanged != null)
// DelegationNotifi.GetInstance.VarNameChanged(_mID);
}
}
private string _mVarName;

/// <summary>
/// 地址
/// </summary>
public string Address { get { return _mAddress; } set { _mAddress = value; OnPropertyChanged(); } }
private string _mAddress;

/// <summary>
/// 数据类型
/// </summary>
public string DataType { get { return _mDataType; } set { _mDataType = value; OnPropertyChanged(); } }
private string _mDataType;

/// <summary>
/// 是否启用报警
/// </summary>
public bool IsEnableAlarm { get { return _mIsEnableAlarm; } set { _mIsEnableAlarm = value; OnPropertyChanged(); } }
private bool _mIsEnableAlarm;

/// <summary>
/// 当前值
/// </summary>
public string CurrentValue { get { return _mCurrentValue; } set { _mCurrentValue = value; OnPropertyChanged(); } }
private string _mCurrentValue;

/// <summary>
/// 报警设置信息
/// </summary>
public AlarmSet AlarmSetProp { get { return _mAlarmSetProp; } set { _mAlarmSetProp = value; OnPropertyChanged(); } }
private AlarmSet _mAlarmSetProp = new AlarmSet();


}
}

+ 81
- 0
HBLConsole.Service/SqlHelper.cs View File

@@ -0,0 +1,81 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using System.IO;

namespace HBLConsole.Service
{
public class SqlHelper<T> : DbContext where T : class, new()
{
private volatile static SqlHelper<T> _Instance;
public static SqlHelper<T> GetInstance => _Instance ?? (_Instance = new SqlHelper<T>());
private SqlHelper() { }

private string path
{
get
{
Directory.CreateDirectory(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "AccessFile"));
return $"{AppDomain.CurrentDomain.BaseDirectory}AccessFile\\{typeof(T).Name}.db";
}
}

Dictionary<T, bool> IsEnsureCreated = new Dictionary<T, bool>();

private static readonly object addLock = new object();

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlite($"FileName={path}");
}

public DbSet<T> DbObj { get; set; }

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
//一对一关系映射
//modelBuilder.Entity<VariableInfo>().HasOne(p => p.AlarmSetProp).WithOne(p => p.VariableInfo).HasForeignKey<AlarmSet>(p => p.VariableInfoId);
//modelBuilder.Entity<AlarmSet>().HasOne(P => P.DiscreteAlarmInfoSet).WithOne(P => P.AlarmSet).HasForeignKey<DiscreteAlarmInfo>(P => P.AlarmSetId);

////一对多关系映射
//modelBuilder.Entity<AnalogAlarmModel>().HasOne(p => p.AlarmSet).WithMany(p => p.AnalogAlarmModels).HasForeignKey(p => p.AlarmSetId);
}

public List<T> GetData()
{
Database.EnsureCreated();
return DbObj.ToList();
}

public void Save()
{
//if (DbObj != null)
//{
// if (Entry(DbObj).State == EntityState.Modified)
// {
//Database.EnsureDeleted();
Database.EnsureCreated();
SaveChanges();
// }
//}

}

public void Add(T data)
{
//lock (addLock)
//{
//if (!IsEnsureCreated[data])
//Database.EnsureCreated();
//if (DbObj.Contains(data))
// DbObj.Update(data);
//else
DbObj.Add(data);
// }

}
}
}

+ 13
- 1
HBLConsole.sln View File

@@ -25,7 +25,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HBLConsole.Abstract", "HBLC
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HBLConsole.Factory", "HBLConsole.Factory\HBLConsole.Factory.csproj", "{1B19BE8D-AFB9-4635-B114-8648B0C8BDF7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HBLConsole.Attributes", "HBLConsole.Attribute\HBLConsole.Attributes.csproj", "{9F022DDD-B69C-4AC9-AFB0-0A688EAA1F64}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HBLConsole.Attributes", "HBLConsole.Attribute\HBLConsole.Attributes.csproj", "{9F022DDD-B69C-4AC9-AFB0-0A688EAA1F64}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HBLConsole.MORKS", "HBLConsole.MORKS\HBLConsole.MORKS.csproj", "{B14C829F-CE03-4DBC-93A7-5E3D2787E280}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HBLConsole.MORKD", "HBLConsole.MORKD\HBLConsole.MORKD.csproj", "{FE578C47-A26C-48EF-A06A-EF359B04737F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -81,6 +85,14 @@ Global
{9F022DDD-B69C-4AC9-AFB0-0A688EAA1F64}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9F022DDD-B69C-4AC9-AFB0-0A688EAA1F64}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9F022DDD-B69C-4AC9-AFB0-0A688EAA1F64}.Release|Any CPU.Build.0 = Release|Any CPU
{B14C829F-CE03-4DBC-93A7-5E3D2787E280}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B14C829F-CE03-4DBC-93A7-5E3D2787E280}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B14C829F-CE03-4DBC-93A7-5E3D2787E280}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B14C829F-CE03-4DBC-93A7-5E3D2787E280}.Release|Any CPU.Build.0 = Release|Any CPU
{FE578C47-A26C-48EF-A06A-EF359B04737F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FE578C47-A26C-48EF-A06A-EF359B04737F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FE578C47-A26C-48EF-A06A-EF359B04737F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FE578C47-A26C-48EF-A06A-EF359B04737F}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE


+ 1
- 1
HBLConsole/App.xaml.cs View File

@@ -26,7 +26,7 @@ namespace HBLConsole
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
GeneralConfig.DeviceType = DeviceClientType.MORKS;
SystemHelper.GetInstance.AutoStart(false);
SystemHelper.GetInstance.CreateDesktopShortcut();
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;


+ 38
- 0
HBLConsole/Converter/AlarmTypeTextConvert.cs View File

@@ -0,0 +1,38 @@
using HBLConsole.Model;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;

namespace HBLConsole.Converter
{
/// <summary>
/// 报警类型文本转换
/// </summary>
public class AlarmTypeTextConvert : IValueConverter
{
//当值从绑定源传播给绑定目标时,调用方法Convert,绑定源是控件的数据,绑定目标是后台值
//界面传递给后台数据
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value != null)
{
if (value.ToString() == "Bool")
return EAlarmType.离散量报警.ToString();
else
return EAlarmType.模拟量报警.ToString();
}
return EAlarmType.无.ToString();
}

//当值从绑定目标传播给绑定源时,调用此方法ConvertBack
//从后台数据传递给界面
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return value.ToString();
}
}
}

+ 31
- 0
HBLConsole/Converter/AnalogAlarmConvert.cs View File

@@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Data;

namespace HBLConsole.Converter
{
/// <summary>
/// 模拟量报警显示转换
/// </summary>
public class AnalogAlarmConvert : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value != null)
{
return value.ToString() != "Bool" ? Visibility.Visible : Visibility.Collapsed;
}
return Visibility.Visible;
}

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}

+ 31
- 0
HBLConsole/Converter/DiscreteAlarmConvert.cs View File

@@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Data;

namespace HBLConsole.Converter
{
/// <summary>
/// 离散量报警显示转换
/// </summary>
public class DiscreteAlarmConvert : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value != null)
{
return value.ToString() == "Bool" ? Visibility.Visible : Visibility.Collapsed;
}
return Visibility.Visible;
}

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}

+ 39
- 0
HBLConsole/Converter/IsEnableConvert.cs View File

@@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;

namespace HBLConsole.Converter
{
public class IsEnableConvert : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
bool returnValue = false;
if (value != null)
{
switch (value.ToString())
{
case "无":
returnValue = false;
break;
case "离散量报警":
case "模拟量报警":
returnValue = true;
break;
default:
break;
}
}
return returnValue;
}

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}

+ 34
- 0
HBLConsole/Converter/TextDisplayConvert.cs View File

@@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;

namespace HBLConsole.Converter
{
public class TextDisplayConvert : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value != null && bool.TryParse(value.ToString(), out bool result))
{
if (result)
{
return "取消报警";
}
else
{
return "启用报警";
}
}
return "启用报警";
}

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}

+ 2
- 0
HBLConsole/HBLConsole.csproj View File

@@ -194,6 +194,8 @@
<ItemGroup>
<ProjectReference Include="..\HBLConsole.MainConsole\HBLConsole.MainConsole.csproj" />
<ProjectReference Include="..\HBLConsole.Model\HBLConsole.Model.csproj" />
<ProjectReference Include="..\HBLConsole.MORKD\HBLConsole.MORKD.csproj" />
<ProjectReference Include="..\HBLConsole.MORKS\HBLConsole.MORKS.csproj" />
<ProjectReference Include="..\HBLConsole.PryUserControl\HBLConsole.PryUserControl.csproj" />
<ProjectReference Include="..\HBLConsole.Service\HBLConsole.Service.csproj" />
</ItemGroup>


+ 18
- 0
HBLConsole/View/DeviceManageView.xaml View File

@@ -77,6 +77,24 @@
</Grid.RowDefinitions>

<StackPanel HorizontalAlignment="Right" Orientation="Horizontal">

<TextBlock Style="{StaticResource TextBlockStyle}" Text="请选择客户端启动设备类型:" />

<ComboBox
Margin="0,0,20,0"
VerticalAlignment="Center"
BorderBrush="#FF23CACA"
Width="150"
BorderThickness="1"
FontFamily="楷体"
FontSize="20"
Foreground="#ff23caca"
IsEditable="False"
ItemsSource="{Binding ClientDevices}"
SelectedIndex="0"
Style="{StaticResource ComboBoxStyle}"
Text="{Binding ClientDeviceType}" />

<Button
Width="140"
Margin="0,0,20,0"


+ 2
- 1
HBLConsole/View/MainView.xaml View File

@@ -212,10 +212,11 @@

<RadioButton
Margin="-10,0,0,0"
Command="{Binding NavChangedCommand}"
CommandParameter="ProcessMonitoringView"
Content="流程监控"
Style="{StaticResource ParallelogramRadioButtonStyle}" />


<RadioButton
Margin="-10,0,0,0"
Command="{Binding NavChangedCommand}"


+ 177
- 9
HBLConsole/View/ProcessMonitoringView.xaml View File

@@ -1,12 +1,180 @@
<UserControl x:Class="HBLConsole.View.ProcessMonitoringView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:HBLConsole.View"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl
x:Class="HBLConsole.View.ProcessMonitoringView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:HBLConsole.View"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:pry="clr-namespace:HBLConsole.PryUserControl;assembly=HBLConsole.PryUserControl"
xmlns:vm="clr-namespace:HBLConsole.ViewModel"
d:DesignHeight="450"
d:DesignWidth="800"
mc:Ignorable="d">

<UserControl.DataContext>
<vm:ProcessMonitoringViewModel />
</UserControl.DataContext>

<UserControl.Resources>

<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="../Resources/ResourceDictionarys/BasicStyle.xaml">

<!--#region 开关按钮样式-->
<Style x:Key="ToggleButStyle" TargetType="{x:Type ToggleButton}">
<Setter Property="IsChecked" Value="False" />
<Setter Property="FontFamily" Value="楷体" />
<Setter Property="Foreground" Value="#ddd" />
<Setter Property="IsEnabled" Value="False" />
<Setter Property="FontSize" Value="18" />
<Setter Property="Margin" Value="0,0,10,0" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<!--<Grid x:Name="gr" SnapsToDevicePixels="True">-->
<Border
Name="br"
Background="#FF1E9614"
CornerRadius="5">
<ContentPresenter
x:Name="contentPresenter"
Margin="4,2"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Content="{TemplateBinding Content}"
ContentStringFormat="{TemplateBinding ContentStringFormat}"
ContentTemplate="{TemplateBinding ContentTemplate}"
Focusable="False"
RecognizesAccessKey="True"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</Border>

<!--</Grid>-->
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="br" Property="Background" Value="#FF1E9614" />
</Trigger>

<Trigger Property="IsChecked" Value="False">
<Setter TargetName="br" Property="Background" Value="#FFF11A38" />
</Trigger>

<Trigger Property="IsMouseOver" Value="True">
<!--<Setter TargetName="tb" Property="Foreground" Value="#2695FF" />-->
</Trigger>

</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

<!--#endregion-->

<!--#region ListBox样式-->
<Style x:Key="ListBoxItemStyle1" TargetType="{x:Type ListBoxItem}">
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="BorderBrush" Value="{x:Null}" />
<Setter Property="Foreground" Value="White" />
<Setter Property="FontSize" Value="20" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border x:Name="border" CornerRadius="8">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
</Border>
<!--<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="border" Property="Background">
<Setter.Value>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Offset="0.5" Color="#FF6B6B6B" />
<GradientStop Offset="0.5" Color="#FF535353" />
<GradientStop Offset="0.022" Color="#FF535353" />
<GradientStop Offset="0.991" Color="#FF555555" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>-->
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!--#endregion-->
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>

<Grid>
<ScrollViewer
HorizontalScrollBarVisibility="Visible"
Style="{StaticResource ScrollViewerStyle}"
VerticalScrollBarVisibility="Visible">
<ItemsControl ItemsSource="{Binding processConditions}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,10" VerticalAlignment="Center">

<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200" />
<ColumnDefinition />
</Grid.ColumnDefinitions>

<pry:BeveledButton
x:Name="bb"
IsParallelogram="False"
StrokeThickness="1">
<pry:BeveledButton.FillColor>
<LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
<GradientStop Color="#ff1247EC" />
<GradientStop Offset="1" Color="#111247EC" />
</LinearGradientBrush>
</pry:BeveledButton.FillColor>
</pry:BeveledButton>

<TextBlock
Margin="2"
VerticalAlignment="Center"
FontFamily="楷体"
FontSize="16"
Foreground="Aqua"
Text="{Binding ProcessTitl}" />
</Grid>

<ListBox
x:Name="lstEnt"
Margin="0,3,0,0"
Background="{x:Null}"
BorderBrush="{x:Null}"
BorderThickness="0"
ItemContainerStyle="{StaticResource ResourceKey=ListBoxItemStyle1}"
ItemsSource="{Binding Conditions}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<ToggleButton
Content="{Binding propertyIllustrate}"
IsChecked="{Binding ConditionMet}"
Style="{StaticResource ToggleButStyle}"
ToolTip="{Binding ToolTip}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</Grid>
</UserControl>

+ 453
- 0
HBLConsole/View/VariableConfig.xaml View File

@@ -0,0 +1,453 @@
<UserControl
x:Class="HBLConsole.View.VariableConfig"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:convert="clr-namespace:HBLConsole.Converter"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:HBLConsole.View"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:pry="clr-namespace:HBLConsole.PryUserControl;assembly=HBLConsole.PryUserControl"
xmlns:vm="clr-namespace:HBLConsole.ViewModel"
d:DesignHeight="450"
d:DesignWidth="1000"
mc:Ignorable="d">

<UserControl.DataContext>
<vm:VariableConfig />
</UserControl.DataContext>

<UserControl.Resources>
<ResourceDictionary Source="../Resources/ResourceDictionarys/BasicStyle.xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary>
<convert:TextDisplayConvert x:Key="textDisplayConvert" />
<convert:IsEnableConvert x:Key="isEnableConvert" />
<convert:AnalogAlarmConvert x:Key="analogAlarmConvert" />
<convert:DiscreteAlarmConvert x:Key="discreteAlarmConvert" />
<convert:AlarmTypeTextConvert x:Key="alarmTypeTextConvert" />
<SolidColorBrush x:Key="BorderSolid" Color="#5523CACA" />
<SolidColorBrush x:Key="FontColor" Color="#FF2AB2E7" />
<SolidColorBrush x:Key="TitleFontColor" Color="#ddd" />
<SolidColorBrush x:Key="CursorColor" Color="Aqua" />
<SolidColorBrush x:Key="TitleBorderColor" Color="#FF2AB2E7" />

<Style x:Key="TextBlockStyle" TargetType="TextBlock">
<Setter Property="FontFamily" Value="楷体" />
<Setter Property="FontSize" Value="18" />
<Setter Property="Foreground" Value="{StaticResource TextBlockForeground}" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="HorizontalAlignment" Value="Center" />
</Style>

<Style x:Key="TextBoxStyle" TargetType="TextBox">
<Setter Property="FontFamily" Value="楷体" />
<Setter Property="FontSize" Value="22" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="Foreground" Value="{StaticResource TextBlockForeground}" />
<Setter Property="BorderBrush" Value="#FF23CACA" />
<Setter Property="CaretBrush" Value="Aqua" />
<Setter Property="VerticalAlignment" Value="Center" />
</Style>

</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>

<Grid Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="30" />
<RowDefinition Height="30" />
<RowDefinition />
</Grid.RowDefinitions>
<StackPanel HorizontalAlignment="Right" Orientation="Horizontal">
<!--<Button
Margin="20,0,20,0"
Command="{Binding GenerateData}"
Content="添加数据" />
<Button
Margin="20,0,20,0"
Command="{Binding SaveData}"
Content="保存数据" />-->
</StackPanel>

<!--#region 表格标题栏设置-->
<Grid Grid.Row="1" Background="#dd2AB2E7">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.3*" />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition Width="0.7*" />
<ColumnDefinition Width="0" />
<ColumnDefinition Width="0.7*" />
<ColumnDefinition Width="0.5*" />
</Grid.ColumnDefinitions>
<TextBlock
Grid.Column="0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="16"
Foreground="{StaticResource TitleFontColor}"
Text="ID" />

<Grid Grid.Column="1">
<TextBlock
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="16"
Foreground="{StaticResource TitleFontColor}"
Text="名称" />
<Border BorderBrush="{StaticResource TitleBorderColor}" BorderThickness="1,0,1,0" />
</Grid>

<TextBlock
Grid.Column="2"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="16"
Foreground="{StaticResource TitleFontColor}"
Text="地址" />

<Grid Grid.Column="3">
<TextBlock
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="16"
Foreground="{StaticResource TitleFontColor}"
Text="数据类型" />
<Border BorderBrush="{StaticResource TitleBorderColor}" BorderThickness="1,0,1,0" />
</Grid>

<TextBlock
Grid.Column="4"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="16"
Foreground="{StaticResource TitleFontColor}"
Text="报警类型" />

<Grid Grid.Column="5">
<TextBlock
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="16"
Foreground="{StaticResource TitleFontColor}"
Text="是否启用报警" />
<Border BorderBrush="{StaticResource TitleBorderColor}" BorderThickness="0,0,1,0" />
</Grid>

<TextBlock
Grid.Column="6"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="16"
Foreground="{StaticResource TitleFontColor}"
Text="报警配置" />

</Grid>
<!--#endregion-->

<!--#region 表格数据显示-->
<ScrollViewer
Grid.Row="2"
HorizontalScrollBarVisibility="Hidden"
VerticalScrollBarVisibility="Hidden">
<ItemsControl ItemsSource="{Binding varialeInfos}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.3*" />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition Width="0.7*" />
<ColumnDefinition Width="0" />
<ColumnDefinition Width="0.7*" />
<ColumnDefinition Width="0.5*" />
</Grid.ColumnDefinitions>

<TextBlock
Grid.Column="0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Background="Transparent"
FontSize="14"
Foreground="{StaticResource FontColor}"
Text="{Binding ID}" />

<Grid Grid.Column="1">
<TextBox
Background="Transparent"
CaretBrush="{StaticResource CursorColor}"
Foreground="{StaticResource FontColor}"
Style="{StaticResource InputTextboxStyle}"
Text="{Binding VarName}" />
<Border BorderBrush="{StaticResource BorderSolid}" BorderThickness="1,0,1,0" />
</Grid>


<TextBox
Grid.Column="2"
Background="Transparent"
CaretBrush="{StaticResource CursorColor}"
Foreground="{StaticResource FontColor}"
Style="{StaticResource InputTextboxStyle}"
Text="{Binding Address}" />

<Grid Grid.Column="3">
<ComboBox
VerticalAlignment="Center"
BorderBrush="Transparent"
BorderThickness="1"
FontFamily="楷体"
FontSize="20"
Foreground="{StaticResource FontColor}"
IsEditable="False"
ItemsSource="{Binding dataType}"
SelectedValue="{Binding DataType}"
Style="{StaticResource ComboBoxStyle}"
Text="{Binding DataType}" />
<Border BorderBrush="{StaticResource BorderSolid}" BorderThickness="1,0,1,0" />
</Grid>


<Grid Grid.Column="5">
<CheckBox
HorizontalAlignment="Center"
VerticalAlignment="Center"
Background="#ff23CACA"
Content="{Binding IsEnableAlarm, Converter={StaticResource textDisplayConvert}}"
FontSize="16"
Foreground="{StaticResource FontColor}"
IsChecked="{Binding IsEnableAlarm}"
Template="{StaticResource CbTemplate}" />
<Border BorderBrush="{StaticResource BorderSolid}" BorderThickness="0,0,1,0" />
</Grid>

<Grid Grid.Column="6">
<Grid>
<ToggleButton
Name="tb"
Width="{Binding RelativeSource={RelativeSource AncestorType=Grid, AncestorLevel=1}, Path=ActualWidth}"
Height="{Binding RelativeSource={RelativeSource AncestorType=Grid, AncestorLevel=1}, Path=ActualHeight}"
Background="Transparent"
BorderThickness="0"
Content="编辑"
FontSize="14"
IsChecked="{Binding IsOpen}"
IsEnabled="{Binding IsEnableAlarm}"
Style="{StaticResource EditToggleButtonStyle}" />
</Grid>

<!-- 当 StaysOpen 设置为 True 时 popup失去焦点的时候不会自动关闭 -->
<Popup
AllowsTransparency="True"
Focusable="False"
IsOpen="{Binding IsOpen}"
Placement="Left"
PlacementTarget="{Binding ElementName=tb}"
StaysOpen="False">
<Border Background="#081424" ClipToBounds="True">
<Grid Margin="0">
<Grid.Background>
<ImageBrush ImageSource="../Resource/Images/边框1.png" />
</Grid.Background>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>

<!--#region 离散量报警设置-->
<StackPanel
Grid.Row="0"
Margin="10"
Orientation="Vertical"
Visibility="{Binding DataType, Converter={StaticResource discreteAlarmConvert}}">

<Grid Margin="5">
<pry:TitleTextBlock />
<TextBlock
Margin="10,5,30,5"
Background="Transparent"
FontSize="16"
Foreground="#dd01FFFF"
Text="离散量报警设置" />
</Grid>

<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>

<TextBlock
Margin="5"
Style="{StaticResource TextBlockStyle}"
Text="选择触发条件:" />

<ComboBox
Grid.Column="1"
Width="180"
Margin="5"
VerticalAlignment="Center"
BorderBrush="#FF23CACA"
BorderThickness="1"
FontFamily="楷体"
FontSize="20"
Foreground="#ff23caca"
IsEditable="False"
ItemsSource="{Binding PopupDiscreteAlarmType}"
SelectedIndex="1"
Style="{StaticResource ComboBoxStyle}"
Text="{Binding AlarmSetProp.DiscreteAlarmInfoSet.TrigAlarm}" />
</Grid>

<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock
Grid.Column="0"
Margin="5"
Style="{StaticResource TextBlockStyle}"
Text="输入报警信息:" />
<TextBox
Grid.Column="1"
Grid.ColumnSpan="2"
Margin="5"
Style="{StaticResource TextBoxStyle}"
Text="{Binding AlarmSetProp.DiscreteAlarmInfoSet.AlarmInfo}" />
</Grid>

</StackPanel>
<!--#endregion-->

<!--#region 模拟量报警设置-->
<StackPanel
Grid.Row="1"
Margin="10"
Visibility="{Binding DataType, Converter={StaticResource analogAlarmConvert}}">

<Grid Margin="5">
<pry:TitleTextBlock />
<TextBlock
Margin="10,5,30,5"
Background="Transparent"
FontSize="16"
Foreground="#dd01FFFF"
Text="模拟量报警设置" />
</Grid>

<ItemsControl ItemsSource="{Binding AlarmSetProp.AnalogAlarmModels}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>

<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>

<CheckBox
Margin="5,5,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Background="#ff23CACA"
Content="{Binding AlarmTag}"
FontSize="14"
Foreground="#ff23CACA"
IsChecked="{Binding IsEnable}"
Template="{StaticResource CbTemplate}" />

<TextBlock
Grid.Column="1"
Margin="0,5,5,0"
Style="{StaticResource TextBlockStyle}"
Text="请输入报警值:" />
<TextBox
Grid.Column="2"
Width="100"
Margin="0,5,5,0"
IsEnabled="{Binding IsEnable}"
Style="{StaticResource TextBoxStyle}"
Text="{Binding AlarmValue}" />

<TextBlock
Grid.Row="1"
Grid.Column="0"
Margin="5"
Style="{StaticResource TextBlockStyle}"
Text="输入报警信息:" />
<TextBox
Grid.Row="1"
Grid.Column="1"
Grid.ColumnSpan="2"
Margin="5"
IsEnabled="{Binding IsEnable}"
Style="{StaticResource TextBoxStyle}"
Text="{Binding AlarmInfo}" />

</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>

</StackPanel>
<!--#endregion-->

<!--#region 按钮控制-->
<Grid Grid.Row="2" Margin="10">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>

<Button
Margin="10,5,10,10"
Command="{Binding CancelCommand}"
Content="取消"
FontFamily="楷体"
FontSize="20"
Foreground="#aa01FFFF"
Template="{StaticResource CancelButtonTemp}" />

<Button
Grid.Column="1"
Margin="10,5,10,10"
Command="{Binding ConfirmCommand}"
Content="确认"
FontFamily="楷体"
FontSize="20"
Foreground="#aa01FFFF"
Template="{StaticResource ConfirmButtonTemp}" />
</Grid>
<!--#endregion-->

</Grid>
</Border>
</Popup>
</Grid>

<Border
Grid.ColumnSpan="8"
BorderBrush="{StaticResource BorderSolid}"
BorderThickness="1" />

</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
<!--#endregion-->


</Grid>
</UserControl>

+ 44
- 0
HBLConsole/View/VariableConfig.xaml.cs View File

@@ -0,0 +1,44 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace HBLConsole.View
{
/// <summary>
/// VariableConfig.xaml 的交互逻辑
/// </summary>
public partial class VariableConfig : UserControl
{
public VariableConfig()
{
InitializeComponent();
this.IsVisibleChanged += VariableConfig_IsVisibleChanged;
}

private void VariableConfig_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
var obj = (VariableConfig)sender;
if (!obj.IsVisible)
{
//if (DelegationNotifi.GetInstance.VariableSave != null)
//{
// DelegationNotifi.GetInstance.VariableSave();
//}
//DelegationNotifi.GetInstance.VariableSave = null;
//DelegationNotifi.GetInstance.VarNameChanged = null;
}
}
}
}

+ 20
- 116
HBLConsole/ViewModel/DebugViewModel.cs View File

@@ -6,7 +6,6 @@ using System.Threading.Tasks;
using Microsoft.Toolkit.Mvvm.Input;
using HBLConsole.Service;
using System.Threading;
using HBLConsole.Business.Devices;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using HBLConsole.Communication;
@@ -19,148 +18,53 @@ namespace HBLConsole.ViewModel
{
public class DebugViewModel : ViewModelBase
{
static bool First = false;
public DebugViewModel()
{
WindowName = "调试模式";
SimOrderCommand = new RelayCommand(() =>
{

if (IsEnableRandom)
NoodleLoc = (ushort)(new Random().Next(1, 6));
else
NoodleLoc = (ushort)NoodleLoc;

if (BowlIsEnableRandom)
BowlLoc = (ushort)(new Random().Next(10, 12));
else
BowlLoc = (ushort)BowlLoc;

ActionManagerment.GetInstance.Send("SimOrder", new SimOrderData()
{
NoodleIsEnableRandom = IsEnableRandom,
BowlLoc = BowlLoc,
NoodleLoc = NoodleLoc,
BowlIsEnableRandom = BowlIsEnableRandom
}, new Action(() =>
{
BowlLoc = MORKS.GetInstance.BowlLoc;
NoodleLoc = MORKS.GetInstance.NoodleLoc;
}));
});
});

InitCommand = new RelayCommand(() => { MORKS.GetInstance.DeviceInit(); });
if (!First) ProcessCondition();
}

private void ProcessCondition()
{
First = true;
Type type = MORKS.GetInstance.mORKS.GetType();

//添加流程监控信息
foreach (var item in type.GetProperties())
InitCommand = new RelayCommand(() =>
{
if (item.CustomAttributes.Count() > 0)
{
string? propertyInfo = item.GetCustomAttribute<CircuitAttribute>()?.PropertyIllustrate;
string[]? Classifiactions = item.GetCustomAttribute<CircuitAttribute>()?.Classifiaction;
if (Classifiactions != null)
{
foreach (var itemClassifiactions in Classifiactions)
{
if (ProcessData.GetInstance.Conditions.ContainsKey(itemClassifiactions))
{
if (propertyInfo != null)
{
int index = Array.FindIndex(ProcessData.GetInstance.Conditions[itemClassifiactions].ToArray(), p => p.propertyIllustrate == propertyInfo);
if (index >= 0)
{
ProcessData.GetInstance.Conditions[itemClassifiactions].ElementAt(index).ToolTip = item.Name;
}
}
}
}
}
}
}
var Conditions = ProcessData.GetInstance.Conditions;
if (Conditions != null)
{
foreach (var item in Conditions)
{
ProcessConditions process = new ProcessConditions();
process.ProcessTitl = item.Key;
foreach (var values in item.Value)
{
process.Conditions.Add(new Condition() { propertyIllustrate = values.propertyIllustrate });
}
processConditions.Add(process);
}
}


//更新流程监控图
ThreadManagerment.GetInstance.StartLong(new Action(() =>
{
foreach (var item in type.GetProperties())
{
if (item.CustomAttributes.Count() > 0)
{
string? propertyInfo = item.GetCustomAttribute<CircuitAttribute>()?.PropertyIllustrate;
string[]? Classifiactions = item.GetCustomAttribute<CircuitAttribute>()?.Classifiaction;
if (Classifiactions != null)
{
foreach (string? Titles in Classifiactions)
{
if (Titles != null && propertyInfo != null)
{
bool? isNot = ProcessData.GetInstance.Conditions[Titles]?.FirstOrDefault(p => p.propertyIllustrate == propertyInfo)?.IsNot;
int index = Array.FindIndex(processConditions.ToArray(), p => p.ProcessTitl == Titles);

if (index >= 0)
{
int PropertyIndex = Array.FindIndex(processConditions.ElementAt(index).Conditions.ToArray(), p => p.propertyIllustrate == propertyInfo);
if (PropertyIndex >= 0)
{
var res = type.GetProperty(item.Name)?.GetValue(MORKS.GetInstance.mORKS, null);
if (res != null)
{
if (res is bool blen)
{
if (isNot != null)
{
processConditions.ElementAt(index).Conditions.ElementAt(PropertyIndex).ConditionMet = (bool)isNot ? !blen : blen;
}

}
else if (res is ConcurrentQueue<GVL.OrderLocInfo> OrderLocInfoS)
{
processConditions.ElementAt(index).Conditions.ElementAt(PropertyIndex).ConditionMet = OrderLocInfoS.Count > 0;
}
}

}

}
}
}
}
}
}
Thread.Sleep(1000);
}), "UpdateValue");

//MORKS.GetInstance.DeviceInit();
ActionManagerment.GetInstance.Send("InitCommand");
});
}


public static event EventHandler<PropertyChangedEventArgs> StaticPropertyChanged;
private static void OnStaticPropertyChanged([CallerMemberName] string PropName = "")
{
StaticPropertyChanged?.Invoke(null, new PropertyChangedEventArgs(PropName));
}


public RelayCommand SimOrderCommand { get; set; }

public RelayCommand InitCommand { get; set; }


public static int NoodleLoc { get { return _mNoodleLoc; } set { _mNoodleLoc = value; OnStaticPropertyChanged(); } }
private static int _mNoodleLoc = 1;
public static ushort NoodleLoc { get { return _mNoodleLoc; } set { _mNoodleLoc = value; OnStaticPropertyChanged(); } }
private static ushort _mNoodleLoc = 1;


public static int BowlLoc { get { return _mBowlLoc; } set { _mBowlLoc = value; OnStaticPropertyChanged(); } }
private static int _mBowlLoc = 10;
public static ushort BowlLoc { get { return _mBowlLoc; } set { _mBowlLoc = value; OnStaticPropertyChanged(); } }
private static ushort _mBowlLoc = 10;


public static bool IsEnableRandom { get { return _mIsEnableRandom; } set { _mIsEnableRandom = value; OnStaticPropertyChanged(); } }


+ 65
- 21
HBLConsole/ViewModel/DeviceManageViewModel.cs View File

@@ -11,6 +11,7 @@ using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using BPA.Message.Enum;

namespace HBLConsole.ViewModel
{
@@ -20,41 +21,82 @@ namespace HBLConsole.ViewModel
{
WindowName = "设备管理";

foreach (var item in Enum.GetNames(typeof(DeviceClientType)))
{
ClientDevices.Add(item);
}

NewConnectCommand = new RelayCommand(() => { NewConnect(); });

SaveDeviceData();

VisibleDeviceData();

ActionManagerment.GetInstance.Register(new Func<object, object>((p) =>
{
if (p is DeviceManagermentResult dm)
{
return Json<CommunicationPar>.Data.communicationSets.FirstOrDefault(s => s.DeviceName.ToUpper() == dm.DeviceName.ToUpper()) == null;
}
return false;
}), "AddDeviceVerify");
ClientDeviceType = Json<SetPar>.Data.ClientDeviceType;
}

private void SaveDeviceData()
{
ActionManagerment.GetInstance.Register(new Action(() =>
{
Json<CommunicationPar>.Data.communicationSets.Clear();
foreach (var item in communicationSets)
{
item.RemoveAction = null;
Json<CommunicationPar>.Data.communicationSets.Add(item);
int index = Array.FindIndex(Json<CommunicationPar>.Data.communicationSets.ToArray(), p => p.DeviceName == item.DeviceName && p.ClientDeviceType == item.ClientDeviceType);
if (index >= 0)
{
Json<CommunicationPar>.Data.communicationSets.RemoveAt(index);
Json<CommunicationPar>.Data.communicationSets.Add(item);
}
else
{
Json<CommunicationPar>.Data.communicationSets.Add(item);
}
}
Json<CommunicationPar>.Save();

}), "DataSave");

Json<CommunicationPar>.Read();
communicationSets.Clear();
foreach (var item in Json<CommunicationPar>.Data.communicationSets)
{
item.RemoveAction = RemoveDevice;
communicationSets.Add(item);
}
}

ActionManagerment.GetInstance.Register(new Func<object, object>((p) =>
private void VisibleDeviceData()
{
if (communicationSets.Count <= 0)
{
if (p is DeviceManagermentResult dm)
Json<CommunicationPar>.Read();
foreach (var item in Json<CommunicationPar>.Data.communicationSets)
{
return communicationSets.FirstOrDefault(s => s.DeviceName == dm.DeviceName) == null;
if (item.ClientDeviceType == GVL.GeneralConfig.DeviceType.ToString())
{
item.RemoveAction = RemoveDevice;
communicationSets.Add(item);
}
}
return false;
}), "AddDeviceVerify");
}

}


public string ClientDeviceType
{
get { return _mClientDeviceType; }
set { _mClientDeviceType = value; OnPropertyChanged(); Json<SetPar>.Data.ClientDeviceType = value; }
}
private string _mClientDeviceType;


public static ObservableCollection<CommunicationSet> communicationSets { get; set; } = new ObservableCollection<CommunicationSet>();

public ObservableCollection<string> ClientDevices { get; set; } = new ObservableCollection<string>();

public RelayCommand NewConnectCommand { get; set; }

public RelayCommand SaveConnectSetCommand { get; set; }
@@ -66,8 +108,8 @@ namespace HBLConsole.ViewModel
{
DeviceManagermentSetView deviceManagermentSetView = new DeviceManagermentSetView();
var result = deviceManagermentSetView.ShowDialog();
var ResultTag = (DeviceManagermentResult)deviceManagermentSetView.Tag;
if (ResultTag != null)
var ResultTag = deviceManagermentSetView.Tag as DeviceManagermentResult;
if (ResultTag != null && result != null)
{
if ((bool)result)
{
@@ -76,19 +118,21 @@ namespace HBLConsole.ViewModel
{
CommunicationSet communicationObj = new CommunicationSet();
EDeviceType eDeviceType = (EDeviceType)Enum.Parse(typeof(EDeviceType), ResultTag.DeviceType);



string NameSpace = "HBLConsole.Model";//Load 加载的是dll的名称,GetType获取的是全命名空间下的类
//if (Enum.TryParse(ResultTag.DeviceType, out EDataType eDeviceType))
//{
string? NameSpace = "HBLConsole.Model";//Load 加载的是dll的名称,GetType获取的是全命名空间下的类
Type type = Assembly.Load(NameSpace)?.GetType($"{NameSpace}.{ResultTag.DeviceType}");
if (type != null)
{
communicationObj.Device = (IDeviceType)Activator.CreateInstance(type);
communicationObj.Device = Activator.CreateInstance(type) as IDeviceType;
}
communicationObj.DeviceName = $"{ResultTag.DeviceName}【{eDeviceType}】";
communicationObj.deviceType = eDeviceType;
communicationObj.RemoveAction = RemoveDevice;
communicationObj.ClientDeviceType = GVL.GeneralConfig.DeviceType.ToString();
communicationSets.Add(communicationObj);
//}

}
}
}


+ 31
- 10
HBLConsole/ViewModel/ProcessMonitoringViewModel.cs View File

@@ -1,5 +1,5 @@
using HBLConsole.Attributes;
using HBLConsole.Business.Devices;
//using HBLConsole.Business.Devices;
using HBLConsole.Model;
using HBLConsole.Service;
using System;
@@ -10,21 +10,39 @@ using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using HBLConsole.Factory;
using HBLConsole.Interface;

namespace HBLConsole.ViewModel
{
public class ProcessMonitoringViewModel : ViewModelBase
{
static Type type;
static IGvl InterfaceGVL;
public ProcessMonitoringViewModel()
{
WindowName = "流程监控";
ProcessCondition();
if (type == null)
{
InterfaceGVL = SimpleFactory.GetInstance.GetGvl();
type = InterfaceGVL?.GetType();
if (ProcessData.GetInstance.Conditions?.Count <= 0)
{
if (InterfaceGVL != null && type != null)
{
GetProcessInfo();
UpdateProcess();
}
}
}

}

private void ProcessCondition()
/// <summary>
/// 获取流程信息
/// </summary>
private void GetProcessInfo()
{
Type type = MORKS.GetInstance.mORKS.GetType();

//添加流程监控信息
foreach (var item in type.GetProperties())
{
@@ -66,9 +84,13 @@ namespace HBLConsole.ViewModel
processConditions.Add(process);
}
}
}


//更新流程监控图
/// <summary>
/// 更新流程
/// </summary>
private void UpdateProcess()
{
ThreadManagerment.GetInstance.StartLong(new Action(() =>
{
foreach (var item in type.GetProperties())
@@ -91,7 +113,7 @@ namespace HBLConsole.ViewModel
int PropertyIndex = Array.FindIndex(processConditions.ElementAt(index).Conditions.ToArray(), p => p.propertyIllustrate == propertyInfo);
if (PropertyIndex >= 0)
{
var res = type.GetProperty(item.Name)?.GetValue(MORKS.GetInstance.mORKS, null);
var res = type.GetProperty(item.Name)?.GetValue(InterfaceGVL, null);
if (res != null)
{
if (res is bool blen)
@@ -100,9 +122,8 @@ namespace HBLConsole.ViewModel
{
processConditions.ElementAt(index).Conditions.ElementAt(PropertyIndex).ConditionMet = (bool)isNot ? !blen : blen;
}

}
else if (res is ConcurrentQueue<GVL.OrderLocInfo> OrderLocInfoS)
else if (res is ConcurrentQueue<OrderLocInfo> OrderLocInfoS)
{
processConditions.ElementAt(index).Conditions.ElementAt(PropertyIndex).ConditionMet = OrderLocInfoS.Count > 0;
}


+ 116
- 0
HBLConsole/ViewModel/VariableConfig.cs View File

@@ -0,0 +1,116 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Toolkit.Mvvm.ComponentModel;
using Microsoft.Toolkit.Mvvm.Input;
using System.Diagnostics;
using Microsoft.EntityFrameworkCore;
using HBLConsole.Model;
using HBLConsole.Service;

namespace HBLConsole.ViewModel
{
internal class VariableConfig : ObservableObject
{
public VariableConfig()
{
//DelegationNotifi.GetInstance.VariableSave = new Action(() => { SaveDataAsync(); });

//DelegationNotifi.GetInstance.VarNameChanged = new Action<int>((p) =>
//{
// if ((p - 1) >= 0)
// {
// if (varialeInfos?.Count >= p)
// {
// if (varialeInfos.ElementAt(p - 1).VarName != null)
// {
// if (varialeInfos.ElementAt(p - 1).VarName.Length > 0)
// {
// if (varialeInfos.Count == p) AddRow();
// }
// }
// }
// }
//});
GetLocalDataAsync();
}

/// <summary>
/// 异步获取本地数据
/// </summary>
private Task<bool> GetLocalDataAsync()
{
//SqlHelper<VariableInfo>.GetInstance.Database.EnsureCreated();
////多表查询
var DataList = SqlHelper<VariableInfo>.GetInstance.DbObj.ToList();
App.Current.Dispatcher.Invoke(new Action(() => { varialeInfos.Clear(); }));
foreach (var item in DataList)
{
PropBindInfo propBindInfo = new PropBindInfo();
propBindInfo.ID = item.ID;
propBindInfo.VarName = item.VarName;
propBindInfo.Address = item.Address;
propBindInfo.DataType = item.DataType;
propBindInfo.IsEnableAlarm = item.IsEnableAlarm;
propBindInfo.CurrentValue = item.CurrentValue;
var result = item.AlarmSetProp.AnalogAlarmModels.Where(p => p.AlarmSetId == item.ID).ToList();
result = result?.OrderBy(p => p.SortTag).ToList();
propBindInfo.AlarmSetProp.AnalogAlarmModels.Clear();
result?.ForEach(p => { propBindInfo.AlarmSetProp.AnalogAlarmModels.Add(p); });
propBindInfo.AlarmSetProp.DiscreteAlarmInfoSet = item.AlarmSetProp.DiscreteAlarmInfoSet;
App.Current?.Dispatcher.Invoke(new Action(() => { varialeInfos.Add(propBindInfo); }));
}
if (varialeInfos.Count <= 0) AddRow();
return Task.FromResult(true);
}

/// <summary>
/// 异步保存数据
/// </summary>
/// <returns></returns>
private Task<bool> SaveDataAsync()
{
SqlHelper<VariableInfo>.GetInstance.DbObj.RemoveRange(SqlHelper<VariableInfo>.GetInstance.DbObj.ToArray());
foreach (var item in varialeInfos)
{
SqlHelper<VariableInfo>.GetInstance.Add(new VariableInfo()
{
ID = item.ID,
VarName = item.VarName,
Address = item.Address,
DataType = item.DataType,
IsEnableAlarm = item.IsEnableAlarm,
CurrentValue = item.CurrentValue,
AlarmSetProp = item.AlarmSetProp,

});
}
SqlHelper<VariableInfo>.GetInstance.Save();
return Task.FromResult(true);
}

/// <summary>
/// 添加行
/// </summary>
private void AddRow()
{
App.Current.Dispatcher.Invoke(new Action(() =>
{
varialeInfos.Add(new PropBindInfo()
{
ID = varialeInfos.Count + 1,
});
}));

}

/// <summary>
/// 变量信息
/// </summary>
public ObservableCollection<PropBindInfo> varialeInfos { get; set; } = new ObservableCollection<PropBindInfo>();

}
}

Loading…
Cancel
Save