首次提交:添加src文件夹代码
68
Cowain.Bake.Main/App.config
Normal file
@@ -0,0 +1,68 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<configSections>
|
||||
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
|
||||
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
|
||||
</configSections>
|
||||
<startup>
|
||||
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" /></startup>
|
||||
<entityFramework>
|
||||
<providers>
|
||||
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
|
||||
<provider invariantName="MySql.Data.MySqlClient" type="MySql.Data.MySqlClient.MySqlProviderServices, MySql.Data.EntityFramework, Version=8.0.28.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d"></provider>
|
||||
</providers>
|
||||
</entityFramework>
|
||||
<connectionStrings>
|
||||
<add name="BakingEntities" connectionString="metadata=res://*/DBMappering.csdl|res://*/DBMappering.ssdl|res://*/DBMappering.msl;provider=MySql.Data.MySqlClient;provider connection string="server=127.0.0.1;user id=root;password=123456;Persist Security Info=True;AllowPublicKeyRetrieval=True;sslmode=none;database=6098-6"" providerName="System.Data.EntityClient" />
|
||||
</connectionStrings>
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.1.2" newVersion="4.0.1.2" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Threading.Tasks.Extensions" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.2.0.1" newVersion="4.2.0.1" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.ValueTuple" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Collections.Immutable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-1.2.1.0" newVersion="1.2.1.0" />
|
||||
</dependentAssembly>
|
||||
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Numerics.Vectors" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.1.4.0" newVersion="4.1.4.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Text.Encoding.CodePages" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="5.0.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="HandyControl" publicKeyToken="45be8712787a1e5b" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.5.1.0" newVersion="3.5.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="AvalonDock" publicKeyToken="3e4669d2f30244f4" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.72.1.0" newVersion="4.72.1.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
</configuration>
|
||||
24
Cowain.Bake.Main/App.xaml
Normal file
@@ -0,0 +1,24 @@
|
||||
<prism:PrismApplication x:Class="Cowain.Bake.Main.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:Cowain.Bake.Main"
|
||||
xmlns:prism="http://prismlibrary.com/">
|
||||
|
||||
<Application.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
|
||||
<!--HandyControl-->
|
||||
<ResourceDictionary Source="pack://application:,,,/HandyControl;component/Themes/SkinDefault.xaml"/>
|
||||
<ResourceDictionary Source="pack://application:,,,/HandyControl;component/Themes/Theme.xaml"/>
|
||||
<!--Fluent-->
|
||||
<ResourceDictionary Source="pack://application:,,,/Fluent;component/Themes/Generic.xaml" />
|
||||
<!--<ResourceDictionary Source="pack://application:,,,/Fluent;component/Themes/Themes/Light.Green.xaml" />-->
|
||||
<!--<ResourceDictionary Source="pack://application:,,,/Fluent;component/Themes/Themes/Dark.Green.xaml" />-->
|
||||
<!--AvalonDock-->
|
||||
<ResourceDictionary Source="pack://application:,,,/AvalonDock.Themes.Aero;component/Theme.xaml"/>
|
||||
<ResourceDictionary Source="/Cowain.Bake.Main;component/Views/ComboBoxDictionary.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</Application.Resources>
|
||||
</prism:PrismApplication>
|
||||
274
Cowain.Bake.Main/App.xaml.cs
Normal file
@@ -0,0 +1,274 @@
|
||||
using Cowain.Bake.BLL;
|
||||
using Cowain.Bake.Common.Core;
|
||||
using Cowain.Bake.Common.Interface;
|
||||
using Cowain.Bake.Main.Station;
|
||||
using Prism.Ioc;
|
||||
using Prism.Modularity;
|
||||
using Prism.Regions;
|
||||
using Prism.Unity;
|
||||
using System.Threading.Tasks;
|
||||
using System;
|
||||
using System.Windows;
|
||||
using Unity;
|
||||
using Cowain.Bake.Common;
|
||||
using Cowain.Bake.Main.Views;
|
||||
using Cowain.Bake.Main.ViewModels;
|
||||
using Cowain.Bake.Main.Common;
|
||||
using Cowain.Bake.Communication.MOM;
|
||||
using Cowain.Bake.Main.Models;
|
||||
using System.Reflection;
|
||||
using AutoUpdaterDotNET;
|
||||
using System.Diagnostics;
|
||||
using Prism.Services.Dialogs;
|
||||
|
||||
namespace Cowain.Bake.Main
|
||||
{
|
||||
/// <summary>
|
||||
/// App.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class App : PrismApplication
|
||||
{
|
||||
protected override Window CreateShell() //3
|
||||
{
|
||||
//UI线程未捕获异常处理事件
|
||||
this.DispatcherUnhandledException += OnDispatcherUnhandledException;
|
||||
//Task线程内未捕获异常处理事件
|
||||
TaskScheduler.UnobservedTaskException += OnUnobservedTaskException;
|
||||
//多线程异常
|
||||
AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
|
||||
this.Exit += App_Exit;
|
||||
if (SettingProvider.Instance.AutoUpdate)
|
||||
{
|
||||
AutoUpdaterFun();
|
||||
}
|
||||
|
||||
CheckExistProcess();
|
||||
//IsAskPath(); //正式运行,要放开这,
|
||||
return Container.Resolve<MainWindow>();
|
||||
}
|
||||
|
||||
private void OnDispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
|
||||
{
|
||||
//通常全局异常捕捉的都是致命信息
|
||||
LogHelper.Instance.GetCurrentClassFatal($"{e.Exception.StackTrace},{e.Exception.Message}");
|
||||
}
|
||||
|
||||
public static Process GetRunningInstance()
|
||||
{
|
||||
Process current = Process.GetCurrentProcess();
|
||||
Process[] processes = Process.GetProcessesByName(current.ProcessName);
|
||||
|
||||
foreach (Process process in processes)
|
||||
{
|
||||
if (process.Id != current.Id)
|
||||
if (Assembly.GetExecutingAssembly().Location.Replace("/", "\\") == current.MainModule.FileName)
|
||||
return process;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
bool CheckExistProcess()
|
||||
{
|
||||
Process instance = GetRunningInstance();
|
||||
if (instance != null)//没有已经开启的实例
|
||||
{
|
||||
HandyControl.Controls.MessageBox.Warning("程序已在运行,若要重新运行程序请在后台关闭程序进程!", "警告");
|
||||
Environment.Exit(0);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//是否要求路径运行
|
||||
bool IsAskPath()
|
||||
{
|
||||
string path = System.AppDomain.CurrentDomain.BaseDirectory;
|
||||
|
||||
if (path.Contains(MyPath.MAIN_APP))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
HandyControl.Controls.MessageBox.Warning($"程序必须放在[{ MyPath.MAIN_APP}]路径下运行!", "警告");
|
||||
Environment.Exit(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
private void OnUnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
|
||||
{
|
||||
// 处理未观察到的异常
|
||||
Console.WriteLine("Unobserved task exception occurred: " + e.Exception);
|
||||
LogHelper.Instance.GetCurrentClassFatal($"{e.Exception}");
|
||||
// 获取异常的具体信息
|
||||
if (e.Exception is AggregateException aggregateException)
|
||||
{
|
||||
foreach (var innerException in aggregateException.InnerExceptions)
|
||||
{
|
||||
LogHelper.Instance.GetCurrentClassFatal("Exception: " + innerException.Message);
|
||||
LogHelper.Instance.GetCurrentClassFatal("StackTrace: " + innerException.StackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
// 标记异常已被处理
|
||||
e.SetObserved();
|
||||
//LogHelper.Instance.GetCurrentClassFatal($"{e.Exception.StackTrace},{e.Exception.Message},{e.Exception.Source}");
|
||||
}
|
||||
|
||||
private void OnUnhandledException(object sender, UnhandledExceptionEventArgs e)
|
||||
{
|
||||
Exception ex = e.ExceptionObject as Exception;
|
||||
LogHelper.Instance.GetCurrentClassFatal($"{ex.StackTrace},{ex.Message}");
|
||||
|
||||
//记录dump文件
|
||||
MiniDump.TryDump($"dumps\\CowainPreheat_{DateTime.Now.ToString("HH-mm-ss-ms")}.dmp");
|
||||
}
|
||||
|
||||
private void App_Exit(object sender, ExitEventArgs e)
|
||||
{
|
||||
//程序退出时需要处理的业务
|
||||
}
|
||||
|
||||
protected override void OnInitialized() //5
|
||||
{
|
||||
Container.Resolve<IDialogService>(); // 确保对话框服务已注册 20260121
|
||||
var regionManager = Container.Resolve<IRegionManager>();
|
||||
regionManager.RegisterViewWithRegion("MainHeaderRegion", typeof(Views.MainHeaderView));
|
||||
regionManager.RegisterViewWithRegion("BasicInfoRegion", typeof(Views.BasicInfoView));
|
||||
//regionManager.RegisterViewWithRegion("StationInfoRegion", typeof(EquipmentMonitorView));
|
||||
Container.Resolve<MainRowDefinition>();
|
||||
Container.Resolve<UploadMesStation>();
|
||||
Container.Resolve<DataCollectStation>();
|
||||
Container.Resolve<BakingStation>(); //加了他会实例化二次
|
||||
Container.Resolve<AlarmStation>();
|
||||
Container.Resolve<LoadingStation>();
|
||||
Container.Resolve<UnLoadingStation>();
|
||||
Container.Resolve<LifeCycleStation>();
|
||||
Container.Resolve<TaskStation>();
|
||||
Container.Resolve<MesCollectStation>();
|
||||
|
||||
|
||||
base.OnInitialized();
|
||||
regionManager.RegisterViewWithRegion("StationInfoRegion", typeof(EquipmentMonitorView)); //Loaded,会触发一次
|
||||
if (!HslCommunication.Authorization.SetAuthorizationCode("ac963114-3a46-4444-9a16-080a0ce99535"))
|
||||
{
|
||||
LogHelper.Instance.Fatal("PLC授权失败", true);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void InitializeShell(Window shell)
|
||||
{
|
||||
// 先打开登录窗口,如果登录成功,则打开主窗口
|
||||
if (Container.Resolve<Cowain.Bake.UI.Home.Views.LoginView>().ShowDialog() == false) //4
|
||||
{
|
||||
Environment.Exit(0);
|
||||
//Application.Current?.Shutdown();
|
||||
}
|
||||
else
|
||||
{
|
||||
base.InitializeShell(shell);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog) //2
|
||||
{
|
||||
// 可以改为自动扫描
|
||||
moduleCatalog.AddModule<Bake.BLL.BLLModule>();
|
||||
moduleCatalog.AddModule<Bake.UI.UI>();
|
||||
moduleCatalog.AddModule<Bake.Communication.CommunicationModule>();
|
||||
}
|
||||
|
||||
protected override void RegisterTypes(IContainerRegistry containerRegistry) //1
|
||||
{
|
||||
// 1. 把 Window 注册为“对话框外壳”——仅此一句
|
||||
//containerRegistry.RegisterDialog<CavityDtlView, CavityDtlViewModel>();
|
||||
//containerRegistry.RegisterDialog<MoistureValueView, MoistureValueViewMode>();
|
||||
|
||||
containerRegistry.RegisterSingleton<MainWindow>();
|
||||
containerRegistry.RegisterSingleton<MemoryDataProvider>();
|
||||
containerRegistry.RegisterSingleton<BasicInfoViewModel>();
|
||||
containerRegistry.RegisterSingleton<EquipmentMonitorView>();
|
||||
containerRegistry.RegisterSingleton<EquipmentMonitorViewModel>();
|
||||
containerRegistry.RegisterSingleton<MainWindowViewModel>();
|
||||
containerRegistry.RegisterSingleton<TaskStation>();
|
||||
containerRegistry.RegisterSingleton<MainRowDefinition>();
|
||||
containerRegistry.RegisterSingleton<Views.MainHeaderView>();
|
||||
containerRegistry.RegisterSingleton<SettingProvider>();
|
||||
containerRegistry.RegisterSingleton<UpdateStation>();
|
||||
containerRegistry.RegisterSingleton<ITrigService, TrigStation>();
|
||||
containerRegistry.RegisterSingleton<UploadMesStation>();
|
||||
containerRegistry.RegisterSingleton<MESProcess>();
|
||||
containerRegistry.RegisterSingleton<UploadMesStation>();
|
||||
containerRegistry.RegisterSingleton<ICommonFun, ExecCommonFun>();
|
||||
containerRegistry.RegisterSingleton<AlarmStation>();
|
||||
containerRegistry.RegisterSingleton<DataCollectStation>();
|
||||
|
||||
//containerRegistry.RegisterSingleton<CavityDtlView>();
|
||||
containerRegistry.RegisterSingleton<LoadingStation>();
|
||||
containerRegistry.RegisterSingleton<UnLoadingStation>();
|
||||
containerRegistry.RegisterSingleton<LifeCycleStation>();
|
||||
containerRegistry.RegisterSingleton<CmdFactories>();
|
||||
containerRegistry.RegisterSingleton<MesCollectStation>();
|
||||
containerRegistry.RegisterSingleton<BakingStation>();
|
||||
}
|
||||
|
||||
private void AutoUpdaterFun()
|
||||
{
|
||||
string updateXmlUrl = SettingProvider.Instance.AutoUpdateUrl; // 替换为你的实际 URL
|
||||
//AutoUpdater.AppTitle = "我的WPF应用程序";
|
||||
AutoUpdater.Start(updateXmlUrl);
|
||||
//AutoUpdater.OpenDownloadPage = true; // 不打开浏览器
|
||||
//AutoUpdater.UpdateMode = Mode.ForcedDownload; //常规模式,会显示标准更新对话框
|
||||
//AutoUpdater.UpdateFormSize = new System.Drawing.Size(200, 100);
|
||||
AutoUpdater.Mandatory = true; // 强制更新
|
||||
AutoUpdater.ShowSkipButton = false; // 隐藏跳过按钮
|
||||
AutoUpdater.ShowRemindLaterButton = false; // 隐藏稍后提醒按钮
|
||||
// 事件订阅
|
||||
AutoUpdater.CheckForUpdateEvent += OnCheckForUpdate;
|
||||
AutoUpdater.ApplicationExitEvent += AutoUpdater_CheckForUpdateEvent;
|
||||
}
|
||||
|
||||
private void AutoUpdater_CheckForUpdateEvent()
|
||||
{
|
||||
// 确保应用程序完全退出
|
||||
System.Windows.Forms.Application.Exit();
|
||||
}
|
||||
private void OnCheckForUpdate(UpdateInfoEventArgs args)
|
||||
{
|
||||
if (args.Error != null)
|
||||
{
|
||||
if (args.Error is System.Net.WebException)
|
||||
{
|
||||
// 网络错误,稍后重试
|
||||
LogHelper.Instance.Fatal("无法连接更新服务器,请检查网络连接", true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!args.IsUpdateAvailable)
|
||||
{
|
||||
LogHelper.Instance.Fatal($"当前已是最新版本,服务器版本:{args.CurrentVersion},本程序版本:{args.InstalledVersion},本程序版本:" +
|
||||
Assembly.GetExecutingAssembly().GetName().Version);
|
||||
return;
|
||||
}
|
||||
|
||||
MessageBox.Show($"发现新版本,服务器版本:{args.CurrentVersion},本程序版本:" +
|
||||
Assembly.GetExecutingAssembly().GetName().Version, "新版本", MessageBoxButton.OK, MessageBoxImage.Asterisk);
|
||||
|
||||
// 可以在这里添加自定义逻辑,比如备份配置文件等
|
||||
//BackupApplicationFiles();
|
||||
|
||||
// 自动开始下载更新
|
||||
try
|
||||
{
|
||||
AutoUpdater.DownloadUpdate(args);
|
||||
Environment.Exit(0); //有用
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
LogHelper.Instance.Fatal($"下载更新失败: {ex.Message}", true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
244
Cowain.Bake.Main/Common/CmdFactories.cs
Normal file
@@ -0,0 +1,244 @@
|
||||
using Cowain.Bake.BLL;
|
||||
using Cowain.Bake.Common.Core;
|
||||
using Cowain.Bake.Common.Enums;
|
||||
using Cowain.Bake.Communication.Interface;
|
||||
using Cowain.Bake.Model;
|
||||
using Cowain.Bake.Model.Models;
|
||||
using HslCommunication;
|
||||
using System.Linq;
|
||||
using Unity;
|
||||
|
||||
namespace Cowain.Bake.Main.Common
|
||||
{
|
||||
public class CmdFactories
|
||||
{
|
||||
IUnityContainer _unityContainer { get; set; }
|
||||
//IPLCDevice agv = null;
|
||||
public CmdFactories(IUnityContainer unityContainer)
|
||||
{
|
||||
_unityContainer = unityContainer;
|
||||
}
|
||||
public bool StartBaking(IPLCDevice plc, int stationId, bool[] bakeEanble, bool manual = false)
|
||||
{
|
||||
if (!Write<bool[]>(plc, EStoveSignal.HeatEnableStep.ToString(), stationId, 1, bakeEanble).IsSuccess)
|
||||
{
|
||||
LogHelper.Instance.Error($"层烘烤使能失败!plc:{plc.Name}", true);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Write<bool>(plc, EStoveSignal.BakingStart.ToString(), stationId, 1, true).IsSuccess)
|
||||
{
|
||||
LogHelper.Instance.GetCurrentClassError($"下发开始烘烤失败!plc:{plc.Name}", true);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (manual)
|
||||
{
|
||||
LogHelper.Instance.Info($"下发开始烘烤成功!", true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//public bool EndBaking(int stationId)
|
||||
//{
|
||||
// TDeviceConfig conf = _unityContainer.Resolve<DeviceConfigService>().GetConfig(stationId);
|
||||
// IPLCDevice plc = _unityContainer.Resolve<IPLCDevice>(conf.Name);
|
||||
// if (plc == null || !plc.IsConnect)
|
||||
// {
|
||||
// LogHelper.Instance.GetCurrentClassError($"连接PLC失败!plc:{plc.Name}", true);
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// if (!Write<bool>(plc, EStoveSignal.BakingEnd.ToString(), stationId, true).IsSuccess)
|
||||
// {
|
||||
// LogHelper.Instance.GetCurrentClassError($"下发结束烘烤失败!plc:{plc.Name}", true);
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// LogHelper.Instance.Info($"下发结束烘烤成功!", true);
|
||||
// return true;
|
||||
//}
|
||||
|
||||
//复位结束烘烤
|
||||
public bool ResetEndBaking(int machineId)
|
||||
{
|
||||
TDeviceConfig conf = _unityContainer.Resolve<DeviceConfigService>().GetConfig(machineId);
|
||||
IPLCDevice plc = _unityContainer.Resolve<IPLCDevice>(conf.Name);
|
||||
if (plc == null || !plc.IsConnect)
|
||||
{
|
||||
LogHelper.Instance.GetCurrentClassError($"连接PLC失败!plc:{plc.Name}", true);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Write<bool>(plc, EStoveSignal.BakingMark.ToString(), machineId, 1, false).IsSuccess)
|
||||
{
|
||||
LogHelper.Instance.GetCurrentClassError($"下发复位结束烘烤失败!plc:{plc.Name}", true);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool OpenDoor(int stationId, int layer)
|
||||
{
|
||||
TDeviceConfig fromDev = _unityContainer.Resolve<DeviceConfigService>().GetConfig(stationId);
|
||||
IPLCDevice plc = _unityContainer.Resolve<IPLCDevice>(fromDev.Name);
|
||||
if (plc == null || !plc.IsConnect)
|
||||
{
|
||||
LogHelper.Instance.GetCurrentClassError($"连接PLC失败!plc:{plc.Name},layer:{layer}", true);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CommonFun.Instance.IsStoveQualified(plc, stationId, layer, false, true)) //不在工作中
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Write<bool>(plc, EStoveSignal.OpenDoor.ToString(), stationId,1, true).IsSuccess)
|
||||
{
|
||||
HandyControl.Controls.MessageBox.Show($@"下发开门指令成功!", "操作提示");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
HandyControl.Controls.MessageBox.Error($@"下发开门指令失败。", "操作提示");
|
||||
LogHelper.Instance.GetCurrentClassError($"下发开门指令失败!plc:{plc.Name},layer:{layer}");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool CloseDoor(int machineId, int layer)
|
||||
{
|
||||
TDeviceConfig fromDev = _unityContainer.Resolve<DeviceConfigService>().GetConfig(machineId);
|
||||
IPLCDevice plc = _unityContainer.Resolve<IPLCDevice>(fromDev.Name);
|
||||
|
||||
if (plc == null || !plc.IsConnect)
|
||||
{
|
||||
LogHelper.Instance.GetCurrentClassError($"连接PLC失败!plc:{plc.Name},layer:{layer}", true);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CommonFun.Instance.IsStoveQualified(plc, machineId, layer, false, true)) //不在工作中
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Write<bool>(plc, EStoveSignal.CloseDoor.ToString(), machineId, 1, true).IsSuccess)
|
||||
{
|
||||
HandyControl.Controls.MessageBox.Show($@"下发关门指令成功!", "操作提示");
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
HandyControl.Controls.MessageBox.Error($@"下发关门指令失败。", "操作提示");
|
||||
LogHelper.Instance.GetCurrentClassError($"下发关门指令失败!plc:{plc.Name},layer:{layer}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public bool InitStove(int stationId, int layer)
|
||||
{
|
||||
TDeviceConfig dev = _unityContainer.Resolve<DeviceConfigService>().GetConfig(stationId);
|
||||
IPLCDevice plc = _unityContainer.Resolve<IPLCDevice>(dev.Name);
|
||||
|
||||
if (plc == null || !plc.IsConnect)
|
||||
{
|
||||
LogHelper.Instance.GetCurrentClassError($"连接PLC失败!plc:{plc.Name}");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CommonFun.Instance.IsStoveQualified(plc, stationId, layer, false, true)) //不在工作中
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Write<bool>(plc, EStoveSignal.Initial.ToString(), stationId, 1, true).IsSuccess)
|
||||
{
|
||||
HandyControl.Controls.MessageBox.Show($@"下发初始化请求指令成功!", "操作提示");
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
HandyControl.Controls.MessageBox.Error($@"下发初始化请求指令失败。", "操作提示");
|
||||
LogHelper.Instance.GetCurrentClassError($"下发初始化请求指令失败!plc:{plc.Name}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
//public bool NotifyPLCHavePallet(int machineId, int layer, int number)
|
||||
//{
|
||||
// TDeviceConfig dev = _unityContainer.Resolve<DeviceConfigService>().GetConfig(machineId);
|
||||
// IPLCDevice plc = _unityContainer.Resolve<IPLCDevice>(dev.Name);
|
||||
// if (plc == null || !plc.IsConnect)
|
||||
// {
|
||||
// LogHelper.Instance.GetCurrentClassError($"连接PLC失败!plc:{plc.Name},layer:{layer}");
|
||||
// return false;
|
||||
// }
|
||||
// if (!CommonFun.Instance.IsStoveQualified(plc, machineId, layer))
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
// string Tray = number == 1 ? EStoveSignal.Tray1.ToString() : EStoveSignal.Tray2.ToString();
|
||||
// if (Write<bool>(plc, Tray, machineId,layer,true).IsSuccess)
|
||||
// {
|
||||
// HandyControl.Controls.MessageBox.Show($@"下发托盘记忆成功!", "操作提示");
|
||||
// return true;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// HandyControl.Controls.MessageBox.Error($@"下发托盘记忆失败。", "操作提示");
|
||||
// LogHelper.Instance.GetCurrentClassError($"下发托盘记忆失败!plc:{plc.Name},layer:{layer}");
|
||||
// return false;
|
||||
// }
|
||||
//}
|
||||
//public bool NotifyPLCDontHavePallet(int machineId, int layer, int number)
|
||||
//{
|
||||
// TDeviceConfig dev = _unityContainer.Resolve<DeviceConfigService>().GetConfig(machineId);
|
||||
// IPLCDevice plc = _unityContainer.Resolve<IPLCDevice>(dev.Name);
|
||||
// if (plc == null || !plc.IsConnect)
|
||||
// {
|
||||
// LogHelper.Instance.GetCurrentClassError($"连接PLC失败!plc:{plc.Name},layer:{layer}");
|
||||
// return false;
|
||||
// }
|
||||
// if (!CommonFun.Instance.IsStoveQualified(plc, machineId, layer))
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
// string Tray = number == 1 ? EStoveSignal.Tray1.ToString() : EStoveSignal.Tray2.ToString();
|
||||
// if (Write<bool>(plc, Tray, machineId, layer, false).IsSuccess)
|
||||
// {
|
||||
// HandyControl.Controls.MessageBox.Show($@"下发托盘记忆成功!", "操作提示");
|
||||
// return true;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// HandyControl.Controls.MessageBox.Error($@"下发清除托盘记忆失败。", "操作提示");
|
||||
// LogHelper.Instance.GetCurrentClassError($"下发清除托盘记忆失败!plc:{plc.Name},layer:{layer}");
|
||||
// return false;
|
||||
// }
|
||||
//}
|
||||
|
||||
public OperateResult Write<T>(IPLCDevice plc, string paramName, int machineId, int layer, T data)
|
||||
{
|
||||
string nodeAddr = "";
|
||||
OperateResult result = new OperateResult()
|
||||
{
|
||||
IsSuccess = false,
|
||||
};
|
||||
|
||||
Variable node = null;
|
||||
node = (from storage in plc.Storages
|
||||
from item in storage.VariableList
|
||||
where storage.StationId == machineId && item.ParamName == paramName && item.Number == layer
|
||||
select item).FirstOrDefault();
|
||||
|
||||
if (null == node)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
nodeAddr = $"{node.Address}{node.VarName}";
|
||||
return plc.Write<T>(nodeAddr, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
179
Cowain.Bake.Main/Common/CommonFun.cs
Normal file
@@ -0,0 +1,179 @@
|
||||
using ControlzEx.Standard;
|
||||
using Cowain.Bake.Common;
|
||||
using Cowain.Bake.Common.Core;
|
||||
using Cowain.Bake.Common.Enums;
|
||||
using Cowain.Bake.Communication.Interface;
|
||||
using Cowain.Bake.Main.Models;
|
||||
using Cowain.Bake.Main.Station;
|
||||
using Cowain.Bake.Model.Models;
|
||||
using HslCommunication;
|
||||
using Opc.Ua;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using Unity;
|
||||
|
||||
namespace Cowain.Bake.Main.Common
|
||||
{
|
||||
public class CommonFun
|
||||
{
|
||||
private static CommonFun instance;
|
||||
public static CommonFun Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = new CommonFun();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
//public OperateResult Writes(IUnityContainer unityContainer, string reply, object[] values)
|
||||
//{
|
||||
// //string[] arrayAddress = reply.Address1.Split(',');
|
||||
// //var plc = unityContainer.Resolve<IPLCDevice>(reply.PLCName);
|
||||
// //EDataType dt = (EDataType)Enum.Parse(typeof(EDataType), reply.AddressType);
|
||||
// //Type type = Type.GetType(dt.GetDescription());
|
||||
// //var mi = this.GetType().GetMethod(ReflexFun.OPC_WRITE_NODES).MakeGenericMethod(new Type[] { type }); //反射;
|
||||
// //return (OperateResult)mi.Invoke(this, new object[]
|
||||
// //{
|
||||
// // plc,
|
||||
// // arrayAddress,
|
||||
// // values
|
||||
// //});
|
||||
// return null;
|
||||
//}
|
||||
|
||||
//public OperateResult Write(IUnityContainer unityContainer, string reply, object value)
|
||||
//{
|
||||
// //var plc = unityContainer.Resolve<IPLCDevice>(reply.PLCName);
|
||||
// //EDataType dt = (EDataType)Enum.Parse(typeof(EDataType), reply.AddressType);
|
||||
// //Type type = Type.GetType(dt.GetDescription());
|
||||
// //var mi = this.GetType().GetMethod(ReflexFun.OPC_WRITE_NODE).MakeGenericMethod(new Type[] { type }); //反射;
|
||||
// //return (OperateResult)mi.Invoke(this, new object[]
|
||||
// //{
|
||||
// // plc,
|
||||
// // reply.Address,
|
||||
// // value
|
||||
// //});
|
||||
// return null;
|
||||
//}
|
||||
|
||||
//烘箱是否具备条件
|
||||
public bool IsStoveQualified(IPLCDevice plc, int machineId, int layer, bool isWork, bool popupScreen = false) //popupScreen:人工下发指令要弹屏
|
||||
{
|
||||
//远程/本地模式
|
||||
var mode = plc.GetValue<bool>(EStoveSignal.Remote.ToString(), machineId, layer);
|
||||
|
||||
if (!mode.IsSuccess) //本地
|
||||
{
|
||||
//LogHelper.Instance.Error("读取远程模式失败或本地模式!", null, true);
|
||||
return false ;
|
||||
}
|
||||
|
||||
if (!mode.Content) //true:远程, false:本地
|
||||
{
|
||||
if (popupScreen)
|
||||
{
|
||||
LogHelper.Instance.Error("本地模式,不能执行指令操作!", true);
|
||||
}
|
||||
|
||||
//return false; //add by lsm 20250926 test
|
||||
}
|
||||
|
||||
//0 / 空闲 1 / 待机 2 / 停止 3 / 工作 4 / 保压
|
||||
var workStatus = plc.GetValue<Int16>(EStoveSignal.CavityStatus.ToString(), machineId, layer);
|
||||
if (!workStatus.IsSuccess) //系统状态寄存器
|
||||
{
|
||||
if (popupScreen)
|
||||
{
|
||||
LogHelper.Instance.Error("读取烘箱工作状态失败!", true);
|
||||
}
|
||||
return false ;
|
||||
}
|
||||
|
||||
if (isWork) //
|
||||
{
|
||||
if ((int)EStoveWorkMode.Standby >= workStatus.Content) //工作当中判断,0,1
|
||||
{
|
||||
if (popupScreen)
|
||||
{
|
||||
LogHelper.Instance.Error("判断要在工作当中,却为空闲,所以不满足条件执行!");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else //要求不是工作状态
|
||||
{
|
||||
if ((int)EStoveWorkMode.Standby < workStatus.Content) //非工作当中判断,2,3,4
|
||||
{
|
||||
if (popupScreen)
|
||||
{
|
||||
LogHelper.Instance.Error("判断要在空闲当中,却为工作,所以不满足条件执行!");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool IsStoveQualified(IPLCDevice plc, int machineId, int layer)
|
||||
{
|
||||
//远程/本地模式 var mode = plc.GetValue<bool>(EStoveSignal.CavityStatus.ToString(), item.Key, layer);
|
||||
var mode = plc.GetValue<bool>(EStoveSignal.Remote.ToString(), machineId, layer);
|
||||
|
||||
if (!mode.IsSuccess) //本地
|
||||
{
|
||||
LogHelper.Instance.Error("读取远程模式失败或本地模式!", true);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mode.Content) //true:远程, false:本地
|
||||
{
|
||||
LogHelper.Instance.Error("本地模式,不能执行其操作!", true);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//发送一个节点,数据可以是单个,也可以是数组
|
||||
//public OperateResult WriteNode<T>(IPLCDevice plc, string address, object value)
|
||||
//{
|
||||
// if (value is Array)
|
||||
// {
|
||||
// T[] t = (T[])Convert.ChangeType(value, typeof(T[]));
|
||||
// return plc.Write<T[]>(address, t);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// T t = (T)Convert.ChangeType(value, typeof(T));
|
||||
// return plc.Write<T>(address, t);
|
||||
// }
|
||||
//}
|
||||
|
||||
//public OperateResult WriteNodes<T>(IPLCDevice plc, string[] tags, object[] values)
|
||||
//{
|
||||
// //T t = (T)Convert.ChangeType(value, typeof(T));
|
||||
// return plc.Writes(tags, values);
|
||||
//}
|
||||
|
||||
public float[] UShortToFloat(Int16[] datas)
|
||||
{
|
||||
List<float> f = new List<float>();
|
||||
|
||||
for (int i = 1; i < datas.Count(); i++)
|
||||
{
|
||||
f.Add(datas[i] / 1.0f / 100);
|
||||
}
|
||||
|
||||
return f.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
79
Cowain.Bake.Main/Common/ExecCommonFun.cs
Normal file
@@ -0,0 +1,79 @@
|
||||
using Cowain.Bake.BLL;
|
||||
using Cowain.Bake.Common.Core;
|
||||
using Cowain.Bake.Common.Interface;
|
||||
using Cowain.Bake.Communication.MOM;
|
||||
using Cowain.Bake.Main.Station;
|
||||
using Cowain.Bake.Main.ViewModels;
|
||||
using Cowain.Bake.Main.Views;
|
||||
using Cowain.Bake.Model;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Unity;
|
||||
using JSON = Newtonsoft.Json.JsonConvert;
|
||||
using static Cowain.Bake.Common.Models.MESModel;
|
||||
|
||||
namespace Cowain.Bake.Main.Common
|
||||
{
|
||||
public class ExecCommonFun : ICommonFun
|
||||
{
|
||||
readonly IUnityContainer _unityContainer;
|
||||
public ExecCommonFun(IUnityContainer unityContainer)
|
||||
{
|
||||
_unityContainer = unityContainer;
|
||||
}
|
||||
|
||||
public void ModifyOrderNum()
|
||||
{
|
||||
var basicInfoViewModel = _unityContainer.Resolve<BasicInfoViewModel>();
|
||||
var memory = _unityContainer.Resolve<MemoryDataProvider>();
|
||||
basicInfoViewModel.CurrentJobNum = memory.CurrentUser.JobNum;
|
||||
basicInfoViewModel.CurrentOperation = memory.CurrentUser.ProcessParamName;
|
||||
SettingProvider.Instance.WaterPallet = 0;
|
||||
}
|
||||
|
||||
public bool ManualTaskCmd(TTaskRecord task, short stepId)
|
||||
{
|
||||
return _unityContainer.Resolve<TaskStation>().ManualTaskCmd(task, stepId); //发送
|
||||
}
|
||||
|
||||
public void InitWindows()
|
||||
{
|
||||
_unityContainer.Resolve<MainHeaderView>().ClearWindows(); //
|
||||
_unityContainer.Resolve<MainHeaderView>().Init(); //
|
||||
}
|
||||
|
||||
public void SetBatteryCodeLen()
|
||||
{
|
||||
_unityContainer.Resolve<LoadingStation>().SetBatteryCodeLen(); //
|
||||
}
|
||||
|
||||
public string ManualMesOutUnBinding(TPalletInfo palletInfo, TBatteryInfo battery)
|
||||
{
|
||||
string msg = "";
|
||||
List<TBatteryInfo> betterys = new List<TBatteryInfo>() ;
|
||||
betterys.Add(battery);
|
||||
|
||||
var mesResult = _unityContainer.Resolve<UnLoadingStation>().MesOutUnBinding(palletInfo, betterys, true);
|
||||
if (mesResult == null)
|
||||
{
|
||||
msg = $"出站,MOM返回超时,电芯条码:{string.Join(",", betterys.Select(x => x.BatteryCode).ToList())}";
|
||||
LogHelper.Instance.Error(msg); //偶尔会返回空,
|
||||
}
|
||||
else if (mesResult.Info.ResultFlag.ToUpper() == "NG")
|
||||
{
|
||||
msg = $"出站,MOM返回信息异常,信息:{JSON.SerializeObject(mesResult)}";
|
||||
}
|
||||
else
|
||||
{
|
||||
msg = $"信息:{JSON.SerializeObject(mesResult)}";
|
||||
}
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
public MESReturnCmdModel SendData(string info)
|
||||
{
|
||||
return _unityContainer.Resolve<MESProcess>().SendData(info); //发送
|
||||
}
|
||||
}
|
||||
}
|
||||
106
Cowain.Bake.Main/Common/HeaderCMD.cs
Normal file
@@ -0,0 +1,106 @@
|
||||
using Cowain.Bake.BLL;
|
||||
using Cowain.Bake.Common;
|
||||
using Cowain.Bake.Common.Enums;
|
||||
using Cowain.Bake.Main.Station;
|
||||
using Cowain.Bake.Main.ViewModels;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Unity;
|
||||
|
||||
namespace Cowain.Bake.Main.Common
|
||||
{
|
||||
public class HeaderCMD
|
||||
{
|
||||
private readonly IUnityContainer _unityContainer;
|
||||
public HeaderCMD(IUnityContainer unityContainer)
|
||||
{
|
||||
_unityContainer = unityContainer;
|
||||
//_basicInfo = basicInfo;
|
||||
}
|
||||
public void Auto(string JSON)
|
||||
{
|
||||
Views.MainHeaderView.ribbonButtonDic["Auto"].IsEnabled = false;
|
||||
Views.MainHeaderView.ribbonButtonDic["Manual"].IsEnabled = true;
|
||||
Bake.Common.Core.SettingProvider.Instance.DispMode = EDispatchMode.Auto;
|
||||
HandyControl.Controls.MessageBox.Success("自动调度", "切换调度模式");
|
||||
_unityContainer.Resolve<TaskStation>()._newTaskEvent.Set();
|
||||
_unityContainer.Resolve<BasicInfoViewModel>().DispMode= EDispatchMode.Auto.GetDescription();
|
||||
}
|
||||
|
||||
public void Manual(string JSON)
|
||||
{
|
||||
if (System.Windows.MessageBoxResult.OK ==HandyControl.Controls.MessageBox.Ask("调度机器人将停下来,您确定手动调度?", "切换调度模式"))
|
||||
{
|
||||
Views.MainHeaderView.ribbonButtonDic["Manual"].IsEnabled = false;
|
||||
Views.MainHeaderView.ribbonButtonDic["Auto"].IsEnabled = true;
|
||||
Bake.Common.Core.SettingProvider.Instance.DispMode = EDispatchMode.Manual;
|
||||
_unityContainer.Resolve<BasicInfoViewModel>().DispMode = EDispatchMode.Manual.GetDescription();
|
||||
}
|
||||
}
|
||||
|
||||
public void ScanCodeMode(string JSON)
|
||||
{
|
||||
string methodName = System.Reflection.MethodBase.GetCurrentMethod().Name;
|
||||
UpdateSwitch(JSON, Cowain.Bake.Common.Enums.ESysSetup.ScanCodeMode.ToString(), methodName);
|
||||
_unityContainer.Resolve<LogService>().AddLog($@"切换【{Cowain.Bake.Common.Enums.ESysSetup.ScanCodeMode.GetDescription()}】!", E_LogType.Operate.ToString());
|
||||
}
|
||||
private bool UpdateSwitch(string JSON, string paraID, string methodName)
|
||||
{
|
||||
DataTable table = _unityContainer.Resolve<Cowain.Bake.BLL.MenuInfoService>().GetLabelName(methodName);
|
||||
string labelName = table.Rows[0]["Header"].ToString();
|
||||
var service = _unityContainer.Resolve<Cowain.Bake.BLL.SysSetupService>();
|
||||
if (Views.MainHeaderView.toggleButtonLabelDic[labelName].Content.ToString()
|
||||
== table.Rows[0]["Value0"].ToString())
|
||||
{
|
||||
Views.MainHeaderView.toggleButtonLabelDic[labelName].Content = table.Rows[0]["Value1"].ToString();
|
||||
return service.UpdateValue(paraID, "1");
|
||||
}
|
||||
else
|
||||
{
|
||||
Views.MainHeaderView.toggleButtonLabelDic[labelName].Content = table.Rows[0]["Value0"].ToString();
|
||||
return service.UpdateValue(paraID, "0");
|
||||
}
|
||||
}
|
||||
public void DebugMode(string JSON)
|
||||
{
|
||||
string methodName = System.Reflection.MethodBase.GetCurrentMethod().Name;
|
||||
DataTable table = _unityContainer.Resolve<Cowain.Bake.BLL.MenuInfoService>().GetLabelName(methodName);
|
||||
string labelName = table.Rows[0]["Header"].ToString();
|
||||
|
||||
if (Views.MainHeaderView.toggleButtonLabelDic[labelName].Content.ToString()
|
||||
== table.Rows[0]["Value0"].ToString())
|
||||
{
|
||||
Views.MainHeaderView.toggleButtonLabelDic[labelName].Content = table.Rows[0]["Value1"].ToString();
|
||||
_unityContainer.Resolve<BLL.SysSetupService>().UpdateValue(ESysSetup.DebugMode.ToString(), ((int)EProductionMode.Normal).ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
Views.MainHeaderView.toggleButtonLabelDic[labelName].Content = table.Rows[0]["Value0"].ToString();
|
||||
_unityContainer.Resolve<BLL.SysSetupService>().UpdateValue(ESysSetup.DebugMode.ToString(), ((int)EProductionMode.Debug).ToString());
|
||||
}
|
||||
}
|
||||
|
||||
public void MOMEnable(string JSON)
|
||||
{
|
||||
string methodName = System.Reflection.MethodBase.GetCurrentMethod().Name;
|
||||
DataTable table = _unityContainer.Resolve<Cowain.Bake.BLL.MenuInfoService>().GetLabelName(methodName);
|
||||
string labelName = table.Rows[0]["Header"].ToString();
|
||||
|
||||
if (Views.MainHeaderView.toggleButtonLabelDic[labelName].Content.ToString()
|
||||
== table.Rows[0]["Value0"].ToString())
|
||||
{
|
||||
Views.MainHeaderView.toggleButtonLabelDic[labelName].Content = table.Rows[0]["Value1"].ToString();
|
||||
_unityContainer.Resolve<BLL.SysSetupService>().UpdateValue(ESysSetup.MOMEnable.ToString(), ((int)EMOMEnable.Enable).ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
Views.MainHeaderView.toggleButtonLabelDic[labelName].Content = table.Rows[0]["Value0"].ToString();
|
||||
_unityContainer.Resolve<BLL.SysSetupService>().UpdateValue(ESysSetup.MOMEnable.ToString(), ((int)EMOMEnable.Disable).ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
392
Cowain.Bake.Main/Cowain.Bake.Main.csproj
Normal file
@@ -0,0 +1,392 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{8E1456EF-EDF6-4DC3-BF95-62655997D912}</ProjectGuid>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<RootNamespace>Cowain.Bake.Main</RootNamespace>
|
||||
<AssemblyName>Cowain.Bake.Main</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<Deterministic>true</Deterministic>
|
||||
<TargetFrameworkProfile />
|
||||
<NuGetPackageImportStamp>
|
||||
</NuGetPackageImportStamp>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ApplicationIcon>cowain.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="AutoUpdater.NET, Version=1.9.2.0, Culture=neutral, PublicKeyToken=501435c91b35f4bc, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Autoupdater.NET.Official.1.9.2\lib\net462\AutoUpdater.NET.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="AvalonDock, Version=4.72.1.0, Culture=neutral, PublicKeyToken=3e4669d2f30244f4, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Dirkster.AvalonDock.4.72.1\lib\net40\AvalonDock.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="AvalonDock.Themes.Aero, Version=4.72.1.0, Culture=neutral, PublicKeyToken=3e4669d2f30244f4, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Dirkster.AvalonDock.Themes.Aero.4.72.1\lib\net40\AvalonDock.Themes.Aero.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="AvalonDock.Themes.Expression, Version=4.72.1.0, Culture=neutral, PublicKeyToken=3e4669d2f30244f4, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Dirkster.AvalonDock.Themes.Expression.4.72.1\lib\net40\AvalonDock.Themes.Expression.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="AvalonDock.Themes.Metro, Version=4.71.2.0, Culture=neutral, PublicKeyToken=3e4669d2f30244f4, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Dirkster.AvalonDock.Themes.Metro.4.71.2\lib\net40\AvalonDock.Themes.Metro.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="AvalonDock.Themes.VS2013, Version=4.72.1.0, Culture=neutral, PublicKeyToken=3e4669d2f30244f4, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Dirkster.AvalonDock.Themes.VS2013.4.72.1\lib\net40\AvalonDock.Themes.VS2013.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="ControlzEx, Version=5.0.0.0, Culture=neutral, PublicKeyToken=69f1c32f803d307e, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\ControlzEx.5.0.1\lib\net462\ControlzEx.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Cowain.Bake.BLL">
|
||||
<HintPath>..\Cowain.Bake.BLL\bin\Debug\Cowain.Bake.BLL.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Cowain.Bake.Common">
|
||||
<HintPath>..\Cowain.Bake.Common\bin\Debug\Cowain.Bake.Common.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Cowain.Bake.Communication">
|
||||
<HintPath>..\Cowain.Bake.Communication\bin\Debug\Cowain.Bake.Communication.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Cowain.Bake.Model">
|
||||
<HintPath>..\Cowain.Bake.Model\bin\Debug\Cowain.Bake.Model.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Cowain.Bake.UI">
|
||||
<HintPath>..\Cowain.Bake.UI\bin\Debug\Cowain.Bake.UI.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="CsvHelper">
|
||||
<HintPath>..\Libs\CsvHelper.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Fluent, Version=9.0.0.0, Culture=neutral, PublicKeyToken=3e436e32a8c5546f, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Fluent.Ribbon.9.0.4\lib\net462\Fluent.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Google.Protobuf, Version=3.14.0.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Google.Protobuf.3.14.0\lib\net45\Google.Protobuf.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="HandyControl, Version=3.5.1.0, Culture=neutral, PublicKeyToken=45be8712787a1e5b, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\HandyControl.3.5.1\lib\net472\HandyControl.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="HslCommunication">
|
||||
<HintPath>..\Libs\HslCommunication.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="K4os.Compression.LZ4, Version=1.2.6.0, Culture=neutral, PublicKeyToken=2186fa9121ef231d, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\K4os.Compression.LZ4.1.2.6\lib\net46\K4os.Compression.LZ4.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="K4os.Compression.LZ4.Streams, Version=1.2.6.0, Culture=neutral, PublicKeyToken=2186fa9121ef231d, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\K4os.Compression.LZ4.Streams.1.2.6\lib\net46\K4os.Compression.LZ4.Streams.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="K4os.Hash.xxHash, Version=1.0.6.0, Culture=neutral, PublicKeyToken=32cd54395057cec3, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\K4os.Hash.xxHash.1.0.6\lib\net46\K4os.Hash.xxHash.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Bcl.AsyncInterfaces, Version=7.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.Bcl.AsyncInterfaces.7.0.0\lib\net462\Microsoft.Bcl.AsyncInterfaces.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Bcl.HashCode">
|
||||
<HintPath>..\Libs\Microsoft.Bcl.HashCode.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.VisualBasic" />
|
||||
<Reference Include="Microsoft.Web.WebView2.Core, Version=1.0.2592.51, Culture=neutral, PublicKeyToken=2a8ab48044d2601e, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.Web.WebView2.1.0.2592.51\lib\net462\Microsoft.Web.WebView2.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Web.WebView2.WinForms, Version=1.0.2592.51, Culture=neutral, PublicKeyToken=2a8ab48044d2601e, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.Web.WebView2.1.0.2592.51\lib\net462\Microsoft.Web.WebView2.WinForms.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Web.WebView2.Wpf, Version=1.0.2592.51, Culture=neutral, PublicKeyToken=2a8ab48044d2601e, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.Web.WebView2.1.0.2592.51\lib\net462\Microsoft.Web.WebView2.Wpf.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Xaml.Behaviors, Version=1.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.Xaml.Behaviors.Wpf.1.1.31\lib\net45\Microsoft.Xaml.Behaviors.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="MySql.Data, Version=8.0.28.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\Libs\MySql.Data.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Opc.Ua.Core">
|
||||
<HintPath>..\Libs\Opc.Ua.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Prism">
|
||||
<HintPath>..\Libs\Prism.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Prism.Unity.Wpf">
|
||||
<HintPath>..\Libs\Prism.Unity.Wpf.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Prism.Wpf">
|
||||
<HintPath>..\Libs\Prism.Wpf.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Buffers, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.ComponentModel" />
|
||||
<Reference Include="System.ComponentModel.DataAnnotations" />
|
||||
<Reference Include="System.Configuration" />
|
||||
<Reference Include="System.Configuration.Install" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Management" />
|
||||
<Reference Include="System.Memory, Version=4.0.1.2, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Memory.4.5.5\lib\net461\System.Memory.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Numerics" />
|
||||
<Reference Include="System.Numerics.Vectors, Version=4.1.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.6.0.0\lib\net461\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Runtime.Serialization" />
|
||||
<Reference Include="System.ServiceModel" />
|
||||
<Reference Include="System.Text.Encodings.Web, Version=7.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Text.Encodings.Web.7.0.0\lib\net462\System.Text.Encodings.Web.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Text.Json, Version=7.0.0.2, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Text.Json.7.0.2\lib\net462\System.Text.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Threading.Tasks.Extensions, Version=4.2.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Transactions" />
|
||||
<Reference Include="System.ValueTuple, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Web" />
|
||||
<Reference Include="System.Web.Extensions" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xaml">
|
||||
<RequiredTargetFramework>4.0</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="Ubiety.Dns.Core, Version=2.2.1.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\Libs\Ubiety.Dns.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UIAutomationProvider" />
|
||||
<Reference Include="UIAutomationTypes" />
|
||||
<Reference Include="Unity.Abstractions, Version=5.11.7.0, Culture=neutral, PublicKeyToken=489b6accfaf20ef0, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Unity.Abstractions.5.11.7\lib\net47\Unity.Abstractions.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Unity.Container, Version=5.11.11.0, Culture=neutral, PublicKeyToken=489b6accfaf20ef0, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Unity.Container.5.11.11\lib\net47\Unity.Container.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="WindowsBase" />
|
||||
<Reference Include="PresentationCore" />
|
||||
<Reference Include="PresentationFramework" />
|
||||
<Reference Include="WindowsFormsIntegration" />
|
||||
<Reference Include="ZstdNet, Version=1.4.5.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\Libs\ZstdNet.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ApplicationDefinition Include="App.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</ApplicationDefinition>
|
||||
<Compile Include="Common\CmdFactories.cs" />
|
||||
<Compile Include="Common\CommonFun.cs" />
|
||||
<Compile Include="Common\ExecCommonFun.cs" />
|
||||
<Compile Include="Common\HeaderCMD.cs" />
|
||||
<Compile Include="Models\LogModel.cs" />
|
||||
<Compile Include="Models\MainHeaderModel.cs" />
|
||||
<Compile Include="Models\MainRowDefinition.cs" />
|
||||
<Compile Include="Models\MultiComboBox.cs" />
|
||||
<Compile Include="Models\PallletTemp.cs" />
|
||||
<Compile Include="Station\AlarmStation.cs" />
|
||||
<Compile Include="Station\BakingStation.cs" />
|
||||
<Compile Include="Station\DataCollectStation.cs" />
|
||||
<Compile Include="Station\LifeCycleStation.cs" />
|
||||
<Compile Include="Station\MesCollectStation.cs" />
|
||||
<Compile Include="Station\LoadingStation.cs" />
|
||||
<Compile Include="Station\StoveProcessParam.cs" />
|
||||
<Compile Include="Station\TaskStation.cs" />
|
||||
<Compile Include="Station\TrigStation.cs" />
|
||||
<Compile Include="Station\UnLoadingStation.cs" />
|
||||
<Compile Include="Station\UpdateStation.cs" />
|
||||
<Compile Include="Station\UploadMesStation.cs" />
|
||||
<Compile Include="ViewModels\AddBatteryViewModel.cs" />
|
||||
<Compile Include="ViewModels\BasicInfoViewModel.cs" />
|
||||
<Compile Include="ViewModels\EquipmentMonitorViewModel.cs" />
|
||||
<Compile Include="ViewModels\MainWindowViewModel.cs" />
|
||||
<Compile Include="ViewModels\ManualTaskViewModel.cs" />
|
||||
<Compile Include="ViewModels\MoistureValueViewMode.cs" />
|
||||
<Compile Include="ViewModels\CavityDtlViewModel.cs" />
|
||||
<Compile Include="ViewModels\PalletIdInputWindowViewModel.cs" />
|
||||
<Compile Include="Views\AddBatteryView.xaml.cs">
|
||||
<DependentUpon>AddBatteryView.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\BasicInfoView.xaml.cs">
|
||||
<DependentUpon>BasicInfoView.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\CavityDtlView.xaml.cs">
|
||||
<DependentUpon>CavityDtlView.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\EquipmentMonitorView.xaml.cs">
|
||||
<DependentUpon>EquipmentMonitorView.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\LogManagement.xaml.cs">
|
||||
<DependentUpon>LogManagement.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\ManualTask.xaml.cs">
|
||||
<DependentUpon>ManualTask.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\MoistureValueView.xaml.cs">
|
||||
<DependentUpon>MoistureValueView.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\PalletIdInputWindow.xaml.cs">
|
||||
<DependentUpon>PalletIdInputWindow.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Page Include="Views\AddBatteryView.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Views\BasicInfoView.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\CavityDtlView.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Views\ComboBoxDictionary.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Views\EquipmentMonitorView.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Views\LogManagement.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Views\MainHeaderView.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\MainWindow.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Compile Include="App.xaml.cs">
|
||||
<DependentUpon>App.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Models\MenuItemModel.cs" />
|
||||
<Compile Include="ViewModels\MainHeaderViewModel.cs" />
|
||||
<Compile Include="Views\MainHeaderView.xaml.cs">
|
||||
<DependentUpon>MainHeaderView.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\MainWindow.xaml.cs">
|
||||
<DependentUpon>MainWindow.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Page Include="Views\ManualTask.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Views\MoistureValueView.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Views\PalletIdInputWindow.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Properties\AssemblyInfo.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Properties\Settings.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
</Compile>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
<None Include="packages.config" />
|
||||
<None Include="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Images\Images\Navigation\Backward_16x16.png" />
|
||||
<Resource Include="Images\Images\Navigation\Backward_32x32.png" />
|
||||
<Resource Include="Images\Images\Navigation\DocumentMap_16x16.png" />
|
||||
<Resource Include="Images\Images\Navigation\DocumentMap_32x32.png" />
|
||||
<Resource Include="Images\Images\Navigation\Forward_16x16.png" />
|
||||
<Resource Include="Images\Images\Navigation\Forward_32x32.png" />
|
||||
<Resource Include="Images\Images\Navigation\Home_16x16.png" />
|
||||
<Resource Include="Images\Images\Navigation\Home_32x32.png" />
|
||||
<Resource Include="Images\Images\Navigation\NavigationBar_16x16.png" />
|
||||
<Resource Include="Images\Images\Navigation\NavigationBar_32x32.png" />
|
||||
<Resource Include="Images\Images\Navigation\Next_16x16.png" />
|
||||
<Resource Include="Images\Images\Navigation\Next_32x32.png" />
|
||||
<Resource Include="Images\Images\Navigation\Previous_16x16.png" />
|
||||
<Resource Include="Images\Images\Navigation\Previous_32x32.png" />
|
||||
<Resource Include="Images\Images\Navigation\Up_16x16.png" />
|
||||
<Resource Include="Images\Images\Navigation\Up_32x32.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="cowain.ico" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Images\png\RgvError.png" />
|
||||
<Resource Include="Images\png\RgvMove.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Images\png\RgvWait.png" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="..\packages\Microsoft.Web.WebView2.1.0.2592.51\build\Microsoft.Web.WebView2.targets" Condition="Exists('..\packages\Microsoft.Web.WebView2.1.0.2592.51\build\Microsoft.Web.WebView2.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\packages\Microsoft.Web.WebView2.1.0.2592.51\build\Microsoft.Web.WebView2.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Web.WebView2.1.0.2592.51\build\Microsoft.Web.WebView2.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
||||
6
Cowain.Bake.Main/Cowain.Bake.Main.csproj.user
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<ProjectView>ProjectFiles</ProjectView>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
BIN
Cowain.Bake.Main/Images/Images/Navigation/Backward_16x16.png
Normal file
|
After Width: | Height: | Size: 1000 B |
BIN
Cowain.Bake.Main/Images/Images/Navigation/Backward_32x32.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
Cowain.Bake.Main/Images/Images/Navigation/DocumentMap_16x16.png
Normal file
|
After Width: | Height: | Size: 553 B |
BIN
Cowain.Bake.Main/Images/Images/Navigation/DocumentMap_32x32.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
Cowain.Bake.Main/Images/Images/Navigation/Forward_16x16.png
Normal file
|
After Width: | Height: | Size: 997 B |
BIN
Cowain.Bake.Main/Images/Images/Navigation/Forward_32x32.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
Cowain.Bake.Main/Images/Images/Navigation/Home_16x16.png
Normal file
|
After Width: | Height: | Size: 856 B |
BIN
Cowain.Bake.Main/Images/Images/Navigation/Home_32x32.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 976 B |
|
After Width: | Height: | Size: 2.7 KiB |
BIN
Cowain.Bake.Main/Images/Images/Navigation/Next_16x16.png
Normal file
|
After Width: | Height: | Size: 983 B |
BIN
Cowain.Bake.Main/Images/Images/Navigation/Next_32x32.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
Cowain.Bake.Main/Images/Images/Navigation/Previous_16x16.png
Normal file
|
After Width: | Height: | Size: 1002 B |
BIN
Cowain.Bake.Main/Images/Images/Navigation/Previous_32x32.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
Cowain.Bake.Main/Images/Images/Navigation/Up_16x16.png
Normal file
|
After Width: | Height: | Size: 842 B |
BIN
Cowain.Bake.Main/Images/Images/Navigation/Up_32x32.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
Cowain.Bake.Main/Images/png/RgvError.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
Cowain.Bake.Main/Images/png/RgvMove.png
Normal file
|
After Width: | Height: | Size: 4.0 KiB |
BIN
Cowain.Bake.Main/Images/png/RgvWait.png
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
50
Cowain.Bake.Main/Models/LogModel.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
using Prism.Mvvm;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Cowain.Bake.Main.Models
|
||||
{
|
||||
public class LogModel : BindableBase
|
||||
{
|
||||
private DateTime logTime;
|
||||
/// <summary>
|
||||
/// 日志时间
|
||||
/// </summary>
|
||||
public DateTime LogTime
|
||||
{
|
||||
get => logTime;
|
||||
set => SetProperty(ref logTime, value);
|
||||
}
|
||||
private string logText;
|
||||
/// <summary>
|
||||
/// 日志内容
|
||||
/// </summary>
|
||||
public string LogText
|
||||
{
|
||||
get => logText;
|
||||
set => SetProperty(ref logText, value);
|
||||
}
|
||||
private string logLevel;
|
||||
/// <summary>
|
||||
/// 日志等级
|
||||
/// </summary>
|
||||
public string LogLevel
|
||||
{
|
||||
get => logLevel;
|
||||
set => SetProperty(ref logLevel, value);
|
||||
}
|
||||
|
||||
private string fontColor;
|
||||
/// <summary>
|
||||
/// 日志等级字体颜色
|
||||
/// </summary>
|
||||
public string FontColor
|
||||
{
|
||||
get => fontColor;
|
||||
set => SetProperty(ref fontColor, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
18
Cowain.Bake.Main/Models/MainHeaderModel.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Cowain.Bake.Main.Models
|
||||
{
|
||||
public class RibbonMenuModel
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string GroupName { get; set; }
|
||||
public double MenuWidth { get; set; }
|
||||
public string Content { get; set; }
|
||||
public string Header { get; set; }
|
||||
public string FilePath { get; set; }
|
||||
}
|
||||
}
|
||||
25
Cowain.Bake.Main/Models/MainRowDefinition.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using Cowain.Bake.BLL;
|
||||
using System.Linq;
|
||||
using Unity;
|
||||
|
||||
|
||||
namespace Cowain.Bake.Main.Models
|
||||
{
|
||||
public class MainRowDefinition
|
||||
{
|
||||
public static float UpperSpacing = 6;
|
||||
public static float UpperHeight = 0;
|
||||
public static float MidHeight = 3;
|
||||
public static float LowerHeight = 0;
|
||||
public static float LowerSpacing = 1.5f;
|
||||
public static float TotalHeight = 0;
|
||||
|
||||
public MainRowDefinition(IUnityContainer unityContainer)
|
||||
{
|
||||
var memory = unityContainer.Resolve<MemoryDataProvider>();
|
||||
UpperHeight = memory.AllStation.Where(x => x.PosX == 1).Max(x => x.Layers)+1;
|
||||
LowerHeight = memory.AllStation.Where(x => x.PosX == 3).Max(x => x.Layers)+1; //1:就是抬头
|
||||
TotalHeight = UpperSpacing + LowerSpacing + UpperHeight + LowerHeight + MidHeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
58
Cowain.Bake.Main/Models/MenuItemModel.cs
Normal file
@@ -0,0 +1,58 @@
|
||||
using Prism.Commands;
|
||||
using Prism.Mvvm;
|
||||
using Prism.Regions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Cowain.Bake.Main.Models
|
||||
{
|
||||
public class MenuItemModel : BindableBase
|
||||
{
|
||||
public string MenuIcon { get; set; }
|
||||
public string MenuHeader { get; set; }
|
||||
public string HeaderName { get; set; }
|
||||
public string TargetView { get; set; }
|
||||
|
||||
private bool isExpanded;
|
||||
|
||||
public bool IsExpanded
|
||||
{
|
||||
get { return isExpanded; }
|
||||
set { SetProperty(ref isExpanded, value); }
|
||||
}
|
||||
|
||||
private bool isDefault;
|
||||
|
||||
public bool IsDefault
|
||||
{
|
||||
get { return isDefault; }
|
||||
set { SetProperty(ref isDefault, value); }
|
||||
}
|
||||
|
||||
public List<MenuItemModel> Children { get; set; }
|
||||
|
||||
public ICommand OpenViewCommand
|
||||
{
|
||||
get => new DelegateCommand(() =>
|
||||
{
|
||||
if ((this.Children == null || this.Children.Count == 0) &&
|
||||
!string.IsNullOrEmpty(this.TargetView))
|
||||
{
|
||||
// 页面跳转 使用IRegionManager.RequestNavigate()跳转到目标页面
|
||||
_regionManager.RequestNavigate("MainContentRegion", this.TargetView);
|
||||
}
|
||||
else
|
||||
this.IsExpanded = !this.IsExpanded;
|
||||
});
|
||||
}
|
||||
IRegionManager _regionManager = null;
|
||||
public MenuItemModel(IRegionManager regionManager)
|
||||
{
|
||||
_regionManager = regionManager;
|
||||
}
|
||||
}
|
||||
}
|
||||
127
Cowain.Bake.Main/Models/MultiComboBox.cs
Normal file
@@ -0,0 +1,127 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace Cowain.Bake.Main.Views
|
||||
{
|
||||
public class MultiComboBox:ComboBox
|
||||
{
|
||||
static MultiComboBox()
|
||||
{
|
||||
DefaultStyleKeyProperty.OverrideMetadata(typeof(MultiComboBox), new FrameworkPropertyMetadata(typeof(MultiComboBox)));
|
||||
}
|
||||
|
||||
private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
d.SetValue(e.Property, e.NewValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 选中项列表
|
||||
/// </summary>
|
||||
public ObservableCollection<MultiCbxBaseData> ChekedItems = new ObservableCollection<MultiCbxBaseData>();
|
||||
|
||||
/// <summary>
|
||||
/// ListBox竖向列表
|
||||
/// </summary>
|
||||
private ListBox _ListBoxV;
|
||||
|
||||
/// <summary>
|
||||
/// ListBox横向列表
|
||||
/// </summary>
|
||||
private ListBox _ListBoxH;
|
||||
|
||||
public override void OnApplyTemplate()
|
||||
{
|
||||
base.OnApplyTemplate();
|
||||
_ListBoxV = Template.FindName("PART_ListBox", this) as ListBox;
|
||||
_ListBoxH = Template.FindName("PART_ListBoxChk", this) as ListBox;
|
||||
_ListBoxH.ItemsSource = ChekedItems;
|
||||
_ListBoxV.SelectionChanged += _ListBoxV_SelectionChanged;
|
||||
_ListBoxH.SelectionChanged += _ListBoxH_SelectionChanged;
|
||||
|
||||
if (ItemsSource != null)
|
||||
{
|
||||
foreach (var item in ItemsSource)
|
||||
{
|
||||
MultiCbxBaseData bdc = item as MultiCbxBaseData;
|
||||
if (bdc.IsCheck)
|
||||
{
|
||||
_ListBoxV.SelectedItems.Add(bdc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void _ListBoxH_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
foreach (var item in e.RemovedItems)
|
||||
{
|
||||
MultiCbxBaseData datachk = item as MultiCbxBaseData;
|
||||
|
||||
for (int i = 0; i < _ListBoxV.SelectedItems.Count; i++)
|
||||
{
|
||||
MultiCbxBaseData datachklist = _ListBoxV.SelectedItems[i] as MultiCbxBaseData;
|
||||
if (datachklist.Id == datachk.Id)
|
||||
{
|
||||
_ListBoxV.SelectedItems.Remove(_ListBoxV.SelectedItems[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _ListBoxV_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
foreach (var item in e.AddedItems)
|
||||
{
|
||||
MultiCbxBaseData datachk = item as MultiCbxBaseData;
|
||||
datachk.IsCheck = true;
|
||||
if (ChekedItems.IndexOf(datachk) < 0)
|
||||
{
|
||||
ChekedItems.Add(datachk);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var item in e.RemovedItems)
|
||||
{
|
||||
MultiCbxBaseData datachk = item as MultiCbxBaseData;
|
||||
datachk.IsCheck = false;
|
||||
ChekedItems.Remove(datachk);
|
||||
}
|
||||
}
|
||||
public class MultiCbxBaseData
|
||||
{
|
||||
private int _id;
|
||||
public int Id
|
||||
{
|
||||
get { return _id; }
|
||||
set { _id = value; }
|
||||
}
|
||||
|
||||
private string _viewName;
|
||||
public string ViewName
|
||||
{
|
||||
get { return _viewName; }
|
||||
set
|
||||
{
|
||||
_viewName = value;
|
||||
}
|
||||
}
|
||||
|
||||
private bool _isCheck;
|
||||
/// <summary>
|
||||
/// 是否选中
|
||||
/// </summary>
|
||||
public bool IsCheck
|
||||
{
|
||||
get { return _isCheck; }
|
||||
set { _isCheck = value; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
14
Cowain.Bake.Main/Models/PallletTemp.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Cowain.Bake.Main.Common
|
||||
{
|
||||
public class PallletTemp
|
||||
{
|
||||
public string HeadName { set; get; }
|
||||
public float Value { set; get; }
|
||||
}
|
||||
}
|
||||
55
Cowain.Bake.Main/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
using System.Reflection;
|
||||
using System.Resources;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows;
|
||||
|
||||
// 有关程序集的一般信息由以下
|
||||
// 控制。更改这些特性值可修改
|
||||
// 与程序集关联的信息。
|
||||
[assembly: AssemblyTitle("Cowain.Bake")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Cowain.Bake")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2023")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// 将 ComVisible 设置为 false 会使此程序集中的类型
|
||||
//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
|
||||
//请将此类型的 ComVisible 特性设置为 true。
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
//若要开始生成可本地化的应用程序,请设置
|
||||
//.csproj 文件中的 <UICulture>CultureYouAreCodingWith</UICulture>
|
||||
//例如,如果您在源文件中使用的是美国英语,
|
||||
//使用的是美国英语,请将 <UICulture> 设置为 en-US。 然后取消
|
||||
//对以下 NeutralResourceLanguage 特性的注释。 更新
|
||||
//以下行中的“en-US”以匹配项目文件中的 UICulture 设置。
|
||||
|
||||
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
|
||||
|
||||
|
||||
[assembly: ThemeInfo(
|
||||
ResourceDictionaryLocation.None, //主题特定资源词典所处位置
|
||||
//(未在页面中找到资源时使用,
|
||||
//或应用程序资源字典中找到时使用)
|
||||
ResourceDictionaryLocation.SourceAssembly //常规资源词典所处位置
|
||||
//(未在页面中找到资源时使用,
|
||||
//、应用程序或任何主题专用资源字典中找到时使用)
|
||||
)]
|
||||
|
||||
|
||||
// 程序集的版本信息由下列四个值组成:
|
||||
//
|
||||
// 主版本
|
||||
// 次版本
|
||||
// 生成号
|
||||
// 修订号
|
||||
//
|
||||
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
|
||||
//通过使用 "*",如下所示:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.1")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.1")]
|
||||
63
Cowain.Bake.Main/Properties/Resources.Designer.cs
generated
Normal file
@@ -0,0 +1,63 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// 此代码由工具生成。
|
||||
// 运行时版本:4.0.30319.42000
|
||||
//
|
||||
// 对此文件的更改可能会导致不正确的行为,并且如果
|
||||
// 重新生成代码,这些更改将会丢失。
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace Cowain.Bake.Main.Properties {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 一个强类型的资源类,用于查找本地化的字符串等。
|
||||
/// </summary>
|
||||
// 此类是由 StronglyTypedResourceBuilder
|
||||
// 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
|
||||
// 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
|
||||
// (以 /str 作为命令选项),或重新生成 VS 项目。
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Resources() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 返回此类使用的缓存的 ResourceManager 实例。
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Cowain.Bake.Main.Properties.Resources", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重写当前线程的 CurrentUICulture 属性,对
|
||||
/// 使用此强类型资源类的所有资源查找执行重写。
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
117
Cowain.Bake.Main/Properties/Resources.resx
Normal file
@@ -0,0 +1,117 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
26
Cowain.Bake.Main/Properties/Settings.Designer.cs
generated
Normal file
@@ -0,0 +1,26 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// 此代码由工具生成。
|
||||
// 运行时版本:4.0.30319.42000
|
||||
//
|
||||
// 对此文件的更改可能会导致不正确的行为,并且如果
|
||||
// 重新生成代码,这些更改将会丢失。
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace Cowain.Bake.Main.Properties {
|
||||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.10.0.0")]
|
||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
|
||||
|
||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||
|
||||
public static Settings Default {
|
||||
get {
|
||||
return defaultInstance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
7
Cowain.Bake.Main/Properties/Settings.settings
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
|
||||
<Profiles>
|
||||
<Profile Name="(Default)" />
|
||||
</Profiles>
|
||||
<Settings />
|
||||
</SettingsFile>
|
||||
190
Cowain.Bake.Main/Station/AlarmStation.cs
Normal file
@@ -0,0 +1,190 @@
|
||||
using Cowain.Bake.BLL;
|
||||
using Cowain.Bake.Common.Core;
|
||||
using Cowain.Bake.Common.Enums;
|
||||
using Cowain.Bake.Common.Interface;
|
||||
using Cowain.Bake.Communication.MOM;
|
||||
using Cowain.Bake.Model;
|
||||
using Cowain.Bake.Model.Models;
|
||||
using Opc.Ua;
|
||||
using Prism.Ioc;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Unity;
|
||||
using JSON = Newtonsoft.Json.JsonConvert;
|
||||
using static Cowain.Bake.Common.Models.MESModel;
|
||||
|
||||
namespace Cowain.Bake.Main.Station
|
||||
{
|
||||
public class AlarmStation : IServerManager
|
||||
{
|
||||
readonly ConcurrentDictionary<string, bool[]> _alarmValues;
|
||||
public string Name { get; set; } = "";
|
||||
List<TAlarm> _allAlarms { get; set; } //ConcurrentBag //验证,如果还报线程问题,就用ConcurrentBag
|
||||
List<TAlarmContent> _allAlarmContent { get; set; }
|
||||
public IUnityContainer _unityContainer { get; set; }
|
||||
List<AlertInfoModel> _arrayAlert = new List<AlertInfoModel>();
|
||||
private readonly Prism.Events.IEventAggregator _eventAggregator;
|
||||
readonly static object _objLock = new object();
|
||||
|
||||
public AlarmStation(IUnityContainer unityContainer, Prism.Events.IEventAggregator eventAggregator)
|
||||
{
|
||||
_unityContainer = unityContainer;
|
||||
_alarmValues = new ConcurrentDictionary<string, bool[]>();
|
||||
_eventAggregator = eventAggregator;
|
||||
Start();
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
_allAlarms = _unityContainer.Resolve<AlarmService>().GetAllInAlarms();
|
||||
_allAlarmContent = _unityContainer.Resolve<AlarmContentService>().GetAll();
|
||||
|
||||
foreach(var item in _allAlarms)
|
||||
{
|
||||
_eventAggregator.GetEvent<AlarmAddEvent>().Publish(item);//2.界面刷新,发布事件(发送消息)
|
||||
}
|
||||
}
|
||||
|
||||
//报警可能是一个数组(TAlarmContent),也可能是一个点(TTagList)。
|
||||
public void AlarmInfo(DataValue data, Variable node)
|
||||
{
|
||||
if (1 == data.WrappedValue.TypeInfo.ValueRank) //数组
|
||||
{
|
||||
lock (_objLock)
|
||||
{
|
||||
AlarmArray(data, node); //会导致恢复后,一条报警信息会显示二次
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogHelper.Instance.Warn("没有单个数据报警!");
|
||||
}
|
||||
}
|
||||
|
||||
public TAlarmContent GetAlarmContent(int nodeId, int offset)
|
||||
{
|
||||
return _allAlarmContent.Where(m => m.Offset == offset
|
||||
&& m.TagIds.Split(',').Any(x => x == nodeId.ToString())
|
||||
&& !string.IsNullOrEmpty(m.Desc)).FirstOrDefault();
|
||||
}
|
||||
|
||||
AlertInfoModel AssembleAlertModel(int code, string reset, string message)
|
||||
{
|
||||
return new AlertInfoModel()
|
||||
{
|
||||
AlertCode = code.ToString(),
|
||||
AlertReset = reset,
|
||||
AlertMessage = message,
|
||||
};
|
||||
}
|
||||
|
||||
//一个数组报警(订阅的是一个数组) --TAlarmContent
|
||||
private void AlarmArray(DataValue data, Variable node)
|
||||
{
|
||||
string key = "";
|
||||
_arrayAlert.Clear();
|
||||
bool[] value = data.WrappedValue.Value as bool[];
|
||||
if (data.WrappedValue.Value is bool[] v)
|
||||
{
|
||||
value = v;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogHelper.Instance.Warn($"数组报警类型异常:{data.WrappedValue.Value.GetType().Name}");
|
||||
return;
|
||||
}
|
||||
|
||||
//LogHelper.Instance.Warn($"数组报警:{JSON.SerializeObject(value)}");
|
||||
key = $"StationId:{node.StationId},Id:{node.Id}";
|
||||
|
||||
if (_alarmValues.TryGetValue(key, out bool[] oldValue)) //有
|
||||
{
|
||||
if (oldValue.Count() != value.Count())
|
||||
{
|
||||
LogHelper.Instance.Error($"报警老值与新值长度不匹配,key:{key},desc:{node.VarDesc}");
|
||||
return;
|
||||
}
|
||||
|
||||
var diffs = value.Zip(oldValue, (a, b) => a != b).Select((b, i) => new { Value = b, Index = i }).Where(x => x.Value);
|
||||
foreach (var item in diffs)
|
||||
{
|
||||
DealAlarmNode(node, item.Index, value[item.Index]);
|
||||
}
|
||||
}
|
||||
else //第一次进入
|
||||
{
|
||||
|
||||
for (int i = 0; i < value.Count(); ++i)
|
||||
{
|
||||
DealAlarmNode(node, i, value[i]);
|
||||
}
|
||||
}
|
||||
|
||||
_alarmValues[key] = value;
|
||||
if (int.Parse(_unityContainer.Resolve<SysSetupService>().GetValueByParaID(ESysSetup.MOMEnable.ToString())) == (int)EMOMEnable.Enable)
|
||||
{
|
||||
_unityContainer.Resolve<MESProcess>().MESEqptAlert(_arrayAlert);
|
||||
}
|
||||
}
|
||||
|
||||
void DealAlarmNode(Variable node, int offset, bool value)
|
||||
{
|
||||
TAlarmContent alarmContent = GetAlarmContent(node.Id, offset); //找到报警信息
|
||||
|
||||
if (alarmContent == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
//报警三种处理,1,入库,2.上传MOM,3.界面显示报警
|
||||
if (value)
|
||||
{
|
||||
AddAlarm(offset, node.StationId, alarmContent.Desc);
|
||||
}
|
||||
else
|
||||
{
|
||||
DeleteAlarm(offset, node.StationId, alarmContent.Desc);
|
||||
}
|
||||
}
|
||||
|
||||
public void AddAlarm(int errCode, int stationId, string desc)
|
||||
{
|
||||
var alarm = _allAlarms.Find(x => x.StationId == stationId && x.Desc == desc);
|
||||
if (null == alarm)
|
||||
{
|
||||
TAlarm currentAlarm = new TAlarm()
|
||||
{
|
||||
StationId = stationId,
|
||||
Desc = desc,
|
||||
StartTime = DateTime.Now,
|
||||
Status = EAlarmStatus.Alert.GetDescription(),
|
||||
};
|
||||
|
||||
_allAlarms.Add(currentAlarm); //增加到内存
|
||||
_arrayAlert.Add(AssembleAlertModel(errCode, ((int)EAlarmStatus.Alert).ToString(), desc)); //上传到MES
|
||||
_unityContainer.Resolve<AlarmService>().Insert<TAlarm>(currentAlarm); //增加到DB
|
||||
_eventAggregator.GetEvent<AlarmAddEvent>().Publish(currentAlarm);//.界面刷新,发布事件(发送消息)
|
||||
}
|
||||
}
|
||||
|
||||
public void DeleteAlarm(int errCode, int stationId, string desc)
|
||||
{
|
||||
TAlarm alarm = _allAlarms.Find(x => x.StationId == stationId
|
||||
&& x.Desc == desc);
|
||||
|
||||
if (null != alarm)
|
||||
{
|
||||
_allAlarms.Remove(alarm);
|
||||
_arrayAlert.Add(AssembleAlertModel(errCode, ((int)EAlarmStatus.Renew).ToString(), desc));
|
||||
_unityContainer.Resolve<AlarmService>().CancelAlarm(alarm);
|
||||
_eventAggregator.GetEvent<AlarmCancelEvent>().Publish(alarm);
|
||||
}
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
307
Cowain.Bake.Main/Station/BakingStation.cs
Normal file
@@ -0,0 +1,307 @@
|
||||
using Cowain.Bake.BLL;
|
||||
using Cowain.Bake.Common;
|
||||
using Cowain.Bake.Common.Core;
|
||||
using Cowain.Bake.Common.Enums;
|
||||
using Cowain.Bake.Common.Interface;
|
||||
using Cowain.Bake.Communication.Interface;
|
||||
using Cowain.Bake.Main.Common;
|
||||
using Cowain.Bake.Model.Models;
|
||||
using Opc.Ua;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Unity;
|
||||
|
||||
namespace Cowain.Bake.Main.Station
|
||||
{
|
||||
public class BakingStation : IServerManager
|
||||
{
|
||||
public string Name { get; set; }
|
||||
readonly StoveProcessParam processParam = null;
|
||||
public IUnityContainer _unityContainer { get; set; }
|
||||
readonly CmdFactories cmdFactories;
|
||||
readonly CancellationTokenSource cts = new CancellationTokenSource();
|
||||
|
||||
public BakingStation(IUnityContainer unityContainer)
|
||||
{
|
||||
_unityContainer = unityContainer;
|
||||
processParam = _unityContainer.Resolve<StoveProcessParam>();
|
||||
cmdFactories = _unityContainer.Resolve<CmdFactories>();
|
||||
Start();
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
Task.Run(async () =>
|
||||
{
|
||||
while (!cts.Token.IsCancellationRequested)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Global.AppExit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
await Task.Delay(6 * 1000);
|
||||
|
||||
List<ExCavityInfoModel> details = _unityContainer.Resolve<CavityInfoService>().GetAllExInfo().Where(
|
||||
x => x.Type == (int)EStationType.Stove
|
||||
&& x.Enable == true
|
||||
&& x.CavityEnable == true).ToList();
|
||||
|
||||
//ProcessEndBaking(details);
|
||||
ProcessStartBaking(details);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Instance.Error("BakingStation:Start:工艺参数,异常" + ex.ToString());
|
||||
_unityContainer.Resolve<LogService>().AddLog("BakingStation:Start:工艺参数,异常" + ex.Message, E_LogType.Debug.ToString());
|
||||
//throw;
|
||||
}
|
||||
|
||||
}
|
||||
}, cts.Token);
|
||||
}
|
||||
|
||||
void ProcessStartBaking(List<ExCavityInfoModel> stoveDetails)
|
||||
{
|
||||
List<bool> bakeFlag = new List<bool>();
|
||||
bool[] bakeEnable = new bool[Global.STOVE_MAX_LAYERS];
|
||||
List<ExCavityInfoModel> layers = null;
|
||||
var stoves = stoveDetails.GroupBy(p => new { p.StationId }).Select(s => s.FirstOrDefault()).ToList();
|
||||
|
||||
foreach (var stove in stoves) //烘烤以层为单位,所以以层为单位循环,这样简单
|
||||
{
|
||||
var conf = _unityContainer.Resolve<DeviceConfigService>().GetConfig(stove.StationId);
|
||||
|
||||
IPLCDevice plc = _unityContainer.Resolve<IPLCDevice>(conf.Name);
|
||||
|
||||
if (null == plc || !plc.IsConnect)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//远程/本地模式 //0 / 空闲 1 / 待机 2 / 停止 3 / 工作 4 / 保压
|
||||
if (!CommonFun.Instance.IsStoveQualified(plc, stove.StationId, 1, false))//工作当中就退出
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
layers = stoveDetails.Where(x => x.StationId == stove.StationId).OrderBy(x => x.Layer).ToList();//一炉子的夹具信息
|
||||
bakeFlag.Clear();
|
||||
//一层的夹具信息
|
||||
foreach (var detail in layers)
|
||||
{
|
||||
//bakeFlag = new bool[layers.Count]; //每一层有多少个可以烘烤的层
|
||||
if (0 == detail.PalletId)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (0 != detail.PalletId && !detail.IsLoad) //有托盘,无信号
|
||||
{
|
||||
LogHelper.Instance.Error($"有夹具,却没有信号或者没有读到信号,machineId:{stove.StationId},layer:{stove.Layer}");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (detail.PalletStatus != (int)EPalletStatus.Advisable
|
||||
&& detail.PalletStatus != (int)EPalletStatus.TestNG)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
bakeEnable[detail.Layer] = true;
|
||||
//if (detail.LastFlag ?? false)
|
||||
//{
|
||||
// bakeFlag = Enumerable.Repeat(true, layers.Count).ToArray();
|
||||
// //break; //为了bakeEnable,所以不退出
|
||||
//}
|
||||
|
||||
bakeFlag.Add(true);
|
||||
//bakeFlag[detail.Layer - 1] = true;
|
||||
}
|
||||
|
||||
if (0 == bakeFlag.Count)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//因为当每个夹具都放水的时候,可能存在一个要复烘,一个不需要,这个时候就有为false
|
||||
if (bakeFlag.Count != layers.Count // (bakeFlag.Contains(false))
|
||||
&& null == layers.Find(x => x.LastFlag == true)) //不是最后一盘
|
||||
{
|
||||
//复烘逻辑:1.有NG,2.没锁,3.无有其它盘
|
||||
var failPallet = layers.Where(x => x.PalletStatus == (int)EPalletStatus.TestNG).ToList();
|
||||
if (0 == failPallet.Count) //没有测试NG的
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (layers.Any(x => x.Lock)) //有锁,也就是还有回炉的夹具
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
int countPallets = layers.Where(x => x.PalletId != 0 && x.IsLoad == true && x.PalletStatus != (int)EPalletStatus.BlankOver).Count();
|
||||
if (failPallet.Count != countPallets)//有其它状态盘,如烘烤完成,也不开始烘烤
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//复烘逻辑满足:1.有NG,2.没锁,3.无有其它状态盘
|
||||
}
|
||||
|
||||
//if (!IsCanBaking(plc, stove.StationId, stove.Layer))
|
||||
//{
|
||||
// continue;
|
||||
//}
|
||||
|
||||
#region 下发工艺参数
|
||||
//清料时,可能为会空,
|
||||
ExCavityInfoModel palletProceParam = stoveDetails.Where(x => !string.IsNullOrEmpty(x.JobNum)
|
||||
&& x.PalletId != 0 && x.StationId == stove.StationId).FirstOrDefault();
|
||||
|
||||
if (!processParam.SendStoveProcessParam(plc, palletProceParam)) //成功了要改变夹具状态 EPalletStatus.
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//启动烤炉自动流程/下发工艺参数完成信号(开始烘烤)
|
||||
if (!cmdFactories.StartBaking(plc, stove.StationId, bakeEnable))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//去复位“烘烤完成”
|
||||
cmdFactories.ResetEndBaking(stove.StationId);
|
||||
|
||||
//托盘绑定烤箱位置
|
||||
List<int> ids = layers.Select(x => x.PalletId).ToList(); //修改夹具状态
|
||||
LogHelper.Instance.Info($"下发工艺参数成功!工站:{stove.Name},工单:{stove.JobNum},托盘号:{JsonSerializer.Serialize(ids)}");
|
||||
|
||||
int updateResult = _unityContainer.Resolve<PalletInfoService>().UpdateStartBakingInfo(
|
||||
layers.Where(x => x.PalletStatus == (int)EPalletStatus.Advisable
|
||||
|| x.PalletStatus == (int)EPalletStatus.TestNG).ToList()); //托盘绑定烤箱位置,状态,时间
|
||||
|
||||
if (updateResult <= 0)
|
||||
{
|
||||
LogHelper.Instance.Warn($"修改夹具{string.Join(",", ids)}状态失败!");
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
bool IsCanBaking(IPLCDevice plc, int mainCode, int layer)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
public void TrigEndBaking(DataValue data, Variable node)
|
||||
{
|
||||
if (!((bool)data.WrappedValue.Value))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
List<ExCavityInfoModel> stoveCavitys = _unityContainer.Resolve<CavityInfoService>().GetAllExInfo().Where(
|
||||
x => x.Type == (int)EStationType.Stove
|
||||
&& x.Enable == true
|
||||
&& x.CavityEnable == true
|
||||
&& x.StationId == node.StationId).ToList();
|
||||
|
||||
if (0 == stoveCavitys.Count)
|
||||
{
|
||||
LogHelper.Instance.Error($"{node.StationId}#炉没有可能的腔体,烘烤完成失效!");
|
||||
return;
|
||||
}
|
||||
|
||||
int[] ids = stoveCavitys.Where(x =>
|
||||
x.PalletStatus == (int)EPalletStatus.Bake
|
||||
&& x.PalletId != 0).Select(x => x.PalletId).ToArray(); //修改夹具状态,BlankOver清料时会有这状态
|
||||
|
||||
if (0 == ids.Count())
|
||||
{
|
||||
LogHelper.Instance.Error($"{node.StationId}#炉没有找到【烘烤中】的腔体,烘烤完成失效!");
|
||||
return;
|
||||
}
|
||||
|
||||
int updateResult = _unityContainer.Resolve<PalletInfoService>().UpdateBakingOverTime(ids);
|
||||
if (updateResult <= 0)
|
||||
{
|
||||
LogHelper.Instance.Warn($"修改夹具为烘烤完成,{string.Join(",", ids)}状态失败!");
|
||||
};
|
||||
}
|
||||
|
||||
//void ProcessEndBaking(List<ExCavityInfoModel> stoveDetails)
|
||||
//{
|
||||
// bool[] bakeFlag = new bool[Global.STOVE_LAYERS];
|
||||
// List<ExCavityInfoModel> layers = null;
|
||||
// var stoves = stoveDetails.GroupBy(p => new { p.StationId }).Select(s => s.FirstOrDefault()).ToList();
|
||||
|
||||
// foreach (var stove in stoves) //烘烤以炉子为单位,所以以炉子为单位循环,这样简单
|
||||
// {
|
||||
// Array.Clear(bakeFlag, 0, Global.STOVE_LAYERS);
|
||||
// var conf = _unityContainer.Resolve<DeviceConfigService>().GetConfig(stove.StationId);
|
||||
|
||||
// IPLCDevice plc = _unityContainer.Resolve<IPLCDevice>(conf.Name);
|
||||
|
||||
// if (null == plc || !plc.IsConnect)
|
||||
// {
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// //远程/本地模式 //0 / 空闲 1 / 待机 2 / 停止 3 / 工作 4 / 保压
|
||||
// if (!CommonFun.Instance.IsStoveQualified(plc, stove.StationId, 1, false)) //工作当中就退出
|
||||
// {
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// //烘烤完成信号
|
||||
// var resultBool = plc.GetValue<bool>(EStoveSignal.BakingMark.ToString(), stove.StationId); //stove.Layer
|
||||
// if (!resultBool.IsSuccess || !resultBool.Content)
|
||||
// {
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// layers = stoveDetails.Where(x => x.StationId == stove.StationId).OrderBy(x => x.Layer).ToList();//一个炉子的夹具信息
|
||||
// foreach (var detail in layers)
|
||||
// {
|
||||
// //只有在烘烤中的,才会有烘烤完成
|
||||
// if (detail.PalletStatus != (int)EPalletStatus.Bake //detail.PalletStatus != (int)EPalletStatus.Advisable
|
||||
// || 0 == detail.PalletId) //detail.PalletStatus != (int)EPalletStatus.Bake
|
||||
// {
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// if (detail.LastFlag ?? false)
|
||||
// {
|
||||
// bakeFlag = Enumerable.Repeat(true, Global.STOVE_LAYERS).ToArray();
|
||||
// break;
|
||||
// }
|
||||
|
||||
// bakeFlag[detail.Number - 1] = true;
|
||||
// }
|
||||
|
||||
// if (bakeFlag.Contains(true)) //有假表示有夹具。
|
||||
// {
|
||||
// int[] ids = layers.Where(x =>
|
||||
// x.PalletStatus == (int)EPalletStatus.Bake
|
||||
// && x.PalletId != 0).Select(x => x.PalletId).ToArray(); //修改夹具状态,BlankOver清料时会有这状态
|
||||
// int updateResult = _unityContainer.Resolve<PalletInfoService>().UpdateBakingOverTime(ids);
|
||||
// if (updateResult <= 0)
|
||||
// {
|
||||
// LogHelper.Instance.Warn($"修改夹具{string.Join(",", ids)}状态失败!");
|
||||
// };
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
// 在需要取消任务的时候,调用以下代码:
|
||||
cts.Cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
312
Cowain.Bake.Main/Station/DataCollectStation.cs
Normal file
@@ -0,0 +1,312 @@
|
||||
using Cowain.Bake.BLL;
|
||||
using Cowain.Bake.Common;
|
||||
using Cowain.Bake.Common.Core;
|
||||
using Cowain.Bake.Common.Enums;
|
||||
using Cowain.Bake.Common.Interface;
|
||||
using Cowain.Bake.Communication.Interface;
|
||||
using Cowain.Bake.Communication.MOM;
|
||||
using Cowain.Bake.Main.Common;
|
||||
using Cowain.Bake.Main.ViewModels;
|
||||
using Cowain.Bake.Model;
|
||||
using Cowain.Bake.Model.Models;
|
||||
using HslCommunication;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Unity;
|
||||
|
||||
namespace Cowain.Bake.Main.Station
|
||||
{
|
||||
public class DataCollectStation : IServerManager
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public IUnityContainer _unityContainer { get; set; }
|
||||
readonly List<TDeviceConfig> stoveConfs = null;
|
||||
readonly CancellationTokenSource cts = new CancellationTokenSource();
|
||||
readonly List<TStoveSctualPatrol> listStoveTemp = new List<TStoveSctualPatrol>();
|
||||
|
||||
private Dictionary<int, StoveDataModel> cacheStoveData { set; get; } = new Dictionary<int, StoveDataModel>();//如果只有一个保存炉子的真空值,数据容易不及时,且冲突
|
||||
//private Dictionary<int, int> cacheElectricEnergyData { set; get; } = new Dictionary<int, int>();
|
||||
private readonly Prism.Events.IEventAggregator _eventAggregator;
|
||||
public DataCollectStation(IUnityContainer unityContainer, Prism.Events.IEventAggregator eventAggregator)
|
||||
{
|
||||
_unityContainer = unityContainer;
|
||||
_eventAggregator = eventAggregator;
|
||||
stoveConfs = _unityContainer.Resolve<DeviceConfigService>().GetConfig(EDeviceType.PLC, EStationType.Stove.ToString());//
|
||||
Start();
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
string tempCycle = _unityContainer.Resolve<Cowain.Bake.BLL.SysSetupService>()
|
||||
.GetValueByParaID(Cowain.Bake.Common.Enums.ESysSetup.DataCollectionCycle.ToString());
|
||||
int tempCycleValue = int.Parse(tempCycle);
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
await Task.Delay(20 * 1000); //等待去读PLC的数据
|
||||
while (!cts.Token.IsCancellationRequested)
|
||||
{
|
||||
await Task.Delay(tempCycleValue * 1000);
|
||||
if (Global.AppExit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CollectTemp();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void CollectTemp()
|
||||
{
|
||||
bool isWork = false;
|
||||
float vacuum = 0;
|
||||
UInt16 workTime = 0;
|
||||
UInt16 totalWorkTime = 0;
|
||||
float[] temps = null;
|
||||
OperateResult<Int16[]> resultTemp;
|
||||
listStoveTemp.Clear();
|
||||
cacheStoveData.Clear();
|
||||
foreach (var conf in stoveConfs)
|
||||
{
|
||||
IPLCDevice plc = _unityContainer.Resolve<IPLCDevice>(conf.Name);
|
||||
|
||||
if (null == plc || !plc.IsConnect)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var stoves = (from v in plc.Storages
|
||||
group v by v.StationId
|
||||
into a
|
||||
orderby a.Key
|
||||
select a).ToList();
|
||||
|
||||
//每个炉子都循环
|
||||
foreach (var item in stoves) //一个PLC控制二台炉子(一台炉子)
|
||||
{
|
||||
//0 / 空闲 1 / 待机 2 / 停止 3 / 工作 4 / 保压
|
||||
var workStatus = plc.GetValue<Int16>(EStoveSignal.CavityStatus.ToString(), item.Key);
|
||||
if (!workStatus.IsSuccess || (int)EStoveWorkMode.Standby >= workStatus.Content) //系统状态寄存器
|
||||
{
|
||||
isWork = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
isWork = true;
|
||||
}
|
||||
|
||||
if (item.Key == Global.DEW_STOVE_NUMBER) //IP:70
|
||||
{
|
||||
//露点温度
|
||||
var dewTemp = plc.GetValue<float>(EStoveSignal.DewTemperature.ToString(), item.Key);
|
||||
if (!dewTemp.IsSuccess)
|
||||
{
|
||||
LogHelper.Instance.Error($"读取露点温度失败!{dewTemp.Message}");
|
||||
_unityContainer.Resolve<BasicInfoViewModel>().SetTempData("-0");
|
||||
}
|
||||
else
|
||||
{
|
||||
DealDewTemp(dewTemp.Content);
|
||||
_unityContainer.Resolve<BasicInfoViewModel>().SetTempData(Math.Round(dewTemp.Content,2).ToString());
|
||||
}
|
||||
}
|
||||
|
||||
//真空值
|
||||
var result = plc.GetValue<int>(EStoveSignal.Vacuum.ToString(), item.Key);
|
||||
if (!result.IsSuccess)
|
||||
{
|
||||
LogHelper.Instance.Error($"读取真空值失败!{result.Message}");
|
||||
continue;
|
||||
}
|
||||
vacuum = (float)(result.Content);
|
||||
|
||||
//工作时长
|
||||
var workTimeResult = plc.GetValue<UInt16>(EStoveSignal.WorkTime.ToString(), item.Key);
|
||||
var totalTimeResult = plc.GetValue<UInt16>(EStoveSignal.TotalWorkTime.ToString(), item.Key);
|
||||
if (!workTimeResult.IsSuccess
|
||||
|| !totalTimeResult.IsSuccess)
|
||||
{
|
||||
LogHelper.Instance.Error($"读取工作时长失败!{workTimeResult.Message},{totalTimeResult.Message}");
|
||||
continue;
|
||||
}
|
||||
workTime = workTimeResult.Content;
|
||||
totalWorkTime = totalTimeResult.Content;
|
||||
|
||||
//获取一个炉子的温度节点
|
||||
var stoveTempNode = (from storage in plc.Storages
|
||||
from itemTemp in storage.VariableList
|
||||
where storage.StationId == item.Key
|
||||
&& itemTemp.TagType == (int)ETagType.Temperature //&& itemTemp.Number == layer
|
||||
select itemTemp).ToList();
|
||||
|
||||
foreach (var tempParam in stoveTempNode) //每一层的温度
|
||||
{
|
||||
int layer = tempParam.Number;
|
||||
int cavityId = _unityContainer.Resolve<CavityInfoService>().GetCavityId(item.Key, layer);
|
||||
TPalletInfo palletInfo = _unityContainer.Resolve<PalletInfoService>().GetPalletCode(cavityId);
|
||||
|
||||
if (null == palletInfo
|
||||
|| 0 == palletInfo.Id) //没有托盘
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (palletInfo.BakingBeginTime == null //没有烘烤开始时间的不用上传
|
||||
|| 0 == palletInfo.VirtualId) //没有绑定电芯
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//PID
|
||||
var resultPID = plc.GetValue<float[]>(EStoveSignal.PID.ToString() + layer, item.Key, layer);
|
||||
if (!resultPID.IsSuccess)
|
||||
{
|
||||
LogHelper.Instance.GetCurrentClassError("读取PID失败!");
|
||||
continue;
|
||||
}
|
||||
|
||||
//温度
|
||||
resultTemp = plc.GetValue<Int16[]>(tempParam.ParamName, item.Key, layer); //温度
|
||||
if (!resultTemp.IsSuccess)
|
||||
{
|
||||
LogHelper.Instance.GetCurrentClassError("读取温度失败!");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (resultTemp.Content.All(x => x == 0)
|
||||
|| resultPID.Content.All(x => x == 0))
|
||||
{
|
||||
//LogHelper.Instance.GetCurrentClassError("读取温度异常,全为0!");
|
||||
continue;
|
||||
}
|
||||
|
||||
temps = CommonFun.Instance.UShortToFloat(resultTemp.Content);
|
||||
|
||||
cacheStoveData[cavityId] = new StoveDataModel() //少了两个条件,1.VirtualId为0,2.工作状态
|
||||
{
|
||||
Temps = temps,
|
||||
Vacuum = vacuum,
|
||||
WorkTime = workTime,
|
||||
TotalWorkTime = totalWorkTime
|
||||
};
|
||||
|
||||
if (isWork) //add by lsm 20250926, 测试用
|
||||
{
|
||||
string tempData = MakeJsonTemperature(tempParam.VarDesc, temps);
|
||||
string pid = MakeJsonPid(EStoveSignal.PID.ToString(), resultPID.Content);
|
||||
listStoveTemp.Add(MakeTStoveSctualPatrol(palletInfo.VirtualId, cavityId, palletInfo.PalletCode, vacuum, tempData, pid));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//UploadProcessData(cacheStoveData); //1.上传Mom //太多,太卡,不上传
|
||||
_eventAggregator.GetEvent<StoveDataEvent>().Publish(cacheStoveData);//2.界面刷新,发布事件(发送消息)
|
||||
if (0 != listStoveTemp.Count)
|
||||
{
|
||||
_unityContainer.Resolve<StoveSctualPatrolService>().Insert(listStoveTemp);//批量插入数据
|
||||
}
|
||||
}
|
||||
|
||||
static bool? failDev;
|
||||
void DealDewTemp(float value)
|
||||
{
|
||||
float target = float.Parse(_unityContainer.Resolve<SysSetupService>().GetValueByParaID(ESysSetup.DewTempAlarmTargetValue.ToString()));
|
||||
TAlarm alarm = new TAlarm()
|
||||
{
|
||||
StationId = (int)EAlarmStationId.DevTemp,
|
||||
Desc = "露点温度超标,请检查压缩空气!",
|
||||
StartTime = DateTime.Now,
|
||||
Status = EAlarmStatus.Alert.GetDescription(),
|
||||
};
|
||||
|
||||
if (value <= target) //正常
|
||||
{
|
||||
if (false != failDev)
|
||||
{
|
||||
failDev = false;
|
||||
_eventAggregator.GetEvent<AlarmCancelEvent>().Publish(alarm);
|
||||
}
|
||||
}
|
||||
else //异常
|
||||
{
|
||||
if (true != failDev)
|
||||
{
|
||||
failDev = true;
|
||||
_eventAggregator.GetEvent<AlarmAddEvent>().Publish(alarm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//上转Mom
|
||||
public void UploadProcessData(Dictionary<int, StoveDataModel> datas)
|
||||
{
|
||||
if (int.Parse(_unityContainer.Resolve<SysSetupService>().GetValueByParaID(ESysSetup.MOMEnable.ToString())) == (int)EMOMEnable.Enable)
|
||||
{
|
||||
foreach (var item in datas)
|
||||
{
|
||||
string cavityName = _unityContainer.Resolve<MemoryDataProvider>().CavityInfo.Find(x => x.Id == item.Key).Name;
|
||||
_unityContainer.Resolve<MESProcess>().MESBakingParameter(item.Value.Vacuum, item.Value.Temps, cavityName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TStoveSctualPatrol MakeTStoveSctualPatrol(int palletVirtualId, int cavityId, string palletCode, float vacuum, string temperature,string pid)
|
||||
{
|
||||
return new TStoveSctualPatrol()
|
||||
{
|
||||
PalletVirtualId = palletVirtualId,
|
||||
CavityId = cavityId,
|
||||
PalletCode = palletCode,
|
||||
Vacuum = vacuum,
|
||||
Temperature = temperature,
|
||||
CreateTime = DateTime.Now,
|
||||
PID = pid
|
||||
};
|
||||
}
|
||||
|
||||
public string MakeJsonTemperature(string headName, float[] value)
|
||||
{
|
||||
headName = Regex.Replace(headName, @"\d", "");
|
||||
List<PallletTemp> listTemp = new List<PallletTemp>();
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
{
|
||||
listTemp.Add(new PallletTemp()
|
||||
{
|
||||
HeadName = $"{headName}{i + 1}",
|
||||
Value = value[i]
|
||||
});
|
||||
}
|
||||
|
||||
return JsonConvert.SerializeObject(listTemp);
|
||||
}
|
||||
|
||||
public string MakeJsonPid(string headName, float[] value)
|
||||
{
|
||||
//headName = Regex.Replace(headName, @"\d", "");
|
||||
List<PallletTemp> listTemp = new List<PallletTemp>();
|
||||
for (int i = 1; i < value.Length; i++) //数组0不使用
|
||||
{
|
||||
listTemp.Add(new PallletTemp()
|
||||
{
|
||||
HeadName = $"{headName}{i}",
|
||||
Value = value[i]
|
||||
});
|
||||
}
|
||||
|
||||
return JsonConvert.SerializeObject(listTemp);
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
// 在需要取消任务的时候,调用以下代码:
|
||||
cts.Cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
215
Cowain.Bake.Main/Station/LifeCycleStation.cs
Normal file
@@ -0,0 +1,215 @@
|
||||
using Cowain.Bake.BLL;
|
||||
using Cowain.Bake.Common;
|
||||
using Cowain.Bake.Common.Core;
|
||||
using Cowain.Bake.Common.Enums;
|
||||
using Cowain.Bake.Common.Interface;
|
||||
using Cowain.Bake.Communication.Interface;
|
||||
using Cowain.Bake.Model;
|
||||
using Cowain.Bake.Model.Models;
|
||||
using HslCommunication;
|
||||
using Newtonsoft.Json;
|
||||
using Opc.Ua;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Unity;
|
||||
|
||||
namespace Cowain.Bake.Main.Station
|
||||
{
|
||||
public class LifeCycleStation : IServerManager
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public List<TStation> _station = null;
|
||||
public IUnityContainer _unityContainer { get; set; }
|
||||
public LifeCycleStation(IUnityContainer unityContainer)
|
||||
{
|
||||
_unityContainer = unityContainer;
|
||||
_station = _unityContainer.Resolve<MemoryDataProvider>().AllStation;
|
||||
}
|
||||
|
||||
// 心跳
|
||||
public void LifeCycle(DataValue data, Variable node)
|
||||
{
|
||||
OperateResult writeResult = null;
|
||||
dynamic d = JsonConvert.DeserializeObject<dynamic>(node.Json);
|
||||
Int16 value = 0;
|
||||
if (data.WrappedValue.TypeInfo.BuiltInType == Opc.Ua.BuiltInType.Int16)
|
||||
{
|
||||
value = (System.Int16)data.WrappedValue.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogHelper.Instance.Warn($"没有找到生命周期信号这个数据类型,节点名为{node.VarDesc}");
|
||||
}
|
||||
|
||||
var config = _unityContainer.Resolve<DeviceConfigService>().GetConfig(node.StationId);
|
||||
var plc = _unityContainer.Resolve<IPLCDevice>(config.Name);
|
||||
|
||||
writeResult = plc.Write<Int16>((string)d.WriteHeart, value); //回复为接收到的计数
|
||||
if (!writeResult.IsSuccess)
|
||||
{
|
||||
LogHelper.Instance.Warn($"LifeCycle-{node.StationId}-{value}-{(string)d.WriteHeart}:{writeResult.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
//向上位机请求任务,PLC请求命令:0=无意义;10=无托盘;20=有托盘
|
||||
public void ReqTask(DataValue data, Variable node)
|
||||
{
|
||||
//bool IsAccord = false; //是否符合取放盘
|
||||
try
|
||||
{
|
||||
dynamic d = JsonConvert.DeserializeObject<dynamic>(node.Json);
|
||||
Int16 value = 0;
|
||||
if (data.WrappedValue.TypeInfo.BuiltInType == Opc.Ua.BuiltInType.Int16)
|
||||
{
|
||||
value = (System.Int16)data.WrappedValue.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogHelper.Instance.Warn($"没有找到请求任务信号这个数据类型,节点名为{node.VarDesc}");
|
||||
return;
|
||||
}
|
||||
|
||||
TStation station = _station.Where(p => p.Id == node.StationId).FirstOrDefault();
|
||||
LogHelper.Instance.Warn($"取放盘,值:{value},station:{node.StationId},层{node.Number}");
|
||||
|
||||
|
||||
//是否符合取放盘
|
||||
//if (_unityContainer.Resolve<CavityInfoService>().IsAccordReq(station, node.Number, (sbyte)value))
|
||||
{
|
||||
//IsAccord = true;
|
||||
//修改取放盘状态
|
||||
if (!_unityContainer.Resolve<CavityInfoService>().UpdateReqStatus(station, node.Number, (sbyte)value))
|
||||
{
|
||||
LogHelper.Instance.GetCurrentClassError($"修改请求任务失败,StationId:{node.StationId},Number:{node.Number},value:{value}");
|
||||
return;
|
||||
}
|
||||
}
|
||||
//else
|
||||
//{
|
||||
// LogHelper.Instance.GetCurrentClassError($"不符合取放盘,StationId:{node.StationId},Number:{node.Number},value:{value}");
|
||||
//}
|
||||
|
||||
//DealPalletRequest(value, node); //取消这个,不然上位机启动,会报异常
|
||||
|
||||
var config = _unityContainer.Resolve<DeviceConfigService>().GetConfig(node.StationId);
|
||||
var plc = _unityContainer.Resolve<IPLCDevice>(config.Name);
|
||||
var writeResult = plc.Write<int>((string)d.WriteRetCommand, value); //收到什么反馈什么。
|
||||
if (!writeResult.IsSuccess)
|
||||
{
|
||||
LogHelper.Instance.Warn($"ReqTask-{(string)d.WriteRetCommand}:{writeResult.Message}");
|
||||
}
|
||||
|
||||
value = (short)(value == 0 ? -1 : 1); //1=OK,2=重新上传,如果PLC请求命令是0,WCS返回-1
|
||||
writeResult = plc.Write<int>((string)d.WriteResult, value); //收到什么反馈什么。
|
||||
if (!writeResult.IsSuccess)
|
||||
{
|
||||
LogHelper.Instance.Warn($"ReqTask-{(string)d.WriteResult}:{writeResult.Message}");
|
||||
}
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
LogHelper.Instance.Error($"请求解析出错:{node.Json},{node.TrigJson},{ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
void DealPalletRequest(int value, Variable node)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case (int)ECavityStatus.RequestPick:
|
||||
DealPick(node);
|
||||
break;
|
||||
case (int)ECavityStatus.RequestPlace:
|
||||
//DealPlace(station, json);
|
||||
break;
|
||||
case (int)ECavityStatus.None:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void DealPlace(TStation station, string json)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void DealPick(Variable node)
|
||||
{
|
||||
MethodInfo mi = null;
|
||||
dynamic d = JsonConvert.DeserializeObject<dynamic>(node.TrigJson);
|
||||
string service = d.ReflexService;
|
||||
string func = d.ReflexFunc;
|
||||
string param = d.Param; //方法的参数,如果是扫码,则是扫码的编号
|
||||
|
||||
if (string.IsNullOrEmpty(service))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LogHelper.Instance.Info($"请求取盘触发事件:{node.TrigJson}");
|
||||
var instnce = _unityContainer.Resolve<TrigStation>();
|
||||
Type type = Type.GetType(MyPath.SIGNAL_TRIGGER + service);
|
||||
mi = this.GetType().GetMethod(ReflexFun.TRIG_REPLY).MakeGenericMethod(new Type[] { type }); //回复信息;
|
||||
mi.Invoke(this, new object[]
|
||||
{
|
||||
func,
|
||||
1,
|
||||
param,
|
||||
node
|
||||
});
|
||||
}
|
||||
|
||||
public void TrigReply<T>(string func, int curValue, string param, Variable node)
|
||||
{
|
||||
//取得实例
|
||||
var instnce = _unityContainer.Resolve<T>(); //上下料实例
|
||||
Type t = instnce.GetType();
|
||||
|
||||
//取得方法
|
||||
MethodInfo mi = t.GetMethod(func);
|
||||
//调用方法
|
||||
mi.Invoke(instnce, new object[]
|
||||
{
|
||||
curValue,
|
||||
param,
|
||||
node
|
||||
});
|
||||
}
|
||||
|
||||
//心跳
|
||||
public void Alive(DataValue data, Variable node)
|
||||
{
|
||||
dynamic d = JsonConvert.DeserializeObject<dynamic>(node.Json);
|
||||
Int16 value = 0;
|
||||
if (data.WrappedValue.TypeInfo.BuiltInType == Opc.Ua.BuiltInType.Int16)
|
||||
{
|
||||
value = (System.Int16)data.WrappedValue.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogHelper.Instance.Warn($"收到心跳解析出错,工站:{node.StationId},节点名为{node.VarDesc}");
|
||||
return;
|
||||
}
|
||||
|
||||
var config = _unityContainer.Resolve<DeviceConfigService>().GetConfig(node.StationId);
|
||||
var plc = _unityContainer.Resolve<IPLCDevice>(config.Name);
|
||||
var writeResult = plc.Write<int>(d.RetCommand, value); //收到什么反馈什么。
|
||||
if (!writeResult.IsSuccess)
|
||||
{
|
||||
LogHelper.Instance.Warn($"Alive-{d.WriteResult}:{writeResult.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
|
||||
}
|
||||
public void Stop()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
553
Cowain.Bake.Main/Station/LoadingStation.cs
Normal file
@@ -0,0 +1,553 @@
|
||||
using Cowain.Bake.BLL;
|
||||
using Cowain.Bake.Common;
|
||||
using Cowain.Bake.Common.Core;
|
||||
using Cowain.Bake.Common.Enums;
|
||||
using Cowain.Bake.Common.Interface;
|
||||
using Cowain.Bake.Communication.Interface;
|
||||
using Cowain.Bake.Communication.MOM;
|
||||
using Cowain.Bake.Main.ViewModels;
|
||||
using Cowain.Bake.Main.Views;
|
||||
using Cowain.Bake.Model;
|
||||
using Cowain.Bake.Model.Models;
|
||||
using Cowain.Bake.UI.CsvMap;
|
||||
using HslCommunication;
|
||||
using Newtonsoft.Json;
|
||||
using Prism.Ioc;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using Unity;
|
||||
using static Cowain.Bake.Common.Models.MESModel;
|
||||
using JSON = Newtonsoft.Json.JsonConvert;
|
||||
|
||||
namespace Cowain.Bake.Main.Station
|
||||
{
|
||||
public class LoadingStation : IServerManager
|
||||
{
|
||||
private int _batteryCodeLen = 0;
|
||||
public string Name { get; set; }
|
||||
IPLCDevice PLC { get; set; }
|
||||
readonly List<IScanCodeBase> _deviceScann = new List<IScanCodeBase>();
|
||||
public IUnityContainer _unityContainer { get; set; }
|
||||
public LoadingStation(IUnityContainer unityContainer)
|
||||
{
|
||||
_unityContainer = unityContainer;
|
||||
TDeviceConfig config = _unityContainer.Resolve<DeviceConfigService>().GetConfig(EDeviceType.PLC, EDeviceName.Loading)[0];
|
||||
Name = config.Name;
|
||||
SetBatteryCodeLen();
|
||||
Start();
|
||||
}
|
||||
|
||||
public void SetBatteryCodeLen()
|
||||
{
|
||||
_batteryCodeLen = int.Parse(_unityContainer.Resolve<Cowain.Bake.BLL.SysSetupService>().GetValueByParaID(ESysSetup.BatteryCodeLen.ToString()));
|
||||
}
|
||||
|
||||
bool IsConnectPLC()
|
||||
{
|
||||
if (null == PLC || !PLC.IsConnect)
|
||||
{
|
||||
LogHelper.Instance.Error($"PalletVirtualId:{PLC.Name},PLC为空!");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
var configScann = _unityContainer.Resolve<DeviceConfigService>().GetConfig(EDeviceType.SCANNER).OrderBy(x => x.Id).Take((int)EScanCode.PalletScan2).ToList();
|
||||
foreach (var item in configScann)
|
||||
{
|
||||
IScanCodeBase device = _unityContainer.Resolve<IScanCodeBase>(item.Name);
|
||||
_deviceScann.Add(device);
|
||||
}
|
||||
|
||||
PLC = _unityContainer.Resolve<IPLCDevice>(Name); //上料PLC
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
}
|
||||
/*
|
||||
* 编译器自动在方法入口/出口加 lock(this),简单但锁粒度粗;
|
||||
* 高频调用或重入场景容易成瓶颈,只适合做原型或低并发工具类。
|
||||
*/
|
||||
//托盘满盘信号
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
public void ExecuteFullPallet(int curValue, string param, Variable node)
|
||||
{
|
||||
dynamic d = JsonConvert.DeserializeObject<dynamic>(node.Json);
|
||||
LogHelper.Instance.Warn($"LoadingStation:ExecuteFullPallet:开始,线程ID:{System.Threading.Thread.CurrentThread.ManagedThreadId}");
|
||||
int result ;
|
||||
int batteryQty;
|
||||
_unityContainer.Resolve<BasicInfoViewModel>().SetEvent("开始:" + node.VarDesc);
|
||||
int palletId = _unityContainer.Resolve<CavityInfoService>().GetPalletId((int)EStationType.Loading, int.Parse(param));
|
||||
TPalletInfo palletInfo = _unityContainer.Resolve<BLL.PalletInfoService>().GetPalletInfo(palletId);
|
||||
if (null == palletInfo) //如果当前夹具状态为"满夹具可取",就退出,上位机重启会重复触发!
|
||||
{
|
||||
LogHelper.Instance.Warn($"托盘满信号,上料平台无夹具,异常");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((int)EPalletStatus.Advisable == palletInfo.PalletStatus) //如果当前夹具状态为"满夹具可取",就退出,上位机重启会重复触发!
|
||||
{
|
||||
//LogHelper.Instance.Warn($"托盘满信号,当前托盘为满夹具夹,异常");
|
||||
//return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
int debugMode = int.Parse(_unityContainer.Resolve<SysSetupService>().GetValueByParaID(ESysSetup.DebugMode.ToString())); //0
|
||||
if (!IsConnectPLC()) return;
|
||||
|
||||
var resultBatterys = PLC.Read<int[]>((string)d.ReadVirtualIds); //可以改成直接读PLC
|
||||
var resultPalletVirtualId = PLC.Read<int>((string)d.ReadPalletVirtualId); //这是直接读PLC
|
||||
var lastFlag = PLC.Read<Int16>((string)d.ReadLastFlag).Content; //这是直接读PLC
|
||||
if (!resultBatterys.IsSuccess || !resultPalletVirtualId.IsSuccess)
|
||||
{
|
||||
LogHelper.Instance.Error($"PalletVirtualId:{resultPalletVirtualId.Content},没有读取电芯信息或托盘信息!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (0 == resultPalletVirtualId.Content ||
|
||||
1 == resultPalletVirtualId.Content)
|
||||
{
|
||||
LogHelper.Instance.Error($"托盘满盘信号异常, 托盘虚拟码为【{resultPalletVirtualId.Content}】!", true);
|
||||
return;
|
||||
}
|
||||
|
||||
//批量更新电芯表
|
||||
batteryQty = _unityContainer.Resolve<BatteryInfoService>().InsertBatch(resultBatterys.Content, resultPalletVirtualId.Content); //add by lsm 20250219 要300耗秒以上
|
||||
|
||||
SavePalletInfo(resultPalletVirtualId.Content);
|
||||
|
||||
if (0 == batteryQty)
|
||||
{
|
||||
//HandyControl.Controls.MessageBox.Error("触发满盘时没有电芯数据!"); //启动上位机时,会触发这个东西。
|
||||
LogHelper.Instance.Error($"启动上位机时,上料:{resultPalletVirtualId.Content},电芯地址里没有电芯数据!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (Global.PALLET_TOTAL_BATTERYS != batteryQty)
|
||||
{
|
||||
LogHelper.Instance.Error($"PalletVirtualId:{resultPalletVirtualId.Content},{batteryQty},上料电芯是{Global.PALLET_TOTAL_BATTERYS}!", false);
|
||||
}
|
||||
|
||||
result = _unityContainer.Resolve<PalletInfoService>().LoadingUpdatePalletStatus(resultPalletVirtualId.Content, (int)EPalletStatus.Advisable, batteryQty, lastFlag == 1);
|
||||
if (0 == result)
|
||||
{
|
||||
LogHelper.Instance.Error($"PalletVirtualId:{resultPalletVirtualId.Content},修改托盘状态失败!");
|
||||
}
|
||||
|
||||
//writeResult = PLC.Write<bool>((string)d.WriteResult, true);//回复收到托盘1满盘信号
|
||||
//if (!writeResult.IsSuccess)
|
||||
//{
|
||||
// LogHelper.Instance.GetCurrentClassWarn($"{(string)d.WriteResult}:{writeResult.Message}");
|
||||
//}
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
LogHelper.Instance.GetCurrentClassWarn($",{ex.Message}:{ex.StackTrace}");
|
||||
}
|
||||
|
||||
_unityContainer.Resolve<BasicInfoViewModel>().SetEvent("结束:" + node.VarDesc);
|
||||
}
|
||||
|
||||
//假电芯扫码 验证数据库OK
|
||||
public void ExecuteScanDummy(int curValue, string param, Variable node)
|
||||
{
|
||||
dynamic d = JsonConvert.DeserializeObject<dynamic>(node.Json);
|
||||
if (!IsConnectPLC()) return;
|
||||
int virtualId;
|
||||
OperateResult writeResult = null;
|
||||
EScanCode scanName = EScanCode.DummyScan; //(EScanCode)(int.Parse(param));
|
||||
IScanCodeBase scanDevice = _deviceScann.Find(x => x.Name == scanName.ToString());
|
||||
HslCommunication.OperateResult<string> scanResult = new HslCommunication.OperateResult<string>()
|
||||
{
|
||||
IsSuccess = false,
|
||||
};
|
||||
|
||||
scanResult.IsSuccess = true;
|
||||
scanResult.Content = System.Guid.NewGuid().ToString("N").Substring(0, 12);
|
||||
if (scanResult.IsSuccess)
|
||||
{
|
||||
virtualId = _unityContainer.Resolve<BatteryInfoService>().InsertBattery(scanResult.Content, (int)EBatteryStatus.ScanOver, (int)EDummyState.Have, "");
|
||||
writeResult = PLC.Write<int>((string)d.WriteVirtualId, virtualId); //假电芯虚拟码
|
||||
if (!writeResult.IsSuccess)
|
||||
{
|
||||
LogHelper.Instance.GetCurrentClassWarn($"写假电芯虚拟码失败,{(string)d.WriteVirtualId}:{writeResult.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
writeResult = PLC.Write<Int16>((string)d.WriteResult, scanResult.IsSuccess ? (Int16)EResult.OK : (Int16)EResult.NG); //假电芯结果
|
||||
if (!writeResult.IsSuccess)
|
||||
{
|
||||
LogHelper.Instance.GetCurrentClassWarn($"{(string)d.WriteResult}:{writeResult.Message}");
|
||||
}
|
||||
|
||||
writeResult = PLC.Write<Int16>((string)d.WriteAsk, 1); //回复
|
||||
if (!writeResult.IsSuccess)
|
||||
{
|
||||
LogHelper.Instance.Warn($"ExecuteScanDummy-{(string)d.WriteAsk}:{writeResult.Message}");
|
||||
}
|
||||
|
||||
_unityContainer.Resolve<BasicInfoViewModel>().SetEvent("结束:" + node.VarDesc);
|
||||
}
|
||||
|
||||
//托盘扫码
|
||||
public void ExecuteScanPallet(int curValue, string param, Variable node)
|
||||
{
|
||||
string msg = "";
|
||||
dynamic d = JsonConvert.DeserializeObject<dynamic>(node.Json);
|
||||
_unityContainer.Resolve<LogService>().AddLog("LoadingStation:ExecuteScanPallet:托盘扫码开始", E_LogType.Info.ToString());
|
||||
string palletCode = "";
|
||||
int VID = 0;
|
||||
OperateResult writeResult = null;
|
||||
HslCommunication.OperateResult<string> scanResult = new HslCommunication.OperateResult<string>()
|
||||
{
|
||||
IsSuccess = false,
|
||||
};
|
||||
|
||||
|
||||
EScanCode scanName = (EScanCode)((int)EScanCode.PalletScan1 + int.Parse(param) - 1); //param这个就是扫码枪的编号
|
||||
|
||||
try
|
||||
{
|
||||
IScanCodeBase scanDevice = _deviceScann.Find(x => x.Name == scanName.ToString());
|
||||
|
||||
while (!scanDevice.IsConnect)
|
||||
{
|
||||
msg = $"获取{scanName.GetDescription()}连接异常!";
|
||||
LogHelper.Instance.Error(msg);
|
||||
_unityContainer.Resolve<MainWindowViewModel>().AddPromptContent(msg);
|
||||
scanDevice.Connect();
|
||||
}
|
||||
|
||||
scanResult = scanDevice.ReadCode();
|
||||
////------------------------ //add by lsm
|
||||
//scanResult.IsSuccess = true;
|
||||
//scanResult.Content = System.Guid.NewGuid().ToString("N").Substring(0, 6); // add by lsm测试用
|
||||
//------------------------
|
||||
palletCode = scanResult.Content;
|
||||
|
||||
//夹具扫码异常处理
|
||||
while (string.IsNullOrEmpty(palletCode))
|
||||
{
|
||||
Application.Current.Dispatcher.Invoke((Action)(() =>
|
||||
{
|
||||
PalletIdInputWindow f = new PalletIdInputWindow("托盘码输入框", "请输入托盘码", "确定输入托盘码?")
|
||||
{
|
||||
WindowStartupLocation = System.Windows.WindowStartupLocation.CenterScreen,
|
||||
};
|
||||
f.ShowDialog();
|
||||
palletCode = f.PalletId;
|
||||
}));
|
||||
}
|
||||
|
||||
//绑定托盘
|
||||
VID = _unityContainer.Resolve<PalletInfoService>().BindingPallet(palletCode, (int)EPalletStatus.Loading, (int)EStationType.Loading, int.Parse(param)); //防呆
|
||||
|
||||
if (0 == VID)
|
||||
{
|
||||
LogHelper.Instance.Debug($"===ProcBindPallet卡死,{palletCode},{int.Parse(param)},VID:{VID}");
|
||||
return; //此时会卡死上位机
|
||||
}
|
||||
|
||||
LogHelper.Instance.Debug($"===ProcBindPallet,{palletCode},{(int)EPalletStatus.Loading},{int.Parse(param)},VID:{VID}");
|
||||
|
||||
if (CurrentWeaterPallet())
|
||||
{
|
||||
Int16 DummyLocationX = Int16.Parse(_unityContainer.Resolve<Cowain.Bake.BLL.SysSetupService>().GetValueByParaID(ESysSetup.DummyLocationX.ToString()));
|
||||
writeResult = PLC.Write<Int16>((string)d.WriteDummyX, DummyLocationX); //假电芯行号
|
||||
if (!writeResult.IsSuccess)
|
||||
{
|
||||
LogHelper.Instance.GetCurrentClassWarn($"假电芯行号:{(string)d.WriteDummyX}:{writeResult.Message},失败");
|
||||
}
|
||||
|
||||
Int16 DummyLocationY = Int16.Parse(_unityContainer.Resolve<Cowain.Bake.BLL.SysSetupService>().GetValueByParaID(ESysSetup.DummyLocationY.ToString()));
|
||||
writeResult = PLC.Write<Int16>((string)d.WriteDummyY, DummyLocationY); //假电芯列号
|
||||
if (!writeResult.IsSuccess)
|
||||
{
|
||||
LogHelper.Instance.GetCurrentClassWarn($"假电芯列号:{(string)d.WriteDummyY}:{writeResult.Message},失败");
|
||||
}
|
||||
}
|
||||
writeResult = PLC.Write<int>((string)d.WritePattleVirtualId, VID); //托盘1托盘虚拟码
|
||||
if (!writeResult.IsSuccess)
|
||||
{
|
||||
LogHelper.Instance.GetCurrentClassWarn($"{(string)d.WritePattleVirtualId}:{writeResult.Message}");
|
||||
}
|
||||
|
||||
writeResult = PLC.Write<Int16>((string)d.WriteResult, 1); //托盘1扫码结果
|
||||
if (!writeResult.IsSuccess)
|
||||
{
|
||||
LogHelper.Instance.GetCurrentClassWarn($"{(string)d.WriteResult}:{writeResult.Message}");
|
||||
}
|
||||
|
||||
writeResult = PLC.Write<Int16>((string)d.WriteAsk, 1); //回复
|
||||
if (!writeResult.IsSuccess)
|
||||
{
|
||||
LogHelper.Instance.Warn($"ExecuteScanPallet-{(string)d.WriteAsk}:{writeResult.Message}");
|
||||
}
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
LogHelper.Instance.GetCurrentClassWarn($"ExecuteScanPallet:{ex},{scanResult.Content},{scanResult.Message}");
|
||||
}
|
||||
|
||||
_unityContainer.Resolve<MainWindowViewModel>().DeletePromptContent();
|
||||
_unityContainer.Resolve<BasicInfoViewModel>().SetEvent("结束:" + node.VarDesc);
|
||||
}
|
||||
/// <summary>
|
||||
/// 根据工单判断是否放水含量
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool CurrentWeaterPallet()
|
||||
{
|
||||
bool IsWaertPallet = false;
|
||||
var productionInformation = _unityContainer.Resolve<ProductionInformationService>().GetCurrentProductInfo();
|
||||
|
||||
if (productionInformation.DummyRule == (int)DummyPlaceRule.DEFAULT_EVERY_STOVE_LAYER_PLACED_ONE)
|
||||
{
|
||||
if (SettingProvider.Instance.WaterPallet % 2 == 1)
|
||||
{
|
||||
IsWaertPallet = true;
|
||||
}
|
||||
SettingProvider.Instance.WaterPallet++;
|
||||
}
|
||||
else if (productionInformation.DummyRule == (int)DummyPlaceRule.EVERY_PALLET_PLACED_ONE)
|
||||
{
|
||||
IsWaertPallet = true;
|
||||
}
|
||||
|
||||
return IsWaertPallet;
|
||||
|
||||
}
|
||||
|
||||
//电芯扫码
|
||||
public async Task ExecutScanBattery(int curValue, string param, Variable node)
|
||||
{
|
||||
dynamic d = JsonConvert.DeserializeObject<dynamic>(node.Json);
|
||||
if (!IsConnectPLC()) return;
|
||||
|
||||
int scannIndex = 0;
|
||||
OperateResult writeResult = null;
|
||||
int mesIndex = 0;
|
||||
int index = 1; //1..4,第0个索引不用
|
||||
string[] codeBatterys = new string[Global.ONCE_SCAN_BATTERY + 1];
|
||||
Int16[] result = new Int16[Global.ONCE_SCAN_BATTERY + 1];
|
||||
Int16[] ask = new Int16[Global.ONCE_SCAN_BATTERY + 1];
|
||||
int[] batteryVirtualIds = new int[Global.ONCE_SCAN_BATTERY + 1];
|
||||
result = Enumerable.Repeat<Int16>(3, Global.ONCE_SCAN_BATTERY + 1).ToArray();
|
||||
Array.Clear(ask, 0, Global.ONCE_SCAN_BATTERY + 1); //3:无电芯
|
||||
Array.Clear(batteryVirtualIds, 0, Global.ONCE_SCAN_BATTERY + 1);
|
||||
List<OperateResult<string>> scannList = new List<OperateResult<string>>();
|
||||
List<MESReturnCmdModel> mesResultList = new List<MESReturnCmdModel>();
|
||||
List<Task<OperateResult<string>>> scannTasks = new List<Task<OperateResult<string>>>();
|
||||
List<Task<MESReturnCmdModel>> mesResultTasks = new List<Task<MESReturnCmdModel>>();
|
||||
int mesEnable = int.Parse(_unityContainer.Resolve<SysSetupService>().GetValueByParaID(ESysSetup.MOMEnable.ToString()));
|
||||
int debugMode = int.Parse(_unityContainer.Resolve<SysSetupService>().GetValueByParaID(ESysSetup.DebugMode.ToString())); //0为测试模式,1为正式模式
|
||||
|
||||
Array.Clear(codeBatterys, 0, Global.ONCE_SCAN_BATTERY + 1); //几个条码一起保存
|
||||
HslCommunication.OperateResult<string> scanResult = new HslCommunication.OperateResult<string>()
|
||||
{
|
||||
IsSuccess = false,
|
||||
};
|
||||
|
||||
if (mesEnable == (int)EMOMEnable.Enable
|
||||
&& (int)EProductionMode.Debug == debugMode)
|
||||
{
|
||||
LogHelper.Instance.Error($"MOM【在线模式】,设备模式却是【调试模式】,模式不匹配,请修改!", true);
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
index = 1;
|
||||
for (EScanCode s = EScanCode.LoadingBatteryScan1; s <= EScanCode.LoadingBatteryScan8; s++, index++)
|
||||
{
|
||||
if (((curValue >> index) & 1) != 1) //第index位不是1,就是不需要扫码
|
||||
{
|
||||
continue;
|
||||
}
|
||||
ask[(int)s] = 1;
|
||||
|
||||
IScanCodeBase scanDevice = _deviceScann.Find(x => x.Name == s.ToString());
|
||||
|
||||
if (!scanDevice.IsConnect)
|
||||
{
|
||||
string msg = $"获取{s.GetDescription()}失败,请检测线路!";
|
||||
LogHelper.Instance.Error(msg, true); //弹屏,人为处理好后,再次触发
|
||||
_unityContainer.Resolve<MainWindowViewModel>().AddPromptContent(msg);
|
||||
scanDevice.Connect();
|
||||
--s; //再次获取
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((int)EProductionMode.Debug == debugMode) //调试模式
|
||||
{
|
||||
scanResult.IsSuccess = true;
|
||||
scanResult.Content = System.Guid.NewGuid().ToString("N").Substring(0, _batteryCodeLen);
|
||||
scannList.Add(scanResult);
|
||||
}
|
||||
else
|
||||
{
|
||||
//scanResult = scanDevice.ReadCode();
|
||||
scannTasks.Add(Task.Run(() => scanDevice.ReadCode())); // 启动并行任务
|
||||
}
|
||||
}
|
||||
|
||||
if ((int)EProductionMode.Normal == debugMode)
|
||||
{
|
||||
await Task.WhenAll(scannTasks); //等待所有任务(扫码)完成
|
||||
foreach (var task in scannTasks)
|
||||
{
|
||||
scannList.Add(task.Result);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#region 同时请求MOM
|
||||
if (mesEnable == (int)EMOMEnable.Enable)//生产模式,才会请求MES(不是离线就要请求)
|
||||
{
|
||||
foreach (var item in scannList) //四个电芯扫码结果
|
||||
{
|
||||
if (item.IsSuccess) //可能是三个扫码OK,一个扫码NG,所以只有三个电芯请求到MOM
|
||||
{
|
||||
mesResultTasks.Add(Task.Run(() => _unityContainer.Resolve<MESProcess>().GetBatteryStatus(item.Content))); //多线程入库,会有先后顺序的
|
||||
}
|
||||
}
|
||||
|
||||
if (0 != mesResultTasks.Count)
|
||||
{
|
||||
MESReturnCmdModel[] tt = await Task.WhenAll(mesResultTasks); // //发送MES,等待所有的MES请求。
|
||||
foreach (var item in mesResultTasks) //发送MOM,不一定是四个
|
||||
{
|
||||
mesResultList.Add(item.Result);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
index = 1; //1..4,第0个索引不用
|
||||
for (EScanCode s = EScanCode.LoadingBatteryScan1; s <= EScanCode.LoadingBatteryScan8; s++, index++)
|
||||
{
|
||||
if (((curValue >> index) & 1) != 1) //第index位不是1,就是不需要扫码
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
scanResult = scannList[scannIndex++];
|
||||
|
||||
result[index] = scanResult.IsSuccess ? (Int16)EResult.OK : (Int16)EResult.NG;
|
||||
if (scanResult.IsSuccess) //扫码成功
|
||||
{
|
||||
//长度判断
|
||||
//if (_batteryCodeLen != scanResult.Content.Length)
|
||||
//{
|
||||
// result[index] = (Int32)EResult.NG; //长度不对,赋NG
|
||||
// _unityContainer.Resolve<BatteryNGService>().Insert("入站拦截", scanResult.Content, $"要求电芯条码长度为{_batteryCodeLen},实际长度为:{scanResult.Content.Length}");
|
||||
// continue;
|
||||
//}
|
||||
|
||||
//0:正常扫码,1:复投扫码
|
||||
if ("0" == _unityContainer.Resolve<Cowain.Bake.BLL.SysSetupService>().GetValueByParaID(Cowain.Bake.Common.Enums.ESysSetup.ScanCodeMode.ToString()))
|
||||
{
|
||||
if (_unityContainer.Resolve<BatteryInfoService>().IsBatteryCodeRepeat(scanResult.Content))
|
||||
{
|
||||
result[index] = (Int32)EResult.NG; //有相同电芯,赋NG
|
||||
LogHelper.Instance.Warn($"{s.GetDescription()},电芯条码:[{scanResult.Content}]重复扫码,将会排出到NG位;"); //不要弹屏
|
||||
_unityContainer.Resolve<BatteryNGService>().Insert("入站拦截", scanResult.Content, $"重复扫码,将会排出到NG位");
|
||||
}
|
||||
}
|
||||
|
||||
//MES结果判断
|
||||
if (mesEnable == (int)EMOMEnable.Enable) ////mes-mom 7.电芯状态获取 只有联机才调用MES接口,MES返回成功,失败
|
||||
{
|
||||
MESReturnCmdModel mesResult = mesResultList[mesIndex++];//_unityContainer.Resolve<MESProcess>().MESCellState(scanResult.Content);
|
||||
if (mesResult == null)
|
||||
{
|
||||
result[index] = (int)EResult.NG;
|
||||
_unityContainer.Resolve<BatteryNGService>().Insert("入站拦截", scanResult.Content, "MOM返回信息为空,请判断MOM是否离线,未离线则是MOM回复异常");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mesResult.Info.ResultFlag != EResultFlag.OK.ToString())
|
||||
{
|
||||
result[index] = (int)EResult.NG;
|
||||
_unityContainer.Resolve<BatteryNGService>().Insert("入站拦截", scanResult.Content, JSON.SerializeObject(mesResult));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
codeBatterys[index] = scanResult.Content; //MES判断OK的电芯,才放到电芯表中。
|
||||
}
|
||||
}
|
||||
|
||||
batteryVirtualIds = _unityContainer.Resolve<BatteryInfoService>().InsertBattery(string.Join(",", codeBatterys)).ToArray(); //新加的,四个一起存,并返回虚拟码
|
||||
//InsertBattery//四个电芯一起存数据库
|
||||
LogHelper.Instance.Info($"电芯虚拟码写入到PLC:{string.Join(",", batteryVirtualIds)},codes={string.Join(",", codeBatterys)},扫码状态:{string.Join(",", result)}");
|
||||
writeResult = PLC.Write<int[]>((string)d.WriteVirtualIds, batteryVirtualIds); //电芯1...4虚拟码
|
||||
if (!writeResult.IsSuccess)
|
||||
{
|
||||
LogHelper.Instance.Warn($"写虚拟地址-{(string)d.WriteVirtualIds}:{writeResult.Message}");
|
||||
}
|
||||
//g_U01_HMI.UpLoadFromWcs.iCell_ScanCodeResults
|
||||
writeResult = PLC.Write<Int16[]>((string)d.WriteResult, result); //电芯1...8扫码结果
|
||||
if (!writeResult.IsSuccess)
|
||||
{
|
||||
LogHelper.Instance.Warn($"ExecutScanBattery-{(string)d.WriteResult}:{writeResult.Message}");
|
||||
}
|
||||
|
||||
writeResult = PLC.Write<Int16[]>((string)d.WriteAsk, ask); //回复
|
||||
if (!writeResult.IsSuccess)
|
||||
{
|
||||
LogHelper.Instance.Warn($"ExecutScanBattery-{(string)d.WriteAsk}:{writeResult.Message}");
|
||||
}
|
||||
|
||||
_unityContainer.Resolve<MainWindowViewModel>().DeletePromptContent();
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
LogHelper.Instance.Fatal($"ExecutScanBattery-出错-param:{param}:{ex.Message},{index}");
|
||||
}
|
||||
_unityContainer.Resolve<BasicInfoViewModel>().SetEvent("结束:" + node.VarDesc);
|
||||
}
|
||||
|
||||
//保存组盘信息
|
||||
private void SavePalletInfo(int palletVID)
|
||||
{
|
||||
string dateFile;
|
||||
string filePath;
|
||||
|
||||
try
|
||||
{
|
||||
List<TBatteryInfo> batterys = _unityContainer.Resolve<BatteryInfoService>().GetBatteryInfos(palletVID);
|
||||
|
||||
if (0 == batterys.Count)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
string path = _unityContainer.Resolve<SysSetupService>().GetValueByParaID(ESysSetup.DataFilePath.ToString());
|
||||
path += "\\组盘";
|
||||
dateFile = DateTime.Now.ToString("yyyyMMdd");
|
||||
filePath = path + $"\\{dateFile}.csv";
|
||||
|
||||
if (!Directory.Exists(path))
|
||||
{
|
||||
Directory.CreateDirectory(path);
|
||||
}
|
||||
|
||||
CSVHelper.WriteMap<TBatteryInfo, BatteryInfoMap>(batterys, filePath);
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
LogHelper.Instance.Error($"SavePalletInfo:{ex.Message},{ex.StackTrace}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
73
Cowain.Bake.Main/Station/MesCollectStation.cs
Normal file
@@ -0,0 +1,73 @@
|
||||
using Cowain.Bake.BLL;
|
||||
using Cowain.Bake.Common.Enums;
|
||||
using Cowain.Bake.Communication.MOM;
|
||||
using Cowain.Bake.Main.ViewModels;
|
||||
using Cowain.Bake.Model;
|
||||
using Cowain.Bake.Model.Models;
|
||||
using Opc.Ua;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using Unity;
|
||||
using JSON = Newtonsoft.Json.JsonConvert;
|
||||
|
||||
namespace Cowain.Bake.Main.Station
|
||||
{
|
||||
public class MesCollectStation
|
||||
{
|
||||
readonly CancellationTokenSource cts = new CancellationTokenSource();
|
||||
readonly List<TDeviceConfig> stoveConfs = null;
|
||||
IUnityContainer _unityContainer { get; set; }
|
||||
public MesCollectStation(IUnityContainer unityContainer)
|
||||
{
|
||||
|
||||
_unityContainer = unityContainer;
|
||||
stoveConfs = _unityContainer.Resolve<DeviceConfigService>().GetConfig(EDeviceType.PLC, EDeviceName.StovePlc1);
|
||||
}
|
||||
/*
|
||||
1 运行状态
|
||||
2 待机状态
|
||||
3 报警状态
|
||||
4 停机状态
|
||||
*/
|
||||
//mes-mom 2.设备状态 只有联机才调用MES接口,MOM返回成功,失败
|
||||
public void EqptStatus(DataValue data, Variable node)
|
||||
{
|
||||
Int16 value = (Int16)data.WrappedValue.Value;
|
||||
List<TAlarm> models = null;
|
||||
if (int.Parse(_unityContainer.Resolve<SysSetupService>().GetValueByParaID(ESysSetup.MOMEnable.ToString())) == (int)EMOMEnable.Enable)
|
||||
{
|
||||
if ((int)EStatusCode.Warn == value)
|
||||
{
|
||||
var alarms = _unityContainer.Resolve<MainWindowViewModel>().Alarms.Where(x=>x.StationId == node.StationId).ToList();
|
||||
models = JSON.DeserializeObject<List<TAlarm>>(JSON.SerializeObject(alarms));
|
||||
}
|
||||
//_unityContainer.Resolve<MESProcess>().MESEqptStatus((UInt16)value, models); //经常超时 2026-2-9
|
||||
}
|
||||
_unityContainer.Resolve<BasicInfoViewModel>().DeviceStatusName = ((EStatusCode)value).GetDescription();
|
||||
}
|
||||
|
||||
//public string MakeJsonTemperature(string headName, float[] value)
|
||||
//{
|
||||
// headName = Regex.Replace(headName, @"\d", "");
|
||||
// List<PallletTemp> listTemp = new List<PallletTemp>();
|
||||
// for (int i = 1; i <= value.Length; i++)
|
||||
// {
|
||||
// listTemp.Add(new PallletTemp()
|
||||
// {
|
||||
// HeadName = $"{headName}{i}",
|
||||
// Value = value[i - 1]
|
||||
// });
|
||||
// }
|
||||
|
||||
// return JsonConvert.SerializeObject(listTemp);
|
||||
//}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
// 在需要取消任务的时候,调用以下代码:
|
||||
cts.Cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
397
Cowain.Bake.Main/Station/StoveProcessParam.cs
Normal file
@@ -0,0 +1,397 @@
|
||||
using Cowain.Bake.BLL;
|
||||
using Cowain.Bake.Common;
|
||||
using Cowain.Bake.Common.Core;
|
||||
using Cowain.Bake.Common.Enums;
|
||||
using Cowain.Bake.Common.Models;
|
||||
using Cowain.Bake.Communication.Interface;
|
||||
using Cowain.Bake.Model;
|
||||
using Cowain.Bake.Model.Models;
|
||||
using HslCommunication;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Unity;
|
||||
using JSON = System.Text.Json.JsonSerializer;
|
||||
|
||||
namespace Cowain.Bake.Main.Station
|
||||
{
|
||||
public class StoveProcessParam
|
||||
{
|
||||
const int PROCESS_PARAM_NUM = 21;
|
||||
//ProcessParamService procParamService;
|
||||
public IUnityContainer _unityContainer { get; set; }
|
||||
public StoveProcessParam(IUnityContainer unityContainer)
|
||||
{
|
||||
_unityContainer = unityContainer;
|
||||
//procParamService = _unityContainer.Resolve<ProcessParamService>();
|
||||
}
|
||||
|
||||
public bool SendStoveProcessParam(IPLCDevice plc, ExCavityInfoModel palletProceParam)
|
||||
{
|
||||
ProceParamList proceParam = null;
|
||||
TProcessParameter proceParamModel = null;
|
||||
//_unityContainer.Resolve<LogService>().AddLog("StoveProcessParam:SendStoveProcessParam:下发工艺参数开始"
|
||||
// , E_LogType.Info.ToString());
|
||||
OperateResult<AddrValue> operateResult = null;
|
||||
Model.Models.Variable node = null;
|
||||
List<AddrValue> makeAddrValues = new List<AddrValue>();
|
||||
List<ProceParamList> listParams = null;
|
||||
if (null == palletProceParam)
|
||||
{
|
||||
LogHelper.Instance.GetCurrentClassWarn("发送工艺参数时,没有获取到托盘信息!");
|
||||
return false;
|
||||
}
|
||||
|
||||
//判断是否是复烘
|
||||
if (palletProceParam.PalletStatus == (int)EPalletStatus.TestNG)
|
||||
{
|
||||
//使用复烘工艺
|
||||
proceParamModel = _unityContainer.Resolve<ProcessParamService>().GetReProcessParam(palletProceParam.JobNum);
|
||||
}
|
||||
else
|
||||
{
|
||||
proceParamModel = _unityContainer.Resolve<ProcessParamService>().GetProcessParam(palletProceParam.JobNum);
|
||||
}
|
||||
|
||||
if (null == proceParamModel)
|
||||
{
|
||||
LogHelper.Instance.GetCurrentClassWarn("没有找到工艺参数列表!");
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
listParams = JSON.Deserialize<List<ProceParamList>>(proceParamModel.Parameters);
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
LogHelper.Instance.GetCurrentClassFatal(ex.Message);
|
||||
return false;
|
||||
}
|
||||
|
||||
//温度上限预警值
|
||||
node = plc.GetVariable(EStoveSignal.TemperatureUpperWarnValue.ToString(), palletProceParam.StationId);
|
||||
proceParam = listParams.Where(x => x.ParameterCode.ToLower() == EStoveSignal.TemperatureUpperWarnValue.ToString().ToLower()).FirstOrDefault();
|
||||
operateResult = SetNodeValue(node, proceParam);
|
||||
if (operateResult.IsSuccess)
|
||||
{
|
||||
makeAddrValues.Add(operateResult.Content);
|
||||
}
|
||||
|
||||
//真空上限预警值
|
||||
node = plc.GetVariable(EStoveSignal.VacuumUpperWarnValue.ToString(), palletProceParam.StationId);
|
||||
proceParam = listParams.Where(x => x.ParameterCode.ToLower() == EStoveSignal.VacuumUpperWarnValue.ToString().ToLower()).FirstOrDefault();
|
||||
operateResult = SetNodeValue(node, proceParam);
|
||||
if (operateResult.IsSuccess)
|
||||
{
|
||||
makeAddrValues.Add(operateResult.Content);
|
||||
}
|
||||
|
||||
////参数_设定温度
|
||||
node = plc.GetVariable(EStoveSignal.SetTemp.ToString(), palletProceParam.StationId);
|
||||
proceParam = listParams.Where(x => x.ParameterCode.ToLower() == EStoveSignal.SetTemp.ToString().ToLower()).FirstOrDefault();
|
||||
operateResult = SetNodeValue(node, proceParam, 100); //乘以100,设定10000,表示100度
|
||||
if (operateResult.IsSuccess)
|
||||
{
|
||||
makeAddrValues.Add(operateResult.Content);
|
||||
}
|
||||
|
||||
//参数_温度公差
|
||||
node = plc.GetVariable(EStoveSignal.TemperatureTolerance.ToString(), palletProceParam.StationId);
|
||||
proceParam = listParams.Where(x => x.ParameterCode.ToLower() == EStoveSignal.TemperatureTolerance.ToString().ToLower()).FirstOrDefault();
|
||||
operateResult = SetNodeValue(node, proceParam, 100); //乘以100,设定10000
|
||||
if (operateResult.IsSuccess)
|
||||
{
|
||||
makeAddrValues.Add(operateResult.Content);
|
||||
}
|
||||
|
||||
//参数_温度上限
|
||||
node = plc.GetVariable(EStoveSignal.TemperatureLimit.ToString(), palletProceParam.StationId);
|
||||
proceParam = listParams.Where(x => x.ParameterCode.ToLower() == EStoveSignal.TemperatureLimit.ToString().ToLower()).FirstOrDefault();
|
||||
operateResult = SetNodeValue(node, proceParam, 100); //乘以100,设定10000
|
||||
if (operateResult.IsSuccess)
|
||||
{
|
||||
makeAddrValues.Add(operateResult.Content);
|
||||
}
|
||||
|
||||
//参数_真空到达值
|
||||
node = plc.GetVariable(EStoveSignal.VacuumArriveValue.ToString(), palletProceParam.StationId);
|
||||
proceParam = listParams.Where(x => x.ParameterCode.ToLower() == EStoveSignal.VacuumArriveValue.ToString().ToLower()).FirstOrDefault();
|
||||
operateResult = SetNodeValue(node, proceParam);
|
||||
if (operateResult.IsSuccess)
|
||||
{
|
||||
makeAddrValues.Add(operateResult.Content);
|
||||
}
|
||||
|
||||
//参数_真空上限
|
||||
node = plc.GetVariable(EStoveSignal.VacuumUpValue.ToString(), palletProceParam.StationId);
|
||||
proceParam = listParams.Where(x => x.ParameterCode.ToLower() == EStoveSignal.VacuumUpValue.ToString().ToLower()).FirstOrDefault();
|
||||
operateResult = SetNodeValue(node, proceParam);
|
||||
if (operateResult.IsSuccess)
|
||||
{
|
||||
makeAddrValues.Add(operateResult.Content);
|
||||
}
|
||||
|
||||
//参数_真空下限
|
||||
node = plc.GetVariable(EStoveSignal.VacuumDownValue.ToString(), palletProceParam.StationId);
|
||||
proceParam = listParams.Where(x => x.ParameterCode.ToLower() == EStoveSignal.VacuumDownValue.ToString().ToLower()).FirstOrDefault();
|
||||
operateResult = SetNodeValue(node, proceParam);
|
||||
if (operateResult.IsSuccess)
|
||||
{
|
||||
makeAddrValues.Add(operateResult.Content);
|
||||
}
|
||||
|
||||
//参数_氮气到达值
|
||||
node = plc.GetVariable(EStoveSignal.NitrogenArriveValue.ToString(), palletProceParam.StationId);
|
||||
proceParam = listParams.Where(x => x.ParameterCode.ToLower() == EStoveSignal.NitrogenArriveValue.ToString().ToLower()).FirstOrDefault();
|
||||
operateResult = SetNodeValue(node, proceParam);
|
||||
if (operateResult.IsSuccess)
|
||||
{
|
||||
makeAddrValues.Add(operateResult.Content);
|
||||
}
|
||||
|
||||
//参数_氮气上限
|
||||
node = plc.GetVariable(EStoveSignal.NitrogenUpValue.ToString(), palletProceParam.StationId);
|
||||
proceParam = listParams.Where(x => x.ParameterCode.ToLower() == EStoveSignal.NitrogenUpValue.ToString().ToLower()).FirstOrDefault();
|
||||
operateResult = SetNodeValue(node, proceParam);
|
||||
if (operateResult.IsSuccess)
|
||||
{
|
||||
makeAddrValues.Add(operateResult.Content);
|
||||
}
|
||||
|
||||
//参数_氮气下限
|
||||
node = plc.GetVariable(EStoveSignal.NitrogenDownValue.ToString(), palletProceParam.StationId);
|
||||
proceParam = listParams.Where(x => x.ParameterCode.ToLower() == EStoveSignal.NitrogenDownValue.ToString().ToLower()).FirstOrDefault();
|
||||
operateResult = SetNodeValue(node, proceParam);
|
||||
if (operateResult.IsSuccess)
|
||||
{
|
||||
makeAddrValues.Add(operateResult.Content);
|
||||
}
|
||||
|
||||
//参数_常压到达值
|
||||
node = plc.GetVariable(EStoveSignal.AtmosphericArriveValue.ToString(), palletProceParam.StationId);
|
||||
proceParam = listParams.Where(x => x.ParameterCode.ToLower() == EStoveSignal.AtmosphericArriveValue.ToString().ToLower()).FirstOrDefault();
|
||||
operateResult = SetNodeValue(node, proceParam);
|
||||
if (operateResult.IsSuccess)
|
||||
{
|
||||
makeAddrValues.Add(operateResult.Content);
|
||||
}
|
||||
|
||||
//参数_常压上限
|
||||
node = plc.GetVariable(EStoveSignal.AtmosphericUpValue.ToString(), palletProceParam.StationId);
|
||||
proceParam = listParams.Where(x => x.ParameterCode.ToLower() == EStoveSignal.AtmosphericUpValue.ToString().ToLower()).FirstOrDefault();
|
||||
operateResult = SetNodeValue(node, proceParam);
|
||||
if (operateResult.IsSuccess)
|
||||
{
|
||||
makeAddrValues.Add(operateResult.Content);
|
||||
}
|
||||
|
||||
//参数_常压下限
|
||||
node = plc.GetVariable(EStoveSignal.AtmosphericDownValue.ToString(), palletProceParam.StationId);
|
||||
proceParam = listParams.Where(x => x.ParameterCode.ToLower() == EStoveSignal.AtmosphericDownValue.ToString().ToLower()).FirstOrDefault();
|
||||
operateResult = SetNodeValue(node, proceParam);
|
||||
if (operateResult.IsSuccess)
|
||||
{
|
||||
makeAddrValues.Add(operateResult.Content);
|
||||
}
|
||||
|
||||
//参数_循环启动工步
|
||||
node = plc.GetVariable(EStoveSignal.CycleStartStep.ToString(), palletProceParam.StationId);
|
||||
operateResult = SetNodeValues(node, listParams, EStoveSignal.CycleStartStep.ToString(), false);
|
||||
if (operateResult.IsSuccess)
|
||||
{
|
||||
makeAddrValues.Add(operateResult.Content);
|
||||
}
|
||||
|
||||
//参数_循环结束工步
|
||||
node = plc.GetVariable(EStoveSignal.CycleEndStep.ToString(), palletProceParam.StationId);
|
||||
operateResult = SetNodeValues(node, listParams, EStoveSignal.CycleEndStep.ToString(), false);
|
||||
if (operateResult.IsSuccess)
|
||||
{
|
||||
makeAddrValues.Add(operateResult.Content);
|
||||
}
|
||||
|
||||
//参数_循环次数
|
||||
node = plc.GetVariable(EStoveSignal.CycleNumber.ToString(), palletProceParam.StationId);
|
||||
operateResult = SetNodeValues(node, listParams, EStoveSignal.CycleNumber.ToString(), false);
|
||||
if (operateResult.IsSuccess)
|
||||
{
|
||||
makeAddrValues.Add(operateResult.Content);
|
||||
}
|
||||
|
||||
//参数_加热启用
|
||||
node = plc.GetVariable(EStoveSignal.HeatingEnabled.ToString(), palletProceParam.StationId);
|
||||
operateResult = SetNodeValues(node, listParams, EStoveSignal.HeatingEnabled.ToString(), true);
|
||||
if (operateResult.IsSuccess)
|
||||
{
|
||||
makeAddrValues.Add(operateResult.Content);
|
||||
}
|
||||
|
||||
//参数_真空启用
|
||||
node = plc.GetVariable(EStoveSignal.VacuumEnabled.ToString(), palletProceParam.StationId);
|
||||
operateResult = SetNodeValues(node, listParams, EStoveSignal.VacuumEnabled.ToString(), true);
|
||||
if (operateResult.IsSuccess)
|
||||
{
|
||||
makeAddrValues.Add(operateResult.Content);
|
||||
}
|
||||
|
||||
//参数_氮气启用
|
||||
node = plc.GetVariable(EStoveSignal.NitrogenEnabled.ToString(), palletProceParam.StationId);
|
||||
operateResult = SetNodeValues(node, listParams, EStoveSignal.NitrogenEnabled.ToString(), true);
|
||||
if (operateResult.IsSuccess)
|
||||
{
|
||||
makeAddrValues.Add(operateResult.Content);
|
||||
}
|
||||
|
||||
//参数_工步时间
|
||||
node = plc.GetVariable(EStoveSignal.StepWorkTime.ToString(), palletProceParam.StationId);
|
||||
operateResult = SetNodeValues(node, listParams, EStoveSignal.StepWorkTime.ToString(), true);
|
||||
if (operateResult.IsSuccess)
|
||||
{
|
||||
makeAddrValues.Add(operateResult.Content);
|
||||
}
|
||||
|
||||
if (PROCESS_PARAM_NUM != makeAddrValues.Count)
|
||||
{
|
||||
LogHelper.Instance.GetCurrentClassError("发送工艺数据项不够!", true);
|
||||
return false;
|
||||
}
|
||||
|
||||
OperateResult result = plc.Writes(makeAddrValues.Select(x => x.Addr).ToArray(), makeAddrValues.Select(x => x.Value).ToArray());
|
||||
|
||||
if (!result.IsSuccess)
|
||||
{
|
||||
LogHelper.Instance.GetCurrentClassError($"发送工艺数据失败,{result.Message}!");
|
||||
return false;
|
||||
}
|
||||
_unityContainer.Resolve<LogService>().AddLog("StoveProcessParam:SendStoveProcessParam:下发工艺参数结束", E_LogType.Info.ToString());
|
||||
return true;
|
||||
}
|
||||
|
||||
OperateResult<AddrValue> SetNodeValues(Model.Models.Variable node, List<ProceParamList> proceParams, string key, bool fristNull)
|
||||
{
|
||||
object obj;
|
||||
EDataType dt = EDataType.UINT32;
|
||||
OperateResult<AddrValue> result = new OperateResult<AddrValue>() { IsSuccess = false };
|
||||
AddrValue nodeValue = new AddrValue();
|
||||
List<object> vaules = new List<object>();
|
||||
|
||||
if (fristNull)
|
||||
{
|
||||
vaules.Add(StringToObject("0", node.VarType));
|
||||
}
|
||||
|
||||
foreach (var item in proceParams)
|
||||
{
|
||||
if (item.ParameterCode.ToLower().StartsWith(key.ToLower())) //在JOSN里面,数组一定要按顺序排,或者顺序乱了
|
||||
{
|
||||
dt = (EDataType)System.Enum.Parse(typeof(EDataType), node.VarType);
|
||||
obj = StringToObject(item.TargetValue, node.VarType);
|
||||
|
||||
if (null == obj)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
vaules.Add(obj);
|
||||
}
|
||||
}
|
||||
|
||||
if (vaules.Count == 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
nodeValue.Addr = node.Address + node.VarName;
|
||||
System.Type type = System.Type.GetType(dt.GetDescription());
|
||||
MethodInfo mi = this.GetType().GetMethod(ReflexFun.OBJECT_TO_T).MakeGenericMethod(new System.Type[] { type }); //如果不转T,直接object会写不进去
|
||||
nodeValue.Value = mi.Invoke(this, new object[]
|
||||
{
|
||||
vaules
|
||||
});
|
||||
result.Content = nodeValue;
|
||||
result.IsSuccess = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
public T[] ObjectToT<T>(List<object> vaules) //where T : class
|
||||
{
|
||||
return vaules.OfType<T>().ToArray(); //object[]转T[]
|
||||
}
|
||||
|
||||
object StringToObject(string value, string varType, float multiples = 1)
|
||||
{
|
||||
object obj = null;
|
||||
EDataType dt = (EDataType)Enum.Parse(typeof(EDataType), varType);
|
||||
try
|
||||
{
|
||||
switch (dt)
|
||||
{
|
||||
case EDataType.BOOL:
|
||||
obj = (value == "1");
|
||||
break;
|
||||
case EDataType.UINT16:
|
||||
obj = (UInt16)(System.Convert.ToSingle(value) * multiples);
|
||||
break;
|
||||
case EDataType.INT16:
|
||||
obj = (Int16)(System.Convert.ToSingle(value) * multiples);
|
||||
break;
|
||||
case EDataType.INT32:
|
||||
obj = (Int32)(System.Convert.ToSingle(value) * multiples);
|
||||
break;
|
||||
case EDataType.UINT32:
|
||||
obj = (UInt32)(System.Convert.ToSingle(value) * multiples);
|
||||
break;
|
||||
case EDataType.FLOAT:
|
||||
case EDataType.REAL:
|
||||
obj = (float)(System.Convert.ToSingle(value) * multiples);
|
||||
break;
|
||||
default:
|
||||
LogHelper.Instance.Fatal($"没有这种数据类型:{varType}");
|
||||
break;
|
||||
}
|
||||
if (null == obj)
|
||||
{
|
||||
LogHelper.Instance.GetCurrentClassError("获取工艺数据的值为空");
|
||||
}
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
LogHelper.Instance.GetCurrentClassDebug(ex.Message);
|
||||
}
|
||||
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
OperateResult<AddrValue> SetNodeValue(Model.Models.Variable node, ProceParamList proceParam, float multiples = 1)
|
||||
{
|
||||
OperateResult<AddrValue> result = new OperateResult<AddrValue>() { IsSuccess = false};
|
||||
AddrValue nodeValue = new AddrValue();
|
||||
if (null == node)
|
||||
{
|
||||
LogHelper.Instance.GetCurrentClassError("获取节点数据失败");
|
||||
return result;
|
||||
}
|
||||
|
||||
if (null == proceParam)
|
||||
{
|
||||
LogHelper.Instance.GetCurrentClassError("获取工艺数据失败");
|
||||
return result;
|
||||
}
|
||||
|
||||
nodeValue.Addr = node.Address + node.VarName;
|
||||
nodeValue.Value = StringToObject(proceParam.TargetValue, node.VarType, multiples);
|
||||
|
||||
if (null == nodeValue.Value)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
result.IsSuccess = true;
|
||||
result.Content = nodeValue;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
582
Cowain.Bake.Main/Station/TaskStation.cs
Normal file
@@ -0,0 +1,582 @@
|
||||
using Cowain.Bake.BLL;
|
||||
using Cowain.Bake.Common;
|
||||
using Cowain.Bake.Common.Core;
|
||||
using Cowain.Bake.Common.Enums;
|
||||
using Cowain.Bake.Common.Interface;
|
||||
using Cowain.Bake.Common.Models;
|
||||
using Cowain.Bake.Communication.Interface;
|
||||
using Cowain.Bake.Communication.MOM;
|
||||
using Cowain.Bake.Main.ViewModels;
|
||||
using Cowain.Bake.Model;
|
||||
using Cowain.Bake.Model.Entity;
|
||||
using Cowain.Bake.Model.Models;
|
||||
using HslCommunication;
|
||||
using Newtonsoft.Json;
|
||||
using Opc.Ua;
|
||||
using Prism.Ioc;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Unity;
|
||||
using JSON = Newtonsoft.Json.JsonConvert;
|
||||
|
||||
namespace Cowain.Bake.Main.Station
|
||||
{
|
||||
public class TaskStation: IServerManager
|
||||
{
|
||||
public string Name { get; set; }
|
||||
static Int16 _lastStepId = 0;
|
||||
public IUnityContainer _unityContainer { get; set; }
|
||||
readonly CancellationTokenSource cts = new CancellationTokenSource();
|
||||
readonly TDeviceConfig config;
|
||||
IPLCDevice agv = null;
|
||||
readonly List<CavityInfoModel> _stationCavity;
|
||||
public List<TStation> _station = null;
|
||||
public AutoResetEvent _newTaskEvent = new AutoResetEvent(true);
|
||||
public TaskStation(IUnityContainer unityContainer)
|
||||
{
|
||||
_unityContainer = unityContainer;
|
||||
_station = _unityContainer.Resolve<MemoryDataProvider>().AllStation;
|
||||
config = _unityContainer.Resolve<DeviceConfigService>().GetConfig(EDeviceType.PLC, EDeviceName.AGV)[0];
|
||||
_stationCavity = _unityContainer.Resolve<CavityInfoService>().GetAllStation();
|
||||
Start();
|
||||
StartNewTask();
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
var task = _unityContainer.Resolve<TaskRecordService>().UnexecuteTask();
|
||||
if (null == task)
|
||||
{
|
||||
_lastStepId = (int)ETaskStep.None;
|
||||
}
|
||||
else
|
||||
{
|
||||
_lastStepId = (short)task.StepId;
|
||||
}
|
||||
|
||||
agv = _unityContainer.Resolve<IPLCDevice>(config.Name);
|
||||
//TTaskRecord task = await GenerateTask(); #测试
|
||||
}
|
||||
public async Task DealTask(DataValue data, Variable node)
|
||||
{
|
||||
bool dealResult = false; //进去这里,看会不会触发别的
|
||||
LogHelper.Instance.Info($"开始任务--------------信号,线程ID:{System.Threading.Thread.CurrentThread.ManagedThreadId},{node.VarDesc}");
|
||||
do
|
||||
{
|
||||
// 启动任务并等待结果
|
||||
//dealResult = await Task.Run(() => ThreadDealTask(data, node));
|
||||
dealResult = ThreadDealTask(data, node);
|
||||
if (!dealResult)
|
||||
{
|
||||
LogHelper.Instance.Error("-------------------------处理任务异常!");
|
||||
await Task.Delay(2 * 1000);
|
||||
}
|
||||
} while(!dealResult);
|
||||
LogHelper.Instance.Info($"完成任务--------------信号,线程ID:{System.Threading.Thread.CurrentThread.ManagedThreadId}");
|
||||
}
|
||||
|
||||
void StartNewTask()
|
||||
{
|
||||
Task.Run( () =>
|
||||
{
|
||||
agv = _unityContainer.Resolve<IPLCDevice>(config.Name);
|
||||
while (!cts.Token.IsCancellationRequested)
|
||||
{
|
||||
if (Global.AppExit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
DealNewTask();
|
||||
}
|
||||
});
|
||||
}
|
||||
public void DealNewTask()
|
||||
{
|
||||
_newTaskEvent.WaitOne(10*1000);
|
||||
|
||||
Variable nodeTemp = (from secondaryList in agv.Storages //不能做触发,因为没有任务。要地直运行里面,来检测是否有任务
|
||||
from item in secondaryList.VariableList
|
||||
where item.ParamName == EAgvPLC.RetCount.ToString()
|
||||
select item).FirstOrDefault();
|
||||
Variable node = BasicFramework.DeepCopy<Variable>(nodeTemp);
|
||||
|
||||
if (null == node || !node.Quality || null == node.CurValue) //无值,退出
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
TTaskRecord oldTask = _unityContainer.Resolve<TaskRecordService>().UnexecuteTask();
|
||||
|
||||
//1.有任务 + 自动 ,退出
|
||||
//2.有任务 + 手动 + 任务执行中: 退出
|
||||
if (null != oldTask)
|
||||
{
|
||||
if (oldTask.Status != (int)ETaskStatus.UnExecute)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
TaskEntity task = GetTask();
|
||||
|
||||
if (null == task)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CommonCoreHelper.Instance.BlockTask.Add(task); //更新界面(任务未执行)
|
||||
SetCount(node);
|
||||
_lastStepId = (int)ETaskStep.MoveFrom; //StepId:手动第一次为1,自动第一次为10
|
||||
if (!SendNextStep(task, node.Json, false)) //发送第一步
|
||||
{
|
||||
return; //发送失败
|
||||
}
|
||||
|
||||
|
||||
//一条任务第一次发任务时
|
||||
if (!_unityContainer.Resolve<TaskRecordService>().ModifyTaskStatus(ETaskStatus.Executing)) //更新任务状态为执行中
|
||||
{
|
||||
LogHelper.Instance.Fatal("更改任务状态失败");
|
||||
}
|
||||
CommonCoreHelper.Instance.BlockTask.Add(task); //任务没有执行完。所以不需要更新界面
|
||||
}
|
||||
|
||||
void SetCount(Variable node)
|
||||
{
|
||||
var model = agv.Read<Int16>(node.Address + node.VarName);
|
||||
if (!model.IsSuccess
|
||||
|| 1 != model.Content)
|
||||
{
|
||||
SettingProvider.Instance.CountCmd = 0; //每条任务从1开始
|
||||
}
|
||||
else
|
||||
{
|
||||
SettingProvider.Instance.CountCmd = 100;
|
||||
}
|
||||
}
|
||||
|
||||
private TaskEntity GetTask()
|
||||
{
|
||||
if (SettingProvider.Instance.DispMode == EDispatchMode.Auto)
|
||||
{
|
||||
var oldTask = _unityContainer.Resolve<TaskRecordService>().UnexecuteTask();
|
||||
if (oldTask != null)
|
||||
{
|
||||
return GetStationManualTask(oldTask);
|
||||
}
|
||||
|
||||
//看到过有任务还生成
|
||||
return _unityContainer.Resolve<TaskRecordService>().GetTask(); //获得调度任务,并插入一条任务进任务记录表
|
||||
}
|
||||
else //手动从数据库获取
|
||||
{
|
||||
TTaskRecord manualTask = _unityContainer.Resolve<TaskRecordService>().UnexecuteTask();
|
||||
if (null == manualTask)
|
||||
{
|
||||
return null; //没有任务(手动任务),就退出
|
||||
}
|
||||
return GetStationManualTask(manualTask);
|
||||
}
|
||||
}
|
||||
/*
|
||||
//1.执行中:机器人正在执行任务中, 如果上位机重启,会触发,
|
||||
//2.无务任或任务执行完成:计命令计算为0或最后一步执行完成,更新状态(无任务不需要),生成任务,下发下一步指令
|
||||
//3.一步任务完成: 更新状态, 下发下一步指令
|
||||
*/
|
||||
public bool ThreadDealTask(DataValue data, Variable node)
|
||||
{
|
||||
string msg = "";
|
||||
LogHelper.Instance.Error("开始接收调度机器人信息!");
|
||||
Int16 countValue ;
|
||||
dynamic d = JsonConvert.DeserializeObject<dynamic>(node.TrigJson);
|
||||
if (null == agv || !agv.IsConnect)
|
||||
{
|
||||
msg = "连接机器人的PLC断开!";
|
||||
LogHelper.Instance.Error(msg);
|
||||
_unityContainer.Resolve<MainWindowViewModel>().AddPromptContent(msg);
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var stepValue = agv.Read<Int16>((string)d.ReadCmd); //可以改成直接读PLC [命令地址]
|
||||
var resultValue = agv.Read<int>((string)d.ReadResult); //这是直接读PLC [执行命令结果]
|
||||
|
||||
if (!stepValue.IsSuccess || !resultValue.IsSuccess)
|
||||
{
|
||||
LogHelper.Instance.Error($"PLC反馈任务时,读取失败!,失败原因:{stepValue.Message},{stepValue.Message}");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (data.WrappedValue.TypeInfo.BuiltInType == Opc.Ua.BuiltInType.Int16)
|
||||
{
|
||||
countValue = (Int16)data.WrappedValue.Value;
|
||||
LogHelper.Instance.Debug($"接收任务信息:计数:{countValue},命令步:{stepValue.Content},结果:{resultValue.Content},当前命令步:{_lastStepId},当前计数:{SettingProvider.Instance.CountCmd}");
|
||||
}
|
||||
else
|
||||
{
|
||||
LogHelper.Instance.Warn($"没有找到这个数据类型,节点名为{node.VarDesc}", true);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!EnumHelper.IsDefined<ETaskStep>(stepValue.Content)) //不在范围内
|
||||
{
|
||||
LogHelper.Instance.Warn($"获取PLC的命令有问题,值:{countValue}", true);
|
||||
return false;
|
||||
}
|
||||
|
||||
_unityContainer.Resolve<EquipmentMonitorViewModel>().SetAgvImage(resultValue.Content);
|
||||
if (resultValue.Content == (int)EAgvMoveStatus.Error) // -1:表示没有完成
|
||||
{
|
||||
//if (countValue > SettingProvider.Instance.CountCmd) 此时上位机是1,PLC是3。 如果执行下面,后续PLC执行1,就不会任务了
|
||||
//{
|
||||
// SettingProvider.Instance.CountCmd = countValue;
|
||||
// LogHelper.Instance.Debug($"更改当前计数:{SettingProvider.Instance.CountCmd}");
|
||||
//}
|
||||
return false;
|
||||
}
|
||||
|
||||
//1.机器人正在执行任务中, 如果上位机重启,此时又有任务
|
||||
//如果:countValue=3000,Instance.CountCmd=1,时,到下面退出,也不影响。
|
||||
if (countValue == SettingProvider.Instance.CountCmd - 1) //(重启上位机,任务在执行中)
|
||||
{
|
||||
LogHelper.Instance.Warn($"重启上位机,此时又有任务在执行中!");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_lastStepId == (int)ETaskStep.None)
|
||||
{
|
||||
LogHelper.Instance.Warn($"重启上位机, 没有任务在执行!");
|
||||
return true;
|
||||
}
|
||||
|
||||
//表示执行完成了,执行下一个; 或无任务
|
||||
if (
|
||||
countValue >= SettingProvider.Instance.CountCmd
|
||||
&& stepValue.Content == _lastStepId
|
||||
)
|
||||
{
|
||||
SettingProvider.Instance.CountCmd = countValue; //PLC跳步
|
||||
TTaskRecord task = _unityContainer.Resolve<TaskRecordService>().UnexecuteTask();
|
||||
if (null == task) //无任务:不需要做什么,有任务:更新状态
|
||||
{
|
||||
LogHelper.Instance.Fatal($"此时应该数据库中要有未执行的任务,计数:{countValue},命令:{stepValue}");
|
||||
return true;
|
||||
}
|
||||
|
||||
TaskEntity detailTask = GetStationManualTask(task); //通过任务,获取工站信息
|
||||
detailTask.StepId = (sbyte)stepValue.Content;
|
||||
|
||||
if (!DealFinishCmd(detailTask, _lastStepId))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_lastStepId == (int)ETaskStep.Place //表示当前是一个任务的最后一条命令
|
||||
/* || 0 == countCmd*/) //PLC重启为0,一条完整的任务完成了,将获取最后一条指令
|
||||
{
|
||||
detailTask.StepId = (int)ETaskStep.Finish;
|
||||
CommonCoreHelper.Instance.BlockTask.Add(detailTask); //机器人界面显示
|
||||
CommonCoreHelper.Instance.MainViewAutoEvent.Set();
|
||||
_newTaskEvent.Set();
|
||||
return true; //完成了一条完整的任务,另外一个方法生成新的任务
|
||||
}
|
||||
|
||||
//发送下一步命令
|
||||
if (!SendNextStep(detailTask, node.Json))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
CommonCoreHelper.Instance.BlockTask.Add(detailTask); //机器人界面显示
|
||||
CommonCoreHelper.Instance.MainViewAutoEvent.Set();
|
||||
LogHelper.Instance.Error("处理完接收调度机器人信息!");
|
||||
}
|
||||
else
|
||||
{
|
||||
LogHelper.Instance.Error($"接收到的信息PLC的调试任务异常,plc cmd:{stepValue},plc 计数:{countValue};\r" +
|
||||
$"上位机 cmd:{_lastStepId},上位机 计数:{SettingProvider.Instance.CountCmd},正常不会执行到这里!");
|
||||
}
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
LogHelper.Instance.GetCurrentClassError($"{ex.Message}-{ex.StackTrace}");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool SendNextStep(TaskEntity detailTask, string json, bool next = true)
|
||||
{
|
||||
LogHelper.Instance.Info($"发送步骤:{detailTask.StepId},命令计数:{SettingProvider.Instance.CountCmd}");
|
||||
|
||||
detailTask = SetNextStep(detailTask, next); //会设置CountCmd StepId
|
||||
if (!SendTask(detailTask, json)) //发送任务
|
||||
{
|
||||
LogHelper.Instance.Error($"发送任务信息失败,{JsonConvert.SerializeObject(detailTask)}!");
|
||||
return false;
|
||||
}
|
||||
|
||||
_lastStepId = detailTask.StepId;
|
||||
SettingProvider.Instance.CountCmd = detailTask.CountCmd;
|
||||
LogHelper.Instance.Debug($"计数改变:{SettingProvider.Instance.CountCmd}");
|
||||
return StartStep(detailTask);
|
||||
}
|
||||
|
||||
public bool ManualTaskCmd(TTaskRecord task, short stepId) //界面上指定再发送一次时,
|
||||
{
|
||||
Variable nodeCountCmd = (from secondaryList in agv.Storages //不能做触发,因为没有任务。要地直运行里面,来检测是否有任务
|
||||
from item in secondaryList.VariableList
|
||||
where item.ParamName == EAgvPLC.RetCount.ToString()
|
||||
select item).FirstOrDefault();
|
||||
|
||||
_lastStepId = (short)stepId;
|
||||
TaskEntity detailTask = GetStationManualTask(task); //通过任务,获取工站信息
|
||||
return SendNextStep(detailTask, nodeCountCmd.Json, false);
|
||||
}
|
||||
bool DealFinishCmd(TaskEntity detailTask, Int16 cmdValue)
|
||||
{
|
||||
if (0 >= _unityContainer.Resolve<TaskStepService>().UpdateEndTime(detailTask.Id, (ETaskStep)cmdValue))
|
||||
{
|
||||
LogHelper.Instance.Error($"修改命令结束时间失败!任务ID:{detailTask.Id},命令:{_lastStepId}");
|
||||
}
|
||||
|
||||
return UpdateFinishStep(detailTask);
|
||||
}
|
||||
|
||||
bool StartStep(TaskEntity detailTask)
|
||||
{
|
||||
if (0 >= _unityContainer.Resolve<TaskStepService>().UpdateStartTime((int)detailTask.Id, detailTask.CountCmd, detailTask.StepId))
|
||||
{
|
||||
LogHelper.Instance.Error($"修改命令开始时间失败!任务ID:{detailTask.Id},命令:{detailTask.StepId},命令计算:{detailTask.CountCmd}");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
bool UpdateFinishStep(TaskEntity stationTask)
|
||||
{
|
||||
int result = 0;
|
||||
switch (stationTask.StepId)
|
||||
{
|
||||
case (int)ETaskStep.MoveFrom:
|
||||
//修改机器人的位置,给界面发信号
|
||||
result =_unityContainer.Resolve<CavityInfoService>().SetRobotPos(stationTask.FromStationNumber);
|
||||
break;
|
||||
case (int)ETaskStep.Pick:
|
||||
UpdateOutStoveTime(stationTask); //更改出炉时间
|
||||
result = _unityContainer.Resolve<TaskRecordService>().BindPalletToRobot(); //将夹具绑定在机器人上
|
||||
break;
|
||||
case (int)ETaskStep.MoveTo:
|
||||
result = _unityContainer.Resolve<CavityInfoService>().SetRobotPos(stationTask.ToStationNumber);
|
||||
break;
|
||||
case (int)ETaskStep.Place:
|
||||
result = _unityContainer.Resolve<TaskRecordService>().UpdateTask(); //1.加锁,解锁,2.绑定,解绑夹具,3.更新机器人的位置,4.更新任务状态完成,
|
||||
SendIntoStove(stationTask); //如果是满载夹具,要将调用烘烤进站接口
|
||||
_unityContainer.Resolve<TaskRecordService>().UpdateFinishStepId(stationTask.Id); //修改任务步为完成
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (result <= 0)
|
||||
{
|
||||
LogHelper.Instance.Error($"接到任务完成,但处理异常:{result},cmd:{stationTask.StepId}");
|
||||
//return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void UpdateOutStoveTime(TaskEntity stationTask)
|
||||
{
|
||||
var cavityStove = _stationCavity.Where(x => x.Id == stationTask.Source && x.Type == (int)EStationType.Stove).FirstOrDefault();
|
||||
if (null != cavityStove) //更改出炉时间
|
||||
{
|
||||
_unityContainer.Resolve<PalletInfoService>().UpdateOutStoveTime(cavityStove.PalletId);
|
||||
}
|
||||
}
|
||||
|
||||
void SendIntoStove(TaskEntity stationTask)
|
||||
{
|
||||
//if (!_unityContainer.Resolve<TaskTypeService>().IsPullInBaker(stationTask.TaskTypeId))
|
||||
if (1 != stationTask.TaskTypeId)// 1: 上料满夹具->烤箱
|
||||
{
|
||||
return ;
|
||||
}
|
||||
|
||||
var cavityInfo = _stationCavity.Where(x=>x.Id == stationTask.Target).FirstOrDefault();
|
||||
var palletInfo = _unityContainer.Resolve<PalletInfoService>().GetPalletInfo(stationTask.PalletId);
|
||||
List<string> batteryCodes = _unityContainer.Resolve<BatteryInfoService>().GetBatteryInfos(palletInfo.VirtualId).Select(x=>x.BatteryCode).ToList();
|
||||
|
||||
if (int.Parse(_unityContainer.Resolve<SysSetupService>().GetValueByParaID(ESysSetup.MOMEnable.ToString())) == (int)EMOMEnable.Enable
|
||||
&& 0 != batteryCodes.Count)
|
||||
{
|
||||
_unityContainer.Resolve<MESProcess>().MESBakingInput(cavityInfo.CavityName, palletInfo.PalletCode, batteryCodes, _unityContainer.Resolve<BasicInfoViewModel>().CurrentOperation);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public TaskEntity GetStationManualTask(TTaskRecord task)
|
||||
{
|
||||
TaskEntity taskEn = JSON.DeserializeObject<TaskEntity>(JSON.SerializeObject(task));
|
||||
var sourceDetail = _unityContainer.Resolve<CavityInfoService>().GetStationDetailById(task.Source);
|
||||
var targetDetail = _unityContainer.Resolve<CavityInfoService>().GetStationDetailById(task.Target);
|
||||
var stationTask = MakeManualTask(taskEn, sourceDetail, targetDetail);
|
||||
//stationTask.Copy(task, stationTask);
|
||||
return stationTask;
|
||||
}
|
||||
|
||||
TaskEntity SetNextStep(TaskEntity task, bool isNext = true)
|
||||
{
|
||||
sbyte nextStepId = (sbyte)_lastStepId;
|
||||
if (isNext)
|
||||
{
|
||||
nextStepId = (sbyte)_unityContainer.Resolve<RgvActionService>().GetNext(_lastStepId); //下一步
|
||||
}
|
||||
task.CountCmd = SettingProvider.Instance.CountCmd + 1; //下一个计数
|
||||
task.StepId = (sbyte)nextStepId;
|
||||
return task;
|
||||
}
|
||||
|
||||
public TaskEntity MakeManualTask(TaskEntity taskEn, TCavityInfo src, TCavityInfo desc)
|
||||
{
|
||||
taskEn.FromStationNumber = src.StationNumber;
|
||||
taskEn.FromRow = src.Layer;
|
||||
taskEn.FromColumn = src.Column;
|
||||
taskEn.ToStationNumber = desc.StationNumber;
|
||||
taskEn.ToRow = desc.Layer;
|
||||
taskEn.ToColumn = desc.Column;
|
||||
return taskEn;
|
||||
}
|
||||
|
||||
public bool SendTask(TaskEntity task, string json)
|
||||
{
|
||||
LogHelper.Instance.Info($"发送任务开始");
|
||||
List<AddrValue> makeAddrValues = new List<AddrValue>();
|
||||
dynamic d = JsonConvert.DeserializeObject<dynamic>(json);
|
||||
string fromStation = d.FromStation;
|
||||
string fromLayer = d.FromRow;
|
||||
string fromColumn = d.FromColumn;
|
||||
string toStation = d.ToStation;
|
||||
string toLayer = d.ToRow;
|
||||
string toColumn = d.ToColumn;
|
||||
string cmd = d.Cmd;
|
||||
string countAddr = d.Count;
|
||||
|
||||
makeAddrValues.Add(new AddrValue()
|
||||
{
|
||||
Addr = fromStation,
|
||||
Value = (int)task.FromStationNumber,
|
||||
});
|
||||
|
||||
var from = _station.Where(p => p.Id == (int)task.FromStationNumber).FirstOrDefault();
|
||||
if (from.Type == (int)EStationType.Loading
|
||||
|| from.Type == (int)EStationType.UnLoading)
|
||||
{
|
||||
makeAddrValues.Add(new AddrValue()
|
||||
{
|
||||
Addr = fromLayer,
|
||||
Value = (int)task.FromRow,
|
||||
});
|
||||
|
||||
makeAddrValues.Add(new AddrValue()
|
||||
{
|
||||
Addr = fromColumn,
|
||||
Value = (int)task.FromColumn,
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
makeAddrValues.Add(new AddrValue()
|
||||
{
|
||||
Addr = fromLayer,
|
||||
Value = (int)task.FromColumn,
|
||||
});
|
||||
|
||||
makeAddrValues.Add(new AddrValue()
|
||||
{
|
||||
Addr = fromColumn,
|
||||
Value = (int)task.FromRow,
|
||||
});
|
||||
}
|
||||
|
||||
makeAddrValues.Add(new AddrValue()
|
||||
{
|
||||
Addr = toStation,
|
||||
Value = (int)task.ToStationNumber,
|
||||
});
|
||||
var to = _station.Where(p => p.Id == (int)task.ToStationNumber).FirstOrDefault();
|
||||
if (to.Type == (int)EStationType.Loading
|
||||
|| to.Type == (int)EStationType.UnLoading)
|
||||
{
|
||||
makeAddrValues.Add(new AddrValue()
|
||||
{
|
||||
Addr = toLayer,
|
||||
Value = (int)task.ToRow,
|
||||
});
|
||||
|
||||
makeAddrValues.Add(new AddrValue()
|
||||
{
|
||||
Addr = toColumn,
|
||||
Value = (int)task.ToColumn,
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
makeAddrValues.Add(new AddrValue()
|
||||
{
|
||||
Addr = toLayer,
|
||||
Value = (int)task.ToColumn,
|
||||
});
|
||||
|
||||
makeAddrValues.Add(new AddrValue()
|
||||
{
|
||||
Addr = toColumn,
|
||||
Value = (int)task.ToRow,
|
||||
});
|
||||
}
|
||||
|
||||
makeAddrValues.Add(new AddrValue()
|
||||
{
|
||||
Addr = cmd,
|
||||
Value = (Int16)task.StepId,
|
||||
});
|
||||
|
||||
//makeAddrValues.Add(new AddrValue()
|
||||
//{
|
||||
// Addr = countAddr,
|
||||
// Value = (Int16)task.CountCmd, //必须最后一个写
|
||||
//});
|
||||
|
||||
OperateResult result = agv.Writes(makeAddrValues.Select(x => x.Addr).ToArray(), makeAddrValues.Select(x => x.Value).ToArray());
|
||||
if (!result.IsSuccess)
|
||||
{
|
||||
LogHelper.Instance.Fatal($"写任务步骤失败:{JsonConvert.SerializeObject(makeAddrValues)},{JsonConvert.SerializeObject(makeAddrValues)}");
|
||||
}
|
||||
|
||||
result = agv.Write<Int16>(countAddr, (Int16)task.CountCmd);
|
||||
if (!result.IsSuccess)
|
||||
{
|
||||
LogHelper.Instance.Fatal($"写任务计数失败:{JsonConvert.SerializeObject(makeAddrValues)},{JsonConvert.SerializeObject(makeAddrValues)}");
|
||||
}
|
||||
|
||||
LogHelper.Instance.Debug($"发送任务:{JsonConvert.SerializeObject(makeAddrValues)}");
|
||||
LogHelper.Instance.Debug($"发送计数:{countAddr}:{(Int16)task.CountCmd}");
|
||||
//_unityContainer.Resolve<LogService>().AddLog("TaskStation:SendTask:发送任务结束", E_LogType.Info.ToString());
|
||||
return result.IsSuccess;
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
// 在需要取消任务的时候,调用以下代码:
|
||||
cts.Cancel();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
225
Cowain.Bake.Main/Station/TrigStation.cs
Normal file
@@ -0,0 +1,225 @@
|
||||
using Cowain.Bake.Common;
|
||||
using Cowain.Bake.Common.Core;
|
||||
using Cowain.Bake.Common.Interface;
|
||||
using Cowain.Bake.Communication.PLC;
|
||||
using Cowain.Bake.Main.ViewModels;
|
||||
using Cowain.Bake.Model.Models;
|
||||
using Newtonsoft.Json;
|
||||
using Opc.Ua;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Unity;
|
||||
|
||||
namespace Cowain.Bake.Main.Station
|
||||
{
|
||||
public class TrigStation : ITrigService
|
||||
{
|
||||
IUnityContainer _unityContainer;
|
||||
readonly CancellationTokenSource cts = new CancellationTokenSource();
|
||||
public TrigStation(IUnityContainer unityContainer)
|
||||
{
|
||||
_unityContainer = unityContainer;
|
||||
//怕消息先后导致异常,所以只能单个去
|
||||
//for (int i = 0; i < 3; i++) //还有心跳,就放开这个功能
|
||||
{
|
||||
Start();
|
||||
}
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
Task.Run( () =>
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (Global.AppExit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
BlockData item = _unityContainer.Resolve<PLCBlockingCollection>().MsgBlock.Take();
|
||||
int msgCount = _unityContainer.Resolve<PLCBlockingCollection>().MsgBlock.Count;
|
||||
if ("Heart" == item.Node.ParamName) //消息队列太多,就删除心跳
|
||||
{
|
||||
if (msgCount >= 5)
|
||||
{
|
||||
LogHelper.Instance.Error($"----------消费者消息数:{msgCount}");
|
||||
continue;
|
||||
}
|
||||
|
||||
Task.Run(() => ExecuteHeartTask(item.Data, item.Node));
|
||||
}
|
||||
else
|
||||
{
|
||||
RecvTrigInfo(item.Data, item.Node);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void ExecuteHeartTask(DataValue data, Variable node)
|
||||
{
|
||||
RecvTrigInfo(data, node);
|
||||
}
|
||||
//多线程处理
|
||||
public void RecvTrigInfo(DataValue data, Variable node)
|
||||
{
|
||||
int value = 0;
|
||||
dynamic d = JsonConvert.DeserializeObject<dynamic>(node.TrigJson);
|
||||
string service = d.Service;
|
||||
string func = d.Func;
|
||||
string trigValue = d.TrigValue;
|
||||
string param = d.Param; //方法的参数,如果是扫码,则是扫码的编号
|
||||
MethodInfo mi = null;
|
||||
|
||||
if (string.IsNullOrEmpty(service)
|
||||
|| string.IsNullOrEmpty(func))
|
||||
{
|
||||
LogHelper.Instance.Error("解析触发信号信息失败!解析内容:" + node.TrigJson);
|
||||
return;
|
||||
}
|
||||
|
||||
Type type = Type.GetType(MyPath.SIGNAL_TRIGGER + service);
|
||||
|
||||
if (!string.IsNullOrEmpty(trigValue))
|
||||
{
|
||||
value = GetTrigValue(data);
|
||||
|
||||
if (data.Value.GetType().IsArray)
|
||||
{
|
||||
if (value == 0) //节点的值跟所触发的信号相同(6098,扫码是数组)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (value != int.Parse(trigValue)) //节点值
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//LogHelper.Instance.Info($"5--------------信号,线程ID:{System.Threading.Thread.CurrentThread.ManagedThreadId},{node.VarDesc}:{param},func:{func},value:{value},{node.Json}"); //执行到这,信号都会丢,
|
||||
|
||||
_unityContainer.Resolve<BasicInfoViewModel>().SetEvent("开始:" + node.VarDesc);
|
||||
mi = this.GetType().GetMethod(ReflexFun.TRIG_REPLY).MakeGenericMethod(new Type[] { type }); //回复信息;
|
||||
mi.Invoke(this, new object[]
|
||||
{
|
||||
func,
|
||||
value,
|
||||
param,
|
||||
node
|
||||
});
|
||||
//_unityContainer.Resolve<BasicInfoViewModel>().SetEvent("结束0:" + node.VarDesc);
|
||||
}
|
||||
else
|
||||
{
|
||||
mi = this.GetType().GetMethod(ReflexFun.TRIG_INSTANCE).MakeGenericMethod(new Type[] { type }); //夹具信号,报警这些;
|
||||
mi.Invoke(this, new object[]
|
||||
{
|
||||
func,
|
||||
data,
|
||||
node
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void TrigInstance<T>(string func, DataValue data, Variable node)
|
||||
{
|
||||
//取得实例
|
||||
var instnce = _unityContainer.Resolve<T>();
|
||||
Type t = instnce.GetType();
|
||||
//取得方法
|
||||
MethodInfo mi = t.GetMethod(func);
|
||||
//调用方法
|
||||
mi.Invoke(instnce, new object[]
|
||||
{
|
||||
data,
|
||||
node
|
||||
});
|
||||
}
|
||||
|
||||
public void TrigReply<T>(string func, int curValue, string param, Variable node)
|
||||
{
|
||||
//取得实例
|
||||
var instnce = _unityContainer.Resolve<T>(); //上下料实例
|
||||
Type t = instnce.GetType();
|
||||
|
||||
//取得方法
|
||||
MethodInfo mi = t.GetMethod(func);
|
||||
//调用方法
|
||||
mi.Invoke(instnce, new object[]
|
||||
{
|
||||
curValue,
|
||||
param,
|
||||
node
|
||||
});
|
||||
}
|
||||
|
||||
private int GetTrigValue(DataValue data)
|
||||
{
|
||||
int value = 0;
|
||||
if (data.WrappedValue.TypeInfo.ValueRank == 1) //数组
|
||||
{
|
||||
if (data.WrappedValue.TypeInfo.BuiltInType == Opc.Ua.BuiltInType.Boolean) //下料扫码
|
||||
{
|
||||
bool[] values = (bool[])data.Value;
|
||||
for (int i = 0; i < values.Count(); i++)
|
||||
{
|
||||
if (values[i])
|
||||
{
|
||||
double temp = Math.Pow(2, i); //o
|
||||
value += (int)temp;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else //上料扫码
|
||||
{
|
||||
Int16[] values = (Int16[])data.Value;
|
||||
for (int i = 0; i < values.Count(); i++)
|
||||
{
|
||||
double temp = values[i] * Math.Pow(2, i); //ok
|
||||
value += (int)temp;
|
||||
}
|
||||
LogHelper.Instance.Fatal($"接收扫码信号:{string.Join(",", values)},{value}");
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (data.WrappedValue.TypeInfo.BuiltInType == Opc.Ua.BuiltInType.UInt16)
|
||||
{
|
||||
value = (UInt16)data.WrappedValue.Value;
|
||||
}
|
||||
else if (data.WrappedValue.TypeInfo.BuiltInType == Opc.Ua.BuiltInType.Int16)
|
||||
{
|
||||
value = (Int16)data.WrappedValue.Value;
|
||||
}
|
||||
else if (data.WrappedValue.TypeInfo.BuiltInType == Opc.Ua.BuiltInType.Int32)
|
||||
{
|
||||
value = (Int32)data.WrappedValue.Value;
|
||||
}
|
||||
else if (data.WrappedValue.TypeInfo.BuiltInType == Opc.Ua.BuiltInType.UInt32)
|
||||
{
|
||||
value = (int)data.WrappedValue.Value;
|
||||
}
|
||||
else if (data.WrappedValue.TypeInfo.BuiltInType == Opc.Ua.BuiltInType.Boolean)
|
||||
{
|
||||
value = ((bool)data.WrappedValue.Value) ? 1 : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
value = (int)data.WrappedValue.Value;
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
772
Cowain.Bake.Main/Station/UnLoadingStation.cs
Normal file
@@ -0,0 +1,772 @@
|
||||
using Cowain.Bake.BLL;
|
||||
using Cowain.Bake.Common;
|
||||
using Cowain.Bake.Common.Core;
|
||||
using Cowain.Bake.Common.Enums;
|
||||
using Cowain.Bake.Common.Interface;
|
||||
using Cowain.Bake.Common.Models;
|
||||
using Cowain.Bake.Communication.Interface;
|
||||
using Cowain.Bake.Communication.MOM;
|
||||
using Cowain.Bake.Main.ViewModels;
|
||||
using Cowain.Bake.Main.Views;
|
||||
using Cowain.Bake.Model;
|
||||
using Cowain.Bake.Model.Entity;
|
||||
using Cowain.Bake.Model.Models;
|
||||
using Cowain.Bake.UI.CsvMap;
|
||||
using HslCommunication;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using Unity;
|
||||
using static Cowain.Bake.Common.Models.MESModel;
|
||||
using JSON = Newtonsoft.Json.JsonConvert;
|
||||
|
||||
namespace Cowain.Bake.Main.Station
|
||||
{
|
||||
public class UnLoadingStation : IServerManager
|
||||
{
|
||||
IPLCDevice PLC { get; set; }
|
||||
const int DUMMY_POS_SIZE = 3;
|
||||
private int _batteryCodeLen = 0;
|
||||
List<IScanCodeBase> _deviceScann = new List<IScanCodeBase>();
|
||||
List<TBatteryInfo> _tempList = new List<TBatteryInfo>();
|
||||
public string Name { get; set; }
|
||||
public IUnityContainer _unityContainer { get; set; }
|
||||
private readonly Prism.Events.IEventAggregator _eventAggregator;
|
||||
public UnLoadingStation(IUnityContainer unityContainer, Prism.Events.IEventAggregator eventAggregator)
|
||||
{
|
||||
_unityContainer = unityContainer;
|
||||
_eventAggregator = eventAggregator;
|
||||
TDeviceConfig config = _unityContainer.Resolve<DeviceConfigService>().GetConfig(EDeviceType.PLC, EDeviceName.Loading)[0]; //上下料一个PLC
|
||||
Name = config.Name;
|
||||
SetBatteryCodeLen();
|
||||
Start();
|
||||
}
|
||||
|
||||
bool IsConnectPLC()
|
||||
{
|
||||
if (null == PLC || !PLC.IsConnect)
|
||||
{
|
||||
LogHelper.Instance.Error($"PalletVirtualId:{PLC.Name},PLC为空!");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public void Start()
|
||||
{
|
||||
var configScann = _unityContainer.Resolve<DeviceConfigService>().GetConfig(EDeviceType.SCANNER).OrderByDescending(x => x.Id).Take(8).ToList();
|
||||
foreach (var item in configScann)
|
||||
{
|
||||
IScanCodeBase device = _unityContainer.Resolve<IScanCodeBase>(item.Name);
|
||||
_deviceScann.Add(device);
|
||||
}
|
||||
|
||||
PLC = _unityContainer.Resolve<IPLCDevice>(Name); //下料PLC
|
||||
System.Threading.Tasks.Task.Run(() => BuildRecordFile());
|
||||
}
|
||||
|
||||
void BuildRecordFile()
|
||||
{
|
||||
string dateFile = "";
|
||||
string filePath = "";
|
||||
string path = _unityContainer.Resolve<SysSetupService>().GetValueByParaID(ESysSetup.DataFilePath.ToString());//
|
||||
path += "\\出站";
|
||||
while (true)
|
||||
{
|
||||
Thread.Sleep(1000 * 60);
|
||||
|
||||
if (!Directory.Exists(path))
|
||||
{
|
||||
Directory.CreateDirectory(path);
|
||||
}
|
||||
|
||||
dateFile = DateTime.Now.ToString("yyyyMMdd");
|
||||
filePath = path + $"\\{dateFile}.csv";
|
||||
var batteryList = _unityContainer.Resolve<BatteryInfoService>().GetOutbound();
|
||||
|
||||
if (null == batteryList)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
CSVHelper.WriteMap<BatteryInfoEntity, BatteryInfoDetailMap>(batteryList, filePath);
|
||||
foreach (var item in batteryList)
|
||||
{
|
||||
if (0 == _unityContainer.Resolve<BatteryInfoService>().UpdateStatus(item.Id, (int)EBatteryStatus.OutBoundRecord))
|
||||
{
|
||||
LogHelper.Instance.Fatal("修改记录出站状态失败!");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Instance.Fatal($"BuildRecordFile:{ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
void SetDummyToWaterPlatform(string param)
|
||||
{
|
||||
int number = int.Parse(param);
|
||||
int palletId = _unityContainer.Resolve<CavityInfoService>().GetPalletId((int)EStationType.UnLoading, number);
|
||||
_unityContainer.Resolve<BLL.BatteryInfoService>().SetDummyToWaterPlatform(palletId);
|
||||
}
|
||||
|
||||
//开始下料 ,,验证数据库OK (分二次执行,一次取假电芯,一次取正常电芯)
|
||||
public void ExecuteUnLoading(int curValue, string param, Variable node)
|
||||
{
|
||||
//Int16 batteryType = 1; //1:假电芯, 0:正常电芯
|
||||
dynamic d = JsonConvert.DeserializeObject<dynamic>(node.Json);
|
||||
|
||||
if (!IsConnectPLC()) return;
|
||||
|
||||
try
|
||||
{
|
||||
if (GetUnloadBattery(param, node.Json, out bool isUnLodingDummy, out TPalletInfo palletInfo))
|
||||
{
|
||||
_unityContainer.Resolve<LogService>().AddLog("ExecuteUnLoading:下料写入托盘电池信息!", E_LogType.Info.ToString());
|
||||
WriteBatteryPostionToPLC(palletInfo, node.Json, isUnLodingDummy);
|
||||
}
|
||||
else
|
||||
{
|
||||
//SetEmptyPallet(node.Json); //如果上料中写了下料电芯数据,此时再重启上位机,状态为“下料中”,会清除,所以注释
|
||||
}
|
||||
|
||||
var writeResult = PLC.Write<Int16>((string)d.WriteResult, 1);
|
||||
if (!writeResult.IsSuccess)
|
||||
{
|
||||
LogHelper.Instance.Error($"ExecuteScanPallet-写数据失败:{(string)d.WriteResult}:{writeResult.Message}");
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Instance.Error($"ExecuteUnLoading,出错,{ex.Message},param{param},{node.Json}");
|
||||
}
|
||||
_unityContainer.Resolve<BasicInfoViewModel>().SetEvent("结束:" + node.VarDesc);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 结果数据上传到MOM,烘烤开始时间,烘烤结束时间,烘烤温度,真空值,出炉冷却后温度
|
||||
/// </summary>BakingOutputCmd,MESReturnCmdModel
|
||||
/// <param name="batterys"></param>
|
||||
/// <param name="palletInfo"></param>
|
||||
public MESReturnCmdModel MesOutUnBinding(TPalletInfo palletInfo, List<TBatteryInfo> betterys, bool realTimeSend = false)
|
||||
{
|
||||
if (0 == palletInfo.BakingPosition.Value)
|
||||
{
|
||||
palletInfo.BakingPosition = 1; //防呆
|
||||
LogHelper.Instance.Error("手动触发烘烤完成,没有烘烤位置!");
|
||||
}
|
||||
|
||||
TCavityInfo cavityInfo = _unityContainer.Resolve<CavityInfoService>().GetStationDetailById(palletInfo.BakingPosition.Value);
|
||||
if (null == cavityInfo)
|
||||
{
|
||||
LogHelper.Instance.GetCurrentClassError("通过烘烤位置查找托盘位置失败");
|
||||
return null;
|
||||
}
|
||||
|
||||
return _unityContainer.Resolve<MESProcess>().MESBakingOutput(cavityInfo.Name, palletInfo, betterys, true, realTimeSend);
|
||||
}
|
||||
|
||||
//请求下料,出现异常处理
|
||||
TPalletInfo DealStartUnloadFail(int number)
|
||||
{
|
||||
//去机器人上获取夹具信息,此时没有转移。
|
||||
TPalletInfo palletInfo = _unityContainer.Resolve<BLL.PalletInfoService>().GetRobotPallet();
|
||||
if (null != palletInfo)
|
||||
{
|
||||
LogHelper.Instance.Error("请求下料的夹具在机器人上面!");
|
||||
return palletInfo;
|
||||
}
|
||||
|
||||
//如果还没有,再到下料获取。
|
||||
int palletId = _unityContainer.Resolve<CavityInfoService>().GetPalletId((int)EStationType.UnLoading, number);
|
||||
return _unityContainer.Resolve<BLL.PalletInfoService>().GetPalletInfo(palletId);
|
||||
}
|
||||
private bool GetUnloadBattery(string param, string reply, out bool isUnLodingDummy, out TPalletInfo palletInfo)
|
||||
{
|
||||
isUnLodingDummy = false;
|
||||
dynamic d = JsonConvert.DeserializeObject<dynamic>(reply);
|
||||
OperateResult operateResultX = null, operateResultY = null;
|
||||
OperateResult operateResult = null;
|
||||
List<TBatteryInfo> batterys = null;
|
||||
TBatteryInfo dummy;
|
||||
Int16 batteryType = 1; //1:假电芯, 0:正常电芯
|
||||
int number = int.Parse(param);
|
||||
Int16[] dummyPos = new Int16[DUMMY_POS_SIZE];
|
||||
int[] batteryVirtualId = new int[Global.PALLET_MAX_BATTERYS];
|
||||
Array.Clear(batteryVirtualId, 0, Global.PALLET_MAX_BATTERYS);
|
||||
|
||||
int palletId = _unityContainer.Resolve<CavityInfoService>().GetPalletId((int)EStationType.UnLoading, number);
|
||||
palletInfo = _unityContainer.Resolve<BLL.PalletInfoService>().GetPalletInfo(palletId);
|
||||
//要求PLC必须在上位机反馈任务完成之后再请求托盘参数
|
||||
|
||||
if (null == palletInfo) //会出现异常(发触发下料,再告诉上位机放)
|
||||
{
|
||||
palletInfo = DealStartUnloadFail(number);
|
||||
if (null == palletInfo) //
|
||||
{
|
||||
LogHelper.Instance.Error($"接收到下料信号,但获取不到下料工站{param}的夹具信息!", true);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
batterys = _unityContainer.Resolve<BLL.BatteryInfoService>().GetBatteryInfos(palletInfo.VirtualId);
|
||||
|
||||
if (0 == batterys.Count)
|
||||
{
|
||||
_unityContainer.Resolve<LogService>().AddLog($"下料工站{param},找不到电池位置数据!", E_LogType.Info.ToString());
|
||||
return false;
|
||||
}
|
||||
|
||||
//要满足下料条件
|
||||
if (palletInfo.PalletStatus != (int)EPalletStatus.BakeOver
|
||||
&& palletInfo.PalletStatus != (int)EPalletStatus.TestOK)
|
||||
{
|
||||
LogHelper.Instance.Fatal($"下料夹具状态不对,请人为处理,要求状态:{EPalletStatus.BakeOver.GetDescription()},{EPalletStatus.TestOK.GetDescription()},实际状态:" +
|
||||
$"{((EPalletStatus)palletInfo.PalletStatus).GetDescription()}");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (palletInfo.PalletStatus == (int)EPalletStatus.BakeOver
|
||||
&& _unityContainer.Resolve<BLL.BatteryInfoService>().IsPalletDummy(palletInfo.VirtualId)) //带水含量电芯,要测试
|
||||
{
|
||||
dummy = _unityContainer.Resolve<BLL.BatteryInfoService>().FindDummy(palletInfo, batterys);
|
||||
isUnLodingDummy = true;
|
||||
if (null == dummy)
|
||||
{
|
||||
LogHelper.Instance.Fatal("获取假电芯信息失败!");
|
||||
return false;
|
||||
}
|
||||
dummyPos[1] = (Int16)dummy.PositionX.Value;
|
||||
dummyPos[2] = (Int16)dummy.PositionY.Value;
|
||||
operateResultX = PLC.Write<Int16>((string)d.WriteDummyX, dummyPos[1]); //托盘假电池行列数
|
||||
operateResultY = PLC.Write<Int16>((string)d.WriteDummyY, dummyPos[2]); //托盘假电池行列数
|
||||
if (!operateResultX.IsSuccess
|
||||
|| !operateResultY.IsSuccess)
|
||||
{
|
||||
LogHelper.Instance.Debug($"设置托盘假电池行列数失败:{operateResultX.Message},{operateResultY.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
batteryType = 0; //正常电芯
|
||||
_unityContainer.Resolve<BLL.PalletInfoService>().UpdateUnLoadingBegingTime(palletInfo.Id);
|
||||
List<TBatteryInfo> normalBatterys = (from b in batterys
|
||||
where b.BatteryStatus <= (int)EBatteryStatus.ToPallet
|
||||
select b).ToList();
|
||||
if (Global.PALLET_ROWS < Global.PALLET_COLS) //7行,24列:行少列多
|
||||
{
|
||||
foreach (var item in normalBatterys)
|
||||
{
|
||||
batteryVirtualId[(item.PositionX.Value - 1) * Global.PALLET_COLS + item.PositionY.Value] = item.Id;
|
||||
}
|
||||
}
|
||||
else//48行,2列,: 行少列多
|
||||
{
|
||||
foreach (var item in normalBatterys)
|
||||
{
|
||||
batteryVirtualId[(item.PositionY.Value - 1) * Global.PALLET_ROWS + item.PositionX.Value] = item.Id;
|
||||
}
|
||||
}
|
||||
|
||||
LogHelper.Instance.Info("下料写入电芯位置:" + JSON.SerializeObject(batteryVirtualId));
|
||||
}
|
||||
//水含量电芯时,全为0
|
||||
operateResult = PLC.Write<int[]>((string)d.WriteVirtualIds, batteryVirtualId); //托盘_有无电池[1-120]
|
||||
if (!operateResult.IsSuccess)
|
||||
{
|
||||
LogHelper.Instance.Error($"设置托盘_有无电池失败:{operateResult.Message}");
|
||||
}
|
||||
|
||||
//电芯类型
|
||||
operateResult = PLC.Write<Int16>((string)d.WriteType, batteryType); //托盘1正常电芯下料
|
||||
if (!operateResult.IsSuccess)
|
||||
{
|
||||
LogHelper.Instance.Error($"写下料电芯类型失败:{(string)d.WriteType},{operateResult.Message}");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
//写下料位置的电池位置信息给PLC
|
||||
private void WriteBatteryPostionToPLC(TPalletInfo palletInfo, string reply, bool isUnLodingDummy)
|
||||
{
|
||||
Int16 lastValue = 0;
|
||||
dynamic d = JsonConvert.DeserializeObject<dynamic>(reply);
|
||||
OperateResult operateResult = null;
|
||||
|
||||
|
||||
|
||||
////水含量电芯时,全为0
|
||||
//operateResult = PLC.Write<int[]>((string)d.WriteVirtualIds, batteryVirtualId); //托盘_有无电池[1-120]
|
||||
//if (!operateResult.IsSuccess)
|
||||
//{
|
||||
// LogHelper.Instance.Error($"设置托盘_有无电池失败:{operateResult.Message}");
|
||||
//}
|
||||
if (!isUnLodingDummy)
|
||||
{
|
||||
lastValue = (Int16)(palletInfo.LastFlag ? 1 : 0);
|
||||
}
|
||||
|
||||
operateResult = PLC.Write<Int16>((string)d.WriteLastFlag, lastValue); //最后一盘
|
||||
if (!operateResult.IsSuccess)
|
||||
{
|
||||
LogHelper.Instance.Error($"设置托盘最后一盘失败:{operateResult.Message},{operateResult.Message}");
|
||||
}
|
||||
|
||||
//在给下料参数成功之后,再更新托盘状态。
|
||||
if (0 == _unityContainer.Resolve<BLL.PalletInfoService>().UpdatePalletStatus(palletInfo.Id, (int)EPalletStatus.Blank))
|
||||
{
|
||||
LogHelper.Instance.Error($"在给下料参数成功之后,再更新托盘状态:{operateResult.Message},{operateResult.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
public void SetEmptyPallet(string reply)
|
||||
{
|
||||
_unityContainer.Resolve<LogService>().AddLog("SetEmptyPallet:设置空托盘", E_LogType.Info.ToString());
|
||||
dynamic d = JsonConvert.DeserializeObject<dynamic>(reply);
|
||||
List<AddrValue> makeAddrValues = new List<AddrValue>();
|
||||
int[] batteryVirtualId = new int[Global.PALLET_MAX_BATTERYS];
|
||||
Array.Clear(batteryVirtualId, 0, Global.PALLET_MAX_BATTERYS);
|
||||
|
||||
makeAddrValues.Add(new AddrValue()
|
||||
{
|
||||
Addr = (string)d.WriteDummyX,
|
||||
Value = (Int16)0
|
||||
});
|
||||
|
||||
makeAddrValues.Add(new AddrValue()
|
||||
{
|
||||
Addr = (string)d.WriteDummyY,
|
||||
Value = (Int16)0
|
||||
});
|
||||
|
||||
makeAddrValues.Add(new AddrValue()
|
||||
{
|
||||
Addr = (string)d.WriteType,
|
||||
Value = (Int16)0
|
||||
});
|
||||
|
||||
makeAddrValues.Add(new AddrValue()
|
||||
{
|
||||
Addr = (string)d.WriteVirtualIds,
|
||||
Value = batteryVirtualId
|
||||
});
|
||||
|
||||
makeAddrValues.Add(new AddrValue()
|
||||
{
|
||||
Addr = (string)d.WriteResult,
|
||||
Value = true
|
||||
});
|
||||
|
||||
OperateResult result = PLC.Writes(makeAddrValues.Select(x => x.Addr).ToArray(), makeAddrValues.Select(x => x.Value).ToArray());
|
||||
|
||||
if (!result.IsSuccess)
|
||||
{
|
||||
LogHelper.Instance.GetCurrentClassError("清空托盘失败!");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void ExecuteUnLoadingFinish(int curValue, string param, Variable node)
|
||||
{
|
||||
dynamic d = JsonConvert.DeserializeObject<dynamic>(node.Json);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
int debugMode = int.Parse(_unityContainer.Resolve<SysSetupService>().GetValueByParaID(ESysSetup.DebugMode.ToString())); //0为测试模式,1为正式模式
|
||||
|
||||
if (!IsConnectPLC()) return;
|
||||
|
||||
//得到这个工站的夹具,通过夹具得到电芯
|
||||
int number = int.Parse(param);
|
||||
int palletId = _unityContainer.Resolve<BLL.CavityInfoService>().GetPalletId((int)EStationType.UnLoading, number);
|
||||
TPalletInfo palletInfo = _unityContainer.Resolve<BLL.PalletInfoService>().GetPalletInfo(palletId);
|
||||
|
||||
if (null == palletInfo)
|
||||
{
|
||||
LogHelper.Instance.Error($"托盘为空, 下料{number}#工站,palletId:{palletId}");
|
||||
return;
|
||||
}
|
||||
|
||||
_unityContainer.Resolve<BLL.PalletInfoService>().UpdateUnLoadingOverTime(palletInfo.Id);
|
||||
|
||||
if (0 == palletInfo.VirtualId
|
||||
|| 1 == palletInfo.Id)
|
||||
{
|
||||
LogHelper.Instance.Error($"下料夹具异常, 下料托盘的虚拟码为0,或下料托盘为【新夹具】");
|
||||
}
|
||||
else
|
||||
{
|
||||
_unityContainer.Resolve<BLL.PalletInfoService>().PalletInfoToHistory(palletInfo.VirtualId,
|
||||
(int)EPalletStatus.BlankOver, (int)EBatteryStatus.Over, (int)EStationType.UnLoading, number);
|
||||
}
|
||||
|
||||
var writeResult = PLC.Write<Int16>((string)d.WriteResult, 1);
|
||||
if (!writeResult.IsSuccess)
|
||||
{
|
||||
LogHelper.Instance.Warn($"ExecuteUnLoadingFinish-{(string)d.WriteResult}:{writeResult.Message}");
|
||||
}
|
||||
_unityContainer.Resolve<BasicInfoViewModel>().SetEvent("结束:" + node.VarDesc);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 核对电芯条码,下料扫码
|
||||
/// </summary>
|
||||
//void VerifyBatteryCode(int curValue, string param, string reply)
|
||||
//{
|
||||
// dynamic d = JsonConvert.DeserializeObject<dynamic>(reply);
|
||||
// var result = DealVerify(reply);
|
||||
|
||||
// var writeResult = PLC.Write<bool[]>((string)d.WriteResult, result.Result);//
|
||||
// if (!writeResult.IsSuccess)
|
||||
// {
|
||||
// LogHelper.Instance.GetCurrentClassWarn($"{(string)d.WriteResult}:{writeResult.Message}");
|
||||
// }
|
||||
//}
|
||||
|
||||
//async Task<bool[]> DealVerify(string reply)
|
||||
//{
|
||||
// int index = 0, j = 0;
|
||||
// bool[] results = new bool[Global.ONCE_SCAN_BATTERY];
|
||||
// Array.Clear(results, 0, Global.ONCE_SCAN_BATTERY);
|
||||
// List<Task<OperateResult<string>>> scannTasks = new List<Task<OperateResult<string>>>();
|
||||
// dynamic d = JsonConvert.DeserializeObject<dynamic>(reply);
|
||||
// if (!IsConnectPLC()) return results;
|
||||
|
||||
// OperateResult<Int32[]> batterys = PLC.Read<Int32[]>((string)d.ReadVirtualIds); //下料处电芯虚拟码 读取下料温度[1..8]
|
||||
// if (!batterys.IsSuccess)
|
||||
// {
|
||||
// LogHelper.Instance.Warn($"核对电芯条码时,读取电芯虚拟码错误:{batterys.Message}");
|
||||
// return results;
|
||||
// }
|
||||
|
||||
// if (batterys.Content.All(x => x == 0)) //True 全部为0
|
||||
// {
|
||||
// LogHelper.Instance.Warn($"核对电芯条码时,读取电芯虚拟码异常,全部虚拟码都为0");
|
||||
// return results;
|
||||
// }
|
||||
|
||||
// //读条码
|
||||
// for (EScanCode s = EScanCode.UnLoadingBatteryScan1; s <= EScanCode.UnLoadingBatteryScan8; s++, index++)
|
||||
// {
|
||||
// if (0 == batterys.Content[index])
|
||||
// {
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// IScanCodeBase scanDevice = _deviceScann.Find(x => x.Name == s.ToString());
|
||||
|
||||
// if (!scanDevice.IsConnect)
|
||||
// {
|
||||
// string msg = $"获取{s.GetDescription()}失败,请检测线路!";
|
||||
// LogHelper.Instance.Error(msg, true); //弹屏,人为处理好后,再次触发
|
||||
// _unityContainer.Resolve<MainWindowViewModel>().AddPromptContent(msg);
|
||||
// scanDevice.Connect();
|
||||
// --s; //再次获取
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// scannTasks.Add(Task.Run(() => scanDevice.ReadCode())); // 启动并行任务
|
||||
// }
|
||||
|
||||
// await Task.WhenAll(scannTasks); //等待所有任务(扫码)完成
|
||||
// index = 0;
|
||||
// var batteryCodes = GetBatteryCode(batterys.Content);//获取PLC传过来的虚拟码
|
||||
|
||||
// //比较条码
|
||||
// for (EScanCode s = EScanCode.UnLoadingBatteryScan1; s <= EScanCode.UnLoadingBatteryScan8; s++, j++)
|
||||
// {
|
||||
// if (0 == batterys.Content[index])
|
||||
// {
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// if (!batteryCodes.Contains(scannTasks[index++].Result.Content)) //没有用等于号,是因为这样兼容更好一点
|
||||
// {
|
||||
// LogHelper.Instance.Warn($"下料核对电芯异常,PLC电芯:{string.Join(",", batteryCodes)},扫码电芯:{JSON.SerializeObject(scannTasks)}");
|
||||
// //continue; //异常
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// results[j] = true;
|
||||
// }
|
||||
// }
|
||||
// _unityContainer.Resolve<MainWindowViewModel>().DeletePromptContent();
|
||||
// return results;
|
||||
//}
|
||||
|
||||
//取假电芯完成,验证数据库OK
|
||||
public void ExecuteTakeDummyFinish(int curValue, string param, Variable node)
|
||||
{
|
||||
dynamic d = JsonConvert.DeserializeObject<dynamic>(node.Json);
|
||||
if (!IsConnectPLC()) return;
|
||||
_unityContainer.Resolve<LogService>().AddLog("UnLoadingStation:ExecuteTakeDummyFinish:取假电池开始:" + param, E_LogType.Info.ToString());
|
||||
int number = int.Parse(param);
|
||||
int palletId = _unityContainer.Resolve<BLL.CavityInfoService>().GetPalletId((int)EStationType.UnLoading, number);
|
||||
TPalletInfo palletInfo = _unityContainer.Resolve<BLL.PalletInfoService>().GetPalletInfo(palletId);
|
||||
|
||||
if (null == palletInfo)
|
||||
{
|
||||
LogHelper.Instance.Error($"接收下料{number}工站取假电芯完成信号,但获取不到下料夹具!", true);
|
||||
return;
|
||||
}
|
||||
|
||||
//这里再改假电芯状态
|
||||
SetDummyToWaterPlatform(param);
|
||||
|
||||
//重启后,可能再次收到1#托盘取假电池完成信号(待水含量测试),此时状态可能测试OK或NG
|
||||
if (palletInfo.PalletStatus == (int)EPalletStatus.BakeOver
|
||||
|| palletInfo.PalletStatus == (int)EPalletStatus.Blank) //取水含量电芯时,也是下料中状态
|
||||
{
|
||||
_unityContainer.Resolve<BLL.PalletInfoService>().UpdatePalletStatus(palletInfo.Id, (int)EPalletStatus.WaitTest);
|
||||
}
|
||||
|
||||
var writeResult = PLC.Write<Int16>((string)d.WriteResult, 1);
|
||||
if (!writeResult.IsSuccess)
|
||||
{
|
||||
LogHelper.Instance.Warn($"ExecuteTakeDummyFinish-{(string)d.WriteResult}:{writeResult.Message}");
|
||||
}
|
||||
_unityContainer.Resolve<BasicInfoViewModel>().SetEvent("结束:" + node.VarDesc);
|
||||
}
|
||||
|
||||
public void SetBatteryCodeLen()
|
||||
{
|
||||
_batteryCodeLen = int.Parse(_unityContainer.Resolve<Cowain.Bake.BLL.SysSetupService>().GetValueByParaID(ESysSetup.BatteryCodeLen.ToString()));
|
||||
}
|
||||
public async Task<List<OperateResult<string>>> GetScannResult(int curValue)
|
||||
{
|
||||
int index = 1;
|
||||
List<string> batteryCodes = new List<string>();
|
||||
List<OperateResult<string>> scannList = new List<OperateResult<string>>();
|
||||
List<Task<OperateResult<string>>> scannTasks = new List<Task<OperateResult<string>>>();
|
||||
|
||||
OperateResult<string> scanResult = new OperateResult<string>()
|
||||
{
|
||||
IsSuccess = false,
|
||||
};
|
||||
|
||||
for (EScanCode s = EScanCode.UnLoadingBatteryScan1; s <= EScanCode.UnLoadingBatteryScan8; s++, index++)
|
||||
{
|
||||
if (((curValue >> index) & 1) != 1) //第index位不是1,就是不需要扫码
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
IScanCodeBase scanDevice = _deviceScann.Find(x => x.Name == s.ToString());
|
||||
|
||||
if (!scanDevice.IsConnect)
|
||||
{
|
||||
string msg = $"获取{s.GetDescription()}失败,请检测线路!";
|
||||
LogHelper.Instance.Error(msg, true); //弹屏,人为处理好后,再次触发
|
||||
_unityContainer.Resolve<MainWindowViewModel>().AddPromptContent(msg);
|
||||
scanDevice.Connect();
|
||||
--s; //再次获取
|
||||
continue;
|
||||
}
|
||||
|
||||
scannTasks.Add(Task.Run(() => scanDevice.ReadCode())); // 启动并行任务
|
||||
}
|
||||
|
||||
await Task.WhenAll(scannTasks); //等待所有任务(扫码)完成
|
||||
foreach (var task in scannTasks)
|
||||
{
|
||||
scannList.Add(task.Result);
|
||||
}
|
||||
|
||||
return scannList;
|
||||
}
|
||||
|
||||
public async Task<bool[]> DealTemp(IPLCDevice plc, int curValue, string reply)
|
||||
{
|
||||
string msg = "";
|
||||
int index = 1;
|
||||
int scannIndex = 0;
|
||||
bool[] repResults = new bool[Global.ONCE_SCAN_BATTERY + 1];
|
||||
dynamic d = JsonConvert.DeserializeObject<dynamic>(reply);
|
||||
List<string> batteryCodes = null;
|
||||
List<OperateResult<string>> scannList;
|
||||
MESReturnCmdModel result = null;
|
||||
bool isDummy = false;
|
||||
Array.Clear(repResults, 0, Global.ONCE_SCAN_BATTERY + 1);
|
||||
int debugMode = int.Parse(_unityContainer.Resolve<SysSetupService>().GetValueByParaID(ESysSetup.DebugMode.ToString())); //0为测试模式,1为正式模式
|
||||
_tempList.Clear();
|
||||
try
|
||||
{
|
||||
if (!IsConnectPLC()) return null;
|
||||
|
||||
OperateResult<float[]> readTemps = plc.Read<float[]>((string)d.ReadTemp); //下料处电芯温度,读取下料温度[1..4]
|
||||
if (!readTemps.IsSuccess)
|
||||
{
|
||||
LogHelper.Instance.Warn("读取下料温度失败");
|
||||
return null;
|
||||
}
|
||||
|
||||
if ((int)EProductionMode.Debug == debugMode) //调试模式
|
||||
{
|
||||
repResults[1] = true;
|
||||
return repResults;
|
||||
}
|
||||
|
||||
scannList = await GetScannResult(curValue); //
|
||||
for (EScanCode s = EScanCode.UnLoadingBatteryScan1; s <= EScanCode.UnLoadingBatteryScan8; s++, index++)
|
||||
{
|
||||
if (((curValue >> index) & 1) != 1) //第index位不是1,就是不需要扫码
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
repResults[index] = true;
|
||||
|
||||
if (scannList[scannIndex].IsSuccess)
|
||||
{
|
||||
_tempList.Add(new TBatteryInfo()
|
||||
{
|
||||
BatteryCode = scannList[scannIndex].Content, //实际要扫码
|
||||
CoolTemp = readTemps.Content[index] //1...8排序
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
if (MessageBoxResult.Yes == HandyControl.Controls.MessageBox.Show($"[{s.GetDescription()}]扫码失败,您确定此位置是否有电芯?", "提示", MessageBoxButton.YesNo, MessageBoxImage.Information))
|
||||
{
|
||||
_tempList.Add(new TBatteryInfo()
|
||||
{
|
||||
BatteryCode = GetBatteryCode(s.GetDescription()), //弹屏,输入电芯条码
|
||||
CoolTemp = readTemps.Content[index] //1...8排序
|
||||
});
|
||||
}
|
||||
else //无电芯
|
||||
{
|
||||
repResults[index] = false; //扫码NG,并人为确认无电芯
|
||||
}
|
||||
}
|
||||
|
||||
scannIndex++;
|
||||
}
|
||||
|
||||
batteryCodes = _tempList.Select(x => x.BatteryCode).ToList();
|
||||
LogHelper.Instance.Info($"读取下料PLC的电芯虚拟码:{string.Join(",", batteryCodes)}");
|
||||
List<TBatteryInfo> currentBatterys = _unityContainer.Resolve<BatteryInfoService>().GetBatterys(batteryCodes); //8个电芯(最多),可能会来自多个托盘
|
||||
if (null == currentBatterys
|
||||
|| currentBatterys.Count == 0) //PLC有BUG,有时为0,导致上位机没办法回复,会PLC超时
|
||||
{
|
||||
msg = $"下发温度读取失败,{Global.ONCE_SCAN_BATTERY}个电池虚拟码为0!";
|
||||
LogHelper.Instance.Error("下发温度读取完成失败,电池虚拟码为0!");
|
||||
_unityContainer.Resolve<LogService>().AddLog("下发温度读取完成失败,电池虚拟码为0!", E_LogType.Fatal.ToString());
|
||||
_unityContainer.Resolve<MainWindowViewModel>().AddPromptContent(msg);
|
||||
return repResults;
|
||||
}
|
||||
else if (currentBatterys.Count == 1) //一个电芯,判断是否是假电芯
|
||||
{
|
||||
if (_unityContainer.Resolve<BatteryInfoService>().IsDummy(currentBatterys[0].Id))
|
||||
{
|
||||
isDummy = true;
|
||||
return repResults; //假电芯就不上传了
|
||||
}
|
||||
}
|
||||
|
||||
_unityContainer.Resolve<BatteryInfoService>().UpdateCoolTempAndUnBindingTime(currentBatterys, _tempList);// temps);
|
||||
if (int.Parse(_unityContainer.Resolve<SysSetupService>().GetValueByParaID(ESysSetup.MOMEnable.ToString())) == (int)EMOMEnable.Enable)
|
||||
{
|
||||
var batterySort = currentBatterys.GroupBy(p => new { p.PalletVirtualId }).Select(s => s.FirstOrDefault()).ToList(); //获取一个托盘中的一个电芯
|
||||
|
||||
foreach (var item in batterySort) //一个托盘只返回第一个电芯
|
||||
{
|
||||
var palletBatterys = currentBatterys.Where(x => batteryCodes.Contains(x.BatteryCode) && x.PalletVirtualId == item.PalletVirtualId).ToList(); //获取一个托盘中的电芯
|
||||
TPalletInfo palletInfo = _unityContainer.Resolve<BLL.PalletInfoService>().GetPalletInfoByBatteryVirtualId(item.PalletVirtualId); //此时托盘可能已经转历史盘托了
|
||||
|
||||
if (null == palletInfo)
|
||||
{
|
||||
msg = $"MOM上传冷却温度时,找不到电芯所在托盘,电芯:{string.Join(",", palletBatterys.Select(x => x.BatteryCode).ToList())}!";
|
||||
LogHelper.Instance.Fatal(msg);
|
||||
_unityContainer.Resolve<MainWindowViewModel>().AddPromptContent(msg);
|
||||
return null;
|
||||
}
|
||||
|
||||
var mesResult = MesOutUnBinding(palletInfo, palletBatterys);//组装数据 发送
|
||||
//因为没有等MOM,所以注掉下面代码
|
||||
//if (mesResult == null)
|
||||
//{
|
||||
// LogHelper.Instance.Error($"自动出站,MOM返回超时,电芯条码:{string.Join(",", palletBatterys.Select(x => x.BatteryCode).ToList())}"); //偶尔会返回空,导致人为要处理,麻烦,所以只保存到日志
|
||||
//}
|
||||
//else if (mesResult.Info.ResultFlag.ToUpper() == "NG" && (!isDummy))
|
||||
//{
|
||||
// msg = $"自动出站,MOM返回信息异常,信息:{JSON.SerializeObject(result)}";
|
||||
// LogHelper.Instance.Error(msg);
|
||||
// _unityContainer.Resolve<MainWindowViewModel>().AddPromptContent(msg);
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// _unityContainer.Resolve<MainWindowViewModel>().DeletePromptContent();
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LogHelper.Instance.Fatal($"读温失败:{e.Message},{e.StackTrace}");
|
||||
}
|
||||
|
||||
return repResults;
|
||||
}
|
||||
|
||||
public string GetBatteryCode(string desc)
|
||||
{
|
||||
string batteryCode = "";
|
||||
while (string.IsNullOrEmpty(batteryCode))
|
||||
{
|
||||
Application.Current.Dispatcher.Invoke((Action)(() =>
|
||||
{
|
||||
PalletIdInputWindow f = new PalletIdInputWindow("电芯码输入框", $"{desc}扫码失败," + "请输入电芯条码", "确定输入电芯条码?")
|
||||
{
|
||||
WindowStartupLocation = System.Windows.WindowStartupLocation.CenterScreen,
|
||||
};
|
||||
f.ShowDialog();
|
||||
batteryCode = f.PalletId;
|
||||
}));
|
||||
|
||||
if (!_unityContainer.Resolve<BatteryInfoService>().IsBatteryCodeRepeat(batteryCode))
|
||||
{
|
||||
LogHelper.Instance.Error($"【{batteryCode}】,不存在,请重新输入!", true);
|
||||
batteryCode = "";
|
||||
}
|
||||
}
|
||||
return batteryCode;
|
||||
}
|
||||
//获取下料温度
|
||||
public async Task GetTemp(int curValue, string param, Variable node)
|
||||
{
|
||||
OperateResult operateResult = null;
|
||||
dynamic d = JsonConvert.DeserializeObject<dynamic>(node.Json);
|
||||
IPLCDevice plc = _unityContainer.Resolve<IPLCDevice>((string)d.PLCName); //上料PLC
|
||||
var result = await DealTemp(plc, curValue, node.Json);
|
||||
|
||||
if (result == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
operateResult = plc.Write<bool[]>((string)d.WriteResult, result); //MOM没有返回数据,导致
|
||||
if (!operateResult.IsSuccess)
|
||||
{
|
||||
LogHelper.Instance.Error("下发温度读取完成失败!");
|
||||
return;
|
||||
}
|
||||
|
||||
_unityContainer.Resolve<BasicInfoViewModel>().SetEvent("结束:" + node.VarDesc);
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
200
Cowain.Bake.Main/Station/UpdateStation.cs
Normal file
@@ -0,0 +1,200 @@
|
||||
using Cowain.Bake.BLL;
|
||||
using Cowain.Bake.Common;
|
||||
using Cowain.Bake.Common.Core;
|
||||
using Cowain.Bake.Common.Enums;
|
||||
using Cowain.Bake.Common.Interface;
|
||||
using Cowain.Bake.Communication.Interface;
|
||||
using Cowain.Bake.Model.Models;
|
||||
using Newtonsoft.Json;
|
||||
using Opc.Ua;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Linq;
|
||||
using Unity;
|
||||
|
||||
namespace Cowain.Bake.Main.Station
|
||||
{
|
||||
public class UpdateStation : IServerManager
|
||||
{
|
||||
readonly ConcurrentDictionary<int, bool[]> _stovePalletSignal;
|
||||
public string Name { get; set; }
|
||||
|
||||
public IUnityContainer _unityContainer { get; set; }
|
||||
|
||||
|
||||
public UpdateStation(IUnityContainer unityContainer)
|
||||
{
|
||||
_unityContainer = unityContainer;
|
||||
_stovePalletSignal = new ConcurrentDictionary<int, bool[]>();
|
||||
}
|
||||
bool IsConnectPLC(IPLCDevice PLC)
|
||||
{
|
||||
if (null == PLC || !PLC.IsConnect)
|
||||
{
|
||||
LogHelper.Instance.GetCurrentClassError($"连接PLC失败:{PLC.Name},PLC为空!");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//LifeCycle PLC请求命令:0=无意义;10=无托盘;20=有托盘
|
||||
public int UpdateCavityStatus(DataValue data, Variable node)
|
||||
{
|
||||
Int16 signalValue = 0;
|
||||
Int16 result = (Int16)EResult.OK; //1=OK,2=重新上传
|
||||
dynamic d = JsonConvert.DeserializeObject<dynamic>(node.TrigJson); //生命周期
|
||||
dynamic reply = JsonConvert.DeserializeObject<dynamic>(node.Json); //反馈收到PLC的周期信号,反馈PLC的命令,0也要反馈,1=OK,2=重新上传
|
||||
|
||||
var config = _unityContainer.Resolve<DeviceConfigService>().GetConfig(node.StationId);
|
||||
IPLCDevice PLC = _unityContainer.Resolve<IPLCDevice>(config.Name);
|
||||
if (!IsConnectPLC(PLC)) return 0;
|
||||
|
||||
var countCavitySignal = PLC.GetValue<System.Int16>((string)d.CountCavitySignal, node.StationId, node.Number);
|
||||
if (!countCavitySignal.IsSuccess)
|
||||
{
|
||||
result = (Int16)EResult.NG;
|
||||
LogHelper.Instance.Error($"读取腔体的信号计数失败!原因:{countCavitySignal.Message}");
|
||||
}
|
||||
|
||||
if (data.WrappedValue.TypeInfo.BuiltInType == Opc.Ua.BuiltInType.Int16)
|
||||
{
|
||||
signalValue = (System.Int16)data.WrappedValue.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = (Int16)EResult.NG;
|
||||
LogHelper.Instance.Warn($"没有找到夹具信号这个数据类型,节点名为{node.VarDesc}");
|
||||
}
|
||||
|
||||
var writeResult = PLC.Write<Int16>(reply.CountCavitySignal, countCavitySignal.Content);
|
||||
if (!writeResult.IsSuccess)
|
||||
{
|
||||
LogHelper.Instance.GetCurrentClassWarn($"写腔体的信号计数失败,地址:{reply.CountCavitySignal},值:{countCavitySignal.Content},{writeResult.Message}");
|
||||
}
|
||||
|
||||
writeResult = PLC.Write<Int16>(reply.SignalValue, signalValue);
|
||||
if (!writeResult.IsSuccess)
|
||||
{
|
||||
LogHelper.Instance.GetCurrentClassWarn($"写腔体的信号失败,地址:{reply.SignalValue},值:{signalValue},{writeResult.Message}");
|
||||
}
|
||||
|
||||
writeResult = PLC.Write<Int16>(reply.CavitySignalResult, result);
|
||||
if (!writeResult.IsSuccess)
|
||||
{
|
||||
LogHelper.Instance.GetCurrentClassWarn($"写回复腔体的信号失败,地址:{reply.CavitySignalResult},值:{result},{writeResult.Message}");
|
||||
}
|
||||
|
||||
return _unityContainer.Resolve<CavityInfoService>().UpdateCavitySignal(node.StationId, node.Number, signalValue);
|
||||
}
|
||||
|
||||
public int UpdateDoorStatus(DataValue data, Variable node)
|
||||
{
|
||||
dynamic d = JsonConvert.DeserializeObject<dynamic>(node.TrigJson);
|
||||
string layer = d.Layer;
|
||||
bool status = false;
|
||||
|
||||
if (string.IsNullOrEmpty(layer))
|
||||
{
|
||||
LogHelper.Instance.Warn($"触发夹具到位信号,但获取相关信息失败{node.TrigJson}");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (data.WrappedValue.TypeInfo.BuiltInType == Opc.Ua.BuiltInType.Boolean)
|
||||
{
|
||||
status = (bool)data.WrappedValue.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogHelper.Instance.Warn($"没有找到开/关门这个数据类型,节点名为{node.VarDesc}");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!status)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (node.ParamName == EStoveSignal.OpenDoorPlace.ToString())
|
||||
{
|
||||
status = true;
|
||||
}
|
||||
|
||||
return _unityContainer.Resolve<CavityInfoService>().UpdateDoorStatus(node.StationId, int.Parse(layer), status);
|
||||
}
|
||||
|
||||
public int UpdateLoadStatus(DataValue data, Variable node)
|
||||
{
|
||||
dynamic d = JsonConvert.DeserializeObject<dynamic>(node.TrigJson);
|
||||
string layer = d.Layer;
|
||||
string number = d.Number;
|
||||
bool[] status = null;
|
||||
|
||||
if (data.WrappedValue.TypeInfo.ValueRank == 1) //数组,炉子夹具传感器信号
|
||||
{
|
||||
if (data.WrappedValue.TypeInfo.BuiltInType == Opc.Ua.BuiltInType.Boolean)
|
||||
{
|
||||
status = (bool[])data.WrappedValue.Value;
|
||||
}
|
||||
|
||||
if (_stovePalletSignal.TryGetValue(node.StationId, out bool[] oldValue)) //有
|
||||
{
|
||||
if (oldValue.Count() != status.Count())
|
||||
{
|
||||
LogHelper.Instance.Error($"烤箱到位信号老值与新值长度不匹配,工站:{node.StationId},desc:{string.Join(",", status)}");
|
||||
return 0;
|
||||
}
|
||||
|
||||
_stovePalletSignal[node.StationId] = status;
|
||||
var diffs = status.Zip(oldValue, (a, b) => a != b).Select((b, i) => new { Value = b, Index = i }).Where(x => x.Value);
|
||||
|
||||
foreach (var item in diffs)
|
||||
{
|
||||
if (0 == item.Index)
|
||||
{
|
||||
continue; //第一个不用
|
||||
}
|
||||
|
||||
int result = _unityContainer.Resolve<CavityInfoService>().UpdateLoadStatus(node.StationId, item.Index, 1, status[item.Index]);
|
||||
if (0 != result)
|
||||
{
|
||||
LogHelper.Instance.Warn($"修改状态数据失败,StationId:{node.StationId},layer:{item.Index},{status[item.Index]}");
|
||||
}
|
||||
}
|
||||
}
|
||||
else //重启时,更新所有信号
|
||||
{
|
||||
|
||||
|
||||
_stovePalletSignal[node.StationId] = status;
|
||||
for (int i = 1; i <= Global.STOVE_LAYERS; ++i) //上位机启动
|
||||
{
|
||||
int result = _unityContainer.Resolve<CavityInfoService>().UpdateLoadStatus(node.StationId, i, 1, status[i]);
|
||||
if (0 != result)
|
||||
{
|
||||
LogHelper.Instance.Warn($"修改状态数据失败,StationId:{node.StationId},layer:{i},{status[i]}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else //上下料和人工夹具平台
|
||||
{
|
||||
var value = (bool)data.WrappedValue.Value;
|
||||
int result = _unityContainer.Resolve<CavityInfoService>().UpdateLoadStatus(node.StationId, int.Parse(layer), int.Parse(number), value);
|
||||
if (0 != result)
|
||||
{
|
||||
LogHelper.Instance.Warn($"修改状态数据失败,StationId:{node.StationId},layer:{layer},{number},{value}");
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
public void Start()
|
||||
{
|
||||
|
||||
}
|
||||
public void Stop()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
227
Cowain.Bake.Main/Station/UploadMesStation.cs
Normal file
@@ -0,0 +1,227 @@
|
||||
using Cowain.Bake.BLL;
|
||||
using Cowain.Bake.Common;
|
||||
using Cowain.Bake.Common.Core;
|
||||
using Cowain.Bake.Common.Enums;
|
||||
using Cowain.Bake.Common.Models;
|
||||
using Cowain.Bake.Model;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using Unity;
|
||||
using JSON = Newtonsoft.Json.JsonConvert;
|
||||
using Cowain.Bake.Main.ViewModels;
|
||||
using static Cowain.Bake.Common.Models.MESModel;
|
||||
using Cowain.Bake.Communication.MOM;
|
||||
using Cowain.Bake.Model.Models;
|
||||
|
||||
namespace Cowain.Bake.Main.Station
|
||||
{
|
||||
//自动上传模块
|
||||
public class UploadMesStation
|
||||
{
|
||||
public bool? OrdeIsMesOnline { get; set; }
|
||||
public string Name { get; set; }
|
||||
public bool haveWarn = true;
|
||||
public string IpAddress { get; set; }
|
||||
public int Port { get; set; }
|
||||
public string URL { get; set; }
|
||||
public IUnityContainer _unityContainer { get; set; }
|
||||
public int Id { get; set; }
|
||||
List<ProceParamList> listParams = new List<ProceParamList>();
|
||||
private readonly Prism.Events.IEventAggregator _eventAggregator;
|
||||
public UploadMesStation(IUnityContainer unityContainer, Prism.Events.IEventAggregator eventAggregator)
|
||||
{
|
||||
bool IsMesOnline = false;
|
||||
_unityContainer = unityContainer;
|
||||
TDeviceConfig dev = _unityContainer.Resolve<DeviceConfigService>().GetConfig(EDeviceType.MOM)[0];
|
||||
Id = dev.Id;
|
||||
Name = dev.Name;
|
||||
_eventAggregator = eventAggregator;
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (Global.AppExit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
IsMesOnline = false;
|
||||
if (int.Parse(_unityContainer.Resolve<SysSetupService>().GetValueByParaID(ESysSetup.MOMEnable.ToString())) == (int)EMOMEnable.Enable)
|
||||
{
|
||||
MESReturnCmdModel mesResult = _unityContainer.Resolve<MESProcess>().Alive();
|
||||
IsMesOnline = DealAlive(mesResult);
|
||||
}
|
||||
|
||||
if (OrdeIsMesOnline != IsMesOnline)
|
||||
{
|
||||
;
|
||||
OrdeIsMesOnline = IsMesOnline;
|
||||
_unityContainer.Resolve<DeviceConfigService>().UpdateStatus(this.Id, IsMesOnline);
|
||||
_unityContainer.Resolve<BasicInfoViewModel>().MesStatus = IsMesOnline;
|
||||
}
|
||||
|
||||
await Task.Delay(5000); //放这里的目的,是心跳后,再执行上传
|
||||
}
|
||||
});
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
await Task.Delay(3000);
|
||||
if (Global.AppExit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (int.Parse(_unityContainer.Resolve<SysSetupService>().GetValueByParaID(ESysSetup.MOMEnable.ToString())) == (int)EMOMEnable.Enable)
|
||||
{
|
||||
Run();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//MOM在回复心跳时通过KeyFlag= 2提醒设备需要调用MOM的工艺参数下发接口
|
||||
//MOM在回复心跳时通过KeyFlag= 2提醒设备需要调用MOM的工艺参数下发接口
|
||||
bool DealAlive(MESReturnCmdModel mesResult)
|
||||
{
|
||||
if (null == mesResult)
|
||||
{
|
||||
LogHelper.Instance.Warn($"MES不在线:{JSON.SerializeObject(mesResult)}");
|
||||
return false;
|
||||
}
|
||||
|
||||
else if (((int)EKeyFlag.NG).ToString() == mesResult.Info.KeyFlag)
|
||||
{
|
||||
TAlarm model = new TAlarm()
|
||||
{
|
||||
StationId = (int)EAlarmStationId.Mom,
|
||||
Desc = $"MOM心跳报警->{mesResult.Info.MOMMessage}", //会存在多次不同的报警
|
||||
StartTime = DateTime.Now,
|
||||
Status = EAlarmStatus.Alert.GetDescription(),
|
||||
};
|
||||
haveWarn = true;
|
||||
|
||||
_eventAggregator.GetEvent<AlarmAddEvent>().Publish(model);//2.界面刷新,发布事件(发送消息)
|
||||
_unityContainer.Resolve<AlarmService>().Insert(model);
|
||||
return true;
|
||||
}
|
||||
else if (((int)EKeyFlag.ProcessParam).ToString() == mesResult.Info.KeyFlag) //心跳时通过KeyFlag= 2提醒设备需要调用MOM的工艺参数下发接口
|
||||
{
|
||||
listParams.Clear();
|
||||
EqptParameterReturnCmd resultModel = _unityContainer.Resolve<MESProcess>().GetProcessParam();//获取返回的JOSN
|
||||
if (null == resultModel)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
TProductionInformation model = _unityContainer.Resolve<ProductionInformationService>().GetCurrentProductInfo();//实例化工单类
|
||||
|
||||
if (!_unityContainer.Resolve<ProcessParamService>().UpdateProcessParam(model.ProcessParamId, JSON.SerializeObject(resultModel.Info.ParameterInfo)))
|
||||
{
|
||||
LogHelper.Instance.Warn("保存工艺参数失败!");
|
||||
}
|
||||
}
|
||||
|
||||
if (haveWarn && ((int)EKeyFlag.NG).ToString() != mesResult.Info.KeyFlag)
|
||||
{
|
||||
_eventAggregator.GetEvent<AlarmStaionCancelEvent>().Publish((int)EAlarmStationId.Mom);//2.界面刷新,发布事件(发送消息)
|
||||
var alarms = _unityContainer.Resolve<AlarmService>().GetInAlarm((int)EAlarmStationId.Mom);
|
||||
foreach (var item in alarms)
|
||||
{
|
||||
_unityContainer.Resolve<AlarmService>().CancelAlarm(item);
|
||||
}
|
||||
haveWarn = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//public void GetJsonParam(string param)
|
||||
//{
|
||||
// dynamic d = JsonConvert.DeserializeObject<dynamic>(param);
|
||||
// this.IpAddress = d.Ip;
|
||||
// this.Port = d.Port;
|
||||
// this.URL = d.URL;
|
||||
//}
|
||||
|
||||
|
||||
|
||||
void Run()
|
||||
{
|
||||
if (int.Parse(_unityContainer.Resolve<SysSetupService>().GetValueByParaID(ESysSetup.MOMEnable.ToString())) != (int)EMOMEnable.Enable)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
List<TMesData> uploadItems = _unityContainer.Resolve<MesDataService>().GetUpLoadData();
|
||||
|
||||
foreach (var item in uploadItems)
|
||||
{
|
||||
dynamic d = JsonConvert.DeserializeObject<dynamic>(item.CommandType);
|
||||
string service = d.Service;
|
||||
string func = d.Func;
|
||||
string url = d.UrlCmd;
|
||||
Type type = Type.GetType(MyPath.SIGNAL_TRIGGER + service);
|
||||
MethodInfo mi = this.GetType().GetMethod("ExecuteUpload").MakeGenericMethod(new Type[] { type }); //回复信息;
|
||||
|
||||
mi.Invoke(this, new object[]
|
||||
{
|
||||
func,
|
||||
url,
|
||||
item,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void ExecuteUpload<T>(string func, string url, TMesData mesModel)
|
||||
{
|
||||
//取得实例
|
||||
var instnce = _unityContainer.Resolve<T>(); //上下料实例
|
||||
Type t = instnce.GetType();
|
||||
//取得方法
|
||||
MethodInfo mi = t.GetMethod(func);
|
||||
//调用方法
|
||||
mi.Invoke(instnce, new object[] //这里会去执行哪个方法上传,参数只有发送的信息
|
||||
{
|
||||
url,
|
||||
mesModel
|
||||
});
|
||||
}
|
||||
|
||||
public void UploadCommon(string url, TMesData mesModel)
|
||||
{
|
||||
try
|
||||
{
|
||||
//这里就是调用上传的接口
|
||||
mesModel.SendTime = DateTime.Now;
|
||||
string result = HttpClientHelper.HttpPost(url, mesModel.Content);
|
||||
if (string.IsNullOrEmpty(result)) //请求失败
|
||||
{
|
||||
mesModel.SendFlag = (sbyte)EMesUpLoadStatus.Fail;
|
||||
}
|
||||
else //请求成功
|
||||
{
|
||||
mesModel.SendFlag = (sbyte)EMesUpLoadStatus.Success;
|
||||
mesModel.RecvContent = result;
|
||||
mesModel.RecvTime = DateTime.Now;
|
||||
_unityContainer.Resolve<MESProcess>().WriteRequestLog(mesModel.Content);
|
||||
_unityContainer.Resolve<MESProcess>().WriteResponseLog(result);
|
||||
}
|
||||
|
||||
_unityContainer.Resolve<MesDataService>().Update(mesModel);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Instance.GetCurrentClassError(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
165
Cowain.Bake.Main/ViewModels/AddBatteryViewModel.cs
Normal file
@@ -0,0 +1,165 @@
|
||||
using Cowain.Bake.BLL;
|
||||
using Cowain.Bake.Common;
|
||||
using Cowain.Bake.Common.Core;
|
||||
using Cowain.Bake.Common.Enums;
|
||||
using Cowain.Bake.Model;
|
||||
using Prism.Commands;
|
||||
using Prism.Mvvm;
|
||||
using Prism.Regions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Unity;
|
||||
using JSON = Newtonsoft.Json.JsonConvert;
|
||||
|
||||
namespace Cowain.Bake.Main.ViewModels
|
||||
{
|
||||
public class AddBatteryViewModel : BindableBase
|
||||
{
|
||||
private EBatteryStatus selectedEnum;
|
||||
|
||||
public EBatteryStatus SelectedEnum
|
||||
{
|
||||
get { return selectedEnum; }
|
||||
set { SetProperty(ref selectedEnum, value); }
|
||||
}
|
||||
public List<object> Options { get; set; }
|
||||
private object selectedOption;
|
||||
|
||||
public object SelectedOption
|
||||
{
|
||||
get { return selectedOption; }
|
||||
set { SetProperty(ref selectedOption, value); }
|
||||
}
|
||||
|
||||
public string batteryCode;
|
||||
public string BatteryCode
|
||||
{
|
||||
get => batteryCode;
|
||||
set => SetProperty(ref batteryCode, value);
|
||||
}
|
||||
int _palletID = 0;
|
||||
int _palletVID = 0;
|
||||
private IUnityContainer _unityContainer;
|
||||
|
||||
public AddBatteryViewModel(IUnityContainer unityContainer, int palletId, int VID)
|
||||
{
|
||||
_unityContainer = unityContainer;
|
||||
_palletID = palletId;
|
||||
_palletVID = VID;
|
||||
SelectedEnum = EBatteryStatus.ToPallet;
|
||||
SelectedPositionX = 1;
|
||||
SelectedPositionY = 2;
|
||||
Options = new List<object> { "否", "是" };
|
||||
SelectedOption = "否";
|
||||
}
|
||||
|
||||
public DelegateCommand<object> AddCommand => new DelegateCommand<object>((x) =>
|
||||
{
|
||||
if (string.IsNullOrEmpty(BatteryCode))
|
||||
{
|
||||
HandyControl.Controls.MessageBox.Warning("请输入电芯条码!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (_unityContainer.Resolve<BatteryInfoService>().IsExistBattery(_palletVID, SelectedPositionX, SelectedPositionY))
|
||||
{
|
||||
HandyControl.Controls.MessageBox.Warning("夹具位置存在电芯,此位置不能再增加电芯!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (0 == _palletVID)
|
||||
{
|
||||
HandyControl.Controls.MessageBox.Warning("此夹具的虚拟ID为0,不能增加电芯!");
|
||||
return;
|
||||
}
|
||||
|
||||
TBatteryInfo batteryInfo = new TBatteryInfo()
|
||||
{
|
||||
PalletVirtualId = _palletVID,
|
||||
BatteryCode = BatteryCode,
|
||||
BatteryStatus = (sbyte)SelectedEnum,
|
||||
PositionX = (sbyte)SelectedPositionX,
|
||||
PositionY = (sbyte)SelectedPositionY,
|
||||
ScanTime = DateTime.Now,
|
||||
BindingTime = DateTime.Now,
|
||||
DummyFlag = (SelectedOption?.ToString() == "是") ? true : false
|
||||
};
|
||||
|
||||
if(0 == _unityContainer.Resolve<BatteryInfoService>().Insert(batteryInfo))
|
||||
{
|
||||
LogHelper.Instance.Debug($"手动增加电芯:【{BatteryCode}】失败!", true);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogHelper.Instance.Info($"手动增加电芯:【{BatteryCode}】成功!", true);
|
||||
_unityContainer.Resolve<LogService>().AddLog($"手动增加电芯成功,{ JSON.SerializeObject(batteryInfo)}", E_LogType.Operate.ToString());
|
||||
_unityContainer.Resolve<PalletInfoService>().ModifyBatteryQty(_palletID); //数据减1
|
||||
}
|
||||
});
|
||||
|
||||
public List<KeyValuePair<EBatteryStatus, string>> EnumOptions
|
||||
{
|
||||
get
|
||||
{
|
||||
var enumType = typeof(EBatteryStatus);
|
||||
var options = new List<KeyValuePair<EBatteryStatus, string>>();
|
||||
|
||||
foreach (var value in Enum.GetValues(enumType))
|
||||
{
|
||||
var field = enumType.GetField(value.ToString());
|
||||
var attributes = field.GetCustomAttributes(typeof(DescriptionAttribute), false);
|
||||
var description = ((DescriptionAttribute)attributes[0]).Description;
|
||||
|
||||
options.Add(new KeyValuePair<EBatteryStatus, string>((EBatteryStatus)value, description));
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
}
|
||||
|
||||
private int selectedPositionY;
|
||||
|
||||
public int SelectedPositionY
|
||||
{
|
||||
get { return selectedPositionY; }
|
||||
set { SetProperty(ref selectedPositionY, value); }
|
||||
}
|
||||
|
||||
private int selectedPositionX;
|
||||
|
||||
public int SelectedPositionX
|
||||
{
|
||||
get { return selectedPositionX; }
|
||||
set { SetProperty(ref selectedPositionX, value); }
|
||||
}
|
||||
public List<int> PositionYRange
|
||||
{
|
||||
get
|
||||
{
|
||||
List<int> numbers = new List<int>();
|
||||
for (int i = 1; i <= Global.PALLET_COLS; i++)
|
||||
{
|
||||
numbers.Add(i);
|
||||
}
|
||||
return numbers;
|
||||
}
|
||||
}
|
||||
|
||||
public List<int> PositionXRange
|
||||
{
|
||||
get
|
||||
{
|
||||
List<int> numbers = new List<int>();
|
||||
for (int i = 1; i <= Global.PALLET_ROWS; i++)
|
||||
{
|
||||
numbers.Add(i);
|
||||
}
|
||||
return numbers;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
155
Cowain.Bake.Main/ViewModels/BasicInfoViewModel.cs
Normal file
@@ -0,0 +1,155 @@
|
||||
using Cowain.Bake.BLL;
|
||||
using Cowain.Bake.Common.Core;
|
||||
using Cowain.Bake.Common.Enums;
|
||||
using Cowain.Bake.Model.Entity;
|
||||
using Prism.Mvvm;
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Windows.Media;
|
||||
using Unity;
|
||||
|
||||
namespace Cowain.Bake.Main.ViewModels
|
||||
{
|
||||
public class BasicInfoViewModel : BindableBase
|
||||
{
|
||||
public static ObservableCollection<string> EventListNoticfication = new ObservableCollection<string>();
|
||||
private string _userName;
|
||||
public string UserName
|
||||
{
|
||||
get { return _userName; }
|
||||
set { SetProperty<string>(ref _userName, value); }
|
||||
}
|
||||
|
||||
private string _currentJobNum;
|
||||
public string CurrentJobNum
|
||||
{
|
||||
get { return _currentJobNum; }
|
||||
set { SetProperty<string>(ref _currentJobNum, value); }
|
||||
}
|
||||
|
||||
private string _dispMode;
|
||||
public string DispMode
|
||||
{
|
||||
get { return _dispMode; }
|
||||
set { SetProperty<string>(ref _dispMode, value); }
|
||||
}
|
||||
|
||||
private string _currentOperation;
|
||||
public string CurrentOperation
|
||||
{
|
||||
get { return _currentOperation; }
|
||||
set { SetProperty<string>(ref _currentOperation, value); }
|
||||
}
|
||||
private string _userId;
|
||||
public string UserId
|
||||
{
|
||||
get { return _userId; }
|
||||
set { SetProperty<string>(ref _userId, value); }
|
||||
}
|
||||
private string _startStatusName;
|
||||
public string StartStatusName
|
||||
{
|
||||
get { return _startStatusName; }
|
||||
set { SetProperty<string>(ref _startStatusName, value); }
|
||||
}
|
||||
|
||||
private string _failPointData;
|
||||
public string FailPointData
|
||||
{
|
||||
get { return _failPointData; }
|
||||
set { SetProperty<string>(ref _failPointData, value); }
|
||||
}
|
||||
|
||||
private string _deviceStatusName;
|
||||
public string DeviceStatusName
|
||||
{
|
||||
get { return _deviceStatusName; }
|
||||
set { SetProperty<string>(ref _deviceStatusName, value); }
|
||||
}
|
||||
|
||||
//EventList
|
||||
private ObservableCollection<string> _eventList = new ObservableCollection<string>();
|
||||
public ObservableCollection<string> EventList
|
||||
{
|
||||
get => _eventList;
|
||||
set => SetProperty(ref _eventList, value);
|
||||
}
|
||||
|
||||
private bool _mesStatus;
|
||||
public bool MesStatus
|
||||
{
|
||||
get { return _mesStatus; }
|
||||
set { SetProperty(ref _mesStatus, value); RaisePropertyChanged(nameof(StatusColor)); }
|
||||
}
|
||||
|
||||
public SolidColorBrush StatusColor
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!MesStatus)
|
||||
{
|
||||
return new SolidColorBrush(Colors.Red);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new SolidColorBrush(Colors.Green);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private readonly IUnityContainer _unityContainer;
|
||||
|
||||
public BasicInfoViewModel(IUnityContainer unityContainer)
|
||||
{
|
||||
_unityContainer = unityContainer;
|
||||
ShowInfo();
|
||||
}
|
||||
|
||||
public void ShowInfo()
|
||||
{
|
||||
UserEntity userInfo = _unityContainer.Resolve<MemoryDataProvider>().CurrentUser;
|
||||
userInfo.JobNum = _unityContainer.Resolve<ProductionInformationService>().GetCurrentProductInfo().JobNum;
|
||||
userInfo.ProcessParamName = _unityContainer.Resolve<ProcessParamService>().Get(_unityContainer.Resolve<ProductionInformationService>().GetCurrentProductInfo().ProcessParamId).ProcessParamName;
|
||||
|
||||
FailPointData = "0";
|
||||
UserName = userInfo.UserName;
|
||||
UserId = userInfo.UserId;
|
||||
CurrentJobNum = userInfo.JobNum;
|
||||
CurrentOperation = userInfo.ProcessParamName;
|
||||
DeviceStatusName = EDeviceStatus.None.GetDescription();
|
||||
DispMode = SettingProvider.Instance.DispMode.GetDescription();
|
||||
}
|
||||
|
||||
public void SetTempData(string value)
|
||||
{
|
||||
System.Threading.SynchronizationContext.SetSynchronizationContext(new
|
||||
System.Windows.Threading.DispatcherSynchronizationContext(System.Windows.Application.Current.Dispatcher));
|
||||
System.Threading.SynchronizationContext.Current.Post(p1 =>
|
||||
{
|
||||
FailPointData = value;
|
||||
}, null);
|
||||
}
|
||||
|
||||
public void SetEvent(string msg)
|
||||
{
|
||||
// 在第一个位置插入新元素
|
||||
System.Threading.SynchronizationContext.SetSynchronizationContext(new
|
||||
System.Windows.Threading.DispatcherSynchronizationContext(System.Windows.Application.Current.Dispatcher));
|
||||
System.Threading.SynchronizationContext.Current.Post(p1 =>
|
||||
{
|
||||
/*
|
||||
RemoveAt:放在外面,会崩
|
||||
该类型的 CollectionView 不支持从调度程序线程以外的线程对其 SourceCollection 进行的更改。, 在 System.Windows.Data.CollectionView.OnCollectionChanged(Object sender, NotifyCollectionChangedEventArgs args)
|
||||
在 System.Collections.ObjectModel.ObservableCollection`1.OnCollectionChanged(NotifyCollectionChangedEventArgs e)
|
||||
在 System.Collections.ObjectModel.ObservableCollection`1.RemoveItem(Int32 index)
|
||||
*/
|
||||
if (EventList.Count > Bake.Common.Global.MAX_QUEUE_SIGNAL)
|
||||
{
|
||||
EventList.RemoveAt(EventList.Count - 1);
|
||||
}
|
||||
|
||||
EventList.Insert(0, $"{ DateTime.Now.ToString("HH:mm:ss")}: {msg}");
|
||||
}, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
769
Cowain.Bake.Main/ViewModels/CavityDtlViewModel.cs
Normal file
@@ -0,0 +1,769 @@
|
||||
using Cowain.Bake.BLL;
|
||||
using Cowain.Bake.Common;
|
||||
using Cowain.Bake.Common.Core;
|
||||
using Cowain.Bake.Common.Enums;
|
||||
using Cowain.Bake.Communication.Interface;
|
||||
using Cowain.Bake.Main.Views;
|
||||
using Cowain.Bake.Model;
|
||||
using Cowain.Bake.Model.Entity;
|
||||
using Cowain.Bake.Model.Models;
|
||||
using HandyControl.Controls;
|
||||
using HslCommunication;
|
||||
using Prism.Commands;
|
||||
using Prism.Mvvm;
|
||||
using Prism.Services.Dialogs;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using Unity;
|
||||
|
||||
namespace Cowain.Bake.Main.ViewModels
|
||||
{
|
||||
public class CavityDtlViewModel: BindableBase//, Prism.Services.Dialogs.IDialogAware
|
||||
{
|
||||
private string stationName;
|
||||
private string palletCode;
|
||||
private string stationEnable;
|
||||
private string batteryCount;
|
||||
private int _virtualId;
|
||||
private string selectedValue;
|
||||
private string selectedJobNum;
|
||||
private string isWaterValue;
|
||||
private List<string> arrJobNum;
|
||||
private List<string> palletStatus;
|
||||
private List<string> lastPalletList;
|
||||
private string lastValue;
|
||||
private int _bakingCount;
|
||||
private bool _isEnabled ;
|
||||
private bool _isEnabledAdd;
|
||||
private bool _lastEnabled;
|
||||
List<CavityInfoModel> _cavityInfo;
|
||||
CavityHeaderModel _cavityHeaderInfo = null;
|
||||
private IUnityContainer _unityContainer;
|
||||
|
||||
public string Title => "工站明细";
|
||||
// 弹窗打开时触发:读取传递的参数
|
||||
//public void OnDialogOpened(IDialogParameters parameters)
|
||||
//{
|
||||
// if (parameters.TryGetValue<string>("StatinName", out var text))
|
||||
// {
|
||||
// StationName = text; // 赋值后界面自动更新
|
||||
// GetInfo();
|
||||
// }
|
||||
//}
|
||||
|
||||
//// 允许关闭弹窗(返回true即可)
|
||||
//public bool CanCloseDialog() => true;
|
||||
|
||||
//// 弹窗关闭后清理资源(可选)
|
||||
//public void OnDialogClosed() { }
|
||||
|
||||
//// Prism 8中用于触发弹窗关闭的事件
|
||||
//public event Action<IDialogResult> RequestClose;
|
||||
|
||||
//// 关闭弹窗的逻辑
|
||||
//public DelegateCommand CloseCommand =>
|
||||
// new DelegateCommand(() =>
|
||||
// RequestClose?.Invoke(new DialogResult(ButtonResult.OK)));
|
||||
|
||||
//private readonly IDialogService _dialogService;
|
||||
public CavityDtlViewModel(IUnityContainer unityContainer)
|
||||
{
|
||||
_unityContainer = unityContainer;
|
||||
//_dialogService = dialogService;
|
||||
_cavityInfo = _unityContainer.Resolve<CavityInfoService>().GetAllStation();
|
||||
}
|
||||
|
||||
private ObservableCollection<string> palletList;
|
||||
public ObservableCollection<string> PalletList
|
||||
{
|
||||
get => palletList;
|
||||
set => SetProperty(ref palletList, value);
|
||||
}
|
||||
|
||||
public string SelectedValue
|
||||
{
|
||||
get => selectedValue;
|
||||
set => SetProperty(ref selectedValue, value);
|
||||
}
|
||||
|
||||
public string SelectedJobNum
|
||||
{
|
||||
get => selectedJobNum;
|
||||
set => SetProperty(ref selectedJobNum, value);
|
||||
}
|
||||
|
||||
public string IsWaterValue
|
||||
{
|
||||
get => isWaterValue;
|
||||
set => SetProperty(ref isWaterValue, value);
|
||||
}
|
||||
|
||||
public List<string> PalletStatus
|
||||
{
|
||||
get => palletStatus;
|
||||
set => SetProperty(ref palletStatus, value);
|
||||
}
|
||||
|
||||
public List<string> ArrJobNum
|
||||
{
|
||||
get => arrJobNum;
|
||||
set => SetProperty(ref arrJobNum, value);
|
||||
}
|
||||
|
||||
public string StationName
|
||||
{
|
||||
get => stationName;
|
||||
set => SetProperty(ref stationName, value);
|
||||
}
|
||||
public string BatteryCount
|
||||
{
|
||||
get => batteryCount;
|
||||
set => SetProperty(ref batteryCount, value);
|
||||
}
|
||||
|
||||
public string WaterValueModel;
|
||||
public string StationEnable
|
||||
{
|
||||
get => stationEnable;
|
||||
set => SetProperty(ref stationEnable, value);
|
||||
}
|
||||
|
||||
public string remark;
|
||||
public string Remark
|
||||
{
|
||||
get => remark;
|
||||
set => SetProperty(ref remark, value);
|
||||
}
|
||||
|
||||
public string PalletCode
|
||||
{
|
||||
get { return palletCode; }
|
||||
set
|
||||
{
|
||||
SetProperty(ref palletCode, value);
|
||||
// 在属性更改时调用需要执行的方法
|
||||
//SetPalletList();
|
||||
}
|
||||
}
|
||||
public int BakingCount
|
||||
{
|
||||
get => _bakingCount;
|
||||
set => SetProperty(ref _bakingCount, value);
|
||||
}
|
||||
public bool IsEnabled
|
||||
{
|
||||
get { return _isEnabled; }
|
||||
set { SetProperty(ref _isEnabled, value); }
|
||||
}
|
||||
|
||||
public bool IsEnabledAdd
|
||||
{
|
||||
get { return _isEnabledAdd; }
|
||||
set { SetProperty(ref _isEnabledAdd, value); }
|
||||
}
|
||||
|
||||
public bool LastEnabled
|
||||
{
|
||||
get { return _lastEnabled; }
|
||||
set { SetProperty(ref _lastEnabled, value); }
|
||||
}
|
||||
|
||||
public List<string> LastPalletList
|
||||
{
|
||||
get => lastPalletList;
|
||||
set => SetProperty(ref lastPalletList, value);
|
||||
}
|
||||
|
||||
public string LastValue
|
||||
{
|
||||
get { return lastValue; }
|
||||
set
|
||||
{
|
||||
SetProperty(ref lastValue, value);
|
||||
if (lastValue != "")
|
||||
{
|
||||
UpdateLastPallet();
|
||||
}
|
||||
}
|
||||
}
|
||||
public int VirtualId
|
||||
{
|
||||
get => _virtualId;
|
||||
set => SetProperty(ref _virtualId, value);
|
||||
}
|
||||
|
||||
public event PropertyChangedEventHandler NotifyPropertyChanged;
|
||||
public void OnPropertyChanged(string propName)
|
||||
{
|
||||
if (NotifyPropertyChanged != null)
|
||||
{
|
||||
NotifyPropertyChanged.Invoke(this, new PropertyChangedEventArgs(propName));
|
||||
}
|
||||
}
|
||||
|
||||
private BatteryInfoEntity batteryInfoSelectedItem;
|
||||
public BatteryInfoEntity BatteryInfoSelectedItem
|
||||
{
|
||||
get { return batteryInfoSelectedItem; }
|
||||
set
|
||||
{
|
||||
if (value != null)
|
||||
{
|
||||
batteryInfoSelectedItem = value;
|
||||
OnPropertyChanged("BatteryInfoSelectedItem");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void GetInfo()
|
||||
{
|
||||
SetPalletCodeCombox();
|
||||
SetPalletStatusCombox();
|
||||
SetPalletLastCombox();
|
||||
SetJobNumCombox();
|
||||
GetHeaderInfo();
|
||||
FillGridView();
|
||||
}
|
||||
|
||||
private void SetPalletCodeCombox()
|
||||
{
|
||||
PalletList = new ObservableCollection<string>();
|
||||
_unityContainer.Resolve<PalletInfoService>().GetAll().ForEach(item => PalletList.Add(item.PalletCode));
|
||||
}
|
||||
|
||||
private void SetPalletLastCombox()
|
||||
{
|
||||
LastPalletList = new List<string>();
|
||||
foreach (EPalletLast ePalletStatus in System.Enum.GetValues(typeof(EPalletLast)))
|
||||
{
|
||||
LastPalletList.Add(ePalletStatus.GetDescription());
|
||||
}
|
||||
}
|
||||
|
||||
private void SetPalletStatusCombox()
|
||||
{
|
||||
PalletStatus = new List<string>();
|
||||
foreach (EPalletStatus ePalletStatus in System.Enum.GetValues(typeof(EPalletStatus)))
|
||||
{
|
||||
PalletStatus.Add(ePalletStatus.GetDescription());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void SetJobNumCombox()
|
||||
{
|
||||
var jobNums = _unityContainer.Resolve<ProductionInformationService>().GeAll();
|
||||
ArrJobNum = jobNums.Select(x => x.JobNum).ToList();
|
||||
}
|
||||
|
||||
bool IsPassWordPass()
|
||||
{
|
||||
// 创建输入对话框
|
||||
//string pwd = Microsoft.VisualBasic.Interaction.InputBox("请您输入密码!", "修改");
|
||||
|
||||
//if (pwd != SettingProvider.Instance.PWD)
|
||||
//{
|
||||
// LogHelper.Instance.Warn("您输入的密码错误!",true);
|
||||
// return false;
|
||||
//}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public DelegateCommand<object> UpdatePalletStatus => new DelegateCommand<object>((x) =>
|
||||
{
|
||||
if (1 == _cavityHeaderInfo.PalletId)
|
||||
{
|
||||
LogHelper.Instance.Warn("新夹具,不能修改夹具状态!",true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (0 == _cavityHeaderInfo.PalletId)
|
||||
{
|
||||
LogHelper.Instance.Error("此机台未绑定托盘!", true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsPassWordPass())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CavityInfoModel stationDetail = _cavityInfo.Where(y => y.CavityName == StationName).FirstOrDefault();
|
||||
var list = EnumHelper.GetEnumList<EPalletStatus>().Where(item => item.EnumDesc == SelectedValue);
|
||||
int palletStatus = list.FirstOrDefault().EnumIntValue;
|
||||
|
||||
if (palletStatus == (int)EPalletStatus.BlankOver) //将清空夹具里的电芯,是确认是否要改成下料完成
|
||||
{
|
||||
if (_unityContainer.Resolve<BatteryInfoService>().IsIntoStation(VirtualId))
|
||||
{
|
||||
if (MessageBoxResult.OK == HandyControl.Controls.MessageBox.Ask("夹具中有电芯,如果改成【下料完成】,将设置电芯为出站,\n请确认是否要改状态?", "操作提示"))
|
||||
{
|
||||
_unityContainer.Resolve<BatteryInfoService>().SetBatteryOutBound(VirtualId);
|
||||
}
|
||||
}
|
||||
_unityContainer.Resolve<PalletInfoService>().SetUnBinding(_cavityHeaderInfo.PalletId);
|
||||
}
|
||||
else if (palletStatus == (int)EPalletStatus.WaitTest)
|
||||
{
|
||||
if (IsUnLoading(stationDetail))
|
||||
{
|
||||
LogHelper.Instance.Error("禁止将在下料机台的托盘状态更改为‘待测水含量!’", true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (palletStatus == (int)EPalletStatus.Advisable)
|
||||
{
|
||||
_unityContainer.Resolve<PalletInfoService>().UpdateNowJobNum(VirtualId);
|
||||
var memory = _unityContainer.Resolve<MemoryDataProvider>();
|
||||
SelectedJobNum = memory.CurrentUser.JobNum;
|
||||
}
|
||||
else if (palletStatus == (int)EPalletStatus.Bake) //烘烤中,设置夹具烘烤位置
|
||||
{
|
||||
TStation station = _unityContainer.Resolve<StationService>().GetStationByCavityId(_cavityHeaderInfo.Id);
|
||||
if (station.Type == (int)EStationType.Stove)
|
||||
{
|
||||
if (0 == _unityContainer.Resolve<PalletInfoService>().UpdateBakingPos(_cavityHeaderInfo.PalletCode,
|
||||
_cavityHeaderInfo.Id))
|
||||
{
|
||||
LogHelper.Instance.Error($"修改烘烤位置失败!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_unityContainer.Resolve<CavityInfoService>().UpdatePalletStatus(_cavityHeaderInfo.PalletId, StationName, palletStatus);
|
||||
HandyControl.Controls.Growl.Success("更新成功!");
|
||||
|
||||
_unityContainer.Resolve<LogService>().AddLog("人为修改状态:" + stationName
|
||||
+ ";" + ((EPalletStatus)palletStatus).GetDescription(), E_LogType.Operate.ToString());
|
||||
BotnnVisible(palletStatus);
|
||||
GetHeaderInfo();
|
||||
FillGridView();
|
||||
});
|
||||
public DelegateCommand<object> UpdatePalletCode => new DelegateCommand<object>((x) =>
|
||||
{
|
||||
if (string.IsNullOrEmpty(palletCode))
|
||||
{
|
||||
LogHelper.Instance.Error("请选托盘编码!", true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_cavityHeaderInfo.Lock)
|
||||
{
|
||||
LogHelper.Instance.Error("该位置已有调度任务锁定,无法绑定托盘!", true);
|
||||
return;
|
||||
}
|
||||
|
||||
_unityContainer.Resolve<CavityInfoService>().UpdateStationPalletCode(stationName, PalletCode);
|
||||
GetHeaderInfo();
|
||||
FillGridView();
|
||||
var list = EnumHelper.GetEnumList<EPalletStatus>().Where(item => item.EnumDesc == SelectedValue);
|
||||
int palletStatus = list.FirstOrDefault().EnumIntValue;
|
||||
if (palletStatus == (int)EPalletStatus.BakeOver || palletStatus == (int)EPalletStatus.Bake)
|
||||
{
|
||||
CavityInfoModel machine = _cavityInfo.Where(y => y.Id ==_cavityHeaderInfo.Id).FirstOrDefault();
|
||||
if (machine.Type == (int)EStationType.Stove)
|
||||
{
|
||||
_unityContainer.Resolve<PalletInfoService>().UpdateBakingPos(PalletCode, _cavityHeaderInfo.Id);
|
||||
}
|
||||
|
||||
}
|
||||
HandyControl.Controls.MessageBox.Success("已更新!");
|
||||
_unityContainer.Resolve<LogService>().AddLog("人为绑定托盘:" + stationName
|
||||
+";"+palletCode, E_LogType.Operate.ToString());
|
||||
});
|
||||
|
||||
public DelegateCommand<object> BindJobNum => new DelegateCommand<object>((x) =>
|
||||
{
|
||||
if (!IsPassWordPass())
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (0 == _unityContainer.Resolve<PalletInfoService>().SetJobNum(stationName, selectedJobNum))
|
||||
{
|
||||
LogHelper.Instance.Error("此机台未绑定托盘!", true);
|
||||
return;
|
||||
}
|
||||
HandyControl.Controls.MessageBox.Success("已更新!");
|
||||
_unityContainer.Resolve<LogService>().AddLog($"人为绑定工单,工站:{stationName},工单:{selectedJobNum}"
|
||||
, E_LogType.Operate.ToString());
|
||||
});
|
||||
|
||||
public DelegateCommand<object> UnBindJobNum => new DelegateCommand<object>((x) =>
|
||||
{
|
||||
if (0 == _unityContainer.Resolve<PalletInfoService>().SetJobNum(stationName, ""))
|
||||
{
|
||||
LogHelper.Instance.Error("此机台未绑定托盘!", true);
|
||||
return;
|
||||
}
|
||||
|
||||
HandyControl.Controls.MessageBox.Success("已更新!");
|
||||
GetHeaderInfo();
|
||||
_unityContainer.Resolve<LogService>().AddLog($"人为解绑工单,工站:{stationName},工单:{selectedJobNum}"
|
||||
, E_LogType.Operate.ToString());
|
||||
|
||||
});
|
||||
|
||||
public DelegateCommand<object> AddBatteryCommand => new DelegateCommand<object>((x) =>
|
||||
{
|
||||
if (!IsPassWordPass())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var viewModel = new AddBatteryViewModel(_unityContainer, _cavityHeaderInfo.PalletId, VirtualId);
|
||||
AddBatteryView dlg = new AddBatteryView { DataContext = viewModel };
|
||||
dlg.ShowDialog();
|
||||
GetHeaderInfo(); //刷新数量
|
||||
FillGridView();
|
||||
});
|
||||
|
||||
|
||||
public DelegateCommand<object> AddRemark => new DelegateCommand<object>((x) =>
|
||||
{
|
||||
if (50 <= remark.Length)
|
||||
{
|
||||
HandyControl.Controls.MessageBox.Error($@"输入的备注长度不能大于50个字符!", "操作提示");
|
||||
return;
|
||||
}
|
||||
|
||||
if (0 == _unityContainer.Resolve<CavityInfoService>().UpdateRemark(stationName, remark))
|
||||
{
|
||||
LogHelper.Instance.Error("修改备注失败!" ,true);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogHelper.Instance.Info("修改备注成功!", true);
|
||||
}
|
||||
});
|
||||
public DelegateCommand<object> UpdatePalletNoneCode => new DelegateCommand<object>((x) =>
|
||||
{
|
||||
if (!IsPassWordPass())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (0 == _cavityHeaderInfo.PalletId)
|
||||
{
|
||||
LogHelper.Instance.Error("此机台未绑定托盘!", true);
|
||||
return;
|
||||
}
|
||||
_unityContainer.Resolve<CavityInfoService>().UpdateStationNonePallet(stationName);
|
||||
GetHeaderInfo();
|
||||
HandyControl.Controls.MessageBox.Success("已更新为无托盘!");
|
||||
_unityContainer.Resolve<LogService>().AddLog("人为解绑," + stationName
|
||||
, E_LogType.Operate.ToString());
|
||||
});
|
||||
|
||||
public DelegateCommand<object> UpdateVirtualId => new DelegateCommand<object>((x) =>
|
||||
{
|
||||
if (!IsPassWordPass())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (1 == _cavityHeaderInfo.PalletId)
|
||||
{
|
||||
LogHelper.Instance.Warn("新夹具,不能修改夹具信息ID!", true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(palletCode))
|
||||
{
|
||||
LogHelper.Instance.Error("请选托盘编码!", true);
|
||||
return;
|
||||
}
|
||||
|
||||
var BatteryList = _unityContainer.Resolve<BatteryInfoService>().GetBatteryInfos(VirtualId);
|
||||
if (BatteryList.Count < 1)
|
||||
{
|
||||
//LogHelper.Instance.Error("所输入的虚拟夹具号没有电芯信息!", true);
|
||||
//return; //add by lsm 后面要开放,暂时为了测温度数据
|
||||
}
|
||||
if (_unityContainer.Resolve<PalletInfoService>().UpdateVirtualId(VirtualId, PalletCode) < 1)
|
||||
{
|
||||
HandyControl.Controls.MessageBox.Error("同一个虚拟码或更新失败!");
|
||||
_unityContainer.Resolve<LogService>().AddLog($"更新失败,人为绑定托盘虚拟码,{stationName},托盘虚拟码:{VirtualId}"
|
||||
, E_LogType.Operate.ToString());
|
||||
return;
|
||||
}
|
||||
GetHeaderInfo();
|
||||
FillGridView();
|
||||
HandyControl.Controls.MessageBox.Success("已更新!");
|
||||
_unityContainer.Resolve<LogService>().AddLog($"人为绑定托盘虚拟码,{stationName},托盘虚拟码:{VirtualId}"
|
||||
, E_LogType.Operate.ToString());
|
||||
});
|
||||
|
||||
|
||||
private void GetHeaderInfo()
|
||||
{
|
||||
_cavityHeaderInfo = _unityContainer.Resolve<CavityInfoService>().GetHeadInfo(StationName);
|
||||
BatteryCount = _cavityHeaderInfo.BatteryQty.ToString();
|
||||
SelectedJobNum = _cavityHeaderInfo.JobNum;
|
||||
stationEnable = _cavityHeaderInfo.Enable;
|
||||
IsWaterValue = _cavityHeaderInfo.IsWater;
|
||||
PalletCode = _cavityHeaderInfo.PalletCode;
|
||||
WaterValueModel = _cavityHeaderInfo.WaterValue;
|
||||
BakingCount = _cavityHeaderInfo.BakingCount;
|
||||
Remark = _cavityHeaderInfo.Remark;
|
||||
VirtualId = _cavityHeaderInfo.VirtualId;
|
||||
|
||||
SelectedValue = "";
|
||||
if (null != _cavityHeaderInfo.PalletStatus)
|
||||
{
|
||||
int enumValue = _cavityHeaderInfo.PalletStatus ?? 1;
|
||||
SelectedValue = EnumHelper.GetEnumList<EPalletStatus>()
|
||||
.Where(item => item.EnumIntValue == enumValue).FirstOrDefault().EnumDesc;
|
||||
BotnnVisible(enumValue);
|
||||
}
|
||||
if (null != _cavityHeaderInfo.LastFlag)
|
||||
{
|
||||
int enumValue = (_cavityHeaderInfo.LastFlag ?? false) ? 1 : 0;
|
||||
LastValue = EnumHelper.GetEnumList<EPalletLast>()
|
||||
.Where(item => item.EnumIntValue == enumValue).FirstOrDefault().EnumDesc;
|
||||
}
|
||||
|
||||
CommonCoreHelper.Instance.MainViewAutoEvent.Set();
|
||||
IsEnabledAdd = ((0 == VirtualId) || (Global.PALLET_TOTAL_BATTERYS == int.Parse(BatteryCount))) ? false : true;
|
||||
}
|
||||
private ObservableCollection<BatteryInfoEntity> batteryDtl2 = new ObservableCollection<BatteryInfoEntity>();
|
||||
public ObservableCollection<BatteryInfoEntity> BatteryDtl2
|
||||
{
|
||||
get => batteryDtl2;
|
||||
set => SetProperty(ref batteryDtl2, value);
|
||||
}
|
||||
private void FillGridView()
|
||||
{
|
||||
List<TBatteryInfo> table = _unityContainer.Resolve<BatteryInfoService>().GetBatteryInfos(VirtualId).
|
||||
OrderBy(x=>x.PositionY).OrderBy(x=>x.PositionX).ToList();
|
||||
//_unityContainer.Resolve<BatteryInfoService>().GetCavityBattery(StationName);
|
||||
|
||||
BatteryDtl2.Clear();
|
||||
if (table.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var item in table)
|
||||
{
|
||||
if ((int)EBatteryStatus.Over != item.BatteryStatus)
|
||||
{
|
||||
BatteryInfoEntity batteryInfoEntity = new BatteryInfoEntity();
|
||||
batteryInfoEntity.Id = item.Id;
|
||||
batteryInfoEntity.BatteryCode = item.BatteryCode;
|
||||
batteryInfoEntity.BatteryStatus = item.BatteryStatus;
|
||||
batteryInfoEntity.PositionX = item.PositionX;
|
||||
batteryInfoEntity.PositionY = item.PositionY;
|
||||
batteryInfoEntity.DummyFlag = item.DummyFlag ;
|
||||
batteryInfoEntity.BindingTime =item.BindingTime;
|
||||
BatteryDtl2.Add(batteryInfoEntity);
|
||||
}
|
||||
}
|
||||
}
|
||||
private void BotnnVisible(int enumValue)
|
||||
{
|
||||
CavityInfoModel stationDetail = _cavityInfo.Where(y => y.CavityName == StationName).FirstOrDefault();
|
||||
//不是待测水含量不能使用判断按钮
|
||||
IsEnabled = (int)EPalletStatus.WaitTest == enumValue ? true: false;
|
||||
if (!_unityContainer.Resolve<BLL.BatteryInfoService>().IsPalletDummy(VirtualId))//不带水的不能使用判断按钮
|
||||
{
|
||||
IsEnabled = false;
|
||||
}
|
||||
//在上料或下料工站的不能修改为最后一盘
|
||||
if (stationDetail.Type == (int)EStationType.Loading
|
||||
|| stationDetail.Type == (int)EStationType.UnLoading)
|
||||
{
|
||||
LastEnabled = false; //显示“最后一盘” Enabled
|
||||
}
|
||||
else
|
||||
{
|
||||
LastEnabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
public DelegateCommand<object> MoistureInput => new DelegateCommand<object>((x) =>
|
||||
{
|
||||
MoistureValueView moisture = new MoistureValueView( _unityContainer, this);
|
||||
moisture.ShowDialog();
|
||||
//var p = new DialogParameters
|
||||
//{
|
||||
// { "this", this }
|
||||
// //{ "waterValue", WaterValueModel }
|
||||
//};
|
||||
//_dialogService.ShowDialog(nameof(MoistureValueView), p, r => { /*回调*/ });
|
||||
GetHeaderInfo();
|
||||
BotnnVisible(_cavityHeaderInfo.PalletStatus??10);
|
||||
});
|
||||
|
||||
/*
|
||||
解锁重点 add by lsm 调度锁放有效,锁对取盘无效
|
||||
5.种状态:1.在烤箱水含量OK,2.在烤箱水含量NG, 3.在下料位水含量OK,4.在下料位水含量NG,5.在下料位待测水含量
|
||||
只有测试OK才解锁
|
||||
1.ProcUpdateTask,烤箱夹具(水含量测试OK)->下料,3.在下料位而且是测试ok,
|
||||
NG或待测不解锁:2,4,5,
|
||||
*/
|
||||
public void MoistureRuturn(int palletstaus,string moistureValue )
|
||||
{
|
||||
if (!UpdatePalletState(palletstaus, moistureValue))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CavityInfoModel stationDetail = _cavityInfo.Where(y => y.CavityName == StationName).FirstOrDefault();
|
||||
if (IsUnLoading(stationDetail))
|
||||
{
|
||||
var conf = _unityContainer.Resolve<DeviceConfigService>().GetConfig(stationDetail.StationId);
|
||||
IPLCDevice plc = _unityContainer.Resolve<IPLCDevice>(conf.Name);
|
||||
if (SelectedValue == EPalletStatus.TestOK.GetDescription())
|
||||
{
|
||||
OperateResult operateResult = plc.Write<bool>($"ns=4;s=PC_IN_Par_Request{stationDetail.Column}", true);
|
||||
if (!operateResult.IsSuccess)
|
||||
{
|
||||
LogHelper.Instance.Debug($"设置请求参数下发失败:{operateResult.Message}");
|
||||
HandyControl.Controls.Growl.Success("设置请求参数下发失败!");
|
||||
}
|
||||
else
|
||||
{
|
||||
//解除锁定
|
||||
_unityContainer.Resolve<CavityInfoService>().GetPalletBakingPosAndUpdateLock(PalletCode); //夹具在下料,解除炉子的锁
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 改变托盘状态以及保存水分值
|
||||
/// </summary>
|
||||
private bool UpdatePalletState(int palletstaus, string moistureValue) //未将对象引用设置到对象的实例
|
||||
{
|
||||
var proceParamModel = _unityContainer.Resolve<ProductionInformationService>().GetProductionInformation(SelectedJobNum);
|
||||
try
|
||||
{
|
||||
if (null == proceParamModel)
|
||||
{
|
||||
LogHelper.Instance.Error($"查询工单信息失败!,工单号:【{SelectedJobNum}】", true);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (proceParamModel.DummyRule == (int)DummyPlaceRule.DEFAULT_EVERY_STOVE_LAYER_PLACED_ONE)//判断是不是一个炉层放一个水含量规则
|
||||
{
|
||||
int updateResult = _unityContainer.Resolve<PalletInfoService>().UpdateDummyLayerValue(_cavityHeaderInfo.BakingPosition, palletstaus, moistureValue, _cavityHeaderInfo.PalletId);
|
||||
if (updateResult <= 0)
|
||||
{
|
||||
LogHelper.Instance.Warn($"修改夹具状态失败!烘烤位置:{_cavityHeaderInfo.BakingPosition},夹具ID:{_cavityHeaderInfo.PalletId}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (0 >= _unityContainer.Resolve<PalletInfoService>().UpdateWaterValue(_cavityHeaderInfo.PalletId, palletstaus, moistureValue))
|
||||
{
|
||||
LogHelper.Instance.Warn($"修改夹具:{_cavityHeaderInfo.Id},状态:{palletstaus}失败!");
|
||||
}
|
||||
}
|
||||
HandyControl.Controls.Growl.Success("更新成功!");
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
LogHelper.Instance.Error($"修改托盘水含量信息失败,{ex.Message}", true);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
private void UpdateLastPallet()
|
||||
{
|
||||
var service = _unityContainer.Resolve<PalletInfoService>();
|
||||
TPalletInfo palletInfo = service.GetPalletInfo(palletCode);
|
||||
int i = palletInfo.LastFlag ? 1 : 0;
|
||||
string palletLast = EnumHelper.GetEnumList<EPalletLast>()
|
||||
.Where(item => item.EnumIntValue == i).FirstOrDefault().EnumDesc;
|
||||
//判断当前和数据库内的值是否相等,不相等就执行更改
|
||||
if (LastValue != palletLast && LastValue != "")
|
||||
{
|
||||
service.UpdateLast(palletCode, LastValue);
|
||||
HandyControl.Controls.MessageBox.Success("修改成功!");
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsUnLoading(CavityInfoModel cavityInfo)
|
||||
{
|
||||
if (cavityInfo.Type == (int)EStationType.UnLoading)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public DelegateCommand<object> DeleteCommand => new DelegateCommand<object>((x) =>
|
||||
{
|
||||
if (!IsPassWordPass())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var result = HandyControl.Controls.MessageBox.Ask($@"确定删除?", "操作提示");
|
||||
if (result == System.Windows.MessageBoxResult.Cancel)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var t = x as BatteryInfoEntity;
|
||||
if (t != null)
|
||||
{
|
||||
if (_unityContainer.Resolve<BatteryInfoService>().Delete<TBatteryInfo>(t.Id) > 0)
|
||||
{
|
||||
batteryDtl2.Remove(t);
|
||||
Growl.Success("删除成功!");
|
||||
_unityContainer.Resolve<PalletInfoService>().ModifyBatteryQty(_cavityHeaderInfo.PalletId, -1); //数据减1
|
||||
GetHeaderInfo(); //刷新界面
|
||||
}
|
||||
else
|
||||
{
|
||||
Growl.Fatal("删除失败!");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Growl.Fatal("删除失败!");
|
||||
}
|
||||
});
|
||||
|
||||
public DelegateCommand<object> ChangeDummyCommand => new DelegateCommand<object>((x) =>
|
||||
{
|
||||
if (null == BatteryInfoSelectedItem)
|
||||
{
|
||||
Growl.Warning("选择失败!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (_unityContainer.Resolve<BLL.BatteryInfoService>().IsPalletDummy(VirtualId))
|
||||
{
|
||||
Growl.Warning("夹具有水含量电芯,不能再设置水含量电芯");
|
||||
FillGridView();
|
||||
return;
|
||||
}
|
||||
|
||||
if (MessageBoxResult.Cancel == HandyControl.Controls.MessageBox.Ask("是否确定要设置此电芯为【水含量电芯】?", "提示"))
|
||||
{
|
||||
FillGridView();
|
||||
return;
|
||||
}
|
||||
|
||||
if (_unityContainer.Resolve<BLL.BatteryInfoService>().SetDummy(BatteryInfoSelectedItem.Id) > 0)
|
||||
{
|
||||
Growl.Info("设置为水含量电芯成功!");
|
||||
}
|
||||
else
|
||||
{
|
||||
Growl.Fatal("设置为水含量电芯失败!");
|
||||
}
|
||||
|
||||
FillGridView(); //刷新界面
|
||||
});
|
||||
}
|
||||
}
|
||||
1673
Cowain.Bake.Main/ViewModels/EquipmentMonitorViewModel.cs
Normal file
24
Cowain.Bake.Main/ViewModels/MainHeaderViewModel.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using Prism.Mvvm;
|
||||
using Prism.Regions;
|
||||
using Unity;
|
||||
|
||||
namespace Cowain.Bake.Main.ViewModels
|
||||
{
|
||||
public class MainHeaderViewModel : BindableBase
|
||||
{
|
||||
IUnityContainer _unityContainer;
|
||||
public MainHeaderViewModel(IUnityContainer unityContainer, IRegionManager regionManager)
|
||||
{
|
||||
_unityContainer = unityContainer;
|
||||
//userInfo = _unityContainer.Resolve<GlobalEntity>();
|
||||
|
||||
////可以看到这种声明方式,提供了一个ObservesProperty方法,不需要显示调用命令状态改变事件,ObservesProperty(属性观察)
|
||||
////属性观察,如果有变化,就触发CanExecute
|
||||
|
||||
//ExecuteAutoCommand = new DelegateCommand(AutoExecute, AutoCanExecute).ObservesProperty(() => IsAutoEnabled);
|
||||
//ExecuteManualCommand = new DelegateCommand(ManualExecute, ManualCanExecute).ObservesProperty(() => IsManualEnabled);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
262
Cowain.Bake.Main/ViewModels/MainWindowViewModel.cs
Normal file
@@ -0,0 +1,262 @@
|
||||
using Cowain.Bake.BLL;
|
||||
using Cowain.Bake.Common;
|
||||
using Cowain.Bake.Common.Core;
|
||||
using Cowain.Bake.Common.Enums;
|
||||
using Cowain.Bake.Main.Models;
|
||||
using Cowain.Bake.Main.Views;
|
||||
using Cowain.Bake.Model;
|
||||
using Cowain.Bake.Model.Models;
|
||||
using Prism.Commands;
|
||||
using Prism.Events;
|
||||
using Prism.Mvvm;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using Unity;
|
||||
|
||||
namespace Cowain.Bake.Main.ViewModels
|
||||
{
|
||||
public class MainWindowViewModel : BindableBase
|
||||
{
|
||||
private string promptContent = "";
|
||||
public string PromptContent
|
||||
{
|
||||
get { return promptContent; }
|
||||
set { SetProperty<string>(ref promptContent, value); }
|
||||
}
|
||||
private string recentMsg; //最新的消息
|
||||
readonly IUnityContainer _unityContainer;
|
||||
private SubscriptionToken _subscriptionToken;
|
||||
private readonly IEventAggregator _eventAggregator;
|
||||
//缩放因子,用于调整在不同分辨率屏幕的位置
|
||||
public MainWindowViewModel(IUnityContainer unityContainer, IEventAggregator eventAggregator)
|
||||
{
|
||||
_unityContainer = unityContainer;
|
||||
//Global.STOVE_LAYERS = _unityContainer.Resolve<MemoryDataProvider>().AllStation.Find(x => x.Type ==(int)EStationType.Stove).Layers;
|
||||
MainTitle = SettingProvider.Instance.ProductionLineName + Global.VS;
|
||||
SetlogDict();
|
||||
LogHelper.Instance.Warn($"-------------{Global.VS}------------------");
|
||||
LogHelper.Instance.Debug($"-------------{Global.VS}------------------");
|
||||
LogHelper.Instance.Error($"-------------{Global.VS}------------------");
|
||||
LogHelper.Instance.Fatal($"-------------{Global.VS}------------------");
|
||||
LogHelper.Instance.Info($"-------------{Global.VS}------------------");
|
||||
InitializeLogLevels();
|
||||
_eventAggregator = eventAggregator;
|
||||
_subscriptionToken = _eventAggregator.GetEvent<AlarmAddEvent>() //Unsubscribe: 取消订阅(如在组件销毁时)
|
||||
.Subscribe(OnAddAlarm, ThreadOption.UIThread); //事件触发时执行的方法,ThreadOption.UIThread,(默认):在发布事件的线程执行
|
||||
|
||||
_subscriptionToken = _eventAggregator.GetEvent<AlarmCancelEvent>()
|
||||
.Subscribe(OnCancelAlarm, ThreadOption.UIThread);
|
||||
|
||||
_subscriptionToken = _eventAggregator.GetEvent<AlarmStaionCancelEvent>()
|
||||
.Subscribe(OnCancelAlarm, ThreadOption.UIThread);
|
||||
|
||||
}
|
||||
|
||||
private void OnAddAlarm(TAlarm alarm)
|
||||
{
|
||||
var model = Alarms.Where(item => item.StationId == alarm.StationId && item.Desc == alarm.Desc).FirstOrDefault();
|
||||
|
||||
if (null == model)
|
||||
{
|
||||
Alarms.Add(alarm);
|
||||
}
|
||||
|
||||
//ShowPromptContent();
|
||||
}
|
||||
|
||||
private void OnCancelAlarm(TAlarm alarm)
|
||||
{
|
||||
var model = Alarms.Where(item => item.StationId == alarm.StationId && item.Desc == alarm.Desc).FirstOrDefault();
|
||||
|
||||
if (null != model)
|
||||
{
|
||||
Alarms.Remove(model);
|
||||
}
|
||||
|
||||
//ShowPromptContent();
|
||||
}
|
||||
|
||||
private void OnCancelAlarm(int stationId)
|
||||
{
|
||||
var models = Alarms.Where(item => item.StationId == stationId).ToList();
|
||||
|
||||
foreach (var model in models)
|
||||
{
|
||||
Alarms.Remove(model);
|
||||
}
|
||||
|
||||
//ShowPromptContent();
|
||||
}
|
||||
public void ShowPromptContent()
|
||||
{
|
||||
int index = 0;
|
||||
PromptContent = "";
|
||||
foreach (var item in Alarms.Reverse())
|
||||
{
|
||||
if (++index > 2)
|
||||
{
|
||||
return; //数据太多了,就会卡,所以只让显示二条数据
|
||||
}
|
||||
PromptContent += item.Desc + " "; //太多了,界面卡
|
||||
}
|
||||
}
|
||||
|
||||
public void AddPromptContent(string msg)
|
||||
{
|
||||
//string addContent = promptContent;
|
||||
//if (string.IsNullOrEmpty(addContent))
|
||||
//{
|
||||
// addContent = msg;
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// var parts = addContent.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
// if (!parts.Contains(msg))
|
||||
// {
|
||||
// addContent += "|" + msg;
|
||||
// }
|
||||
//}
|
||||
|
||||
//if (promptContent == addContent)
|
||||
//{
|
||||
// return;
|
||||
//}
|
||||
;
|
||||
PromptContent = $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} : {msg}";
|
||||
}
|
||||
|
||||
public void DeletePromptContent(string msg ="")
|
||||
{
|
||||
string deleteContent = promptContent;
|
||||
if (string.IsNullOrEmpty(deleteContent))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//if (!deleteContent.Contains(msg))
|
||||
//{
|
||||
// return;
|
||||
//}
|
||||
|
||||
//var parts = deleteContent.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries)
|
||||
// .Select(p => p.Trim())
|
||||
// .Where(p => p != msg)
|
||||
// .ToList();
|
||||
//deleteContent = string.Join("|", parts);
|
||||
|
||||
PromptContent = "";
|
||||
}
|
||||
|
||||
|
||||
private void InitializeLogLevels()
|
||||
{
|
||||
var logTypes = EnumHelper.GetEnumList<E_LogType>();
|
||||
for (int i = 0; i < (logTypes.Count - 3); i++)
|
||||
{
|
||||
LogLevelModel1.Add(new MultiComboBox.MultiCbxBaseData
|
||||
{
|
||||
Id = i,
|
||||
IsCheck = true,
|
||||
ViewName = logTypes[i].EnumString.ToString()
|
||||
});
|
||||
}
|
||||
LogHelper.Instance.OnShowInvoke = LogShow;
|
||||
}
|
||||
|
||||
private Dictionary<E_LogType, (string FontColor, MessageBoxImage Image)> logDict;
|
||||
private void SetlogDict()
|
||||
{
|
||||
logDict = new Dictionary<E_LogType, (string, MessageBoxImage)>
|
||||
{
|
||||
{ E_LogType.Debug, ("#5352ed", MessageBoxImage.Exclamation) },
|
||||
{ E_LogType.Info, ("#1abc9c", MessageBoxImage.Information) },
|
||||
{ E_LogType.Warn, ("#eccc68", MessageBoxImage.Warning) },
|
||||
{ E_LogType.Error, ("red", MessageBoxImage.Error) },
|
||||
{ E_LogType.Fatal, ("red", MessageBoxImage.Error) }
|
||||
};
|
||||
}
|
||||
private void LogShow(string log, bool ispopup, E_LogType logType)
|
||||
{
|
||||
if (recentMsg == log && !ispopup)
|
||||
{
|
||||
return;
|
||||
}
|
||||
recentMsg = log;
|
||||
DateTime date = DateTime.Now;
|
||||
if (logDict.TryGetValue(logType, out var logInfo))
|
||||
{
|
||||
InfoLogModel = new LogModel
|
||||
{
|
||||
LogLevel = logType.ToString(),
|
||||
LogText = log,
|
||||
LogTime = date,
|
||||
FontColor = logInfo.FontColor
|
||||
};
|
||||
if (ispopup)
|
||||
{
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
HandyControl.Controls.MessageBox.Show(log, logType.GetDescription(), MessageBoxButton.OK, logInfo.Image);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public DelegateCommand<object> AlarmQueryCommand => new DelegateCommand<object>((x) =>
|
||||
{
|
||||
HistoryAlarmsData.Clear();
|
||||
var service = _unityContainer.Resolve<AlarmService>();
|
||||
service.GetAlarmReport(AlarmStartTime, AlarmEndTime).ForEach(item => HistoryAlarmsData.Add(item));
|
||||
});
|
||||
#region 定义
|
||||
private string mainTitle;
|
||||
public string MainTitle
|
||||
{
|
||||
get => mainTitle;
|
||||
set => SetProperty(ref mainTitle, value);
|
||||
}
|
||||
|
||||
private LogModel logModel1;
|
||||
public LogModel InfoLogModel
|
||||
{
|
||||
get => logModel1;
|
||||
set => SetProperty(ref logModel1, value);
|
||||
}
|
||||
|
||||
private ObservableCollection<MultiComboBox.MultiCbxBaseData> logLevelModel1 = new ObservableCollection<MultiComboBox.MultiCbxBaseData>();
|
||||
public ObservableCollection<MultiComboBox.MultiCbxBaseData> LogLevelModel1
|
||||
{
|
||||
get => logLevelModel1;
|
||||
set => SetProperty(ref logLevelModel1, value);
|
||||
}
|
||||
|
||||
private string alarmStartTime = DateTime.Now.ToString("yyyy-MM-dd");
|
||||
public string AlarmStartTime
|
||||
{
|
||||
get => alarmStartTime;
|
||||
set => SetProperty(ref alarmStartTime, value);
|
||||
}
|
||||
private string alarmEndTime = DateTime.Now.ToString("yyyy-MM-dd");
|
||||
public string AlarmEndTime
|
||||
{
|
||||
get => alarmEndTime;
|
||||
set => SetProperty(ref alarmEndTime, value);
|
||||
}
|
||||
private ObservableCollection<TAlarm> alarms = new ObservableCollection<TAlarm>();
|
||||
public ObservableCollection<TAlarm> Alarms
|
||||
{
|
||||
get => alarms;
|
||||
set => SetProperty(ref alarms, value);
|
||||
}
|
||||
private ObservableCollection<TAlarm> historyAlarms = new ObservableCollection<TAlarm>();
|
||||
public ObservableCollection<TAlarm> HistoryAlarmsData
|
||||
{
|
||||
get => historyAlarms;
|
||||
set => SetProperty(ref historyAlarms, value);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
123
Cowain.Bake.Main/ViewModels/ManualTaskViewModel.cs
Normal file
@@ -0,0 +1,123 @@
|
||||
using Cowain.Bake.BLL;
|
||||
using Cowain.Bake.Common;
|
||||
using Cowain.Bake.Common.Core;
|
||||
using Cowain.Bake.Common.Enums;
|
||||
using Cowain.Bake.Main.Station;
|
||||
using Cowain.Bake.Model;
|
||||
using Cowain.Bake.Model.Entity;
|
||||
using Cowain.Bake.Model.Models;
|
||||
using Newtonsoft.Json;
|
||||
using Prism.Commands;
|
||||
using Prism.Mvvm;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using Unity;
|
||||
|
||||
namespace Cowain.Bake.Main.ViewModels
|
||||
{
|
||||
public class ManualTaskViewModel: BindableBase
|
||||
{
|
||||
private IUnityContainer _unityContainer;
|
||||
private string selectFromValue;
|
||||
|
||||
public string SelectFromValue
|
||||
{
|
||||
get => selectFromValue;
|
||||
set => SetProperty(ref selectFromValue, value);
|
||||
}
|
||||
private string selectToValue;
|
||||
public string SelectToValue
|
||||
{
|
||||
get => selectToValue;
|
||||
set => SetProperty(ref selectToValue, value);
|
||||
}
|
||||
//不写set;get还设置不了这里的值
|
||||
public List<string> StationDtl { set; get; } = new List<string>();
|
||||
public void GetStationDtl()
|
||||
{
|
||||
List<string> table = _unityContainer.Resolve<CavityInfoService>().GetCanUseStationName();
|
||||
foreach (var item in table)
|
||||
{
|
||||
StationDtl.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
public ManualTaskViewModel(IUnityContainer unityContainer)
|
||||
{
|
||||
_unityContainer = unityContainer;
|
||||
}
|
||||
|
||||
public DelegateCommand GenerateTaskCommand => new DelegateCommand(() =>
|
||||
{
|
||||
GenerateTask();
|
||||
});
|
||||
|
||||
private void GenerateTask()
|
||||
{
|
||||
if (SettingProvider.Instance.DispMode == EDispatchMode.Auto)
|
||||
{
|
||||
HandyControl.Controls.Growl.Warning("自动调度,不能手动生成任务!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(selectFromValue)
|
||||
|| string.IsNullOrEmpty(SelectToValue))
|
||||
{
|
||||
HandyControl.Controls.Growl.Error("取放为空,不能手动生成任务!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (_unityContainer.Resolve<TaskRecordService>().UnexecuteTask() != null)
|
||||
{
|
||||
HandyControl.Controls.Growl.Warning("还有调度任务没有执行完成,不能手动生成任务!");
|
||||
return;
|
||||
}
|
||||
|
||||
TCavityInfo fromTable = _unityContainer.Resolve<CavityInfoService>().GetStationID(selectFromValue);
|
||||
TCavityInfo toTable = _unityContainer.Resolve<CavityInfoService>().GetStationID(SelectToValue);
|
||||
|
||||
Cowain.Bake.Model.TTaskRecord taskRecord = new Model.TTaskRecord();
|
||||
if (0 == fromTable.PalletId)
|
||||
{
|
||||
LogHelper.Instance.Error("添加失败,取位置无托盘记忆!", true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!fromTable.IsLoad)
|
||||
{
|
||||
LogHelper.Instance.Error("添加失败,取位置感应不到夹具到位!", true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (0 != toTable.PalletId || toTable.IsLoad)
|
||||
{
|
||||
LogHelper.Instance.Error("添加失败,放位置有托盘信息!", true);
|
||||
return;
|
||||
}
|
||||
|
||||
TPalletInfo palletInfo = _unityContainer.Resolve<PalletInfoService>().GetPalletInfo(fromTable.PalletId);
|
||||
if (palletInfo.PalletStatus == (int)EPalletStatus.Bake)
|
||||
{
|
||||
LogHelper.Instance.Error("添加失败,无法将在烘烤中的托盘添加到任务!", true);
|
||||
return;
|
||||
}
|
||||
taskRecord.PalletId = fromTable.PalletId;
|
||||
taskRecord.TaskTypeId = 0;
|
||||
taskRecord.Source = fromTable.Id;
|
||||
taskRecord.Target = toTable.Id;
|
||||
taskRecord.Status = (int)ETaskStatus.UnExecute;
|
||||
taskRecord.BuildTime = DateTime.Now;
|
||||
taskRecord.StepId = (int)ETaskStep.Unexecuted;
|
||||
if (0 == _unityContainer.Resolve<TaskRecordService>().Insert(taskRecord))
|
||||
{
|
||||
LogHelper.Instance.Error("插入任务到数据库失败!", true);
|
||||
return;
|
||||
}
|
||||
|
||||
_unityContainer.Resolve<TaskStation>()._newTaskEvent.Set();
|
||||
LogHelper.Instance.Info($"插入任务成功!{JsonConvert.SerializeObject(taskRecord)}");
|
||||
HandyControl.Controls.MessageBox.Success("已添加成功!");
|
||||
}
|
||||
}
|
||||
}
|
||||
156
Cowain.Bake.Main/ViewModels/MoistureValueViewMode.cs
Normal file
@@ -0,0 +1,156 @@
|
||||
using Cowain.Bake.BLL;
|
||||
using Cowain.Bake.Common.Core;
|
||||
using Cowain.Bake.Common.Enums;
|
||||
using Cowain.Bake.Model;
|
||||
using Cowain.Bake.Model.Models;
|
||||
using Newtonsoft.Json;
|
||||
using Prism.Commands;
|
||||
using Prism.Mvvm;
|
||||
using Prism.Services.Dialogs;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using Unity;
|
||||
|
||||
namespace Cowain.Bake.Main.ViewModels
|
||||
{
|
||||
internal class MoistureValueViewMode: BindableBase//, Prism.Services.Dialogs.IDialogAware
|
||||
{
|
||||
private readonly IUnityContainer _unityContainer;
|
||||
private float? septumwaterJudge;
|
||||
private float? cathodewaterJudge;
|
||||
private float? anodewaterJudge ;
|
||||
//public string WaterValueModel;
|
||||
List<WaterModel> waterModels = null;
|
||||
public CavityDtlViewModel thatParent = null;
|
||||
|
||||
//public string Title => "输入水含量值";
|
||||
//// 弹窗打开时触发:读取传递的参数
|
||||
//public void OnDialogOpened(IDialogParameters parameters)
|
||||
//{
|
||||
// thatParent = parameters.GetValue<CavityDtlViewModel>("this");
|
||||
// WaterValueModel = thatParent.WaterValueModel ?? "";
|
||||
//}
|
||||
|
||||
//// 允许关闭弹窗(返回true即可)
|
||||
//public bool CanCloseDialog() => true;
|
||||
|
||||
//// 弹窗关闭后清理资源(可选)
|
||||
//public void OnDialogClosed() { }
|
||||
|
||||
//// Prism 8中用于触发弹窗关闭的事件
|
||||
//public event Action<IDialogResult> RequestClose;
|
||||
|
||||
//public DelegateCommand CloseCommand =>
|
||||
// new DelegateCommand(() =>
|
||||
// RequestClose?.Invoke(new DialogResult(ButtonResult.OK)));
|
||||
|
||||
|
||||
|
||||
public MoistureValueViewMode(IUnityContainer unityContainer)
|
||||
{
|
||||
_unityContainer = unityContainer;
|
||||
}
|
||||
|
||||
public float? SeptumWaterJudge //隔离膜水分
|
||||
{
|
||||
get => septumwaterJudge;
|
||||
set => SetProperty(ref septumwaterJudge, value);
|
||||
}
|
||||
public float? AnodeWaterJudge //正极水分
|
||||
{
|
||||
get => anodewaterJudge;
|
||||
set => SetProperty(ref anodewaterJudge, value);
|
||||
}
|
||||
public float? CathodeWaterJudge //负极水分
|
||||
{
|
||||
get => cathodewaterJudge;
|
||||
set => SetProperty(ref cathodewaterJudge, value);
|
||||
}
|
||||
|
||||
|
||||
public DelegateCommand<object> Judge => new DelegateCommand<object>((x) =>
|
||||
{
|
||||
int septumwaterTargetValue = int.Parse(_unityContainer.Resolve<SysSetupService>().GetValueByParaID(ESysSetup.SeptumwaterTargetJudge.ToString()));
|
||||
int cathodewaterTargetValue = int.Parse(_unityContainer.Resolve<SysSetupService>().GetValueByParaID(ESysSetup.CathodewaterTargetJudge.ToString()));
|
||||
int anodewaterTargetValue = int.Parse(_unityContainer.Resolve<SysSetupService>().GetValueByParaID(ESysSetup.AnodewaterTargetJudge.ToString()));
|
||||
//MessageBoxResult result = HandyControl.Controls.MessageBox.Ask($@"是否确定为手动输入的水含量值?", "操作提示");
|
||||
//if (result == System.Windows.MessageBoxResult.Cancel)
|
||||
//{
|
||||
// return;
|
||||
//}
|
||||
LogHelper.Instance.Warn($"开始测水含量0!");
|
||||
if (!septumwaterJudge.HasValue
|
||||
|| !anodewaterJudge.HasValue
|
||||
|| !cathodewaterJudge.HasValue
|
||||
)
|
||||
{
|
||||
HandyControl.Controls.MessageBox.Warning("数值为空, 请人工输入!");
|
||||
return;
|
||||
}
|
||||
|
||||
var WaterModel = new WaterModel();
|
||||
WaterModel.AnodeWaterValue = anodewaterJudge.ToString();
|
||||
WaterModel.CathodeWaterValue = cathodewaterJudge.ToString();
|
||||
WaterModel.SeptumWaterValue = septumwaterJudge.ToString();
|
||||
int palletStatus = (int)EPalletStatus.TestOK;
|
||||
if (septumwaterJudge >= septumwaterTargetValue
|
||||
|| cathodewaterJudge >= cathodewaterTargetValue
|
||||
|| anodewaterJudge >= anodewaterTargetValue)
|
||||
{
|
||||
palletStatus = (int)EPalletStatus.TestNG;
|
||||
MessageBoxResult judgeResult = HandyControl.Controls.MessageBox.Ask($@"本次判定水含量值为NG,请确认!", "判定提示");
|
||||
if (judgeResult == System.Windows.MessageBoxResult.Cancel)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//WaterValueModel,在这个界面点【判定】,会刷新这个值。也就是这个判断结果会累加,但在【工站明细】中不会
|
||||
waterModels = JsonConvert.DeserializeObject<List<WaterModel>>(thatParent.WaterValueModel??""); //WaterValueModel:数据库中的水含量数据
|
||||
WaterModel.BatteryCode = GetBatteryCode(waterModels);
|
||||
if (null == waterModels)
|
||||
{
|
||||
waterModels = new List<WaterModel>();
|
||||
}
|
||||
else
|
||||
{
|
||||
WaterModel.Id = waterModels.Max(w => w.Id) + 1;
|
||||
}
|
||||
waterModels.Add(WaterModel);
|
||||
|
||||
thatParent.MoistureRuturn(palletStatus, JsonConvert.SerializeObject(waterModels));
|
||||
HandyControl.Controls.MessageBox.Info("设置测试水含量成功");
|
||||
});
|
||||
|
||||
string GetBatteryCode(List<WaterModel> waterList)
|
||||
{
|
||||
var dummys = _unityContainer.Resolve<BatteryInfoService>().GetWaterBatteryCode(thatParent.VirtualId);
|
||||
|
||||
if (0 == dummys.Count)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
if (waterList == null
|
||||
|| 0 == waterList.Count)
|
||||
{
|
||||
return dummys[0].BatteryCode;
|
||||
}
|
||||
|
||||
List<string> dummyCodes = dummys.Select(x => x.BatteryCode).ToList();
|
||||
List<string> waterCodes = waterList.Select(x => x.BatteryCode).ToList();
|
||||
// 查找 list1 中不在 list2 中的字符串 var notInList2 = list1.Except(list2);
|
||||
var batteryCode = dummyCodes.Except(waterCodes);
|
||||
if (0 ==batteryCode.Count())
|
||||
{
|
||||
return waterList.OrderByDescending(x => x.Id).FirstOrDefault().BatteryCode;//最后一次的假电芯码
|
||||
}
|
||||
return batteryCode.First();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
28
Cowain.Bake.Main/ViewModels/PalletIdInputWindowViewModel.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using Cowain.Bake.Common;
|
||||
using Prism.Regions;
|
||||
using Unity;
|
||||
|
||||
namespace Cowain.Bake.Main.ViewModels
|
||||
{
|
||||
public class PalletIdInputWindowViewModel : ViewModelBase
|
||||
{
|
||||
private string _title;
|
||||
|
||||
public string Title
|
||||
{
|
||||
get => _title;
|
||||
set => SetProperty(ref _title, value);
|
||||
}
|
||||
|
||||
private string _msgContent;
|
||||
|
||||
public string MsgContent
|
||||
{
|
||||
get => _msgContent;
|
||||
set => SetProperty(ref _msgContent, value);
|
||||
}
|
||||
public PalletIdInputWindowViewModel(IUnityContainer unityContainer, IRegionManager regionManager) : base(unityContainer, regionManager)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
49
Cowain.Bake.Main/Views/AddBatteryView.xaml
Normal file
@@ -0,0 +1,49 @@
|
||||
<Window x:Class="Cowain.Bake.Main.Views.AddBatteryView"
|
||||
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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:Cowain.Bake.Main.Views"
|
||||
xmlns:prism ="http://prismlibrary.com/"
|
||||
|
||||
mc:Ignorable="d"
|
||||
Title="添加电芯" Height="336" Width="380" ResizeMode="NoResize" WindowStartupLocation="CenterScreen">
|
||||
<Grid Background="DodgerBlue">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="4*"/>
|
||||
<RowDefinition Height="1*"/>
|
||||
</Grid.RowDefinitions>
|
||||
<StackPanel>
|
||||
<WrapPanel Margin="10,30,0,0" >
|
||||
<TextBlock Text="电芯条码:" Margin="50,10,10,0" ></TextBlock>
|
||||
<TextBox HorizontalAlignment="Center" Text="{Binding BatteryCode}" Width="230" ></TextBox>
|
||||
</WrapPanel>
|
||||
<WrapPanel Margin="10,10,0,0" >
|
||||
<TextBlock Text="夹具行号:" Margin="50,10,10,0" ></TextBlock>
|
||||
<ComboBox HorizontalAlignment="Center" ItemsSource="{Binding PositionXRange}" SelectedValue="{Binding SelectedPositionX, Mode=TwoWay}" VerticalAlignment="Center" Width="230"></ComboBox>
|
||||
</WrapPanel>
|
||||
<WrapPanel Margin="10,10,0,0" >
|
||||
<TextBlock Text="夹具列号:" Margin="50,10,10,0" ></TextBlock>
|
||||
<ComboBox HorizontalAlignment="Center" ItemsSource="{Binding PositionYRange}" SelectedValue="{Binding SelectedPositionY, Mode=TwoWay}" VerticalAlignment="Center" Width="230"></ComboBox>
|
||||
</WrapPanel>
|
||||
<WrapPanel Margin="10,10,0,0" >
|
||||
<TextBlock Text="电芯状态:" Margin="50,10,10,0" ></TextBlock>
|
||||
<ComboBox HorizontalAlignment="Center" ItemsSource="{Binding EnumOptions}"
|
||||
DisplayMemberPath="Value"
|
||||
SelectedValuePath="Key"
|
||||
SelectedValue="{Binding SelectedEnum, Mode=TwoWay}" VerticalAlignment="Center" Width="230"></ComboBox>
|
||||
</WrapPanel>
|
||||
<WrapPanel Margin="10,10,0,0" >
|
||||
<TextBlock Text="是否水含量电芯:" Margin="15,10,10,0" ></TextBlock>
|
||||
<ComboBox HorizontalAlignment="Center" VerticalAlignment="Center" Width="230" SelectedItem="{Binding SelectedOption}" ItemsSource="{Binding Options}">
|
||||
</ComboBox>
|
||||
</WrapPanel>
|
||||
</StackPanel>
|
||||
|
||||
<Grid Grid.Row="1">
|
||||
<WrapPanel Margin="10,10,0,0" >
|
||||
<Button Content="增 加" Margin="135,10,10,0" Width="80" Command="{Binding AddCommand}"></Button>
|
||||
</WrapPanel>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Window>
|
||||
27
Cowain.Bake.Main/Views/AddBatteryView.xaml.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
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.Shapes;
|
||||
|
||||
namespace Cowain.Bake.Main.Views
|
||||
{
|
||||
/// <summary>
|
||||
/// AddBatteryView.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class AddBatteryView : Window
|
||||
{
|
||||
public AddBatteryView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
70
Cowain.Bake.Main/Views/BasicInfoView.xaml
Normal file
@@ -0,0 +1,70 @@
|
||||
<UserControl x:Class="Cowain.Bake.Main.Views.BasicInfoView"
|
||||
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:Cowain.Bake.Main.Views"
|
||||
mc:Ignorable="d"
|
||||
xmlns:prism="http://prismlibrary.com/"
|
||||
prism:ViewModelLocator.AutoWireViewModel="True"
|
||||
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Grid Background="#66FFFFFF">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="0.03*"/>
|
||||
<RowDefinition Height="0.07*"/>
|
||||
<RowDefinition Height="0.07*"/>
|
||||
<RowDefinition Height="0.07*"/>
|
||||
<RowDefinition Height="0.07*"/>
|
||||
<RowDefinition Height="0.07*"/>
|
||||
<RowDefinition Height="0.07*"/>
|
||||
<RowDefinition Height="0.07*"/>
|
||||
<RowDefinition Height="0.07*"/>
|
||||
<RowDefinition/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="0.05*"/>
|
||||
<ColumnDefinition Width="0.4*"/>
|
||||
<ColumnDefinition Width="0.5*"/>
|
||||
<ColumnDefinition Width="0.05*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBlock Grid.Column="1" Text="用户:" Grid.Row="1"
|
||||
Height="34" FontSize="16" Background="Transparent"/>
|
||||
<TextBlock Grid.Column="2" Text="{Binding UserId,UpdateSourceTrigger=PropertyChanged}" Grid.Row="1"
|
||||
Height="34" FontSize="16" Background="Transparent"/>
|
||||
|
||||
<TextBlock Grid.Column="1" Text="姓名:" Grid.Row="2"
|
||||
Height="34" FontSize="16" Background="Transparent"/>
|
||||
<TextBlock Grid.Column="2" Text="{Binding UserName,UpdateSourceTrigger=PropertyChanged}" Grid.Row="2"
|
||||
Height="34" FontSize="16" Background="Transparent"/>
|
||||
|
||||
<TextBlock Text="工单:" Grid.Row="3" FontSize="16" Background="Transparent" Grid.Column="1"/>
|
||||
<TextBlock Grid.Column="2" Text="{Binding CurrentJobNum,UpdateSourceTrigger=PropertyChanged}" Grid.Row="3"
|
||||
Height="34" FontSize="16" Background="Transparent"/>
|
||||
|
||||
<TextBlock Text="工艺:" Grid.Row="4" FontSize="16" Background="Transparent" Grid.Column="1"/>
|
||||
<TextBlock Grid.Column="2" Text="{Binding CurrentOperation,UpdateSourceTrigger=PropertyChanged}" Grid.Row="4"
|
||||
Height="34" FontSize="16" Background="Transparent"/>
|
||||
|
||||
<TextBlock Text="露点温度:" Grid.Row="5" FontSize="16" Background="Transparent" Grid.Column="1"/>
|
||||
<TextBlock Grid.Column="2" Text="{Binding FailPointData,UpdateSourceTrigger=PropertyChanged}" Grid.Row="5"
|
||||
Height="34" FontSize="16" Background="Transparent"/>
|
||||
|
||||
<TextBlock Text="设备状态:" Grid.Row="6" FontSize="16" Background="Transparent" Grid.Column="1"/>
|
||||
<TextBlock Grid.Column="2" Text="{Binding DeviceStatusName,UpdateSourceTrigger=PropertyChanged}" Grid.Row="6"
|
||||
Height="34" FontSize="16" Background="Transparent"/>
|
||||
|
||||
<TextBlock Text="调度模式:" Grid.Row="7" FontSize="16" Background="Transparent" Grid.Column="1"/>
|
||||
<TextBlock Grid.Column="2" Text="{Binding DispMode,UpdateSourceTrigger=PropertyChanged}" Grid.Row="7" FontWeight="Bold"
|
||||
Height="34" FontSize="16" Background="Transparent" Foreground="Blue"/>
|
||||
|
||||
<TextBlock Text="MOM状态:" FontSize="16" Grid.Row="8" Grid.Column="1"/>
|
||||
<Border Grid.Row="8" Grid.Column="2" CornerRadius="20" HorizontalAlignment="Left" Margin="4,0,0,13" Background="{Binding StatusColor}" Height="15" Width="15" />
|
||||
|
||||
<GroupBox Header="触发信号" Grid.ColumnSpan="4" Grid.Row="9">
|
||||
<ListBox ItemsSource="{Binding EventList}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
|
||||
</GroupBox>
|
||||
</Grid>
|
||||
|
||||
</UserControl>
|
||||
25
Cowain.Bake.Main/Views/BasicInfoView.xaml.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using Prism.Regions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using Unity;
|
||||
|
||||
namespace Cowain.Bake.Main.Views
|
||||
{
|
||||
/// <summary>
|
||||
/// BasicInfoView.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class BasicInfoView : UserControl
|
||||
{
|
||||
public BasicInfoView(IUnityContainer unityContainer, IRegionManager regionManager)
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
97
Cowain.Bake.Main/Views/CavityDtlView.xaml
Normal file
@@ -0,0 +1,97 @@
|
||||
<Window x:Class="Cowain.Bake.Main.Views.CavityDtlView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:convertor="clr-namespace:Cowain.Bake.Common.Converter;assembly=Cowain.Bake.Common"
|
||||
mc:Ignorable="d"
|
||||
WindowStartupLocation="CenterScreen"
|
||||
Height="586" Width="1000"
|
||||
MinWidth="1000"
|
||||
MaxWidth="1000"
|
||||
MinHeight="586"
|
||||
MaxHeight="586">
|
||||
<Window.Resources>
|
||||
<convertor:BatteryStatusConvertor x:Key="cellStatusConvertor"></convertor:BatteryStatusConvertor>
|
||||
</Window.Resources>
|
||||
<Grid Background="DodgerBlue">
|
||||
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="101*"/>
|
||||
<ColumnDefinition Width="66*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBox x:Name="stationName" FontWeight="Bold" IsReadOnly="True" HorizontalAlignment="Left" Height="23" Margin="90,15,0,0" TextWrapping="Wrap" Text="{Binding StationName,Mode=TwoWay}" VerticalAlignment="Top" Width="120"/>
|
||||
<DataGrid x:Name="mainGrid" IsReadOnly="True" ItemsSource="{Binding BatteryDtl2}" AutoGenerateColumns="False" HorizontalAlignment="Left" Height="435" Margin="7,145,0,0"
|
||||
SelectedItem="{Binding BatteryInfoSelectedItem, Mode=TwoWay}" VerticalAlignment="Top" Width="990" Grid.ColumnSpan="2">
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn Binding="{Binding BatteryCode}" Width="220" Header="电池条码"/>
|
||||
<DataGridTextColumn Binding="{Binding BatteryStatus, Converter={StaticResource cellStatusConvertor}}" Width="100" Header="电池状态"/>
|
||||
<DataGridTextColumn Binding="{Binding PositionX}" Width="95" Header="电池行坐标"/>
|
||||
<DataGridTextColumn Binding="{Binding PositionY}" Width="95" Header="电池列坐标"/>
|
||||
<!--<DataGridTextColumn Binding="{Binding DummyFlag}" Width="95" Header="水含量电芯"/>-->
|
||||
<DataGridTemplateColumn Header="水含量电芯" Width="80" >
|
||||
<DataGridTemplateColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<CheckBox HorizontalAlignment="Center" IsChecked="{Binding DummyFlag,Mode=TwoWay}" >
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="Click">
|
||||
<i:InvokeCommandAction Command="{Binding DataContext.ChangeDummyCommand, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</CheckBox>
|
||||
</DataTemplate>
|
||||
</DataGridTemplateColumn.CellTemplate>
|
||||
</DataGridTemplateColumn>
|
||||
|
||||
<DataGridTextColumn Binding="{Binding BindingTime,StringFormat='yyyy-MM-dd HH:mm:ss'}" Width="170" Header="与托盘绑定时间"/>
|
||||
<DataGridTemplateColumn Header="操作" Width="80">
|
||||
<DataGridTemplateColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<StackPanel Grid.Column="4" VerticalAlignment="Center" HorizontalAlignment="Center" Orientation="Horizontal">
|
||||
<TextBlock Margin="3,0" >
|
||||
<Hyperlink Foreground="Red" Command="{Binding DataContext.DeleteCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid}}" CommandParameter="{Binding}">删除</Hyperlink>
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</DataGridTemplateColumn.CellTemplate>
|
||||
</DataGridTemplateColumn>
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
<Label Content="工站名称:" Foreground="White" FontWeight="Bold" Style="{DynamicResource BaseStyle}" HorizontalContentAlignment="Right" HorizontalAlignment="Left" Margin="0,16,0,0" VerticalAlignment="Top" Width="90"/>
|
||||
<Label Content="托盘条码:" Foreground="White" FontWeight="Bold" Style="{DynamicResource BaseStyle}" HorizontalContentAlignment="Right" HorizontalAlignment="Left" Margin="190,16,0,0" VerticalAlignment="Top" Width="90"/>
|
||||
<!--<TextBox Text="{Binding PalletCode}" FontWeight="Bold" HorizontalAlignment="Left" Height="23" Margin="285,15,0,0" VerticalAlignment="Top" Width="101"/>-->
|
||||
<ComboBox x:Name="palletCode" SelectedValue="{Binding PalletCode}" ItemsSource="{Binding PalletList}" FontWeight="Bold" IsReadOnly="True" HorizontalAlignment="Left" Height="23" Margin="285,15,0,0" VerticalAlignment="Top" Width="135"/>
|
||||
<Label Content="是否可用:" Foreground="White" FontWeight="Bold" Style="{DynamicResource BaseStyle}" HorizontalContentAlignment="Right" HorizontalAlignment="Left" Margin="540,16,0,0" VerticalAlignment="Top" Width="64"/>
|
||||
<TextBox x:Name="stationEnable" Text="{Binding StationEnable}" FontWeight="Bold" IsEnabled="False" HorizontalAlignment="Left" Height="23" Margin="3.2,15,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="55" Grid.Column="1"/>
|
||||
<Label Content="当前烘次:" Foreground="White" FontWeight="Bold" Style="{DynamicResource BaseStyle}" HorizontalContentAlignment="Right" HorizontalAlignment="Left" Margin="66,16,0,0" VerticalAlignment="Top" Width="64" Grid.Column="1"/>
|
||||
<TextBlock x:Name="rebakingNum" Text="{Binding BakingCount}" FontWeight="Bold" HorizontalAlignment="Left" Height="23" Margin="130.2,21,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="45" Grid.Column="1"/>
|
||||
<TextBlock x:Name="bakingBatteryNum" Text="{Binding BatteryCount}" FontWeight="Bold" HorizontalAlignment="Left" Height="24" Margin="216,21,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="40" Grid.Column="1"/>
|
||||
<Label Content="最后一盘:" Foreground="White" FontWeight="Bold" Style="{DynamicResource BaseStyle}" HorizontalContentAlignment="Right" HorizontalAlignment="Left" Margin="250,15,0,0" VerticalAlignment="Top" Width="66" Grid.Column="1"/>
|
||||
<ComboBox ItemsSource="{Binding LastPalletList}" IsEnabled ="{Binding LastEnabled}" FontWeight="Bold" SelectedValue="{Binding LastValue,Mode=TwoWay}" HorizontalAlignment="Left" Margin="325,15,0,0" VerticalAlignment="Top" Width="60" Grid.Column="1"/>
|
||||
<Label Content="电芯数量:" Foreground="White" FontWeight="Bold" Style="{DynamicResource BaseStyle}" HorizontalContentAlignment="Right" HorizontalAlignment="Left" Margin="146,15,0,0" VerticalAlignment="Top" Width="66" Grid.Column="1"/>
|
||||
<Label Content="所属工单:" Foreground="White" FontWeight="Bold" Style="{DynamicResource BaseStyle}" HorizontalContentAlignment="Right" HorizontalAlignment="Left" Margin="514,62,0,0" VerticalAlignment="Top" Width="90"/>
|
||||
<ComboBox ItemsSource="{Binding ArrJobNum}" SelectedValue="{Binding SelectedJobNum,Mode=TwoWay}" FontWeight="Bold" IsReadOnly="True" HorizontalAlignment="Left" Height="23" Margin="4.2,62,0,0" VerticalAlignment="Top" Width="228" Grid.Column="1"/>
|
||||
<Button Content="绑定" Command="{Binding BindJobNum}" HorizontalAlignment="Left" Width="66" Margin="250,62,0,0" VerticalAlignment="Top" Grid.Column="1"/>
|
||||
<Button Content="解绑" Command="{Binding UnBindJobNum}" HorizontalAlignment="Left" Width="66" Margin="320,62,0,0" VerticalAlignment="Top" Grid.Column="1"/>
|
||||
|
||||
|
||||
<ComboBox ItemsSource="{Binding PalletStatus}" FontWeight="Bold" SelectedValue="{Binding SelectedValue,Mode=TwoWay}" IsReadOnly="True" HorizontalAlignment="Left" Margin="285,57,0,0" VerticalAlignment="Top" Width="135"/>
|
||||
<Label Content="托盘状态:" Foreground="White" FontWeight="Bold" Style="{DynamicResource BaseStyle}" HorizontalContentAlignment="Right" HorizontalAlignment="Left" Margin="214,62,0,0" VerticalAlignment="Top" Width="66"/>
|
||||
<Button Content="更新" Command="{Binding UpdatePalletStatus}" HorizontalAlignment="Left" VerticalAlignment="Top" Width="56" Margin="422,57,0,0" />
|
||||
<Label Content="水份判断:" Foreground="White" FontWeight="Bold" Style="{DynamicResource BaseStyle}" HorizontalContentAlignment="Right" HorizontalAlignment="Left" Margin="0,62,0,0" VerticalAlignment="Top" Width="90"/>
|
||||
<Button Content="水分值输入" x:Name="moistureInput" IsEnabled ="{Binding IsEnabled}" Command="{Binding MoistureInput}" HorizontalAlignment="Left" VerticalAlignment="Top" Width="120" Margin="90,60,0,0"/>
|
||||
<Button Content="绑定" Command="{Binding UpdatePalletCode}" HorizontalAlignment="Left" VerticalAlignment="Top" Width="56" Margin="421,15,0,0"/>
|
||||
<Button Content="解绑" Command="{Binding UpdatePalletNoneCode}" HorizontalAlignment="Left" VerticalAlignment="Top" Width="56" Margin="477,15,0,0"/>
|
||||
<Label Content="是否带水:" Foreground="White" FontWeight="Bold" Style="{DynamicResource BaseStyle}" HorizontalContentAlignment="Right" HorizontalAlignment="Left" Margin="25,102,0,0" VerticalAlignment="Top" Width="66"/>
|
||||
<TextBox x:Name="IsWater" Text="{Binding IsWaterValue}" FontWeight="Bold" IsEnabled="False" HorizontalAlignment="Left" Height="23" Margin="90,100,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="50"/>
|
||||
<Button Content="增加电芯" Command="{Binding AddBatteryCommand}" IsEnabled ="{Binding IsEnabledAdd}" HorizontalAlignment="Left" VerticalAlignment="Top" Width="70" Margin="145,100,0,0"/>
|
||||
<Label Content="信息绑定:" Foreground="White" FontWeight="Bold" Style="{DynamicResource BaseStyle}" HorizontalContentAlignment="Right" HorizontalAlignment="Left" Margin="190,102,0,0" VerticalAlignment="Top" Width="90"/>
|
||||
<TextBox Text="{Binding VirtualId}" FontWeight="Bold" HorizontalAlignment="Left" Height="23" Margin="285,100,0,0" VerticalAlignment="Top" Width="135"/>
|
||||
<Button Content="绑定" Command="{Binding UpdateVirtualId}" HorizontalAlignment="Left" VerticalAlignment="Top" Width="56" Margin="421,100,0,0"/>
|
||||
<Label Content="工站备注:" Foreground="White" FontWeight="Bold" Style="{DynamicResource BaseStyle}" HorizontalContentAlignment="Right" HorizontalAlignment="Left" Margin="534,102,0,0" VerticalAlignment="Top" Width="66"/>
|
||||
<TextBox x:Name="stationRemark" FontWeight="Bold" HorizontalAlignment="Left" Height="23" Margin="5,102,0,0" TextWrapping="Wrap" Text="{Binding Remark,Mode=TwoWay}" VerticalAlignment="Top" Width="310" Grid.Column="1"/>
|
||||
<Button Content="备注" Command="{Binding AddRemark}" HorizontalAlignment="Left" Width="66" Margin="320,102,0,0" VerticalAlignment="Top" Grid.Column="1"/>
|
||||
</Grid>
|
||||
</Window>
|
||||
34
Cowain.Bake.Main/Views/CavityDtlView.xaml.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using Prism.Services.Dialogs;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
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.Shapes;
|
||||
using Unity;
|
||||
|
||||
namespace Cowain.Bake.Main.Views
|
||||
{
|
||||
/// <summary>
|
||||
/// StationDtl.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class CavityDtlView : Window
|
||||
{
|
||||
ViewModels.CavityDtlViewModel viewModel = null;
|
||||
public CavityDtlView(string stationNameIn, IUnityContainer unityContainer)
|
||||
{
|
||||
InitializeComponent();
|
||||
viewModel = new ViewModels.CavityDtlViewModel(unityContainer);
|
||||
this.DataContext = viewModel;
|
||||
viewModel.StationName = stationNameIn;
|
||||
viewModel.GetInfo();
|
||||
}
|
||||
}
|
||||
}
|
||||
152
Cowain.Bake.Main/Views/ComboBoxDictionary.xaml
Normal file
@@ -0,0 +1,152 @@
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="clr-namespace:Cowain.Bake.Main.Views">
|
||||
<!--ComboBox-->
|
||||
<!--ComBoBox项选中背景色-->
|
||||
<SolidColorBrush x:Key="ComboBoxSelectdBackground" Color="#ff8c69"/>
|
||||
<!--ComBoBox项鼠标经过背景色-->
|
||||
<SolidColorBrush x:Key="ComboBoxMouseOverBackground" Color="#ff3030"/>
|
||||
<!--ComBoBox项选中前景色-->
|
||||
<SolidColorBrush x:Key="ComboBoxSelectedForeground" Color="Black"/>
|
||||
<!--ComBoBox项鼠标经过前景色-->
|
||||
<SolidColorBrush x:Key="ComboBoxMouseOverForegrond" Color="White"/>
|
||||
|
||||
<ControlTemplate x:Key="ComboBoxToggleButton" TargetType="{x:Type ToggleButton}">
|
||||
<Grid Height="25" HorizontalAlignment="Stretch">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="30"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Border Background="White" Grid.ColumnSpan="2" Opacity="0"/>
|
||||
<Path x:Name="Arrow" Grid.Column="1" Data="M 0 0 6 6 12 0 Z" VerticalAlignment="Center" HorizontalAlignment="Center" Stretch="None" Fill="#999" />
|
||||
</Grid>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsChecked" Value="true">
|
||||
<Setter TargetName="Arrow" Property="RenderTransform">
|
||||
<Setter.Value>
|
||||
<RotateTransform CenterX="6" CenterY="3" Angle="180"></RotateTransform>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
<Setter TargetName="Arrow" Property="Margin" Value="0 0 0 2"/>
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
|
||||
|
||||
|
||||
<!--MultiComboBox普通样式-->
|
||||
<Style TargetType="{x:Type controls:MultiComboBox}">
|
||||
<Setter Property="Width" Value="200" />
|
||||
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
|
||||
<Setter Property="VerticalContentAlignment" Value="Center" />
|
||||
<Setter Property="SnapsToDevicePixels" Value="True" />
|
||||
<Setter Property="MaxDropDownHeight" Value="400" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type controls:MultiComboBox}">
|
||||
<Grid>
|
||||
<Border x:Name="Bg" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
|
||||
Width="{TemplateBinding Width}" Height="{TemplateBinding Height}"
|
||||
BorderBrush="#E0E0E0" CornerRadius="4"
|
||||
BorderThickness="1" >
|
||||
<Grid x:Name="PART_Root">
|
||||
|
||||
<Grid x:Name="PART_InnerGrid" Margin="0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="0.3*" MaxWidth="30" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<ListBox Margin="1" x:Name="PART_ListBoxChk" Background="#ADE5EF" SelectionMode="Multiple" BorderThickness="0" ScrollViewer.VerticalScrollBarVisibility="Disabled">
|
||||
<ListBox.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<VirtualizingStackPanel Orientation="Horizontal" VirtualizingStackPanel.IsVirtualizing="True" />
|
||||
</ItemsPanelTemplate>
|
||||
</ListBox.ItemsPanel>
|
||||
<ListBox.ItemContainerStyle>
|
||||
<Style TargetType="ListBoxItem">
|
||||
<Setter Property="BorderThickness" Value="0"/>
|
||||
<Setter Property="IsSelected" Value="True"/>
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="ListBoxItem">
|
||||
<CheckBox BorderThickness="0" Background="#212f3e" Foreground="Gray" VerticalAlignment="Center" HorizontalAlignment="Center" Content="{Binding ViewName}" IsChecked="{Binding Path=IsSelected,RelativeSource={RelativeSource TemplatedParent},Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</ListBox.ItemContainerStyle>
|
||||
</ListBox>
|
||||
|
||||
<!--下拉按钮-->
|
||||
<ToggleButton x:Name="PART_DropDownToggle" IsTabStop="False"
|
||||
IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
Grid.Column="1" Template="{StaticResource ComboBoxToggleButton}" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Border>
|
||||
<!--弹出多选列表-->
|
||||
<Popup x:Name="PART_Popup" AllowsTransparency="True" Focusable="False" StaysOpen="False"
|
||||
IsOpen="{Binding IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}" Placement="Bottom">
|
||||
<Grid Width="{Binding ActualWidth, RelativeSource={RelativeSource TemplatedParent}}" MaxHeight="{Binding MaxDropDownHeight, RelativeSource={RelativeSource TemplatedParent}}" >
|
||||
<ListBox x:Name="PART_ListBox" SelectionMode="Multiple" BorderThickness="1 0 1 1" Background="White" ItemsSource="{Binding ItemsSource,RelativeSource={RelativeSource TemplatedParent}}"
|
||||
MaxHeight="{TemplateBinding MaxDropDownHeight}" BorderBrush="#eaeaea" >
|
||||
<ListBox.ItemContainerStyle>
|
||||
<Style TargetType="ListBoxItem">
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type ListBoxItem}" >
|
||||
<Grid Height="22">
|
||||
<Border x:Name="bg" BorderBrush="#eaeaea" BorderThickness="0"/>
|
||||
<ContentPresenter x:Name="content" />
|
||||
<Border Background="White" Opacity="0"/>
|
||||
</Grid>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsSelected" Value="True">
|
||||
<Setter TargetName="bg" Property="Background" Value="#ADD6FF" />
|
||||
</Trigger>
|
||||
<MultiTrigger>
|
||||
<MultiTrigger.Conditions>
|
||||
<Condition Property="IsMouseOver" Value="true" />
|
||||
<Condition Property="IsSelected" Value="false"/>
|
||||
</MultiTrigger.Conditions>
|
||||
<Setter TargetName="bg" Property="Background" Value="#009BDB" />
|
||||
<Setter TargetName="bg" Property="Opacity" Value="0.7"/>
|
||||
<Setter Property="Foreground" Value="White" />
|
||||
</MultiTrigger>
|
||||
<Trigger Property="IsEnabled" Value="False">
|
||||
<Setter TargetName="bg" Property="Opacity" Value="0.3" />
|
||||
<Setter Property="Foreground" Value="Gray" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</ListBox.ItemContainerStyle>
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Grid>
|
||||
<CheckBox x:Name="chk" Visibility="Hidden" IsChecked="{Binding IsCheck,Mode=TwoWay}" VerticalAlignment="Center"/>
|
||||
<CheckBox VerticalAlignment="Center" Foreground="{Binding Foreground,RelativeSource={RelativeSource AncestorType=ListBoxItem}}" IsChecked="{Binding RelativeSource={RelativeSource AncestorType=ListBoxItem},Path=IsSelected,Mode=TwoWay}" Content="{Binding Path=ViewName}" />
|
||||
</Grid>
|
||||
<DataTemplate.Triggers>
|
||||
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=ListBoxItem},Path=IsSelected}" Value="true">
|
||||
<Setter TargetName="chk" Property="IsChecked" Value="true"/>
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=ListBoxItem},Path=IsSelected}" Value="false">
|
||||
<Setter TargetName="chk" Property="IsChecked" Value="false"/>
|
||||
</DataTrigger>
|
||||
</DataTemplate.Triggers>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
</Grid>
|
||||
</Popup>
|
||||
</Grid>
|
||||
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</ResourceDictionary>
|
||||
208
Cowain.Bake.Main/Views/EquipmentMonitorView.xaml
Normal file
@@ -0,0 +1,208 @@
|
||||
<UserControl x:Class="Cowain.Bake.Main.Views.EquipmentMonitorView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:prism="http://prismlibrary.com/"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:hc="https://handyorg.github.io/handycontrol"
|
||||
mc:Ignorable="d"
|
||||
prism:ViewModelLocator.AutoWireViewModel="True"
|
||||
Loaded="EquipmentMonitorView_Loaded"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<UserControl.Resources>
|
||||
<Style x:Key="DefaultToolTipStyle" TargetType="{x:Type ToolTip}">
|
||||
<Setter Property="Foreground" Value="Yellow"/>
|
||||
<Setter Property = "Background" Value="Blue"/>
|
||||
<Setter Property = "FontSize" Value="14"/>
|
||||
<Setter Property="BorderBrush" Value="White"/>
|
||||
</Style>
|
||||
<Style x:Key="MyButton" TargetType="Button">
|
||||
<Style.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter Property="Background" Value="LightBlue"/>
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</UserControl.Resources>
|
||||
<Canvas x:Name="mainCanvas" Margin="0,0,0,0" Height="auto" Width="auto" Loaded="Canvas_Loaded">
|
||||
<Canvas.Background>
|
||||
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
|
||||
<!-- 起点颜色 -->
|
||||
<GradientStop Color="LightBlue" Offset="0" />
|
||||
<!-- 终点颜色 -->
|
||||
<GradientStop Color="LightBlue" Offset="1" />
|
||||
</LinearGradientBrush>
|
||||
</Canvas.Background>
|
||||
<Grid Canvas.Left="0" Canvas.Top="0" Width="700" Height="30">
|
||||
<!-- 定义一行七列 -->
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- 为每一列设置单独的背景色和内容 -->
|
||||
<Border Grid.Column="0" Background="White">
|
||||
<TextBlock Text="空夹具" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="Black" FontSize="16"/>
|
||||
</Border>
|
||||
<Border Grid.Column="1" Background="Bisque">
|
||||
<TextBlock Text="上料中" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="Black" FontSize="16"/>
|
||||
</Border>
|
||||
<Border Grid.Column="2" Background="Purple">
|
||||
<TextBlock Text="满载" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="16"/>
|
||||
</Border>
|
||||
<Border Grid.Column="3" Background="DarkOrange">
|
||||
<TextBlock Text="烘烤中" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="16"/>
|
||||
</Border>
|
||||
<Border Grid.Column="4" Background="Green">
|
||||
<TextBlock Text="烘烤完成" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="16"/>
|
||||
</Border>
|
||||
<Border Grid.Column="5" Background="gold">
|
||||
<TextBlock Text="待测结果" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="16"/>
|
||||
</Border>
|
||||
<Border Grid.Column="6" Background="PaleGreen">
|
||||
<TextBlock Text="检测OK" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="16"/>
|
||||
</Border>
|
||||
<Border Grid.Column="7" Background="DeepPink">
|
||||
<TextBlock Text="检测NG" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="16"/>
|
||||
</Border>
|
||||
|
||||
<Border Grid.Column="8" Background="LightSteelBlue">
|
||||
<TextBlock Text="下料中" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="16"/>
|
||||
</Border>
|
||||
|
||||
<Border Grid.Column="9" Background="Tan">
|
||||
<TextBlock Text="维修中" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="16"/>
|
||||
</Border>
|
||||
<Border Grid.Column="10" Background="red">
|
||||
<TextBlock Text="异常" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="16"/>
|
||||
</Border>
|
||||
</Grid>
|
||||
<Grid Canvas.Left="0" Canvas.Top="45" Width="500" Height="60">
|
||||
<hc:StepBar x:Name="StepBarControl" StepIndex="{Binding StepIndex}" >
|
||||
<hc:StepBarItem Content="无任务"/>
|
||||
<hc:StepBarItem Content="移至取位">
|
||||
<hc:StepBarItem.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem Header="发送指令" Command="{Binding ReSendCommand}"
|
||||
CommandParameter="10" />
|
||||
</ContextMenu>
|
||||
</hc:StepBarItem.ContextMenu>
|
||||
</hc:StepBarItem>
|
||||
<hc:StepBarItem Content="取盘">
|
||||
<hc:StepBarItem.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem Header="发送指令" Command="{Binding ReSendCommand}"
|
||||
CommandParameter="20"/>
|
||||
</ContextMenu>
|
||||
</hc:StepBarItem.ContextMenu>
|
||||
</hc:StepBarItem>
|
||||
|
||||
<hc:StepBarItem Content="移至放位">
|
||||
<hc:StepBarItem.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem Header="发送指令" Command="{Binding ReSendCommand}"
|
||||
CommandParameter="11" />
|
||||
</ContextMenu>
|
||||
</hc:StepBarItem.ContextMenu>
|
||||
</hc:StepBarItem>
|
||||
|
||||
<hc:StepBarItem Content="放盘">
|
||||
<hc:StepBarItem.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem Header="发送指令" Command="{Binding ReSendCommand}"
|
||||
CommandParameter="30" />
|
||||
</ContextMenu>
|
||||
</hc:StepBarItem.ContextMenu>
|
||||
</hc:StepBarItem>
|
||||
|
||||
<hc:StepBarItem Content="完成"/>
|
||||
</hc:StepBar>
|
||||
</Grid>
|
||||
<Grid Canvas.Right="0" Canvas.Top="40" Width="700" Height="50">
|
||||
<!-- 定义一行七列 -->
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="1*"/>
|
||||
<ColumnDefinition Width="1.5*"/>
|
||||
<ColumnDefinition Width="1*"/>
|
||||
<ColumnDefinition Width="1.2*"/>
|
||||
<ColumnDefinition Width="1*"/>
|
||||
<ColumnDefinition Width="3*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- 为每一列设置单独的背景色和内容 -->
|
||||
<Border Grid.Row="0" Background="Transparent">
|
||||
<TextBlock Text="取盘位置:" HorizontalAlignment="Right" VerticalAlignment="Center" Foreground="White" FontSize="14"/>
|
||||
</Border>
|
||||
<Border Grid.Row="0" Grid.Column="1" Background="Transparent">
|
||||
<TextBlock Text="{Binding CavitySourceName}" HorizontalAlignment="Left" FontWeight="Bold" VerticalAlignment="Center" Foreground="White" FontSize="16"/>
|
||||
</Border>
|
||||
|
||||
<Border Grid.Row="0" Grid.Column="2" Background="Transparent">
|
||||
<TextBlock Text="任务状态:" HorizontalAlignment="Right" VerticalAlignment="Center" Foreground="White" FontSize="14"/>
|
||||
</Border>
|
||||
<Border Grid.Row="0" Grid.Column="3" Background="Transparent">
|
||||
<TextBlock Text="{Binding TaskStatusName}" HorizontalAlignment="Left" FontWeight="Bold" VerticalAlignment="Center" Foreground="White" FontSize="16"/>
|
||||
</Border>
|
||||
|
||||
<Border Grid.Row="0" Grid.Column="4" Background="Transparent">
|
||||
<TextBlock Text="任务类型:" HorizontalAlignment="Right" VerticalAlignment="Center" Foreground="White" FontSize="14"/>
|
||||
</Border>
|
||||
<Border Grid.Row="0" Grid.Column="5" Background="Transparent">
|
||||
<TextBlock Text="{Binding TaskTypeName}" HorizontalAlignment="Left" FontWeight="Bold" VerticalAlignment="Center" Foreground="White" FontSize="16"/>
|
||||
</Border>
|
||||
|
||||
<Border Grid.Row="1" Grid.Column="0" Background="Transparent">
|
||||
<TextBlock Text="放盘位置:" HorizontalAlignment="Right" VerticalAlignment="Center" Foreground="White" FontSize="14"/>
|
||||
</Border>
|
||||
<Border Grid.Row="1" Grid.Column="1" Background="Transparent">
|
||||
<TextBlock Text="{Binding CavityTargetName}" HorizontalAlignment="Left" FontWeight="Bold" VerticalAlignment="Center" Foreground="White" FontSize="16"/>
|
||||
</Border>
|
||||
|
||||
<Border Grid.Row="1" Grid.Column="2" Background="Transparent">
|
||||
<TextBlock Text="夹具条码:" HorizontalAlignment="Right" VerticalAlignment="Center" Foreground="White" FontSize="14"/>
|
||||
</Border>
|
||||
<Border Grid.Row="1" Grid.Column="3" Background="Transparent">
|
||||
<TextBlock Text="{Binding PalletCode}" HorizontalAlignment="Left" FontWeight="Bold" VerticalAlignment="Center" Foreground="White" FontSize="16"/>
|
||||
</Border>
|
||||
|
||||
<Border Grid.Row="1" Grid.Column="4" Background="Transparent">
|
||||
<TextBlock Text="开始时间:" HorizontalAlignment="Right" VerticalAlignment="Center" Foreground="White" FontSize="14"/>
|
||||
</Border>
|
||||
<Border Grid.Row="1" Grid.Column="5" Background="Transparent">
|
||||
<TextBlock Text="{Binding StartTime,StringFormat=yyyy-MM-dd HH:mm:ss}" HorizontalAlignment="Left" FontWeight="Bold" VerticalAlignment="Center" Foreground="White" FontSize="16"/>
|
||||
</Border>
|
||||
</Grid>
|
||||
|
||||
<Button Content="" x:Name="AGV" HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top" Width="80" Height="73" Canvas.Left="14" Canvas.Top="{Binding HandMachineYLocation}" Panel.ZIndex="101">
|
||||
<Button.RenderTransform>
|
||||
<TranslateTransform x:Name="machineAnimation"/>
|
||||
</Button.RenderTransform>
|
||||
<Button.Template>
|
||||
<ControlTemplate>
|
||||
<Grid>
|
||||
<Label Name="handMachineLabel" Panel.ZIndex="100" HorizontalContentAlignment="Center" Foreground="Black" FontSize="13px" Content="{Binding RgvPalletCode}" Width="80" Height="30" Style="{StaticResource BaseStyle}" Margin="0,0,0,0">
|
||||
</Label>
|
||||
<Image Source="{Binding ImageSource}"></Image>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Button.Template>
|
||||
</Button>
|
||||
<Canvas x:Name="pathCanvas" Panel.ZIndex="99" Margin="0,0,0,0" Height="auto" Width="auto"></Canvas>
|
||||
</Canvas>
|
||||
</UserControl>
|
||||
39
Cowain.Bake.Main/Views/EquipmentMonitorView.xaml.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
using Cowain.Bake.Main.ViewModels;
|
||||
using Prism.Regions;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using Unity;
|
||||
|
||||
namespace Cowain.Bake.Main.Views
|
||||
{
|
||||
/// <summary>
|
||||
/// CutAndFlodView.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class EquipmentMonitorView : UserControl, IRegionMemberLifetime
|
||||
{
|
||||
//IUnityContainer _unityContainer = null;
|
||||
public EquipmentMonitorViewModel vm;
|
||||
public bool KeepAlive => false; // 确保视图被缓存
|
||||
public EquipmentMonitorView(IUnityContainer unityContainer, Prism.Events.IEventAggregator eventAggregator)
|
||||
{
|
||||
InitializeComponent();
|
||||
vm = this.DataContext as EquipmentMonitorViewModel;
|
||||
vm.frameworkElement = this;
|
||||
vm.machineAnimation = machineAnimation;
|
||||
vm.mainCanvas = mainCanvas;
|
||||
vm.pathCanvas = pathCanvas;
|
||||
}
|
||||
|
||||
private void Canvas_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
|
||||
}
|
||||
private void EquipmentMonitorView_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
vm._localScreenWidth = mainCanvas.ActualWidth;// SystemParameters.PrimaryScreenWidth; //1536
|
||||
vm._localScreenHeight = mainCanvas.ActualHeight;// SystemParameters.PrimaryScreenHeight;
|
||||
vm.Init();
|
||||
Loaded -= EquipmentMonitorView_Loaded; //不加这个,切换到主界面时,会触发多次
|
||||
}
|
||||
}
|
||||
}
|
||||
64
Cowain.Bake.Main/Views/LogManagement.xaml
Normal file
@@ -0,0 +1,64 @@
|
||||
<UserControl x:Class="Cowain.Bake.Main.Views.LogManagement"
|
||||
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:Cowain.Bake.Main.Views"
|
||||
xmlns:hc="https://handyorg.github.io/handycontrol"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="auto"/>
|
||||
<RowDefinition/>
|
||||
</Grid.RowDefinitions>
|
||||
<StackPanel Orientation="Horizontal" Height="30">
|
||||
<!--<Label Content="{DynamicResource DateTime}" BorderThickness="0" Background="Transparent"
|
||||
Margin="10,0,0,0" Foreground="Gray" Visibility="Collapsed"/>
|
||||
<hc:DatePicker Width="150" x:Name="datePick" Visibility="Collapsed"/>
|
||||
<Button Content="{DynamicResource Query}" Margin="10,0,0,0" Click="findLog_Click" x:Name="findLog" Visibility="Collapsed"/>
|
||||
<Button Content="{DynamicResource RealTimeLog}" Margin="10,0,0,0" Click="realTime_Click" x:Name="realTime" Visibility="Collapsed"/>-->
|
||||
<!--<hc:Divider Orientation="Vertical" LineStrokeThickness="5"
|
||||
LineStroke="#3D99A0"/>-->
|
||||
<!--<Label Content="{DynamicResource Filter}" BorderThickness="0" Background="Transparent"
|
||||
Margin="0,0,0,0" Foreground="Gray"/>-->
|
||||
<local:MultiComboBox x:Name="mucombo" SelectionChanged="mucombo_SelectionChanged" Margin="5,0,0,0.4" Width="200"/>
|
||||
<Label x:Name="labstate" Background="Transparent" BorderThickness="0"
|
||||
Margin="10,0,0,0" Foreground="YellowGreen"/>
|
||||
</StackPanel>
|
||||
<hc:ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto"
|
||||
HorizontalScrollBarVisibility="Auto"
|
||||
CanMouseWheel="true"
|
||||
IsInertiaEnabled="True"
|
||||
>
|
||||
<ListBox x:Name="loglist" Background="LightGray"
|
||||
hc:ScrollViewer.IsInertiaEnabled="True">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Line X1="0" X2="0" Y1="0" Y2="{Binding ActualHeight,RelativeSource={RelativeSource Mode=Self}}"
|
||||
StrokeThickness="1" Stroke="#551e90ff" HorizontalAlignment="Center"/>
|
||||
<Ellipse Width="6" Height="6" Fill="#AA1e90ff" VerticalAlignment="Top" Margin="0,4,1,0"/>
|
||||
<StackPanel Grid.Column="1">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock Text="{Binding LogLevel}" FontSize="12" Foreground="{Binding FontColor}" Margin="5,0,0,0"></TextBlock>
|
||||
<TextBlock>:</TextBlock>
|
||||
<TextBlock Text="{Binding LogText,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" TextWrapping="Wrap"
|
||||
Foreground="{Binding Foreground, ElementName=onelogs}"
|
||||
FontSize="12" Margin="0,0,0,5"/>
|
||||
</StackPanel>
|
||||
<TextBlock Text="{Binding LogTime,StringFormat='yyyy-MM-dd HH:mm:ss'}" FontSize="11" Margin="5,5,0,10" Opacity="0.6" />
|
||||
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
</hc:ScrollViewer>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
172
Cowain.Bake.Main/Views/LogManagement.xaml.cs
Normal file
@@ -0,0 +1,172 @@
|
||||
using Cowain.Bake.Common.Core;
|
||||
using Prism.Mvvm;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Configuration;
|
||||
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;
|
||||
using System.Windows.Threading;
|
||||
using Cowain.Bake.Main.Views;
|
||||
using Cowain.Bake.Main.Models;
|
||||
using Cowain.Bake.Common;
|
||||
|
||||
namespace Cowain.Bake.Main.Views
|
||||
{
|
||||
/// <summary>
|
||||
/// LogManagement.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class LogManagement : UserControl
|
||||
{
|
||||
/// <summary>
|
||||
/// 绑定数据
|
||||
/// </summary>
|
||||
private ObservableCollection<LogModel> bindingData { set; get; } = new ObservableCollection<LogModel>();
|
||||
/// <summary>
|
||||
/// 实时数据
|
||||
/// </summary>
|
||||
private List<LogModel> realTimeDatas { set; get; } = new List<LogModel>();
|
||||
|
||||
private BlockingCollection<LogModel> logQueue = new BlockingCollection<LogModel>();
|
||||
private Dictionary<string, MultiComboBox.MultiCbxBaseData> IsHaveKeyDic { set; get; } = new Dictionary<string, MultiComboBox.MultiCbxBaseData>();
|
||||
public LogManagement()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
if (loglist.ItemsSource == null)
|
||||
{
|
||||
loglist.ItemsSource = bindingData;
|
||||
}
|
||||
|
||||
Task.Run(() => DispatcherTimer_Tick());
|
||||
Unloaded += LogManagement_Unloaded;
|
||||
}
|
||||
|
||||
private void LogManagement_Unloaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 刷新队列
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
void DispatcherTimer_Tick()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (Global.AppExit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LogModel model = logQueue.Take();
|
||||
if (null == model)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var item = realTimeDatas.Find(x => x.LogText == model.LogText);
|
||||
if (null != item) //表示有相同的数据
|
||||
{
|
||||
continue;
|
||||
}
|
||||
//显示数据
|
||||
if (IsHaveKeyDic.ContainsKey(model.LogLevel) && IsHaveKeyDic[model.LogLevel].IsCheck)
|
||||
{
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
bindingData.Insert(0, model);
|
||||
if (bindingData.Count > Global.MAX_LOG_QTY)
|
||||
{
|
||||
bindingData.RemoveAt(bindingData.Count - 1);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
//实时数据
|
||||
realTimeDatas.Insert(0, model);
|
||||
if (realTimeDatas.Count > Global.MAX_LOG_QTY)
|
||||
{
|
||||
realTimeDatas.RemoveAt(realTimeDatas.Count - 1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#region [日志内容入口]
|
||||
|
||||
private static readonly DependencyProperty LoglistItemProperty = DependencyProperty.Register(
|
||||
"LoglistItem", typeof(LogModel), typeof(LogManagement), new PropertyMetadata(null, OnLoglistSourceChange));
|
||||
|
||||
private static void OnLoglistSourceChange(DependencyObject o, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
if (o is LogManagement log)
|
||||
{
|
||||
var model = e.NewValue as LogModel;
|
||||
//入队
|
||||
log.logQueue.Add(model);
|
||||
}
|
||||
}
|
||||
|
||||
public LogModel LoglistItem
|
||||
{
|
||||
get => (LogModel)GetValue(LoglistItemProperty);
|
||||
set => SetValue(LoglistItemProperty, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region [日志等级源]
|
||||
|
||||
private static readonly DependencyProperty LogLevelSourceProperty = DependencyProperty.Register(
|
||||
"LogLevelSource", typeof(ObservableCollection<MultiComboBox.MultiCbxBaseData>), typeof(LogManagement),
|
||||
new PropertyMetadata(null, OnLogLevelSourceChange));
|
||||
|
||||
private static void OnLogLevelSourceChange(DependencyObject o, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
if (o is LogManagement log)
|
||||
{
|
||||
log.mucombo.ItemsSource = e.NewValue as ObservableCollection<MultiComboBox.MultiCbxBaseData>;
|
||||
}
|
||||
}
|
||||
|
||||
public ObservableCollection<MultiComboBox.MultiCbxBaseData> LogLevelSource
|
||||
{
|
||||
get => (ObservableCollection<MultiComboBox.MultiCbxBaseData>)GetValue(LogLevelSourceProperty);
|
||||
set => SetValue(LogLevelSourceProperty, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
private void mucombo_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (e.Source is MultiComboBox multiComboBox && multiComboBox.ItemsSource is ObservableCollection<MultiComboBox.MultiCbxBaseData> list)
|
||||
{
|
||||
IsHaveKeyDic = list.ToDictionary(d => d.ViewName, d => d);
|
||||
bindingData.Clear();
|
||||
foreach (var item in realTimeDatas)
|
||||
{
|
||||
if (IsHaveKeyDic.ContainsKey(item.LogLevel) && IsHaveKeyDic[item.LogLevel].IsCheck)
|
||||
{
|
||||
bindingData.Add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
31
Cowain.Bake.Main/Views/MainHeaderView.xaml
Normal file
@@ -0,0 +1,31 @@
|
||||
<UserControl x:Class="Cowain.Bake.Main.Views.MainHeaderView"
|
||||
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:Fluent="urn:fluent-ribbon"
|
||||
xmlns:local="clr-namespace:Cowain.Bake.Main.Views"
|
||||
xmlns:prism="http://prismlibrary.com/"
|
||||
prism:ViewModelLocator.AutoWireViewModel="True"
|
||||
mc:Ignorable="d"
|
||||
xmlns:hc="https://handyorg.github.io/handycontrol"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
|
||||
<UserControl.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="pack://application:,,,/Cowain.Bake.Common;component/Styles/BaseResources.xaml"/>
|
||||
<ResourceDictionary Source="pack://application:,,,/Cowain.Bake.Common;component/Styles/ToggleButtonStyle.xaml"/>
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
|
||||
<Grid x:Name="maingrid" >
|
||||
<Fluent:Ribbon Height="auto" BorderBrush="LightGray" BorderThickness="1" Grid.Row="0" x:Name="mainRibbon" ShowQuickAccessToolBarAboveRibbon="True" SelectedTabIndex="2">
|
||||
<Fluent:Ribbon.Menu>
|
||||
<Fluent:Backstage Header="工具栏"></Fluent:Backstage>
|
||||
</Fluent:Ribbon.Menu>
|
||||
</Fluent:Ribbon>
|
||||
</Grid>
|
||||
|
||||
</UserControl>
|
||||
496
Cowain.Bake.Main/Views/MainHeaderView.xaml.cs
Normal file
@@ -0,0 +1,496 @@
|
||||
using Cowain.Bake.BLL;
|
||||
using Cowain.Bake.Common.Core;
|
||||
using Cowain.Bake.Common.Enums;
|
||||
using Cowain.Bake.Model;
|
||||
using Fluent;
|
||||
using Prism.Ioc;
|
||||
using Prism.Regions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using Unity;
|
||||
using System.Linq;
|
||||
using System.Windows.Media;
|
||||
using Newtonsoft.Json;
|
||||
using Cowain.Bake.Main.ViewModels;
|
||||
|
||||
|
||||
namespace Cowain.Bake.Main.Views
|
||||
{
|
||||
/// <summary>
|
||||
/// MainHeaderView.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class MainHeaderView : UserControl
|
||||
{
|
||||
private static Dictionary<string, RibbonGroupBox> parentGroupBoxDic = new Dictionary<string, RibbonGroupBox>();
|
||||
private static IUnityContainer _unityContainer;
|
||||
public static Dictionary<string, Label> toggleButtonLabelDic = new Dictionary<string, Label>();
|
||||
public static Dictionary<string, Fluent.Button> ribbonButtonDic = new Dictionary<string, Fluent.Button>();
|
||||
private static List<Fluent.ToggleButton> toggleButton = new List<Fluent.ToggleButton>();
|
||||
private static Views.MainHeaderView MainHeaderViewForPublic;
|
||||
private static List<Label> toggleBtnLabel = new List<Label>();
|
||||
private static List<TMenuInfo> menuInfos;
|
||||
public static Dictionary<int, StackPanel> dicStackPanel = new Dictionary<int, StackPanel>();
|
||||
Fluent.DropDownButton splitButton = new Fluent.DropDownButton();
|
||||
private static IRegionManager _regionManager = null;
|
||||
private List<string> _theme = new List<string>();
|
||||
public MainHeaderView(IUnityContainer unityContainer, IRegionManager regionManager)
|
||||
{
|
||||
InitializeComponent();
|
||||
_regionManager = regionManager;
|
||||
_unityContainer = unityContainer;
|
||||
//mainRibbonForPublic = mainRibbon;
|
||||
MainHeaderViewForPublic = this;
|
||||
menuInfos = _unityContainer.Resolve<MenuInfoService>().GetMenuInfoList();
|
||||
GenerateMenuImage();
|
||||
ClearWindows();
|
||||
Init();
|
||||
SetTheme();
|
||||
}
|
||||
void SetTheme()
|
||||
{
|
||||
/*
|
||||
“Red”, “Green”, “Blue”, “Purple”, “Orange”, “Lime”, “Emerald”, “Teal”, “Cyan”, “Cobalt”, “Indigo”, “Violet”, “Pink”, “Magenta”, “Crimson”, “Amber”, “Yellow”, “Brown”, “Olive”, “Steel”, “Mauve”, “Taupe”, “Sienna”
|
||||
and these base colors: “Light”, “Dark”
|
||||
*/
|
||||
//var theme = ControlzEx.Theming.ThemeManager.Current.DetectTheme(Application.Current);
|
||||
_theme.Add("Light.Blue");
|
||||
_theme.Add("Light.Amber");
|
||||
|
||||
_theme.Add("Light.Magenta");
|
||||
_theme.Add("Dark.Green");
|
||||
_theme.Add("Light.Green");
|
||||
_theme.Add("Dark.Lime");
|
||||
|
||||
ChangeSkin(SettingProvider.Instance.SkinType);
|
||||
_unityContainer.Resolve<MainWindow>().ChangeSkin(SettingProvider.Instance.SkinType);
|
||||
}
|
||||
public void ChangeSkin(int i)
|
||||
{
|
||||
ControlzEx.Theming.ThemeManager.Current.ChangeTheme(App.Current, _theme[i]);
|
||||
}
|
||||
public void ClearWindows()
|
||||
{
|
||||
parentGroupBoxDic.Clear();
|
||||
toggleButtonLabelDic.Clear();
|
||||
ribbonButtonDic.Clear();
|
||||
mainRibbon.Tabs.Clear();
|
||||
dicStackPanel.Clear();
|
||||
}
|
||||
|
||||
public void Init()
|
||||
{
|
||||
AddMenuFatherLabelItems();
|
||||
AddStackPanel();
|
||||
AddMenuGroupBoxItems();
|
||||
|
||||
|
||||
MainWindow.mainShowWindow.Title = "产量查询";
|
||||
_regionManager.RequestNavigate("MainContentRegion", "ProductionsInfoView");
|
||||
|
||||
if (EDispatchMode.Manual == SettingProvider.Instance.DispMode)
|
||||
{
|
||||
ribbonButtonDic["Manual"].IsEnabled = false;
|
||||
ribbonButtonDic["Auto"].IsEnabled = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
ribbonButtonDic["Manual"].IsEnabled = true;
|
||||
ribbonButtonDic["Auto"].IsEnabled = false;
|
||||
}
|
||||
mainRibbon.Tabs[0].IsSelected = true;
|
||||
}
|
||||
/// <summary>
|
||||
/// 添加菜单标签列表
|
||||
/// </summary>
|
||||
/// <param name="parentId"></param>
|
||||
private void AddMenuFatherLabelItems(int parentId = 0)
|
||||
{
|
||||
var menuParentInfos = menuInfos.Where(p => p.ParentId == parentId);
|
||||
foreach (var item in menuParentInfos)
|
||||
{
|
||||
RibbonTabItem ribbonTabItem = new RibbonTabItem()
|
||||
{
|
||||
Header = item.Header,
|
||||
Name = item.HeaderName
|
||||
};
|
||||
RibbonGroupBox ribbonGroupBox = new RibbonGroupBox();
|
||||
ribbonGroupBox.Name = $"{item.Header}GroupBox";
|
||||
|
||||
ribbonTabItem.Groups.Add(ribbonGroupBox);
|
||||
mainRibbon.Tabs.Add(ribbonTabItem);
|
||||
parentGroupBoxDic.Add(item.Id.ToString(), ribbonGroupBox);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 添加工具栏功能列表
|
||||
/// </summary>
|
||||
private void AddMenuGroupBoxItems()
|
||||
{
|
||||
var roleContainNodes = _unityContainer.Resolve<UserService>().GetCurrentUserAuthority();
|
||||
//var strTolist = CommonCoreHelper.Instance.StringToListConverter(roleContainNodes); && strTolist.Contains(p.HeaderName)
|
||||
|
||||
var menuParentIds = menuInfos.Where(p => p.ParentId == 0).ToList();
|
||||
var btnContentMenuItems = menuInfos.Where(p => menuParentIds.Select(x => x.Id).Contains(p.ParentId)).OrderBy(p => p.ParentId).ThenBy(p => p.MenuIndex);
|
||||
foreach (var item in btnContentMenuItems)
|
||||
{
|
||||
|
||||
switch ((EMenuType)item.MenuType)
|
||||
{
|
||||
case EMenuType.Cmd:
|
||||
case EMenuType.Region:
|
||||
case EMenuType.ShowDialog:
|
||||
FillRibbonButton(item);
|
||||
break;
|
||||
case EMenuType.FunctionSwitch:
|
||||
DrawToggleButton(item);
|
||||
break;
|
||||
case EMenuType.DropDown:
|
||||
DrawSplitButton(item);
|
||||
break;
|
||||
default:
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region 事件
|
||||
//0.按键:弹界面
|
||||
//1.按键:功能,如开始,停止
|
||||
//2.开关:功能开关,如是否启用MOM
|
||||
private static void RibbonButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
string btnName = "";
|
||||
var type = sender.GetType();
|
||||
if (type == typeof(Fluent.Button))
|
||||
{
|
||||
btnName = (sender as Fluent.Button).Name;
|
||||
}
|
||||
else
|
||||
{
|
||||
btnName = (sender as Fluent.ToggleButton).Name;
|
||||
}
|
||||
TMenuInfo menuInfo = menuInfos.FirstOrDefault(p => p.HeaderName == btnName);
|
||||
if (null == menuInfo)
|
||||
{
|
||||
LogHelper.Instance.GetCurrentClassWarn("查找按键信息失败!", true);
|
||||
return;
|
||||
}
|
||||
|
||||
switch ((EMenuType)menuInfo.MenuType)
|
||||
{
|
||||
case EMenuType.ShowDialog:
|
||||
ShowDialog(menuInfo);
|
||||
break;
|
||||
case EMenuType.Region:
|
||||
ShowWindowsRegion(menuInfo);
|
||||
break;
|
||||
case EMenuType.Cmd:
|
||||
case EMenuType.FunctionSwitch:
|
||||
ExecuteMethod(menuInfo);
|
||||
break;
|
||||
default:
|
||||
LogHelper.Instance.Warn($"没有这个菜单[{btnName}]类型:{(int)menuInfo.MenuType}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Instance.GetCurrentClassDebug(ex.Message);
|
||||
}
|
||||
}
|
||||
private static void ShowDialog(TMenuInfo menuInfo)
|
||||
{
|
||||
TMenuInfo asmBaseName = menuInfos.FirstOrDefault(p => p.ParentId == 0 && p.Id == menuInfo.ParentId);
|
||||
if (null == asmBaseName)
|
||||
{
|
||||
HandyControl.Controls.MessageBox.Info($"当前'{asmBaseName.Header}'目标路径不正确,请在数据库中重新配置!!");
|
||||
return;
|
||||
}
|
||||
|
||||
System.Reflection.Assembly asm = System.Reflection.Assembly.Load(asmBaseName.TargetView);// 通过类型的完整限定名和程序集获取类型
|
||||
Type viewNameType = asm.GetType(menuInfo.TargetView);
|
||||
if (null == viewNameType)
|
||||
{
|
||||
LogHelper.Instance.Info($"当前'{menuInfo.Header}'类型的完整限定名不正确,请在数据库中重新配置!", true);
|
||||
return;
|
||||
}
|
||||
|
||||
var dlg = (System.Windows.Window)_unityContainer.Resolve(viewNameType);
|
||||
if (dlg.ShowDialog().Value)
|
||||
{
|
||||
_unityContainer.Resolve<BasicInfoViewModel>().ShowInfo();
|
||||
HandyControl.Controls.MessageBox.Success("切换用户成功");
|
||||
_unityContainer.Resolve<LogService>().AddLog($@"切换用户成功!", E_LogType.Operate.ToString());
|
||||
}
|
||||
//object typeInstance = Activator.CreateInstance(viewNameType); //不会传参数
|
||||
//Window dlg = typeInstance as Window;
|
||||
//dlg.ShowDialog();
|
||||
}
|
||||
|
||||
private static void ShowWindowsRegion(TMenuInfo menuInfo)
|
||||
{
|
||||
MainWindow.mainShowWindow.Title = menuInfo.Header;
|
||||
_regionManager.RequestNavigate("MainContentRegion", menuInfo.TargetView);
|
||||
}
|
||||
|
||||
private static void ExecuteMethod(TMenuInfo menuInfo)
|
||||
{
|
||||
dynamic d = JsonConvert.DeserializeObject<dynamic>(menuInfo.JSON);
|
||||
string methodName = d.CMD;
|
||||
string param = d.Parameter;
|
||||
Type type = Type.GetType(Cowain.Bake.Common.MyPath.HEAD_CMD);
|
||||
object[] instancePara = new object[1];
|
||||
instancePara[0] = _unityContainer;
|
||||
object obj = System.Activator.CreateInstance(type, instancePara);
|
||||
MethodInfo method = type.GetMethod(methodName, new Type[] { typeof(string) });
|
||||
object[] parameters = new object[] { param };
|
||||
method.Invoke(obj, parameters);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 内部方法
|
||||
|
||||
|
||||
private void FillRibbonButton(TMenuInfo menuInfo)
|
||||
{
|
||||
var ribbonGroup = parentGroupBoxDic[menuInfo.ParentId.ToString()];
|
||||
Fluent.Button button = new Fluent.Button();
|
||||
button.Name = menuInfo.HeaderName;
|
||||
button.Header = menuInfo.Header;
|
||||
button.Width = 60; //MyAppContainer.Current.Resolve<UserService>().IsHasAuthority(menuInfo.HeaderName == null ? "" : menuInfo.HeaderName);
|
||||
button.IsEnabled = _unityContainer.Resolve<UserService>().IsHasAuthority(menuInfo.HeaderName == null ? "" : menuInfo.HeaderName);
|
||||
string imagePath = Environment.CurrentDirectory + $@"\images\{menuInfo.Header}.png";
|
||||
if (File.Exists(imagePath))
|
||||
{
|
||||
button.LargeIcon = imagePath; //imagePath;
|
||||
}
|
||||
button.Click += RibbonButton_Click;
|
||||
|
||||
if (ribbonGroup != null)
|
||||
{
|
||||
ribbonGroup.Items.Add(button);
|
||||
}
|
||||
|
||||
if (!ribbonButtonDic.ContainsKey(menuInfo.HeaderName))
|
||||
{
|
||||
ribbonButtonDic.Add(menuInfo.HeaderName, button);
|
||||
}
|
||||
}
|
||||
|
||||
private void SplitButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
//if (sender is Fluent.MenuItem item)
|
||||
//{
|
||||
// var name = item.Tag.ToString().Replace("_", ".");
|
||||
// maingrid.Background = new ImageBrush
|
||||
// {
|
||||
// ImageSource = new System.Windows.Media.Imaging.BitmapImage(new Uri($"pack://application:,,,/Cowain.Bake.Main;component/Images/UserControls/{name}"))
|
||||
// };
|
||||
//}
|
||||
Fluent.MenuItem currentMenu = (Fluent.MenuItem)sender;
|
||||
splitButton.IsDropDownOpen = false;
|
||||
|
||||
for (int i = 0; i < splitButton.Items.Count; ++i)
|
||||
{
|
||||
Fluent.MenuItem menu = (Fluent.MenuItem)splitButton.Items.GetItemAt(i);
|
||||
if (menu.Header != currentMenu.Header
|
||||
&& menu.IsChecked)
|
||||
{
|
||||
menu.IsChecked = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentMenu.IsChecked)
|
||||
{
|
||||
int value = (int)EnumHelper.GetValueByDescription<ESkin>((string)currentMenu.Header);
|
||||
ChangeSkin(value);
|
||||
_unityContainer.Resolve<MainWindow>().ChangeSkin(value);
|
||||
SettingProvider.Instance.SkinType = value;
|
||||
}
|
||||
}
|
||||
|
||||
private Fluent.MenuItem CreateSplitButtonMenu(ESkin eskin, bool isCheck)
|
||||
{
|
||||
var menu = new Fluent.MenuItem
|
||||
{
|
||||
Header = eskin.GetDescription(),
|
||||
Tag = eskin.ToString(),
|
||||
IsCheckable = true,
|
||||
IsChecked = isCheck, // 默认选中
|
||||
};
|
||||
menu.Click += SplitButton_Click;
|
||||
return menu;
|
||||
}
|
||||
private void DrawSplitButton(TMenuInfo menuInfo)
|
||||
{
|
||||
splitButton.Header = menuInfo.Header;
|
||||
// 设置大图标(LargeIcon)new BitmapImage(new Uri("pack://application:,,,/Images/LargeIcon.png"));
|
||||
splitButton.LargeIcon = new System.Windows.Media.Imaging.BitmapImage
|
||||
(new Uri(Environment.CurrentDirectory + $@"\images\{menuInfo.Header}.png"));
|
||||
// 其他属性(尺寸、边距等)
|
||||
splitButton.Width = 60;
|
||||
//splitButton.Margin = new Thickness(1);
|
||||
//splitButton.HorizontalAlignment = HorizontalAlignment.Left;
|
||||
//splitButton.VerticalAlignment = VerticalAlignment.Top;
|
||||
|
||||
foreach (ESkin skin in System.Enum.GetValues(typeof(ESkin)))
|
||||
{
|
||||
splitButton.Items.Add(CreateSplitButtonMenu(skin, SettingProvider.Instance.SkinType == (int)skin));
|
||||
}
|
||||
|
||||
var ribbonGroup = parentGroupBoxDic[menuInfo.ParentId.ToString()];
|
||||
ribbonGroup.Items.Add(splitButton);
|
||||
}
|
||||
private static void AddStackPanel()
|
||||
{
|
||||
var toggles = menuInfos.Where(x => x.MenuType == (int)EMenuType.FunctionSwitch && x.State == true).ToList();
|
||||
int count = toggles.Count();
|
||||
var ribbonGroupBox = parentGroupBoxDic[toggles[0].ParentId.ToString()];
|
||||
count = (int)Math.Ceiling((double)count / 2); //两个一组
|
||||
StackPanel h = new StackPanel { Orientation = Orientation.Horizontal }; //行
|
||||
ribbonGroupBox.Items.Add(h);
|
||||
for (int i = 1; i <= count; i++ )
|
||||
{
|
||||
StackPanel v = new StackPanel { Orientation = Orientation.Vertical }; //列
|
||||
h.Children.Add(v);
|
||||
dicStackPanel[i] = v;
|
||||
}
|
||||
}
|
||||
private static void DrawToggleButton(TMenuInfo item)
|
||||
{
|
||||
var header = item.Header;
|
||||
var model = Newtonsoft.Json.JsonConvert.DeserializeObject<ParaJSON>(item.JSON);
|
||||
var ribbonGroupBox = parentGroupBoxDic[item.ParentId.ToString()];
|
||||
|
||||
if (ribbonGroupBox == null) return;
|
||||
|
||||
var paraValue = _unityContainer.Resolve<MenuInfoService>().GetMenuParam(header);
|
||||
var isChecked = paraValue == 1;
|
||||
var labelContent = isChecked ? model.Value1 : model.Value0;
|
||||
var toggleButton = CreateToggleButton(item, isChecked);
|
||||
var labelRight = CreateLabel(header, labelContent);
|
||||
var labelLeft = CreateLabelLeft(header, model.Text);
|
||||
var canvas = new Canvas { Height = 25, Width = 200 };
|
||||
canvas.Children.Add(toggleButton);
|
||||
canvas.Children.Add(labelLeft);
|
||||
canvas.Children.Add(labelRight);
|
||||
//ribbonGroupBox.Items.Add(canvas);
|
||||
toggleButtonLabelDic.Add(header, labelRight);
|
||||
|
||||
int index = (int)Math.Ceiling((double)item.MenuIndex / 2);
|
||||
if (dicStackPanel.ContainsKey(index)) //如果MenuIndex编号乱编,会导致溢出
|
||||
{
|
||||
dicStackPanel[index].Children.Add(canvas);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static Label CreateLabelLeft(string header, object content)
|
||||
{
|
||||
var label = new Label
|
||||
{
|
||||
BorderThickness = new Thickness(0),
|
||||
Name = header + "HeaderLabelLeft",
|
||||
Content = content
|
||||
};
|
||||
label.SetValue(System.Windows.Window.LeftProperty, 0d);
|
||||
label.SetValue(System.Windows.Window.TopProperty, 0d);
|
||||
return label;
|
||||
}
|
||||
|
||||
private static Label CreateLabel(string header, object content)
|
||||
{
|
||||
var label = new Label
|
||||
{
|
||||
BorderThickness = new Thickness(0),
|
||||
Name = header + "HeaderLabel",
|
||||
Content = content
|
||||
};
|
||||
label.SetValue(System.Windows.Window.LeftProperty, 120d);
|
||||
label.SetValue(System.Windows.Window.TopProperty, 0d);
|
||||
return label;
|
||||
}
|
||||
|
||||
private static ToggleButton CreateToggleButton(TMenuInfo item, bool isChecked)
|
||||
{
|
||||
var toggleButton = new ToggleButton
|
||||
{
|
||||
Name = item.HeaderName,
|
||||
Content = item.Header,
|
||||
Header = item.Header,
|
||||
Width = 50,
|
||||
Style = MainHeaderViewForPublic.FindResource("ToggleButtonStyle") as Style,
|
||||
IsChecked = isChecked
|
||||
};
|
||||
toggleButton.Click += RibbonButton_Click;
|
||||
toggleButton.SetValue(System.Windows.Window.LeftProperty, 69d);
|
||||
toggleButton.SetValue(System.Windows.Window.TopProperty, 5d);
|
||||
return toggleButton;
|
||||
}
|
||||
|
||||
private void ChangeModeColor(Fluent.ComboBox comboBox)
|
||||
{
|
||||
string comboBoxColor = Colors.Black.ToString();
|
||||
switch ((int)comboBox.SelectedValue)
|
||||
{
|
||||
case (int)EMOMMode.OnLine:
|
||||
comboBoxColor = Colors.Green.ToString();
|
||||
break;
|
||||
|
||||
case (int)EMOMMode.OffLine:
|
||||
comboBoxColor = Colors.Red.ToString();
|
||||
break;
|
||||
}
|
||||
comboBox.Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString(comboBoxColor));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region
|
||||
private void GenerateMenuImage()//获取菜单图标
|
||||
{
|
||||
var table = _unityContainer.Resolve<MenuInfoService>().GetImage();
|
||||
byte[] imageByte = null;
|
||||
string path = Environment.CurrentDirectory + "/images";
|
||||
if (!Directory.Exists(path))
|
||||
{
|
||||
Directory.CreateDirectory(path);
|
||||
}
|
||||
|
||||
foreach (DataRow item in table.Rows)
|
||||
{
|
||||
imageByte = Newtonsoft.Json.JsonConvert.DeserializeObject<byte[]>(item["MenuImage"].ToString());
|
||||
CreateFile(imageByte, path + "/" + item["Header"] + ".png");
|
||||
}
|
||||
}
|
||||
|
||||
private static void CreateFile(byte[] fileBuffer, string newFilePath)
|
||||
{
|
||||
if (File.Exists(newFilePath))
|
||||
{
|
||||
File.Delete(newFilePath);
|
||||
}
|
||||
FileStream fs = new FileStream(newFilePath, FileMode.CreateNew);
|
||||
BinaryWriter bw = new BinaryWriter(fs);
|
||||
bw.Write(fileBuffer, 0, fileBuffer.Length); //用文件流生成一个文件
|
||||
bw.Close();
|
||||
fs.Close();
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
public class ParaJSON
|
||||
{
|
||||
public string CMD { get; set; }
|
||||
public string Parameter { get; set; }
|
||||
public string Value0 { get; set; }
|
||||
public string Value1 { get; set; }
|
||||
public string Text { get; set; }
|
||||
}
|
||||
}
|
||||
185
Cowain.Bake.Main/Views/MainWindow.xaml
Normal file
@@ -0,0 +1,185 @@
|
||||
<Window 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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:prism="http://prismlibrary.com/"
|
||||
prism:ViewModelLocator.AutoWireViewModel="True"
|
||||
xmlns:ad="https://github.com/Dirkster99/AvalonDock"
|
||||
xmlns:hc="https://handyorg.github.io/handycontrol"
|
||||
x:Class="Cowain.Bake.Main.Views.MainWindow"
|
||||
xmlns:converter="clr-namespace:Cowain.Bake.Common.Converter;assembly=Cowain.Bake.Common"
|
||||
xmlns:bllConverter="clr-namespace:Cowain.Bake.BLL.Converter;assembly=Cowain.Bake.BLL"
|
||||
xmlns:control="clr-namespace:Cowain.Bake.Main.Views"
|
||||
xmlns:local="clr-namespace:Cowain.Bake.Main.ViewModels"
|
||||
mc:Ignorable="d"
|
||||
WindowState="Maximized"
|
||||
Closing="Window_Closing"
|
||||
Title="{Binding MainTitle}" Height="900" Width="1600" Loaded="Window_Loaded">
|
||||
<Window.Resources>
|
||||
<converter:BindingColor x:Key="ColorConverter"/>
|
||||
<bllConverter:StationIdConverter x:Key="StationIdConverter"/>
|
||||
<Style x:Key="DefaultToolTipStyle" TargetType="{x:Type ToolTip}">
|
||||
<Setter Property="Foreground" Value="Yellow"/>
|
||||
<Setter Property = "Background" Value="Blue"/>
|
||||
<Setter Property = "FontSize" Value="14"/>
|
||||
<Setter Property="BorderBrush" Value="White"/>
|
||||
</Style>
|
||||
<Style x:Key="MyButton" TargetType="Button">
|
||||
<Style.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter Property="Background" Value="LightBlue"/>
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
<Style TargetType="{x:Type TabItem}" x:Key="BaseTabItem">
|
||||
<Setter Property="Header" Value="{Binding DataContext.PageTitle}"/>
|
||||
<Setter Property="Background" Value="Transparent"/>
|
||||
<Setter Property="Margin" Value="2,0"/>
|
||||
<Setter Property="Foreground" Value="#444"/>
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type TabItem}">
|
||||
<Grid Background="{TemplateBinding Background}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition Width="auto" MaxWidth="30" MinWidth="10"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Text="{TemplateBinding Header}" VerticalAlignment="Center" Margin="10,5"/>
|
||||
<Grid Grid.Column="1" x:Name="close_grid" Width="30" Visibility="Collapsed">
|
||||
<Button Foreground="{TemplateBinding Foreground}"
|
||||
Visibility="Collapsed" x:Name="close_btn" Height="24"
|
||||
Command="{Binding DataContext.CloseCommand}"
|
||||
CommandParameter="{Binding DataContext.NavUri}"/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<ControlTemplate.Triggers>
|
||||
<DataTrigger Binding="{Binding DataContext.IsCanClose}" Value="True">
|
||||
<Setter TargetName="close_grid" Property="Visibility" Value="Visible"/>
|
||||
</DataTrigger>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter Property="Visibility" Value="Visible" TargetName="close_btn"/>
|
||||
</Trigger>
|
||||
<Trigger Property="IsSelected" Value="True">
|
||||
<Setter Property="Visibility" Value="Visible" TargetName="close_btn"/>
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
<Style.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter Property="Background" Value="#EEE"/>
|
||||
</Trigger>
|
||||
<Trigger Property="IsSelected" Value="True">
|
||||
<Setter Property="Background" Value="#FF0ABEFF"/>
|
||||
<Setter Property="Foreground" Value="White"/>
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Window.Resources>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="88" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="30" />
|
||||
</Grid.RowDefinitions>
|
||||
<ContentControl prism:RegionManager.RegionName="MainHeaderRegion" Grid.Row="0"></ContentControl>
|
||||
<!--工作窗口-->
|
||||
<DockingManager x:Name="dockingManager" Grid.Row="1">
|
||||
<DockingManager.Background>
|
||||
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
|
||||
<!-- 起点颜色 -->
|
||||
<GradientStop Color="LightBlue" Offset="0" />
|
||||
<!-- 终点颜色 -->
|
||||
<GradientStop Color="LightBlue" Offset="1" />
|
||||
</LinearGradientBrush>
|
||||
</DockingManager.Background>
|
||||
|
||||
<DockingManager.Theme>
|
||||
<Vs2013BlueTheme/>
|
||||
</DockingManager.Theme>
|
||||
|
||||
<LayoutRoot>
|
||||
<LayoutPanel Orientation="Horizontal">
|
||||
<LayoutAnchorablePane DockWidth="200">
|
||||
<!--<LayoutAnchorable Title="菜单栏" CanClose="False" CanFloat="False" CanHide="False" ContentId="Solution">
|
||||
-->
|
||||
<!--放置菜单的区域-->
|
||||
<!--
|
||||
<ContentControl prism:RegionManager.RegionName="LeftMenuTreeRegion"/>
|
||||
</LayoutAnchorable>-->
|
||||
<LayoutAnchorable Title="基础信息" CanClose="False" CanFloat="False" CanHide="False" ContentId="Solution">
|
||||
<!--基础-->
|
||||
<ContentControl prism:RegionManager.RegionName="BasicInfoRegion"/>
|
||||
</LayoutAnchorable>
|
||||
<LayoutAnchorable Title="日志信息" CanClose="False" CanFloat="False" CanHide="False" ContentId="Solution">
|
||||
<!--日志-->
|
||||
<control:LogManagement x:Name="logManagement1" LogLevelSource="{Binding LogLevelModel1}"
|
||||
LoglistItem="{Binding InfoLogModel,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
|
||||
<!--<ContentControl prism:RegionManager.RegionName="LogInfoRegion" x:Name="logManagement1"/>-->
|
||||
</LayoutAnchorable>
|
||||
</LayoutAnchorablePane>
|
||||
<LayoutPanel Orientation="Vertical">
|
||||
<LayoutDocumentPane IsMaximized="True" x:Name="tabPanel">
|
||||
<LayoutDocument Title="主窗口" CanClose="False" ContentId="second" IsSelected="True">
|
||||
<ContentControl prism:RegionManager.RegionName="StationInfoRegion"/>
|
||||
</LayoutDocument>
|
||||
<LayoutDocument Title="报警窗口" CanClose="False" ContentId="second">
|
||||
<Grid>
|
||||
<TabControl>
|
||||
<TabItem Header="实时告警">
|
||||
<DataGrid ItemsSource="{Binding Alarms}" AutoGenerateColumns="False" IsReadOnly="True" HorizontalAlignment="Left" Height="850" VerticalAlignment="Top" Width="1387" Margin="15,15,15,15">
|
||||
<DataGrid.RowStyle>
|
||||
<Style TargetType="DataGridRow">
|
||||
<Style.Triggers>
|
||||
<Trigger Property="IsSelected" Value="True">
|
||||
<Setter Property="Background" Value="Blue"/>
|
||||
<Setter Property="Foreground" Value="White"/>
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
<Setter Property="Foreground" Value="{Binding Status, Converter={StaticResource ColorConverter}}"/>
|
||||
</Style>
|
||||
</DataGrid.RowStyle>
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn Header="工站名称" Binding="{Binding StationId,Converter={StaticResource StationIdConverter}}" Width="100" Visibility="Visible"/>
|
||||
<DataGridTextColumn Header="报警内容" Binding="{Binding Desc}" Width="500"/>
|
||||
<DataGridTextColumn Header="开始时间" Binding="{Binding StartTime,StringFormat='yyyy/MM/dd HH:mm:ss'}" Width="200"/>
|
||||
<DataGridTextColumn Header="结束时间" Binding="{Binding StopTime,StringFormat='yyyy/MM/dd HH:mm:ss'}" Width="200" Visibility="Hidden"/>
|
||||
<DataGridTextColumn Header="状态" Binding="{Binding Status}" Width="100"/>
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
</TabItem>
|
||||
<TabItem Header="记录查询">
|
||||
<Grid>
|
||||
<DataGrid Margin="0,50,0,0" AutoGenerateColumns="False" ItemsSource="{Binding HistoryAlarmsData}">
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn Header="工站名称" Binding="{Binding StationId,Converter={StaticResource StationIdConverter}}" Width="100"/>
|
||||
<DataGridTextColumn Header="报警内容" Binding="{Binding Desc}" Width="500"/>
|
||||
<DataGridTextColumn Header="开始时间" Binding="{Binding StartTime,StringFormat='yyyy/MM/dd HH:mm:ss'}" Width="200"/>
|
||||
<DataGridTextColumn Header="结束时间" Binding="{Binding StopTime,StringFormat='yyyy/MM/dd HH:mm:ss'}" Width="200" />
|
||||
<DataGridTextColumn Header="状态" Binding="{Binding Status}" Width="100"/>
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
<hc:DatePicker HorizontalAlignment="Left" Text="{Binding AlarmStartTime,Mode=TwoWay}" VerticalAlignment="Top" Width="131" Margin="8,9,0,0"/>
|
||||
<hc:DatePicker HorizontalAlignment="Left" Text="{Binding AlarmEndTime,Mode=TwoWay}" VerticalAlignment="Top" Width="140" Margin="144,9,0,0"/>
|
||||
<Button Content="查询" Style="{StaticResource ButtonInfo}" Name="alarmReport" Command="{Binding AlarmQueryCommand}" HorizontalAlignment="Left" VerticalAlignment="Top" Width="75" Margin="297,9,0,0"/>
|
||||
<Button Content="导出Excel" Style="{StaticResource ButtonInfo}" x:Name="alarmExportExcel" Command="{Binding AlarmExportExcel}" HorizontalAlignment="Left" VerticalAlignment="Top" Width="75" Margin="391,10,0,0"/>
|
||||
</Grid>
|
||||
</TabItem>
|
||||
<hc:DateTimePicker HorizontalAlignment="Left" VerticalAlignment="Top" Width="195"/>
|
||||
</TabControl>
|
||||
</Grid>
|
||||
</LayoutDocument>
|
||||
<LayoutDocument x:Name="showWindow" Title="" CanClose="False" ContentId="second">
|
||||
<!--数据展示-->
|
||||
<ContentControl prism:RegionManager.RegionName="MainContentRegion" />
|
||||
</LayoutDocument>
|
||||
</LayoutDocumentPane>
|
||||
</LayoutPanel>
|
||||
</LayoutPanel>
|
||||
</LayoutRoot>
|
||||
</DockingManager>
|
||||
<!--底部消息-->
|
||||
<!--<hc:RunningBlock AutoReverse="False" Grid.Row="2" Height="50" Content="{Binding PromptContent,Mode=TwoWay}" FontSize="18" FontWeight="Bold" Foreground="OrangeRed" Duration="0:0:20" VerticalAlignment="Center"/>-->
|
||||
</Grid>
|
||||
</Window>
|
||||
76
Cowain.Bake.Main/Views/MainWindow.xaml.cs
Normal file
@@ -0,0 +1,76 @@
|
||||
using AvalonDock.Layout;
|
||||
using AvalonDock.Themes;
|
||||
using Cowain.Bake.BLL;
|
||||
using Cowain.Bake.Common;
|
||||
using Cowain.Bake.Common.Enums;
|
||||
using Cowain.Bake.Communication.Interface;
|
||||
using Cowain.Bake.Model;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Windows;
|
||||
using Unity;
|
||||
|
||||
namespace Cowain.Bake.Main.Views
|
||||
{
|
||||
/// <summary>
|
||||
/// MainWindow.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class MainWindow : Window
|
||||
{
|
||||
public static LayoutDocument mainShowWindow; //为了设置Title,直接Binding无效
|
||||
IUnityContainer _unityContainer = null;
|
||||
List<Theme> _theme = new List<Theme>();
|
||||
//public static MainWindowViewModel mainWindowModel = null;
|
||||
public MainWindow(IUnityContainer unityContainer)
|
||||
{
|
||||
InitializeComponent();
|
||||
_unityContainer = unityContainer;
|
||||
mainShowWindow = showWindow;
|
||||
_theme.Add(new MetroTheme()); //GenericTheme
|
||||
_theme.Add(new AeroTheme());
|
||||
_theme.Add(new Vs2013BlueTheme());
|
||||
_theme.Add(new Vs2013DarkTheme());
|
||||
_theme.Add(new Vs2013LightTheme());
|
||||
_theme.Add(new ExpressionDarkTheme());
|
||||
}
|
||||
|
||||
public void ChangeSkin(int i)
|
||||
{
|
||||
dockingManager.Theme = _theme[i]; //MetroTheme
|
||||
}
|
||||
|
||||
private void Window_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
}
|
||||
void CloseAllHandle()
|
||||
{
|
||||
System.Collections.Generic.List<TDeviceConfig> plcList = _unityContainer.Resolve<DeviceConfigService>().GetConfig(EDeviceType.PLC);
|
||||
foreach (var item in plcList)
|
||||
{
|
||||
IPLCDevice plc = _unityContainer.Resolve<IPLCDevice>(item.Name); //几个PLC,就实例化几个
|
||||
|
||||
if (null != plc && plc.IsConnect)
|
||||
{
|
||||
plc.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
|
||||
{
|
||||
// 执行窗体的 Closing 事件的逻辑
|
||||
if (MessageBoxResult.OK == HandyControl.Controls.MessageBox.Ask("是否退出自动真空烘烤系统?", "退出"))
|
||||
{
|
||||
Global.AppExit = true;
|
||||
CloseAllHandle();
|
||||
//Thread.Sleep(3000);
|
||||
//await Task.Delay(10000); async
|
||||
e.Cancel = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
e.Cancel = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
17
Cowain.Bake.Main/Views/ManualTask.xaml
Normal file
@@ -0,0 +1,17 @@
|
||||
<Window x:Class="Cowain.Bake.Main.Views.ManualTask"
|
||||
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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:Cowain.Bake.Main.Views"
|
||||
mc:Ignorable="d"
|
||||
Title="手动任务" Height="300" Width="380" WindowStartupLocation="CenterScreen">
|
||||
<Grid>
|
||||
<Label Content="取:" Style="{StaticResource BaseStyle}" HorizontalContentAlignment="Right" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="40,60,0,0" Width="30"/>
|
||||
<Label Content="放:" Style="{StaticResource BaseStyle}" HorizontalContentAlignment="Right" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="40,136,0,0" Width="30"/>
|
||||
<TextBox FontWeight="Bold" Foreground="Black" IsReadOnly="True" Text="{Binding SelectFromValue,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Left" Margin="75,60,0,0" VerticalAlignment="Top" Width="215"/>
|
||||
<ComboBox ItemsSource="{Binding StationDtl}" SelectedValue="{Binding SelectToValue,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Left" Margin="80,131,0,0" VerticalAlignment="Top" Width="210"/>
|
||||
<Button Content="生成任务" Command="{Binding GenerateTaskCommand}" Style="{StaticResource ButtonInfo}" HorizontalAlignment="Left" Height="35" Margin="80,195,0,0" VerticalAlignment="Top" Width="210"/>
|
||||
|
||||
</Grid>
|
||||
</Window>
|
||||
36
Cowain.Bake.Main/Views/ManualTask.xaml.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
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.Shapes;
|
||||
using Unity;
|
||||
|
||||
namespace Cowain.Bake.Main.Views
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// ManualTask.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class ManualTask : Window
|
||||
{
|
||||
ViewModels.ManualTaskViewModel manualTaskViewModel = null;
|
||||
//private IUnityContainer _unityContainer;
|
||||
public ManualTask(string fromStation, IUnityContainer unityContainer)
|
||||
{
|
||||
InitializeComponent();
|
||||
//_unityContainer = unityContainer;
|
||||
manualTaskViewModel = new ViewModels.ManualTaskViewModel(unityContainer);
|
||||
manualTaskViewModel.GetStationDtl();
|
||||
manualTaskViewModel.SelectFromValue = fromStation;
|
||||
this.DataContext = manualTaskViewModel;
|
||||
}
|
||||
}
|
||||
}
|
||||
119
Cowain.Bake.Main/Views/MoistureValueView.xaml
Normal file
@@ -0,0 +1,119 @@
|
||||
<Window x:Class="Cowain.Bake.Main.Views.MoistureValueView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:prism="http://prismlibrary.com/"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d"
|
||||
WindowStartupLocation="CenterScreen"
|
||||
prism:ViewModelLocator.AutoWireViewModel="True"
|
||||
Height="220" Width="420" >
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="70"/>
|
||||
<RowDefinition Height="60"/>
|
||||
<RowDefinition Height="50"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<DockPanel Grid.Row="0" Grid.Column="0">
|
||||
<Label Content="正极水分:"
|
||||
Foreground="Black"
|
||||
FontWeight="Bold"
|
||||
Style="{DynamicResource BaseStyle}"
|
||||
Margin="0,25,0,0"
|
||||
Width="65" />
|
||||
<TextBox
|
||||
Text="{Binding AnodeWaterJudge}"
|
||||
FontWeight="Bold" Height="30"
|
||||
TextWrapping="Wrap"
|
||||
Width="65" />
|
||||
</DockPanel>
|
||||
<DockPanel Grid.Row="0" Grid.Column="1">
|
||||
<Label
|
||||
Content="负极水分:"
|
||||
Foreground="Black"
|
||||
FontWeight="Bold"
|
||||
Style="{DynamicResource BaseStyle}"
|
||||
Margin="0,25,0,0"
|
||||
Width="65" />
|
||||
<TextBox
|
||||
Text="{Binding CathodeWaterJudge}"
|
||||
FontWeight="Bold"
|
||||
TextWrapping="Wrap"
|
||||
VerticalAlignment="Center"
|
||||
Width="65"/>
|
||||
</DockPanel>
|
||||
<DockPanel Grid.Row="0" Grid.Column="2">
|
||||
<Label
|
||||
Content="隔膜水分:"
|
||||
Foreground="Black"
|
||||
FontWeight="Bold"
|
||||
Style="{DynamicResource BaseStyle}"
|
||||
Margin="0,25,0,0"
|
||||
Width="65" />
|
||||
<TextBox
|
||||
Text="{Binding SeptumWaterJudge}"
|
||||
FontWeight="Bold"
|
||||
TextWrapping="Wrap"
|
||||
VerticalAlignment="Center"
|
||||
Width="65" />
|
||||
</DockPanel>
|
||||
|
||||
<DockPanel Grid.Row="1" Grid.Column="0" Visibility="Hidden">
|
||||
<Label Content="正极水分2:"
|
||||
Foreground="Black"
|
||||
FontWeight="Bold"
|
||||
Style="{DynamicResource BaseStyle}"
|
||||
Margin="0,25,0,0"
|
||||
Width="65" />
|
||||
<TextBox
|
||||
Text="{Binding AnodeWaterJudge2}"
|
||||
FontWeight="Bold" Height="30"
|
||||
TextWrapping="Wrap"
|
||||
Width="65" />
|
||||
</DockPanel>
|
||||
|
||||
<DockPanel Grid.Row="1" Grid.Column="1" Visibility="Hidden">
|
||||
<Label
|
||||
Content="负极水分2:"
|
||||
Foreground="Black"
|
||||
FontWeight="Bold"
|
||||
Style="{DynamicResource BaseStyle}"
|
||||
Margin="0,25,0,0"
|
||||
Width="65" />
|
||||
<TextBox
|
||||
Text="{Binding CathodeWaterJudge2}"
|
||||
FontWeight="Bold"
|
||||
TextWrapping="Wrap"
|
||||
VerticalAlignment="Center"
|
||||
Width="65"/>
|
||||
</DockPanel>
|
||||
<DockPanel Grid.Row="1" Grid.Column="2" Visibility="Hidden">
|
||||
<Label
|
||||
Content="隔膜水分2:"
|
||||
Foreground="Black"
|
||||
FontWeight="Bold"
|
||||
Style="{DynamicResource BaseStyle}"
|
||||
Margin="0,25,0,0"
|
||||
Width="65" />
|
||||
<TextBox
|
||||
Text="{Binding SeptumWaterJudge2}"
|
||||
FontWeight="Bold"
|
||||
TextWrapping="Wrap"
|
||||
VerticalAlignment="Center"
|
||||
Width="65" />
|
||||
</DockPanel>
|
||||
|
||||
<StackPanel Grid.Row="2" Grid.Column="1" Orientation="Horizontal">
|
||||
<Button Content="判定" x:Name="judge" Background="DeepSkyBlue" Command="{Binding Judge}" Margin="20,0,0,0" Width="90" />
|
||||
<!--<Button Content="退出" x:Name="Close" Background="DeepSkyBlue" Command="{Binding CloseCommand}" Margin="30,0,0,0" Width="90" />-->
|
||||
</StackPanel>
|
||||
|
||||
|
||||
</Grid>
|
||||
</Window>
|
||||
35
Cowain.Bake.Main/Views/MoistureValueView.xaml.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using Cowain.Bake.Main.ViewModels;
|
||||
using Opc.Ua;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
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.Shapes;
|
||||
using Unity;
|
||||
|
||||
namespace Cowain.Bake.Main.Views
|
||||
{
|
||||
/// <summary>
|
||||
/// MoistureValue.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class MoistureValueView : Window
|
||||
{
|
||||
ViewModels.MoistureValueViewMode viewModel = null;
|
||||
public MoistureValueView(IUnityContainer unityContainer, CavityDtlViewModel station)
|
||||
{
|
||||
InitializeComponent();
|
||||
viewModel = new ViewModels.MoistureValueViewMode(unityContainer);
|
||||
//viewModel.WaterValueModel = WaterValueModel;
|
||||
viewModel.thatParent = station;
|
||||
this.DataContext = viewModel;
|
||||
}
|
||||
}
|
||||
}
|
||||
124
Cowain.Bake.Main/Views/PalletIdInputWindow.xaml
Normal file
@@ -0,0 +1,124 @@
|
||||
<Window
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:prism="http://prismlibrary.com/"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:hc="https://handyorg.github.io/handycontrol"
|
||||
x:Class="Cowain.Bake.Main.Views.PalletIdInputWindow"
|
||||
prism:ViewModelLocator.AutoWireViewModel="True"
|
||||
mc:Ignorable="d"
|
||||
Background="#5f94c3"
|
||||
Title="{Binding Title}" Height="170" Width="380">
|
||||
<Window.Resources>
|
||||
<Style x:Key="ButtonStyle1" TargetType="{x:Type Button}">
|
||||
<Setter Property="Foreground" Value="{DynamicResource PrimaryTextBrush}"/>
|
||||
<Setter Property="BorderThickness" Value="1"/>
|
||||
<Style.BasedOn>
|
||||
<Style TargetType="{x:Type Button}">
|
||||
<Setter Property="Background" Value="{DynamicResource RegionBrush}"/>
|
||||
<Setter Property="hc:BorderElement.CornerRadius" Value="4"/>
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type Button}">
|
||||
<hc:SimplePanel>
|
||||
<Border Background="{TemplateBinding Background}" CornerRadius="{Binding (hc:BorderElement.CornerRadius), RelativeSource={RelativeSource TemplatedParent}}"/>
|
||||
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="{Binding (hc:BorderElement.CornerRadius), RelativeSource={RelativeSource TemplatedParent}}">
|
||||
<StackPanel HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" Orientation="Horizontal" VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
|
||||
<Path x:Name="PathMain" Data="{TemplateBinding hc:IconElement.Geometry}" Fill="{TemplateBinding Foreground}" Height="{TemplateBinding hc:IconElement.Height}" Stretch="Uniform" SnapsToDevicePixels="True" Width="{TemplateBinding hc:IconElement.Width}"/>
|
||||
<ContentPresenter x:Name="ContentPresenterMain" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" Margin="6,0,0,0" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="Center"/>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</hc:SimplePanel>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="Content" Value="{x:Null}">
|
||||
<Setter Property="Visibility" TargetName="ContentPresenterMain" Value="Collapsed"/>
|
||||
</Trigger>
|
||||
<Trigger Property="hc:IconElement.Geometry" Value="{x:Null}">
|
||||
<Setter Property="Visibility" TargetName="PathMain" Value="Collapsed"/>
|
||||
<Setter Property="Margin" TargetName="ContentPresenterMain" Value="0"/>
|
||||
</Trigger>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter Property="Background" Value="#5f62c3"></Setter>
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
<Style.BasedOn>
|
||||
<Style TargetType="{x:Type ButtonBase}">
|
||||
<Setter Property="Height" Value="30"/>
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource BorderBrush}"/>
|
||||
<Setter Property="Padding" Value="10,6"/>
|
||||
<Setter Property="Foreground" Value="{DynamicResource TextIconBrush}"/>
|
||||
<Setter Property="BorderThickness" Value="0"/>
|
||||
<Setter Property="HorizontalAlignment" Value="Center"/>
|
||||
<Setter Property="VerticalAlignment" Value="Center"/>
|
||||
<Setter Property="HorizontalContentAlignment" Value="Center"/>
|
||||
<Setter Property="VerticalContentAlignment" Value="Center"/>
|
||||
<Style.BasedOn>
|
||||
<Style TargetType="{x:Type Control}">
|
||||
<Setter Property="Foreground" Value="{DynamicResource PrimaryTextBrush}"/>
|
||||
<Setter Property="FontSize" Value="12"/>
|
||||
<Setter Property="FocusVisualStyle">
|
||||
<Setter.Value>
|
||||
<Style>
|
||||
<Setter Property="Control.Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate>
|
||||
<Rectangle RadiusY="4" RadiusX="4">
|
||||
<Rectangle.Style>
|
||||
<Style TargetType="{x:Type Rectangle}">
|
||||
<Setter Property="Margin" Value="-2"/>
|
||||
<Setter Property="Opacity" Value="0.6"/>
|
||||
<Setter Property="SnapsToDevicePixels" Value="True"/>
|
||||
<Setter Property="Stroke" Value="{DynamicResource SecondaryBorderBrush}"/>
|
||||
<Setter Property="StrokeThickness" Value="2"/>
|
||||
<Setter Property="StrokeDashArray" Value="1 1"/>
|
||||
</Style>
|
||||
</Rectangle.Style>
|
||||
</Rectangle>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</Style.BasedOn>
|
||||
</Style>
|
||||
</Style.BasedOn>
|
||||
<Style.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter Property="Opacity" Value="0.9"/>
|
||||
</Trigger>
|
||||
<Trigger Property="IsPressed" Value="True">
|
||||
<Setter Property="Opacity" Value="0.6"/>
|
||||
</Trigger>
|
||||
<Trigger Property="IsEnabled" Value="False">
|
||||
<Setter Property="Opacity" Value="0.4"/>
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Style.BasedOn>
|
||||
<Style.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter Property="Background" Value="{DynamicResource SecondaryRegionBrush}"/>
|
||||
</Trigger>
|
||||
<Trigger Property="IsPressed" Value="True">
|
||||
<Setter Property="Background" Value="{DynamicResource BorderBrush}"/>
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Window.Resources>
|
||||
<Grid>
|
||||
<StackPanel Orientation="Vertical">
|
||||
<DockPanel HorizontalAlignment="Center" Margin="3,20,0,20">
|
||||
<Label DockPanel.Dock="Left" Background="#5f94c3" BorderThickness="0" FontSize="15" Content="{Binding MsgContent}" Margin="0,0,0,0"/>
|
||||
<Button DockPanel.Dock="Right" Click="Button_Click" Width=" 50" Height="29" Foreground="White" Background="#6e9bc5" Margin="20,0,0,0" Content="确定" Style="{DynamicResource ButtonStyle1}" BorderThickness="0" />
|
||||
</DockPanel>
|
||||
|
||||
<TextBox x:Name="InputBox" Width="300" Height="30" Margin="0,0,0,10"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Window>
|
||||
51
Cowain.Bake.Main/Views/PalletIdInputWindow.xaml.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
using Cowain.Bake.Main.ViewModels;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
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.Shapes;
|
||||
|
||||
namespace Cowain.Bake.Main.Views
|
||||
{
|
||||
/// <summary>
|
||||
/// PalletIdInputWindow.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class PalletIdInputWindow : Window
|
||||
{
|
||||
public string _btnMsg = "";
|
||||
public string PalletId { get; set; }
|
||||
public PalletIdInputWindow(string title, string msg, string btnMsg)
|
||||
{
|
||||
InitializeComponent();
|
||||
PalletIdInputWindowViewModel vm = this.DataContext as PalletIdInputWindowViewModel;
|
||||
vm.Title = title; //;
|
||||
vm.MsgContent = msg; // ;
|
||||
_btnMsg = btnMsg;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public string ConfirmPalletId()
|
||||
{
|
||||
return PalletId;
|
||||
}
|
||||
|
||||
private void Button_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
MessageBoxResult result = HandyControl.Controls.MessageBox.Show(_btnMsg, "确认", MessageBoxButton.YesNo,MessageBoxImage.Information);
|
||||
if (result == MessageBoxResult.Yes)
|
||||
{
|
||||
PalletId = InputBox.Text;
|
||||
this.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
29
Cowain.Bake.Main/bin/Debug/Cowain.Preheat.BLL.dll.config
Normal file
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<configSections>
|
||||
|
||||
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false"/>
|
||||
</configSections>
|
||||
<entityFramework>
|
||||
<providers>
|
||||
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer"/>
|
||||
|
||||
</providers>
|
||||
</entityFramework>
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.1.2" newVersion="4.0.1.2"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Threading.Tasks.Extensions" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.2.0.1" newVersion="4.2.0.1"/>
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2"/></startup></configuration>
|
||||
39
Cowain.Bake.Main/bin/Debug/Cowain.Preheat.UI.dll.config
Normal file
@@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.1.2" newVersion="4.0.1.2" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Threading.Tasks.Extensions" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.2.0.1" newVersion="4.2.0.1" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Numerics.Vectors" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.1.4.0" newVersion="4.1.4.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.ValueTuple" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Text.Encoding.CodePages" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="5.0.0.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" /></startup></configuration>
|
||||
BIN
Cowain.Bake.Main/bin/Debug/EntityFramework.SqlServer.dll
Normal file
BIN
Cowain.Bake.Main/bin/Debug/MySql.Data.EntityFramework.dll
Normal file
35
Cowain.Bake.Main/bin/Debug/NLog.config
Normal file
@@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" throwExceptions="true">
|
||||
|
||||
<targets xsi:type="AsyncWrapper">
|
||||
<!--保存至文件-->
|
||||
<target name="log_file" xsi:type="File"
|
||||
archiveFileName="../Logs/Archive/${shortdate} ${level:uppercase=false:padding=-5}.log"
|
||||
maxArchiveFiles="30"
|
||||
archiveEvery="Day"
|
||||
fileName="../Logs/${level:uppercase=false:padding=-5}.log"
|
||||
layout="${longdate} | ${message} ${onexception:${exception:format=tostring} ${newline} ${stacktrace} ${newline}" />
|
||||
<!--输出至Debugger-->
|
||||
<target name="debugger" xsi:type="Debugger"
|
||||
layout="NLog: ${date:format=HH\:mm\:ss} | ${message}" />
|
||||
<!--输出至控制台-->
|
||||
<target name="console" xsi:type="ColoredConsole" layout="${longdate} ${message} ${exception:format=tostring}"></target>
|
||||
<!--输出至邮件-->
|
||||
<target xsi:type="File"
|
||||
name="hourlyFile"
|
||||
fileName="../Logs/EqptAlive/${date:format=yyyyMMdd}/${date:format=HH}.log"
|
||||
layout="${date:format=yyyy-MM-dd HH\:mm\:ss}${message}"
|
||||
createDirs="true" />
|
||||
|
||||
<!-- Define a fallback target if logging fails -->
|
||||
</targets>
|
||||
<rules>
|
||||
<logger name="*" levels="Debug" writeTo="log_file" />
|
||||
<logger name="*" level="Fatal" writeTo="log_file" />
|
||||
<logger name="*" level="Warn" writeTo="log_file" />
|
||||
<logger name="*" level="Error" writeTo="log_file" />
|
||||
<logger name="*" level="Info" writeTo="log_file" />
|
||||
<logger name="*" level="Trace" writeTo="hourlyFile" />
|
||||
</rules>
|
||||
</nlog>
|
||||
20
Cowain.Bake.Main/bin/Debug/Notes.txt
Normal file
@@ -0,0 +1,20 @@
|
||||
v1.0.0.2 (2026-02-01)
|
||||
- 新增:露点温度
|
||||
- 作者: 刘少明
|
||||
|
||||
v1.0.0.3 (2026-02-02)
|
||||
- 修复:手动手成任务,快速响应
|
||||
- 作者: 刘少明
|
||||
|
||||
v1.0.0.4 (2026-02-03)
|
||||
- 修复:报警记录显示工站名称
|
||||
- 作者: 刘少明
|
||||
|
||||
v1.0.0.5 (2026-02-04)
|
||||
- 新增:预计结束烘烤时间
|
||||
- 作者: 刘少明
|
||||
|
||||
v1.0.0.6 (2026-02-05)
|
||||
- 修复:数据连接异常,取消登入时密码加密功能!
|
||||
- 作者: 刘少明
|
||||
|
||||
17
Cowain.Bake.Main/bin/Debug/config.ini
Normal file
@@ -0,0 +1,17 @@
|
||||
[Main]
|
||||
PassWord=dy123
|
||||
DispatchMode=Manual
|
||||
ProductionLineName=得壹二期全自动真空烘烤L7-1线
|
||||
WaterPallet=0
|
||||
CountCmd=5
|
||||
SkinType=0
|
||||
AutoUpdate=false
|
||||
AutoUpdateUrl=https://wwww.163.com
|
||||
StoveLayers=17
|
||||
PalletRows=48
|
||||
PalletCols=2
|
||||
|
||||
# 0:正向, 1:反向
|
||||
StoveDispDirection = 0
|
||||
# 0:不反序,1:反序
|
||||
IsReverseOrder = 1
|
||||