CodeManager.cs 13.0 KB

using OnlineStore.Common;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Runtime.ExceptionServices;
using System.Text;
using System.Windows.Forms;
using CodeLibrary;
using System.Drawing.Imaging;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Threading;
using System.Runtime.InteropServices;
using System.Drawing.Drawing2D;
using HalconDotNet;
using System.Web;

namespace DeviceLibrary
{
    public class CodeManager
    {
        public static string CodeType = Setting_Init.Camera_CodeType;
        private static int QRCodeCount = Setting_Init.Camera_QRCodeCount;
        private static int CodeTimeOut = Setting_Init.Camera_CodeTimeOut;
        public static List<string> cameraNameList = new List<string>();
        public static List<string> codeTypeList = new List<string>();
        public static List<string> hikNameList = new List<string>();
        public static event EventHandler<Bitmap> camera_event;
        private static char spiltChar = '#';
        /// <summary>
        /// 初始化摄像机名称和二维码类型
        /// </summary> 
        public static void LoadConfig()
        {
            //onfigHelper.Config.Set("CamTestReel_Test", "Click To Test");
            //ConfigHelper.AdvanceConfigForm.AddCustomEditor<CameraTest>("CamTestReel_Test");

            codeTypeList = new List<string>();
            HDLogUtil.LogName = "RollingLogFileAppender";
            try
            {
                LoadCamera(true);

                codeTypeList = new List<string>();
                string[] codeArray = CodeType.Split(spiltChar);
                foreach (string str in codeArray)
                {
                    if (str.Trim().Equals(""))
                    {
                        continue;
                    }
                    string file = GetCodeParamFilePath(str.Trim());
                    LogUtil.info("加载到配置二维码类型:" + str.Trim() + ",配置文件:" + file);
                    codeTypeList.Add(str.Trim());
                }
                CodeLibrary.HDCodeLearnHelper.LoadConfig("", CodeType);

                //如果未加载到配置相机,自动配置
                if (cameraNameList.Count <= 0 && hikNameList.Count > 0)
                {
                    cameraNameList = new List<string>(hikNameList);
                }
            }
            catch (Exception ex)
            {
                LogUtil.error("解析摄像机配置出错:" + ex.StackTrace);
            }
        }


        public static void LoadCamera(bool isReLoad)
        {
            if (isReLoad || Camera._cam == null)
            {
                try
                {
                    if (Camera._cam != null)
                    {
                        Camera._cam.CloseAll();
                    }
                    Camera.Type = CameraType.HIK;
                    Camera._cam.Load();
                }
                catch (Exception ex)
                {
                    LogUtil.error("加载HIK相机出错:" + ex.ToString());
                }
            }
            string[] names = Camera._cam.Name;


            if (names != null)
            {
                foreach (string n in names)
                {
                    if (!hikNameList.Contains(n))
                    {
                        hikNameList.Add(n);
                    }
                }
                // hikNameList.AddRange(names);
                foreach (string name in hikNameList)
                {
                    LogUtil.info("加载到HIK相机:" + name);
                }
            }
        }

        public static void CloseCamera(string cameraName)
        {
            Camera._cam.Close(cameraName);
        }
        public static void CloseAllCamera()
        {
            Camera._cam.CloseAll();
        }


        [HandleProcessCorruptedStateExceptions]
        public static List<CodeInfo> CameraScan(List<string> cameraNameList)
        {
            HashSet<string> codestr = new HashSet<string>();
            List<CodeInfo> codeList = new List<CodeInfo>();
            string bitmapfilename = "";
            if (cameraNameList == null || cameraNameList.Count <= 0)
            {
                throw new Exception("CameraScan方法没有传入相机名称.");
            }

            try
            {
                Task[] cameraTask = new Task[cameraNameList.Count()];
                for (int ii = 0; ii < cameraNameList.Count(); ii++)
                {
                    var cameraName = cameraNameList[ii];
                    var idx = ii;
                    cameraTask[ii] = Task.Run(new Action(() =>
                    {
                        int retrytime = 0;
                    retry:
                        LogUtil.info($"【" + cameraName + "】开始取图片");
                        if (cameraName.Trim().Equals(""))
                        {
                            return;
                        }
                        DateTime startTime = DateTime.Now;
                        HalconDotNet.HObject ho_Image = null;
                        Bitmap bmp = null;
                        try
                        {
                            bool nohalcon = true;
                            ho_Image = Camera._cam.CaptureOnImage(cameraName, out bmp, nohalcon);
                            if (bmp == null)
                            {
                                if (retrytime > 2)
                                    return;
                                retrytime++;
                                LoadCamera(true);
                                LogUtil.info($"bitmap为空重试第{retrytime}次");
                                Task.Delay(1500).Wait();
                                goto retry;
                            }
                            //HalconDotNet.HOperatorSet.RotateImage()
                            if (ho_Image == null && !nohalcon)
                            {
                                LogUtil.error("  【" + cameraName + "】取图片失败[" + Camera._cam.ErrInfo + "],关闭相机");
                                LoadCamera(true);
                                return;
                            }
                            if (idx == 0)
                                camera_event?.Invoke(null, bmp);
                            LogUtil.info("  【" + cameraName + "】取图片完成,开始扫码");
                            string r = "";
                            RemoteDecodeHelper.RemoteDecodeParam remoteDecodeParam = new RemoteDecodeHelper.RemoteDecodeParam
                            {
                                codeTypeList = codeTypeList.ToArray(),
                                codeCount = QRCodeCount,
                                timeout = CodeTimeOut
                            };
                            List<CodeInfo> cc = new List<CodeInfo>();

                            cc = RemoteDecodeHelper.DecodeRequest(bmp, remoteDecodeParam);
                            if (cc != null && cc.Count > 0)
                            {
                                cc.ForEach((c) =>
                                {
                                    LogUtil.info(c.CodeStr);
                                    c.CodeStr = CodeManager.ReplaceCode(c.CodeStr);
                                    lock (codeList)
                                    {
                                        if (!codeList.Any(a=>a.CodeStr == c.CodeStr) && HasRightCode(c.CodeStr))
                                        {
                                            codeList.Add(c);
                                            r = r + "##" + c.CodeStr;
                                        }
                                    }
                                });
                            }
                            else
                            {
                                bitmapfilename = SaveImageToFile("mimo", cameraName, bmp);
                            }
                            LogUtil.info(" 【" + cameraName + "】" + " 扫码完成【" + FormUtil.GetSpanStr(DateTime.Now - startTime) + "】 :" + r);
                        }
                        catch (AccessViolationException e)
                        {
                            LogUtil.error(" 扫码出现AccessViolationException异常,关闭相机【" + cameraName + "】:" + e.ToString());
                            Camera._cam.Close(cameraName);
                            //  GC.Collect();
                        }
                        catch (Exception ex)
                        {
                            LogUtil.error(" 扫码出错:" + ex.ToString());
                        }
                        finally
                        {
                            if (ho_Image != null)
                            {
                                ho_Image.Dispose();
                            }
                            if (bmp != null)
                                bmp.Dispose();
                        }

                    }));
                    Task.Delay(ii * 700).Wait();
                }

                while (!cameraTask[0].IsCompleted)
                {
                    Application.DoEvents();
                    Thread.Sleep(100);
                }
            }
            catch (AccessViolationException e)
            {
                LogUtil.error(" 扫码出现AccessViolationException异常:" + e.ToString());
                //throw new Exception("扫码出现AccessViolationException异常");
                //    GC.Collect();
            }
            catch (Exception ex)
            {
                LogUtil.error(" 扫码出错:" + ex.ToString());
                //throw new Exception("扫码出错");
            }
            return codeList;
        }

        private static string SaveImageToFile(string deviceName, string cameraName, Bitmap bitmap)
        {
            string date = DateTime.Now.ToString("HH-mm-ss-") + DateTime.Now.Millisecond;
            string dire = @"\image\" + deviceName.Trim().Replace('_', '-') + @"\" + cameraName.Trim().Replace('_', '-').Replace(':', '-') + @"\";
            string iamgeName = date + ".bmp";
            try
            {
                if (Directory.Exists(dire).Equals(false))
                {
                    Directory.CreateDirectory(dire);
                }
                bitmap.Save(dire + iamgeName, ImageFormat.Bmp);
                //bitmap.Dispose();
                LogUtil.info(deviceName + "  【" + cameraName + "】扫码完成,保存图片到【" + dire + iamgeName + "】成功");

            }
            catch (Exception ex)
            {
                LogUtil.error("保存" + deviceName + "  【" + cameraName + "】的图片到【" + dire + iamgeName + "】出错" + ex.ToString());
            }
            return dire + iamgeName;
        }

        /// <summary>
        /// 处理接收后的二维码
        /// </summary>
        /// <param name="message"></param>
        /// <returns></returns>
        public static string ReplaceCode(string message)
        {
            message = message.Trim();
            message = message.Replace("\r", "");
            message = message.Replace("\n", "");
            char a = (char)02;
            message = message.Replace(a.ToString(), "");
            message = message.Trim();
            if (!HasChinese(message))
            {
                System.Text.ASCIIEncoding asciiEncoding = new System.Text.ASCIIEncoding();
                byte[] bytes = asciiEncoding.GetBytes(message);
                List<byte> newBytes = new List<byte>();
                foreach (byte by in bytes)
                {
                    int value = (int)by;
                    if (value.Equals(24) || value.Equals(30) || value.Equals(29) || value.Equals(4))
                    {
                        continue;
                    }
                    if (!value.Equals(24))
                    {
                        newBytes.Add(by);
                    }
                }
                message = asciiEncoding.GetString(newBytes.ToArray());
            }
            return message;
        }
        public static bool HasChinese(string str)
        {
            return Regex.IsMatch(str, @"[\u4e00-\u9fa5]");
        }
        public static string GetCodeParamFilePath(string codePath)
        {
            string appPath = Application.StartupPath;
            string path = Path.Combine(appPath, Setting_Init.Camera_CodeParamPath);
            string filePath = Path.Combine(path, codePath + ".dcm");
            if (File.Exists(filePath))
            {
                return filePath;
            }
            else
            {
                return "";
            }
        }

        public static bool HasRightCode(string codes)
        {
            //78.10222.20L-016651|-20200826|900|W78016651352000A6|SAMSUNG
            LogUtil.info($"HasRightCode: {codes},{codes.Split('|').Count()}");
            return (codes.Split('|').Count() == 5);
        }
    }
}