办法总比困难多(不会或不想用WPF MVVM模式也可以搞工控自动化和上位机编程)...
正文
活到老就该学到老。但是难道我们不可以偷懒么,老技术指哪打哪,游刃有余,如果已经炉火纯青,那么解决问题又快又好它不香吗。本文拒绝讨论技术谁优秀谁该被鄙视。上图的流程是花2天时间搞好的,我不是得瑟有什么不得了的地方。我见很多人都在探讨MVVM,数据驱动业务多么的了不起,其实老技术Winform一样的能办到不信你问问DeepSeek让它给你一个示例代码。比如这样子的,点这里下载。如果只是这么简单的话,就没有写本文的必要了。
我们看看上图的场景,因为现场的实际方案没有最终确定,所以开发人员写了5个版本的代码来验证5种流程,但界面就1个,因为业务的数据是一样的。像这种情况我们这种解决方式是极好的。写代码的同事只需要初级程序员就可以担任。帮忙验证和测试是由高级程序员来担任。我贴一些源码来辅助说明一下是怎么实现的。
1.界面的基类: - using System;
- using System.Collections.Generic;
- using System.Threading;
- using System.Windows.Forms;
- using MES.Core;
- using EES.Common;
- using EES.Controls.Win;
- using EES.Common.Data;
- using System.ComponentModel;
- using System.Runtime.InteropServices;
- using System.Text;
- using System.Linq;
- using WinControls;
- using DataCool_MES.framework;
- using DataCool_MES.config;
- using DataCool_MES.utils;
- using System.Drawing;
- namespace DataCool_MES
- {
- public delegate void FeedInfoHandler(object sender, Exception ex, string message, MessageTipsLevel level);
- /// <summary>
- /// 业务窗体基类
- /// </summary>
- public partial class BaseModuleForm : DockBaseWorkForm
- {
- #region DllImport
- [DllImport("kernel32")]
- public static extern long WritePrivateProfileString(string section, string key, string val, string filepath);
- [DllImport("kernel32")]
- public static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retval, int size, string filePath);
- [DllImport("imm32.dll")]
- public static extern IntPtr ImmGetContext(IntPtr hwnd);
- [DllImport("imm32.dll")]
- public static extern bool ImmGetOpenStatus(IntPtr himc);
- [DllImport("imm32.dll")]
- public static extern bool ImmSetOpenStatus(IntPtr himc, bool b);
- [DllImport("imm32.dll")]
- public static extern bool ImmGetConversionStatus(IntPtr himc, ref int lpdw, ref int lpdw2);
- [DllImport("imm32.dll")]
- #endregion
- public static extern int ImmSimulateHotKey(IntPtr hwnd, int lngHotkey);
- private const int IME_CMODE_FULLSHAPE = 0x8;
- private const int IME_CHOTKEY_SHAPE_TOGGLE = 0x11;
- private SynchronizationContext sc;
- protected string onceScanData = string.Empty;
- private BarCodeHooK hook;
- IModuleFlow coreFlowObj;
- // 获取屏幕分辨率
- private Rectangle primaryScreen;
- private float scaleX; // 基准分辨率宽度
- private float scaleY;
- [Browsable(false)]
- public IModuleFlow CoreFlowObj
- {
- get { return coreFlowObj; }
- }
- [Browsable(false)]
- /// <summary>
- /// 日志记录处理异常信息显示处理对象
- /// 此处用于各种日志和状态信息的记录,并进行对应的信息的显示
- /// </summary>
- internal virtual AlertLog Log
- {
- get
- {
- return null;
- }
- }
- protected event Action CursorBegin;
- protected event Action CursorEnd;
-
- /// <summary>
- /// 实例化脚本对象
- /// </summary>
- /// <returns></returns>
- protected virtual IModuleFlow CreateModuleFlow()
- {
- return null;
- }
- public BaseModuleForm()
- {
- DoubleBuffered = true;
- ImeMode = ImeMode.Off;
- AutoScaleMode = AutoScaleMode.None;
- InitializeComponent();
- #region Cursor
- CursorBegin = () =>
- {
- Clear();
- Cursor = Cursors.WaitCursor;
- };
- CursorEnd = () =>
- {
- Cursor = Cursors.Default;
- };
- #endregion
- Load += BaseModuleForm_Load;
- hook = new BarCodeHooK();
- hook.BarCodeEvent += Hook_BarCodeEvent;
- hook.Start();
- FormClosed += BaseModuleForm_FormClosed;
- }
- private void BaseModuleForm_FormClosed(object sender, FormClosedEventArgs e)
- {
- try
- {
- hook.Stop();
- hook.BarCodeEvent -= Hook_BarCodeEvent;
- hook = null;
- }
- catch (Exception ex)
- {
- FrameAppContext.GetInstance().AppLogger.Error(ex);
- }
- }
- private void Hook_BarCodeEvent(BarCodeHooK.BarCodes barCode)
- {
- if (CoreFlowObj != null && FlowContext.Instance.WorkStatus == WorkStatus.Running && !string.IsNullOrEmpty(barCode.BarCode))
- {
- onceScanData = TrimSpecialChar(barCode.BarCode);
- CoreFlowObj.OnExecScanReceiving(onceScanData);
- }
- }
- private void BaseModuleForm_Load(object sender, EventArgs e)
- {
- sc = SynchronizationContext.Current;
- if (!DesignMode)
- {
- Input = FlowContext.Instance;
- FlowContext.Instance.FlowCustomEvent += OnRaiseFlowCustomEvent;
- }
- }
- private void OnRaiseFlowCustomEvent(object sender, TEventArgs<EventClass> e)
- {
- sc.Post(new SendOrPostCallback(delegate (object obj)
- {
- OnFlowCustomEvent((EventClass)obj);
- }), e.Data);
- }
- protected virtual void OnFlowCustomEvent(EventClass ec)
- {
- if (ec.EventType == FlowViewCommand.ClearCurText)
- {
- Clear();
- }
- }
- /// <summary>
- /// 获取当前窗体绑定的上下文对象
- /// </summary>
- /// <returns></returns>
- public virtual BindingType GetBindingType()
- {
- Type type;
- if (bindingSource.DataSource is Type)
- {
- type = (Type)bindingSource.DataSource;
- }
- else
- {
- if (bindingSource.DataSource != null)
- {
- type = bindingSource.DataSource.GetType();
- }
- else
- {
- type = null;
- }
- }
- if (type == null)
- {
- throw new Exception("界面输入的数据源为空");
- }
- BindingType bindingType = new BindingType();
- Type type2;
- if (type.GUID == typeof(DataCollection<>).GUID)
- {
- type2 = type.GetGenericArguments()[0];
- bindingType.IsArray = true;
- }
- else
- {
- if (type.GUID == typeof(List<>).GUID)
- {
- type2 = type.GetGenericArguments()[0];
- bindingType.IsArray = true;
- }
- else
- {
- type2 = type;
- bindingType.IsArray = false;
- }
- }
- bindingType.Type = Factory.getRawType(type2);
- return bindingType;
- }
- public virtual void Start()
- {
- if (coreFlowObj != null && FlowContext.Instance.WorkStatus == WorkStatus.Running)
- return;
- IModuleFlow core = null;
- try
- {
- CursorBegin.Invoke();
- if (CoreFlowObj != null)
- throw new Exception("正在作业,不能启动!");
- core = CreateModuleFlow();
- if (core != null)
- {
- core.FeedInfo += OnFeedInfo;
- core.ExecBeginWork();
- coreFlowObj = core;
- FlowContext.Instance.WorkStatus = WorkStatus.Running;
- }
- ImeMode = ImeMode.NoControl;
- Log.SetLogFocus();
- }
- catch (Exception ex)
- {
- FlowContext.Instance.WorkStatus = WorkStatus.NoAction;
- if (coreFlowObj != null)
- {
- coreFlowObj.FeedInfo -= OnFeedInfo;
- coreFlowObj = null;
- }
- throw ex;
- }
- finally
- {
- if (FlowContext.Instance.WorkStatus == WorkStatus.Running)
- {
- onceScanData = string.Empty;
- }
- CursorEnd.Invoke();
- }
- }
- public virtual void Stop()
- {
- if (CoreFlowObj != null)
- {
- try
- {
- var configObj = SerializerHelper.LoadFromXML(FrameAppContext.GetInstance().RunTimeConfigPath + "\\AppContentConfig.Config");
- if (configObj != null && !string.IsNullOrEmpty(configObj.EntryModuleName) && configObj.EntryModuleName.Equals("成品装箱作业"))
- {
- using (var dlgFrm = new FlowStopCheckForm())
- {
- var dlg = dlgFrm.ShowDialog();
- if (dlg == DialogResult.OK && !FlowContext.Instance.IsEndPacking)
- {
- CoreFlowObj.ExecEndWork();
- coreFlowObj = null;
- FlowContext.Instance.WorkStatus = WorkStatus.Stopped;
- }
- if (dlg == DialogResult.OK && FlowContext.Instance.IsEndPacking)
- {
- CoreFlowObj.StopWorkCheck();
- }
- }
- }
- else
- {
- CoreFlowObj.ExecEndWork();
- coreFlowObj = null;
- FlowContext.Instance.WorkStatus = WorkStatus.Stopped;
- }
- }
- catch (Exception ex)
- {
- Exception error = new Exception("流程执行异常停止," + ex.InnerException == null ? ex.Message : ex.InnerException.Message);
- FrameAppContext.GetInstance().AppLogger.Error(error);
- }
- finally
- {
- Clear();
- if (FlowContext.Instance.WorkStatus != WorkStatus.Running)
- {
- Log.Write("作业已经停止!", "", MessageTipsLevel.Warning);
- FrameAppContext.GetInstance().AppLogger.Info("作业已经停止!");
- FlowContext.Instance.ResetContext();
- }
- Utility.GCFullCollect();
- }
- }
- }
- public virtual void Pause()
- {
- coreFlowObj.ExecPauseWork();
- coreFlowObj = null;
- FlowContext.Instance.WorkStatus = WorkStatus.Pauseing;
- Clear();
- Log.Write("作业已经暂停!", "", MessageTipsLevel.Warning);
- }
- /// <summary>
- /// 界面UI控件的绑定数据清理
- /// 此处为虚函数,用于UI派生界面的具体绑定调用处理
- /// </summary>
- protected virtual void Clear()
- {
- }
- /// <summary>
- /// 异常信息消息处理队列的回调函数
- /// 主要用于各种消息或异常信息的分类处理
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="ex">异常消息结构体</param>
- /// <param name="message">异常消息</param>
- /// <param name="level">异常消息级别</param>
- protected void OnFeedInfo(object sender, Exception ex, string message, MessageTipsLevel level)
- {
- if (Log == null)
- {
- throw new Exception("AlertLog对象没有绑定或实例化!");
- }
- if (ex != null)
- {
- Log.Write(string.Format("{0}:->", DateTime.Now.ToString("MM/dd HH:mm:ss")), ex.Message, MessageTipsLevel.Error, true);
- }
- else
- {
- Log.Write(string.Format("{0}:->", DateTime.Now.ToString("MM/dd HH:mm:ss")), message, level, true);
- }
- }
- /// <summary>
- /// 响应扫描枪输入
- /// </summary>
- /// <param name="msg"></param>
- /// <param name="keyData"></param>
- /// <returns></returns>
- protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
- {
- #region 快捷键
- if (msg.Msg == 0x0100 && ContextMenuStrip != null)
- {
- foreach (ToolStripMenuItem item in ContextMenuStrip.Items)
- {
- if (keyData == item.ShortcutKeys)
- {
- item.PerformClick();
- }
- }
- }
- #endregion
- if (FlowContext.Instance.WorkStatus != WorkStatus.Running)
- return base.ProcessCmdKey(ref msg, keyData);
- else
- return true;
- }
- /// <summary>
- /// 截取特殊字符
- /// </summary>
- /// <param name="inputString"></param>
- /// <returns></returns>
- protected virtual string TrimSpecialChar(string inputString)
- {
- return inputString.Replace("\u0010", "");
- }
- /// <summary>
- /// 动态绑定DataGridView的列
- /// </summary>
- /// <param name="t"></param>
- /// <param name="dgv"></param>
- protected virtual void BingGridColumn(Type t, DataGridView dgv)
- {
- dgv.Columns.Clear();
- var props = t.GetProperties().Where(prop => prop.GetCustomAttributes(typeof(DisplayNameAttribute), false).Any());
- int col_width = dgv.Width / props.Count() - 8;
- foreach (var prop in props)
- {
- DisplayNameAttribute attrib = (DisplayNameAttribute)prop.GetCustomAttributes(typeof(DisplayNameAttribute), false).FirstOrDefault();
- if (prop.GetCustomAttributes(typeof(ProgressBarCellAttribute), false).Any())
- {
- DataGridViewProgressBarColumn dc = new DataGridViewProgressBarColumn();
- dc.Name = "col" + prop.Name;
- dc.HeaderText = attrib.DisplayName;
- dc.DataPropertyName = prop.Name;
- dc.Width = col_width;
- dgv.Columns.Add(dc);
- }
- else
- {
- DataGridViewTextBoxColumn dc = new DataGridViewTextBoxColumn();
- dc.Name = "col" + prop.Name;
- dc.HeaderText = attrib.DisplayName;
- dc.DataPropertyName = prop.Name;
- dc.Width = col_width;
- dgv.Columns.Add(dc);
- }
- }
- }
- /// <summary>
- /// 窗体激活时设置输入法是半角
- /// </summary>
- /// <param name="e"></param>
- protected override void OnActivated(EventArgs e)
- {
- base.OnActivated(e);
- IntPtr HIme = ImmGetContext(this.Handle);
- if (ImmGetOpenStatus(HIme)) //如果输入法处于打开状态
- {
- int iMode = 0;
- int iSentence = 0;
- bool bSuccess = ImmGetConversionStatus(HIme, ref iMode, ref iSentence); //检索输入法资讯
- if (bSuccess)
- {
- if ((iMode & IME_CMODE_FULLSHAPE) > 0) //如果是全形
- ImmSimulateHotKey(this.Handle, IME_CHOTKEY_SHAPE_TOGGLE); //转换成半形
- }
- }
- }
- /// <summary>
- /// 缩放控件
- /// </summary>
- /// <param name="control"></param>
- protected void ScaleControl(Control control)
- {
- control.Left = (int)(control.Left * scaleX);
- control.Top = (int)(control.Top * scaleY);
- control.Width = (int)(control.Width * scaleX);
- control.Height = (int)(control.Height * scaleY);
- foreach (Control child in control.Controls)
- {
- ScaleControl(child);
- }
- }
- }
- }
复制代码 2、代码的基类- using EES.Common;
- using System;
- using MES.Core;
- namespace DataCool_MES
- {
- /// <summary>
- /// 脚本的基类
- /// </summary>
- public abstract class ModuleBaseFlow : IModuleFlow
- {
- /// <summary>
- /// 传递消息的事件
- /// </summary>
- public event FeedInfoHandler FeedInfo;
- protected FlowContext flowContext = FlowContext.Instance;
- //是否是调试模式
- protected bool debugMode = false;
- //是否显示过程明细信息
- protected bool showDetail = false;
- /// <summary>
- /// 采集到数据后发生
- /// </summary>
- /// <param name="data"></param>
- public virtual void OnExecScanReceiving(string data)
- {
- FrameAppContext.GetInstance().AppLogger.Info(data);
- }
- /// <summary>
- /// 触发消息传递
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="ex"></param>
- /// <param name="message"></param>
- /// <param name="level"></param>
- protected virtual void OnFeedInfo(object sender, Exception ex, string message, MessageTipsLevel level)
- {
- FeedInfo?.Invoke(sender, ex, message, level);
- if (ex != null)
- OnException(ex);
- }
- /// <summary>
- /// 手动处理脚本触发的异常
- /// </summary>
- /// <param name="ex"></param>
- protected virtual void OnException(Exception ex)
- {
- }
- /// <summary>
- /// 触发抛出异常
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="message"></param>
- /// <param name="args"></param>
- protected virtual void RaiseException(object sender, string message, params object[] args)
- {
- OnFeedInfo(sender, new Exception(string.Format(message, args)), message, MessageTipsLevel.Error);
- if (!message.Contains("由于目标计算机积极拒绝"))
- throw new Exception(message);
- }
- /// <summary>
- /// 触发消息提示
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="message"></param>
- protected void RaiseInfo(object sender, string message)
- {
- OnFeedInfo(sender, null, message, MessageTipsLevel.Information);
- }
- /// <summary>
- /// 触发警告信息
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="message"></param>
- protected void RaiseWarning(object sender, string message)
- {
- OnFeedInfo(sender, null, message, MessageTipsLevel.Warning);
- }
- /// <summary>
- /// 脚本触发界面自定义事件响应
- /// </summary>
- /// <param name="eventType"></param>
- /// <param name="portKey"></param>
- /// <param name="portName"></param>
- /// <param name="data"></param>
- public virtual void RaiseCustomEvent(string eventType, string portKey, string portName, object data)
- {
- try
- {
- FlowContext.Instance.RaiseCustomEvent(this, eventType, portKey, portName, data);
- }
- catch (Exception ex)
- {
- RaiseException(this, ex.Message);
- }
- }
- /// <summary>
- /// 执行开始作业
- /// </summary>
- public virtual void ExecBeginWork()
- {
- try
- {
- BeforeWorkInit();
- }
- catch (Exception ex)
- {
- throw ex;
- }
- }
- /// <summary>
- /// 执行结束作业
- /// </summary>
- public virtual void ExecEndWork()
- {
- }
- /// <summary>
- /// 执行暂停作业
- /// </summary>
- public virtual void ExecPauseWork()
- {
- try
- {
- PauseWorkCache();
- }
- catch (Exception ex)
- {
- throw ex;
- }
- finally
- {
- FlowContext.Instance.ResetContext();
- }
- }
- /// <summary>
- /// 开始作业前初始化
- /// </summary>
- protected virtual void BeforeWorkInit()
- {
- RaiseInfo(this,"作业条件检查中...");
- }
- /// <summary>
- /// 结束作业时执行检查
- /// </summary>
- public virtual void StopWorkCheck()
- {
- }
- /// <summary>
- /// 暂停作业时缓存业务临时数据
- /// </summary>
- protected virtual void PauseWorkCache()
- {
- }
- }
- }
复制代码 3.业务窗体- using System;
- using System.Collections.Generic;
- using System.ComponentModel.Composition;
- using System.ComponentModel.Composition.Hosting;
- using System.Data;
- using System.Linq;
- using System.Reflection;
- using System.Text;
- using System.Threading;
- using System.Windows.Forms;
- using MES.Core;
- using MES.Services;
- using DataCool_MES.modules.dto;
- using MES.Services.ModuleFlowServices;
- using System.Net.Sockets;
- using System.IO;
- using WinControls;
- namespace DataCool_MES.modules
- {
- [FullScreenStyle(true)]
- [View("批量扫描tray盘混料检测", EntryType.入口, "一次产品检验", "包装作业")]
- public partial class BatchPackForm : BaseModuleForm
- {
- [Import]
- protected IModuleFlowFormService ModuleFlowFormService { get; set; }
- //已扫记录
- private List<BatchScanLogDto> LogData = new List<BatchScanLogDto>();
- private BatchScanLogDto currentBarcodeData = null;
- private WorkStationConfig config;
- private TcpClient cameraClient;
- private TcpClient transmitDeviceClient;
- private byte[] buffer = new byte[2048];
- public BatchPackForm()
- {
- DoubleBuffered = true;
- CheckForIllegalCrossThreadCalls = false;
- InitializeComponent();
- config = SerializerHelper.LoadFromXML<WorkStationConfig>(AppDomain.CurrentDomain.BaseDirectory + "Config\" + "WorkStationConfig.xml");
- if (config != null)
- {
- FlowContext.Instance.TraySpecifications = config.TraySpecifications;
- }
- Load += BatchPackForm_Load;
- FormClosed += BatchPackForm_FormClosed;
- }
- private void BatchPackForm_FormClosed(object sender, FormClosedEventArgs e)
- {
- if (transmitDeviceClient != null)
- {
- try
- {
- transmitDeviceClient.Client?.Disconnect(false);
- transmitDeviceClient.Client?.Close();
- transmitDeviceClient?.Close();
- transmitDeviceClient = null;
- }
- catch
- {
- }
- }
- Program.Quit();
- }
- AlertLog log;
- internal override AlertLog Log
- {
- get
- {
- if (log == null)
- {
- Interlocked.CompareExchange(ref log, new AlertLog(richTextBox1), null);
- }
- return log;
- }
- }
- private void BatchPackForm_Load(object sender, EventArgs e)
- {
- var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
- var container = new CompositionContainer(catalog);
- container.ComposeParts(this, new FlowWorkService());
- if (!System.Diagnostics.Debugger.IsAttached)
- {
- btnStart.DataBindings.Add(new Binding("Enabled", FlowContext.Instance, "IsStoped", false, DataSourceUpdateMode.OnPropertyChanged));
- btnStop.DataBindings.Add(new Binding("Enabled", FlowContext.Instance, "IsRunning", false, DataSourceUpdateMode.OnPropertyChanged));
- }
- if (config != null && !string.IsNullOrEmpty(config.TransmissionDeviceIP))
- {
- try
- {
- transmitDeviceClient = new TcpClient();
- transmitDeviceClient.BeginConnect(config.TransmissionDeviceIP, config.TransmissionDevicePort, new AsyncCallback(ConnectCallback2), transmitDeviceClient);
- }
- catch (Exception ex)
- {
- FrameAppContext.GetInstance().AppLogger.Error(ex);
- }
- }
- }
- protected override IModuleFlow CreateModuleFlow()
- {
- return new BatchScanWorkFlow(ModuleFlowFormService);
- }
- protected override void Clear()
- {
- richTextBox1.Text = "";
- }
- private void btnStart_Click(object sender, EventArgs e)
- {
- try
- {
- Start();
- if (FlowContext.Instance.WorkStatus == WorkStatus.Running)
- {
- cameraClient = new TcpClient();
- cameraClient.BeginConnect(config.CameraIP, config.CameraPort, new AsyncCallback(ConnectCallback), cameraClient);
- }
- if (FlowContext.Instance.WorkStatus == WorkStatus.Running)
- {
- try
- {
- if (transmitDeviceClient != null)
- {
- var sm = transmitDeviceClient.GetStream();
- SendCommandToDevice(sm, "OK");
- }
- else
- {
- Log.Write("", "没有和传动设备建立连接!!!", MessageTipsLevel.Error);
- }
- }
- catch (Exception ex)
- {
- Log.Write("", "和传动设备通信失败!!!" + Environment.NewLine + ex.Message, MessageTipsLevel.Error);
- }
- }
- }
- catch (Exception ex)
- {
- FrameAppContext.GetInstance().AppLogger.Error($"{ex.Message}");
- }
- }
- void ConnectCallback(IAsyncResult ar)
- {
- TcpClient client = (TcpClient)ar.AsyncState;
- try
- {
- client.EndConnect(ar);
- NetworkStream stream = client.GetStream();
- if (stream != null)
- {
- buffer = new byte[2048];
- stream.BeginRead(buffer, 0, buffer.Length, new AsyncCallback(ReadCallback), stream);
- }
- }
- catch (Exception ex)
- {
- log.Write("", ex.Message, MessageTipsLevel.Error);
- }
- }
- void ReadCallback(IAsyncResult ar)
- {
- NetworkStream stream = (NetworkStream)ar.AsyncState;
- if (FlowContext.Instance.WorkStatus != WorkStatus.Running)
- return;
- int bytesRead = stream.EndRead(ar);
- string responseData = Encoding.ASCII.GetString(buffer, 0, bytesRead);
- log.Write("", $"Received: {Environment.NewLine}{responseData}", MessageTipsLevel.Information);
- FrameAppContext.GetInstance().AppLogger.Info(Environment.NewLine + responseData);
- if (!string.IsNullOrEmpty(responseData) && responseData.IndexOf("+") != -1)
- {
- ScanLog(responseData);
- }
- buffer = new byte[2048];
- stream.BeginRead(buffer, 0, buffer.Length, new AsyncCallback(ReadCallback), stream);
- }
- private void BtnStop_Click(object sender, EventArgs e)
- {
- try
- {
- Stop();
- var config = SerializerHelper.LoadFromXML<WorkStationConfig>(AppDomain.CurrentDomain.BaseDirectory + "Config\" + "WorkStationConfig.xml");
- FlowContext.Instance.TraySpecifications = config.TraySpecifications;
- if (config != null && !string.IsNullOrEmpty(config.TraySpecifications) &&
- config.TraySpecifications.IndexOf(",") == -1)
- {
- string[] cellData = config.TraySpecifications.Split('*');
- if (cellData.Length > 0)
- {
- FlowContext.Instance.TrayRowCount = Convert.ToInt32(cellData[1]);
- FlowContext.Instance.TrayCellCount = Convert.ToInt32(cellData[0]);
- }
- }
- if (cameraClient != null && FlowContext.Instance.WorkStatus != WorkStatus.Running)
- {
- cameraClient.Client?.Disconnect(false);
- cameraClient.Client?.Close();
- cameraClient?.Close();
- cameraClient = null;
- }
- SendCommandToDevice(transmitDeviceClient.GetStream(), "NG");
- }
- catch (Exception ex)
- {
- FrameAppContext.GetInstance().AppLogger.Error($"{ex.Message}");
- }
- }
- protected override void OnFlowCustomEvent(EventClass ec)
- {
- if (ec.EventType.Equals("LoadData"))
- {
- DataAction(LoadData);
- }
- if (ec.EventType.Equals("ExportResultData"))
- {
- DataAction(ExportLogToExcelFile);
- }
- }
- /// <summary>
- /// 从临时xml文件读取扫描历史记录
- /// </summary>
- private void SaveData()
- {
- if (!System.IO.Directory.Exists(AppDomain.CurrentDomain.BaseDirectory + "LocalData"))
- {
- System.IO.Directory.CreateDirectory(AppDomain.CurrentDomain.BaseDirectory + "LocalData");
- }
- if (!System.IO.File.Exists(AppDomain.CurrentDomain.BaseDirectory + "LocalData\" + DateTime.Now.ToString("yyyyMMdd") + ".xml"))
- {
- SerializerHelper.SerializerToXML(AppDomain.CurrentDomain.BaseDirectory + "LocalData\" + DateTime.Now.ToString("yyyyMMdd") + ".xml", LogData);
- }
- else
- {
- System.IO.File.Delete(AppDomain.CurrentDomain.BaseDirectory + "LocalData\" + DateTime.Now.ToString("yyyyMMdd") + ".xml");
- SerializerHelper.SerializerToXML(AppDomain.CurrentDomain.BaseDirectory + "LocalData\" + DateTime.Now.ToString("yyyyMMdd") + ".xml", LogData);
- }
- FlowContext.Instance.L1Count = LogData.Count;
- if (LogData.Count > 0)
- bindingSourceGrid.DataSource = LogData.OrderByDescending(t => t.ScanDatetime).ToList();
- }
- /// <summary>
- /// 加载已有扫描记录
- /// </summary>
- private void LoadData()
- {
- if (!System.IO.Directory.Exists(AppDomain.CurrentDomain.BaseDirectory + "LocalData"))
- {
- System.IO.Directory.CreateDirectory(AppDomain.CurrentDomain.BaseDirectory + "LocalData");
- }
- if (System.IO.File.Exists(AppDomain.CurrentDomain.BaseDirectory + "LocalData\" + DateTime.Now.ToString("yyyyMMdd") + ".xml"))
- {
- LogData = SerializerHelper.LoadFromXML<List<BatchScanLogDto>>(AppDomain.CurrentDomain.BaseDirectory + "LocalData\" + DateTime.Now.ToString("yyyyMMdd") + ".xml");
- FlowContext.Instance.L1Count = LogData.Count;
- if (LogData.Count > 0)
- bindingSourceGrid.DataSource = LogData.OrderByDescending(t => t.ScanDatetime).ToList();
- }
- }
- /// <summary>
- /// 扫描到一组条码
- /// </summary>
- /// <param name="barcodeData"></param>
- private void ScanLog(string barcodeData)
- {
- if (LogData.Any(t => t.BarcodeData == barcodeData))
- {
- log.Write(DateTime.Now + "->:", "重复扫描!", MessageTipsLevel.Error);
- }
- else
- {
- #region 传递收到的数据
- var entity = new BatchScanLogDto();
- entity.BarcodeData = barcodeData;
- entity.MaterialCode = FlowContext.Instance.MaterielCode;
- entity.ScanDatetime = DateTime.Now.ToString();
- entity.TraySpecifications = FlowContext.Instance.TraySpecifications;
- entity.ResourceText = barcodeData;
- currentBarcodeData = entity;
- #endregion
- //校验数据
- ThreeColorled1_Click(threeColorled1, new EventArgs());
- }
- }
- private void ThreeColorled1_Click(object sender, EventArgs e)
- {
- //必须是符合业务场景的扫描数据
- if (FlowContext.Instance.WorkStatus != WorkStatus.Running ||
- currentBarcodeData == null ||
- currentBarcodeData.BarcodeData.IndexOf("+") == -1)
- return;
- #region 展示解析结果
- BarcodeResultViewForm barcodeResultViewForm = new BarcodeResultViewForm(currentBarcodeData);
- var diagResult = barcodeResultViewForm.ShowDialog();
- if (diagResult == DialogResult.OK &&
- !LogData.Any(r => r.ResourceText == currentBarcodeData.ResourceText))
- {
- threeColorled1.StatusCode = "1";
- log.Write("", "校验通过!", MessageTipsLevel.Information);
- LogData.Add(barcodeResultViewForm.BarcodeData);
- DataAction(SaveData);
- FlowContext.Instance.L1Count = LogData.Count;
- SendCommandToDevice(transmitDeviceClient.GetStream(), "OK");
- }
- else if (diagResult != DialogResult.OK &&
- !LogData.Any(r => r.ResourceText == currentBarcodeData.ResourceText))
- {
- threeColorled1.StatusCode = "2";
- var sm = transmitDeviceClient.GetStream();
- SendCommandToDevice(sm, "NG");
- log.Write("", $"{Environment.NewLine}校验结果是有混料,不予通行!!!", MessageTipsLevel.Warning);
- }
- #endregion
- }
- /// <summary>
- /// 和传动设备建立Socket连接回调
- /// </summary>
- /// <param name="ar"></param>
- void ConnectCallback2(IAsyncResult ar)
- {
- TcpClient client = (TcpClient)ar.AsyncState;
- try
- {
- client.EndConnect(ar);
- Log.Write("", "传动设备已准备就绪...", MessageTipsLevel.Information);
- }
- catch (Exception ex)
- {
- Log.Write("", "传动设备连接失败!"+ex.Message, MessageTipsLevel.Error);
- FrameAppContext.GetInstance().AppLogger.Error(ex);
- }
- }
- /// <summary>
- /// 给NetworkStream发送指令
- /// </summary>
- /// <param name="stream"></param>
- /// <param name="cmd"></param>
- private void SendCommandToDevice(NetworkStream stream, string cmd)
- {
- string command = cmd;
- byte[] commandBuffer = ASCIIEncoding.ASCII.GetBytes(command);
- stream.WriteAsync(commandBuffer, 0, commandBuffer.Length);
- }
- /// <summary>
- /// 导出Excel文件(扫码原始记录)
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void BtnExport_Click(object sender, EventArgs e)
- {
- if (LogData.Count == 0)
- {
- MessageTip.ShowError("还没有通过检验的记录不能导出!");
- }
- else
- {
- ExportExcel exportExcel = new ExportExcel();
- string fileName = $"{AppDomain.CurrentDomain.BaseDirectory + "LocalData"}\\{DateTime.Now.Date:yyyyMMdd}{FlowContext.Instance.MaterielCode}.xls";
- exportExcel.GridToExcel(fileName, this.dataGridView1);
- if (File.Exists(fileName))
- {
- MessageTip.ShowOk($"Excel文件导出成功!");
- }
- }
- }
- /// <summary>
- /// 导出Excel文件(MES要求的格式)
- /// </summary>
- private void ExportLogToExcelFile()
- {
- if (LogData.Count == 0)
- return;
- #region 临时表
- var dt = new DataTable();
- dt.Columns.Add(new DataColumn("条码", typeof(string)));
- foreach (var logItem in LogData)
- {
- string[] barcodeList = logItem.BarcodeData.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
- foreach (var barcode in barcodeList)
- {
- DataRow dr = dt.NewRow();
- dr[0] = barcode;
- dt.Rows.Add(dr);
- }
- }
- #endregion
- try
- {
- ExportExcel exportExcel = new ExportExcel();
- string fileName = $"{AppDomain.CurrentDomain.BaseDirectory + "LocalData"}\\{DateTime.Now.Date:yyyyMMdd}{FlowContext.Instance.MaterielCode}(仅条码).xls";
- if (File.Exists(fileName))
- File.Delete(fileName);
- exportExcel.DataTableToExcel(fileName, dt);
- if (File.Exists(fileName))
- {
- MessageTip.ShowOk("生产过程的全部条码已保存!");
- string logMessage = $"本次生产共计扫描条码{dt.Rows.Count}个,通过tray盘{LogData.Count}盘.";
- log.Write("", logMessage, MessageTipsLevel.Information);
- FrameAppContext.GetInstance().AppLogger.Info(logMessage);
- }
- }
- catch (Exception ex)
- {
- log.Write("", ex.Message, MessageTipsLevel.Error);
- }
- finally
- {
- dt.Dispose();
- }
- }
- private void button1_Click(object sender, EventArgs e)
- {
- Program.Quit();
- }
- private void richTextBox1_DoubleClick(object sender, EventArgs e)
- {
- Clear();
- }
- }
- }
复制代码 4.流程代码- using System;
- using System.ComponentModel.Composition;
- using System.IO;
- using System.Net;
- using System.Net.Sockets;
- using System.Text;
- using System.Windows.Forms;
- using MES.Core;
- using MES.Services;
- namespace DataCool_MES.modules
- {
- /// <summary>
- /// 批量扫描作业流程
- /// </summary>
- public class BatchScanWorkFlow : ModuleBaseFlow
- {
- private TcpClient cameraClient;
- protected IModuleFlowFormService ModuleFlowFormService { get; set; }
- /// <summary>
- /// 析构函数
- /// </summary>
- /// <param name="svr"></param>
- public BatchScanWorkFlow(IModuleFlowFormService svr)
- {
- ModuleFlowFormService = svr;
- }
- /// <summary>
- /// 和阅读器建立Socket连接回调
- /// </summary>
- /// <param name="ar"></param>
- void ConnectCallback(IAsyncResult ar)
- {
- try
- {
- TcpClient client = (TcpClient)ar.AsyncState;
- client?.EndConnect(ar);
- NetworkStream stream = client.GetStream();
- if (stream != null)
- {
- RaiseInfo(this, "读码器已准备就绪...");
- if (client != null)
- {
- stream.Close();
- cameraClient?.Close();
- }
- }
- }
- catch (Exception ex)
- {
- RaiseException(this, "读码器连接失败!!!错误码:"+ex.Message);
- }
-
- }
- /// <summary>
- /// 给NetworkStream发送指令
- /// </summary>
- /// <param name="stream"></param>
- /// <param name="cmd"></param>
- private void SendCommandToDevice(NetworkStream stream, string cmd)
- {
- string command = cmd;
- byte[] commandBuffer = ASCIIEncoding.ASCII.GetBytes(command);
- stream.WriteAsync(commandBuffer, 0, commandBuffer.Length);
- }
- /// <summary>
- /// 和传动设备建立Socket连接回调
- /// </summary>
- /// <param name="ar"></param>
- void ConnectCallback2(IAsyncResult ar)
- {
- try
- {
- TcpClient client = (TcpClient)ar.AsyncState;
- client?.EndConnect(ar);
- NetworkStream stream = client.GetStream();
- if (stream != null)
- {
- //发消息让皮带开始转动
- SendCommandToDevice(stream, "OK");
- }
- }
- catch (Exception ex)
- {
- RaiseException(this, "传动设备连接失败!!!错误码:" + ex.Message);
- }
- }
- /// <summary>
- /// 开始作业前准备工作
- /// </summary>
- protected override void BeforeWorkInit()
- {
- base.BeforeWorkInit();
- if (string.IsNullOrEmpty(FlowContext.Instance.TraySpecifications))
- {
- RaiseException($"{DateTime.Now}->:", $"必须设定容器的规格!");
- }
- if (string.IsNullOrEmpty(FlowContext.Instance.MaterielCodeHeader+FlowContext.Instance.MaterielCodeEnder))
- {
- RaiseException($"{DateTime.Now}->:", $"必须输入本次校验的物料代码!");
- }
- flowContext.L1Count = 0;
- RaiseCustomEvent("LoadData", "", "", "");
- var config = SerializerHelper.LoadFromXML<WorkStationConfig>(AppDomain.CurrentDomain.BaseDirectory + "Config\" + "WorkStationConfig.xml");
- if (config != null && !string.IsNullOrEmpty(config.CameraIP))
- {
- try
- {
- cameraClient = new TcpClient();
- cameraClient.BeginConnect(config.CameraIP, config.CameraPort, new AsyncCallback(ConnectCallback), cameraClient);
- }
- catch (Exception ex)
- {
- RaiseException(this,"",ex.Message);
- }
- }
- else
- {
- RaiseException($"{DateTime.Now}->:", $"必须设定阅读器的IP地址!");
- }
- if (config != null && !string.IsNullOrEmpty(config.TraySpecifications) && config.TraySpecifications.IndexOf(",") == -1)
- {
- string[] cellData = config.TraySpecifications.Split('*');
- if (cellData.Length > 0)
- {
- flowContext.TrayRowCount = Convert.ToInt32(cellData[1]);
- flowContext.TrayCellCount = Convert.ToInt32(cellData[0]);
- }
- }
- FlowContext.Instance.MaterielCode= FlowContext.Instance.MaterielCodeHeader+FlowContext.Instance.MaterielCodeEnder;
- RaiseInfo(this, "系统准备就绪...");
- }
- /// <summary>
- /// 扫描到一个条码
- /// </summary>
- /// <param name="data"></param>
- public override void OnExecScanReceiving(string data)
- {
- RaiseCustomEvent("ScanLog", "", "", data);
- }
- /// <summary>
- /// 结束本次作业
- /// </summary>
- public override void ExecEndWork()
- {
- base.ExecEndWork();
- //导出扫描记录
- RaiseCustomEvent("ExportResultData", "", "", "");
- }
- }
- }
复制代码 5.界面绑定代码- protected override IModuleFlow CreateModuleFlow()
- {
- return new BatchScanWorkFlow(ModuleFlowFormService);
- }
复制代码
界面和代码中间还有个上下文对象,也就是一个单例,貌似这样子:- using EES.Common;
- using MES.Core;
- using System;
- using System.ComponentModel;
- namespace DataCool_MES
- {
- /// <summary>
- /// 工作流程上下文对象
- /// </summary>
- [Serializable]
- public class FlowContext : SingletonProvider<FlowContext>, INotifyPropertyChanged
- {
- public System.Configuration.Configuration AppConfig { get; set; }
- public event EventHandler<TEventArgs<EventClass>> FlowCustomEvent;
- public event PropertyChangedEventHandler PropertyChanged;
- private void OnPropertyChanged(string propertyName)
- {
- PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
- }
- private WorkStatus workStatus;
- /// <summary>
- /// 工作流程运行状态
- /// </summary>
- public WorkStatus WorkStatus
- {
- get { return workStatus; }
- set
- {
- workStatus = value;
- OnPropertyChanged("WorkStatus");
- switch (value)
- {
- case WorkStatus.Running:
- IsRunning = true;
- IsStoped = false;
- WorkStatusName = "运行中...";
- break;
- case WorkStatus.Pauseing:
- IsRunning = false;
- IsStoped = true;
- WorkStatusName = "暂停中...";
- break;
- case WorkStatus.Stopped:
- IsRunning = false;
- IsStoped = true;
- WorkStatusName = "已经停止...";
- break;
- default:
- IsRunning = false;
- IsStoped = true;
- WorkStatusName = "未启动";
- break;
- }
- }
- }
- private string workStation;
- /// <summary>
- /// 工位
- /// </summary>
- public string WorkStation
- {
- get { return workStation; }
- set
- {
- workStation = value;
- OnPropertyChanged("WorkStation");
- }
- }
- private string _operator;
- /// <summary>
- /// 工位操作员
- /// </summary>
- public string Operator
- {
- get { return _operator; }
- set { _operator = value; OnPropertyChanged("Operator"); }
- }
- private string lineNo;
- /// <summary>
- /// 线号
- /// </summary>
- public string LineNo
- {
- get { return lineNo; }
- set { lineNo = value; OnPropertyChanged("LineNo"); }
- }
- private string _L1Code;
- /// <summary>
- /// PCBA条码
- /// </summary>
- public string L1Code
- {
- get { return _L1Code; }
- set { _L1Code = value; OnPropertyChanged("L1Code"); }
- }
- private string _L2Code;
- /// <summary>
- /// 过程条码
- /// </summary>
- public string L2Code
- {
- get { return _L2Code; }
- set { _L2Code = value; OnPropertyChanged("L2Code"); }
- }
- private string workStatusName;
- /// <summary>
- /// 状态状态描述信息
- /// </summary>
- public string WorkStatusName
- {
- get { return workStatusName; }
- set { workStatusName = value; OnPropertyChanged("WorkStatusName"); }
- }
- private int _L1Count;
- /// <summary>
- /// 第一道工序计数
- /// </summary>
- public int L1Count
- {
- get { return _L1Count; }
- set
- {
- _L1Count = value;
- OnPropertyChanged("L1Count");
- }
- }
- private int _L1CountEx = 0;
- /// <summary>
- /// 制令计数,可清零
- /// </summary>
- public int L1CountEx
- {
- get { return _L1CountEx; }
- set
- {
- _L1CountEx = value;
- OnPropertyChanged("L1CountEx");
- }
- }
- private int _L2Count;
- /// <summary>
- /// 第二道工序计数
- /// </summary>
- public int L2Count
- {
- get { return _L2Count; }
- set { _L2Count = value; OnPropertyChanged("L2Count"); }
- }
- private string _TraySpecifications;
- /// <summary>
- ///Tray Specifications
- /// </summary>
- public string TraySpecifications
- {
- get { return _TraySpecifications; }
- set
- {
- _TraySpecifications = value;
- OnPropertyChanged("TraySpecifications");
- }
- }
- public int TrayCellCount
- {
- get;set;
- }
- public int TrayRowCount
- {
- get; set;
- }
- private string orderNo;
- /// <summary>
- /// 状态状态描述信息
- /// </summary>
- public string OrderNo
- {
- get { return orderNo; }
- set
- {
- orderNo = value;
- OnPropertyChanged("OrderNo");
- }
- }
- private string _MaterielCode;
- /// <summary>
- /// 物料编码
- /// </summary>
- public string MaterielCode
- {
- get { return _MaterielCode; }
- set { _MaterielCode = value; OnPropertyChanged("MaterielCode"); }
- }
- private string _MaterielCodeEnder;
- /// <summary>
- /// 物料编码
- /// </summary>
- public string MaterielCodeEnder
- {
- get { return _MaterielCodeEnder; }
- set { _MaterielCodeEnder = value; OnPropertyChanged("_MaterielCodeEnder"); }
- }
- private string _MaterielCodeHeader;
- /// <summary>
- /// 物料编码
- /// </summary>
- public string MaterielCodeHeader
- {
- get { return _MaterielCodeHeader; }
- set { _MaterielCodeHeader = value; OnPropertyChanged("MaterielCodeHeader"); }
- }
- private int progress;
- /// <summary>
- /// 本次扫描完成时的进度
- /// </summary>
- public int Progress
- {
- get { return progress; }
- set { progress = value; OnPropertyChanged("Progress"); }
- }
- private bool isStoped = true;
- /// <summary>
- /// WorkStatus是否已经停止
- /// </summary>
- public bool IsStoped
- {
- get { return isStoped; }
- set { isStoped = value; OnPropertyChanged("IsStoped"); }
- }
- private bool isRunning = false;
- /// <summary>
- /// WorkStatus是否正在运行
- /// </summary>
- public bool IsRunning
- {
- get { return isRunning; }
- set { isRunning = value; OnPropertyChanged("IsRunning"); }
- }
- private string _Parameter1;
- /// <summary>
- /// 公用参数1
- /// </summary>
- public string Parameter1
- {
- get { return _Parameter1; }
- set { _Parameter1 = value; OnPropertyChanged("Parameter1"); }
- }
- private string _Parameter2;
- /// <summary>
- /// 公用参数2
- /// </summary>
- public string Parameter2
- {
- get { return _Parameter2; }
- set { _Parameter2 = value; OnPropertyChanged("Parameter2"); }
- }
- private string _Parameter3;
- /// <summary>
- /// 公用参数3
- /// </summary>
- public string Parameter3
- {
- get { return _Parameter3; }
- set { _Parameter3 = value; OnPropertyChanged("Parameter3"); }
- }
- private string _Parameter4;
- /// <summary>
- /// 公用参数4
- /// </summary>
- public string Parameter4
- {
- get { return _Parameter4; }
- set { _Parameter4 = value; OnPropertyChanged("Parameter4"); }
- }
- private string _Parameter5;
- /// <summary>
- /// 公用参数5
- /// </summary>
- public string Parameter5
- {
- get { return _Parameter5; }
- set { _Parameter5 = value; OnPropertyChanged("Parameter5"); }
- }
- private string _Parameter6;
- /// <summary>
- /// 公用参数6
- /// </summary>
- public string Parameter6
- {
- get { return _Parameter6; }
- set { _Parameter6 = value; OnPropertyChanged("Parameter6"); }
- }
- private string _Parameter7;
- /// <summary>
- /// 公用参数7
- /// </summary>
- public string Parameter7
- {
- get { return _Parameter7; }
- set { _Parameter7 = value; OnPropertyChanged("Parameter7"); }
- }
- private string _Parameter8;
- /// <summary>
- /// 公用参数8
- /// </summary>
- public string Parameter8
- {
- get { return _Parameter8; }
- set { _Parameter8 = value; OnPropertyChanged("Parameter8"); }
- }
- private string _Parameter9;
- /// <summary>
- /// 公用参数9
- /// </summary>
- public string Parameter9
- {
- get { return _Parameter9; }
- set { _Parameter9 = value; OnPropertyChanged("Parameter9"); }
- }
- private int packagePCS;
- /// <summary>
- /// 二级包装,PCS数量
- /// </summary>
- public int PackagePCS_Count
- {
- get { return packagePCS; }
- set { packagePCS = value; OnPropertyChanged("PackagePCS_Count"); }
- }
- private bool isEndPacking=false;
- /// <summary>
- /// 是否是在装尾箱
- /// </summary>
- public bool IsEndPacking
- {
- get { return isEndPacking; }
- set { isEndPacking= value; OnPropertyChanged("IsEndPacking"); }
- }
-
- private int _WorkEndNumber;
- public int WorkEndNumber
- {
- get { return _WorkEndNumber; }
- set
- {
- _WorkEndNumber = value;
- OnPropertyChanged("WorkEndNumber");
- }
- }
- public void RaiseCustomEvent(object sender, string eventType, string portKey, string portName, object data)
- {
- RaiseCustomEvent(sender, eventType, portKey, portName, data, null);
- }
- public void RaiseCustomEvent(object sender, string eventType, string portKey, string portName, object data,
- object extend)
- {
- if (FlowCustomEvent != null)
- {
- EventClass ec = new EventClass(sender, eventType, portKey, portName, data, extend);
- FlowCustomEvent(this, new TEventArgs<EventClass>(ec));
- }
- }
- /// <summary>
- /// 重置上下文
- /// </summary>
- public void ResetContext()
- {
- OrderNo = string.Empty;
- MaterielCode = string.Empty;
- Progress = 0;
- L1Code = string.Empty;
- L1Count = 0;
- L2Code = "";
- L2Count = 0;
- L1CountEx = 0;
- TraySpecifications = "";
- Parameter1 = "";
- Parameter2 = "";
- Parameter3 = "";
- Parameter4 = "";
- Parameter5 = "";
- Parameter6 = "";
- Parameter7 = "";
- Parameter8 = "";
- Parameter9 = "";
- IsEndPacking = false;
- }
- }
- }
复制代码 好了,我的言传就是这样。我的表达能力就只能到这样了。
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |