ScanWork.cs 13.9 KB
using Asa.FaceControl;
using BLL;
using Model;
using OnlineStore.Common.util;
using SmartScan.Form;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace SmartScan
{
    public class ScanWork
    {
        public bool isRun = false;
        private bool isTouch = false;
        private readonly FacePictureBox picShow;
        private readonly FaceButton btnMatchedName;

        private List<CameraVisionLib.Model.BarcodeInfo> workCodeInfo;
        public Dictionary<string, string> workCodeKeyword;
        private string[] originalCodeText;
        private bool[] originalCodeIsUsed;

        public ScanWork()
        {
            picShow = (FacePictureBox)Common.frmMain.Controls["PicShow"];
            btnMatchedName = (FaceButton)Common.frmMain.Controls["BtnMatchedName"];
        }

        public void Open()
        {
            isRun = true;
            isTouch = false;
            Common.frmMain.Controls["BtnSet"].Visible = false;
            Common.frmMain.Controls["BtnRetrospect"].Visible = false;
            Common.frmMain.Controls["BtnAbout"].Visible = false;
            Common.frmMain.Controls["BtnTriggerIO"].Visible = true;
            LogNet.log.Info("Work Start");

            if (BLLCommon.config.EnabledCamera)
                Camera.Open();

            if (BLLCommon.config.TriggerOpenLight)  //触发时才打开光源
                BLLCommon.lightSource?.TurnOff();
            else
                BLLCommon.lightSource?.TurnOn();
        }
           
        public void Close()
        {
            isRun = false;
            Common.frmMain.Controls["BtnSet"].Visible = true;
            Common.frmMain.Controls["BtnRetrospect"].Visible = true;
            Common.frmMain.Controls["BtnAbout"].Visible = true;
            Common.frmMain.Controls["BtnTriggerIO"].Visible = false;
            LogNet.log.Info("Work Stop");

            if (BLLCommon.config.EnabledCamera)
                Camera.Close();

            BLLCommon.lightSource?.TurnOff();
        }

        public void TouchOff()
        {
            isTouch = false;
        }

        private readonly object lockObject = new object();

        static System.Diagnostics.Stopwatch reckontime = new System.Diagnostics.Stopwatch();
        public void Scan()
        {
            //此段代码加锁是因为,客户在连续点击识别设备按钮时,线程会同时生成rid=123并且rid赋值是重复的123123
            //在测试时也遇到这个情况,但只成功复现了一次;故加锁。
            lock (lockObject)
            {
                if (!isRun) return;
                if (isTouch) return;
                isTouch = true;
                btnMatchedName.Invoke(delegate ()
                {
                    if (!BLL.Config.Backgrounder)
                        btnMatchedName.Visible = false;
                    BLLCommon.extension.Clear();
                });
                Common.frmMain.SetWaittingMsg(Language.Dialog("MaterialScanning"));//拍照识别...
                var t = Task.Run(() =>
                {
                    reckontime.Restart();
                    try
                    {
                        Common.frmMain.SetWaittingMsg(Language.Dialog("MaterialScanning"));//拍照识别...
                        workCodeInfo = new();
                        workCodeKeyword = new(StringComparer.OrdinalIgnoreCase);
                        originalCodeText = null;
                        originalCodeIsUsed = null;                     
                        if (!GetCodeInfo())
                        {
                            isTouch = false;
                            Common.frmMain.CloseWaittingDialog();
                            return;
                        }                      
                        Common.frmMain.Invoke(delegate ()
                        {
                            AddCodeCenter();
                        });
                        LogNet.log.Info($"获取图片耗时{reckontime.ElapsedMilliseconds}ms");
                        Common.frmMain.SetWaittingMsg(Language.Dialog("MaterialTemplateMatching"),5);//模版匹配...
                        reckontime.Restart();
                        bool hasMatch = MatchingTemplate();
                        LogNet.log.Info($"模板匹配耗时{reckontime.ElapsedMilliseconds}ms");
                        reckontime.Restart();
                        Common.frmMain.SetWaittingMsg(Language.Dialog("MaterialProcessing"),5);//计算结果...
                        Common.frmMain.Invoke(delegate ()
                        {
                            SetKey(hasMatch);
                        });
                        isTouch = false;
                        LogNet.log.Info("Work scan is done");
                        LogNet.log.Info($"渲染控件耗时{reckontime.ElapsedMilliseconds}ms");
                    }
                    catch (Exception ex)
                    {
                        LogNet.log.Error("Scan", ex);
                    }
                    finally
                    {
                        isTouch = false;
                        Common.frmMain.CloseWaittingDialog();
                    }
                });
                Common.frmMain.Invoke(delegate ()
                {
                    Common.frmMain.ShowWaittingDialog();
                });
            }
        }

        public void Scan(string[] code)
        {
            try
            {
                if (!isRun) return;
                if (isTouch) return;

                if (!BLL.Config.Backgrounder)
                    btnMatchedName.Visible = false;
                BLLCommon.extension.Clear();
                workCodeInfo = new();
                workCodeKeyword = new(StringComparer.OrdinalIgnoreCase);
                originalCodeText = code;
                originalCodeIsUsed = null;

                var hasMatch = MatchingTemplate();
                SetKey(hasMatch);

                isTouch = true;
                LogNet.log.Info("Work scan code is done");
            }
            catch (Exception ex)
            {
                LogNet.log.Error("Scan", ex);
            }
        }

        public object[] SaveCodeInfo()
        {
            object[] obj = null;
            if (workCodeInfo == null)
                return obj;

            obj = new object[workCodeInfo.Count];
            for (int i = 0; i < workCodeInfo.Count; i++)
            {
                Dictionary<string, string> dicCode = new()
                {
                    { "X", workCodeInfo[i].Center.X.ToString() },
                    { "Y", workCodeInfo[i].Center.Y.ToString() },
                    { "Text", workCodeInfo[i].Text }
                };
                obj[i] = dicCode;
            }
            return obj;
        }

        public WebCodeAll[] GetWebCodeAll()
        {
            WebCodeAll[] str = new WebCodeAll[workCodeInfo.Count];
            for (int i = 0; i < str.Length; i++)
            {
                str[i] = new()
                {
                    Text = workCodeInfo[i].Text,
                    CodeType = workCodeInfo[i].CodeType,
                    CenterX = workCodeInfo[i].Center.X,
                    CenterY = workCodeInfo[i].Center.Y,
                    Angle = workCodeInfo[i].Angle,
                    Width = workCodeInfo[i].Size.Width,
                    Height = workCodeInfo[i].Size.Height,
                    IsUsed = originalCodeIsUsed[i]
                };
            }
            return str;
        }

        public WebCodeText[] GetWebCodeText()
        {
            WebCodeText[] str = new WebCodeText[originalCodeText.Length];
            for (int i = 0; i < str.Length; i++)
            {
                str[i] = new()
                {
                    Text = originalCodeText[i],
                    IsUsed = originalCodeIsUsed[i]
                };
            }
            return str;
        }

        private bool GetCodeInfo()
        {
            LogNet.log.Info("Work GetCodeInfo");

            if (BLLCommon.config.EnabledCamera)
            {
                if (BLLCommon.config.TriggerOpenLight)
                {
                    BLLCommon.lightSource.TurnOn();
                    System.Threading.Thread.Sleep(100);  //光源打开有一个由暗变亮的过程
                }
                List<Bitmap> image = new List<Bitmap>(Camera.CaptureAndGetCode(out workCodeInfo));
                if (image.Count > 0 && image[0]!=null)
                {
                    BLLCommon.mateEdit.CurrntBitmap = WebCallWork.DeepClone(image[0]);
                    if (!BLL.Config.Backgrounder) 
                        picShow.Image = image[0];
                    if (BLLCommon.mateEdit.CurrntBitmap!=null)
                    _ = UnifiedDataHandler.PostSmfImageAsync(BLLCommon.mateEdit.CurrntBitmap, new Dictionary<string, string> { { "cid", BLLCommon.config.CID + "_1" } }, BLLCommon.mateEdit.CurrntBitmap.Width, BLLCommon.mateEdit.CurrntBitmap.Height);
                }else
                    return false;

                if (BLLCommon.config.TriggerOpenLight)
                    BLLCommon.lightSource.TurnOff();
                return true;
            }
            else
            {
                Common.frmMain.Invoke(delegate ()
                {
                    if (!BLL.Config.Backgrounder)
                        picShow.Image?.Dispose();
                    BLLCommon.mateEdit.CurrntBitmap?.Dispose();
                });
                string filename = "";
                Common.frmMain.Invoke(delegate ()
                {
                    OpenFileDialog dlg = new() { Filter = "图片文件|*.jpg;*.png;*.bmp;*.jpeg" };
                    DialogResult dr = dlg.ShowDialog();
                    filename = dlg.FileName;
                });
                if (string.IsNullOrEmpty(filename))
                    return false;
                Bitmap bmp = null;
                bmp = ObjConversion.ReadImageFile(filename);
                workCodeInfo = Camera.GetBarCode(bmp);
                Common.frmMain.Invoke(delegate ()
                {
                    if (!BLL.Config.Backgrounder)
                        picShow.Image = bmp;
                    BLLCommon.mateEdit.CurrntBitmap = bmp;
                });
                return true;
            }

            if (workCodeInfo.Count == 0 && !BLL.Config.Backgrounder)
            {
                string text = Language.Dialog(LanguageDialogKey.CODE_COUNT);
                new FaceMessageBox("", text, MessageBoxButtons.OK).ShowDialog(Common.frmMain);
            }

            Application.DoEvents();
            LogNet.log.Info("条码个数:" + workCodeInfo.Count);
        }

        private void AddCodeCenter()
        {
            LogNet.log.Info("Work AddCodeCenter");
            if (!BLL.Config.Backgrounder)
                picShow.CodeCenterClear();
            if (workCodeInfo.Count == 0) return;
            PointF[] center = new PointF[workCodeInfo.Count];
            for (int i = 0; i < workCodeInfo.Count; i++)
                center[i] = workCodeInfo[i].Center;
            if (!BLL.Config.Backgrounder)
                picShow.AddCodeCenter(center);
            Application.DoEvents();
        }

        private bool MatchingTemplate()
        {
            LogNet.log.Info("Work MatchingTemplate");
            //没有条码也继续进行模板匹配
            //if (workCodeInfo.Count == 0) return false;
            originalCodeText = Camera.GetBarCodeText(workCodeInfo);

            bool rtn = BLLCommon.mateEdit.MatchingTemplate(workCodeInfo, BLLCommon.config.DefaultMaterialName, false, out string mateName, out workCodeKeyword, out AMatch aMatch);
            BLL.MatchAnalysis.ShowResult();

            Common.frmMain.Invoke(delegate ()
            {
                if (rtn)
                {
                    LogNet.log.Info("模板匹配 " + mateName + ",关键字个数 " + workCodeKeyword.Count);
                    if (!BLL.Config.Backgrounder)
                    {
                        btnMatchedName.Visible = true;
                        btnMatchedName.Text = mateName;
                    }
                }
                else
                {
                    LogNet.log.Info("没有匹配到模板");
                    if (!BLL.Config.Backgrounder)
                    {
                        string text = Language.Dialog("MaterialTemplateNoMatch");
                        var fm = new FaceMessageBox("", text, MessageBoxButtons.OK);
                        fm.TopMost = true;
                        fm.ShowDialog(Common.frmMain);
                    }
                }
            });
            return rtn;
        }

        private void SetKey(bool hasMatch)
        {
            LogNet.log.Info("Work SetKey hasMatch:" + hasMatch);
            //if (workCodeKeyword.Count == 0){ return;}
            //if(hasMatch)
            BLLCommon.extension.SetKey(originalCodeText, workCodeKeyword, hasMatch, out _);
            if (workCodeKeyword.Any(a => a.Value.StartsWith("<OCR>")))
            {
                BLLCommon.extension.DrawTextBackground(workCodeKeyword);
                FrmDrawText frmDraw = new FrmDrawText();
                if (frmDraw.ShowDialog() == DialogResult.OK)
                {
                    Dictionary<string, string> pairs = workCodeKeyword.ToDictionary(val => val.Key, 
                        val => val.Value.StartsWith("<OCR>")?val.Value.Replace("<OCR>", "") : val.Value
                        );  
                    //打印
                    BLLCommon.extension.Print(hasMatch, pairs);
                }
            }
            else
            {
                BLLCommon.extension.Print(hasMatch, workCodeKeyword);              
            }
            if (BLLCommon.config.PromptAfterPrinting && !BLL.Config.Backgrounder)
            {
                string text = Language.Dialog("SelectPrintContent");
                new FaceMessageBox("", text, MessageBoxButtons.OK).ShowDialog();
            }
        }
    }
}