整合監聽程序

背景
由於我們檢驗對串口儀器已經有成熟的方案。而且是數據庫腳本語言通過串口轉網口連的。省去了連儀器要配連接電腦的開銷,同時不用在電腦部署環境和程序,用腳本調試也方便。對於儀器在電腦生成數據文件的、或者監聽對方數據庫、或者需要畫圖的等就不適合用串口轉網口走TCP的模式。爲此需要寫EXE運行在電腦上監聽處理數據。

碰到的問題有:
1.儀器數據格式各種各樣,需要監聽各種格式的數據(可能不同項目文件後綴都不同)。
2.儀器數據存放結構各種各樣,有都在一級目錄的,有在多級目錄的。
3.監聽非簡單文本數據(PDF、Excel、csv、直接數據生成mdb的等)
4.儀器廠商數據庫設計參差不齊(有的給LIS留了標記字段,有的連主鍵都難找出)
5.可能要按數據取指定地方的圖片,也可能要按數據繪圖,也肯能要選圖、截圖
6.監聽數據文件有的儀器的你不是監聽完刪掉(需要監聽變化)。監聽數據庫的要有重傳的問題。
7.怎麼確保監聽的兼容性,項目程序丟了用最新的肯定兼容老的,確保程序向着穩定發展,新加的公共功能之前所有的接口都能獲得,而不是越寫越散。
8.減少開發難度,避免陷入這些重複的繁瑣邏輯裏。

對於以上問題,如果採用碰到個儀器就從相似的儀器拷貝代碼寫一個EXE的做法。首先每個開發都要面臨處理上面這些繁瑣問題,基於拷貝程序帶過來的bug,新的修復了老的程序的bug還存在,接口質量得不到提高。新加的功能也無法惠及老的實現。雖然每個EXE的複雜度沒有統一模式的主程序大,不能實現產品化的把控。仔細觀察不難發現,對文件的監聽最後都可以提取爲一行行的數據讀取解析。對數據庫的監聽最後都可提取爲一行行數據行的讀取解析。對要上傳給儀器數據的最後都可提取爲查詢返回的一行行檢驗數據,按返回數據做不同操作(寫文件或者執行SQL等)。不同的儀器只是解析邏輯不同,對這些共性問題大家都是一致的。因此提取兩個接口:

儀器給檢驗數據處理接口

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;

namespace PreDeal.Interface
{
    ///<summary  NoteObject="Class">
    /// [功能描述:數據前處理接口,所有前處理改實現該接口,配置實現類實現相應的前處理] <para/>
    /// [創建者:zlz] <para/>
    /// [創建時間:2015年10月25日] <para/>
    ///<說明>
    ///  [說明:數據前處理接口,所有前處理改實現該接口,配置實現類實現相應的前處理]<para/>
    ///</說明>
    ///<修改記錄>
    ///    [修改時間:本次修改時間]<para/>
    ///    [修改內容:本次修改內容]<para/>
    ///</修改記錄>
    ///<修改記錄>
    ///    [修改時間:本次修改時間]<para/>
    ///    [修改內容:本次修改內容]<para/>
    ///</修改記錄>
    ///</summary>
    public interface IPreDeal
    {
        /// <summary>
        /// 前處理,實時處理用GetDataJSON方法調M及時響應,用PreDeal.Util.TxtUtil讀寫文本
        /// </summary>
        /// <param name="result">結果串</param>
        /// <param name="machID">儀器ID</param>
        /// <param name="dealProcess">處理程序</param>
        /// <param name="index">當前文件的第幾行</param>
        /// <param name="fileName">當前讀取的文件全名</param>
        /// <returns>是否繼續後處理,true是,false否</returns>
        bool PreDeal(string result,string machID, string dealProcess,int index,string fileName);

        /// <summary>
        /// 前處理數據庫,實時處理用GetDataJSON方法調M及時響應,用PreDeal.Util.TxtUtil讀寫文本
        /// </summary>
        /// <param name="row">當前行數據</param>
        /// <param name="machID">儀器ID</param>
        /// <param name="dealProcess">處理程序</param>
        /// <param name="index">當前文件的第幾行</param>
        /// <returns>是否繼續後處理,true是,false否</returns>
        bool PreDealDataBase(DataRow row, string machID, string dealProcess, int index,string otherPara);
    }
}

檢驗給儀器數據處理接口

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;

namespace PreDeal.Interface
{
    ///<summary  NoteObject="Class">
    /// [功能描述:上傳數據前處理接口,所有上傳前處理改實現該接口,配置實現類實現相應的前處理] <para/>
    /// [創建者:zlz] <para/>
    /// [創建時間:2015年10月25日] <para/>
    ///<說明>
    ///  [說明:數據前處理接口,所有前處理改實現該接口,配置實現類實現相應的前處理]<para/>
    ///</說明>
    ///<修改記錄>
    ///    [修改時間:本次修改時間]<para/>
    ///    [修改內容:本次修改內容]<para/>
    ///</修改記錄>
    ///<修改記錄>
    ///    [修改時間:本次修改時間]<para/>
    ///    [修改內容:本次修改內容]<para/>
    ///</修改記錄>
    ///</summary>
    public interface IUPPreDeal
    {
        /// <summary>
        /// 前處理
        /// </summary>
        /// <param name="labno">檢驗號</param>
        /// <param name="labnoInfo">標本信息</param>
        /// <param name="patInfo">患者信息</param>
        /// <param name="upPara">配置的上傳前處理參數</param>
        /// <param name="machID">儀器</param>
        /// <param name="dealProcess">處理程序</param>
        /// <returns>是否繼續後處理,true是,false否</returns>
        bool UPPreDeal(string labno, string labnoInfo, string patInfo, string upPara, string machID, string dealProcess);
    }
}

關係圖
結構圖

通過以上結構實現的監聽將有以下特點:
1.主程序會隨發展趨於穩定化。
2.主程序加入的功能所有接口實現都會獲得。
3.主程序修復的bug所有接口實現都會修復。
4.只要接口實現提交代碼,監聽可以保證承諾的兼容性(新的程序可以替換老的)。
5.統一的日誌服務,統一的配置。
6.連儀器只要關注業務實現接口,不用關心別的繁瑣的處理。

要點
1.要面向接口編程
2.從各種差異裏抽取出大家的共性
3.結構比實現更重要,良好構思結構能朝預期方向良性發展,無結構只會越改越爛

實現事列

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PreDeal.Interface;
using LIS.Model.Bussiness;
using LIS.DAL.DataAccess;
using PreDeal.Ftp;
using PreDeal.Attributes;

namespace PreDeal
{
    ///<summary  NoteObject="Class">
    /// [功能描述:西森美康帶圖片的處理,處理數據格式] <para/>
    /// [創建者:zlz] <para/>
    /// [創建時間:2015年10月25日] <para/>
    ///<說明>
    ///  [說明:西森美康帶圖片的處理,處理數據格式
    ///  0,2015-10-26,00:00:00,9999,XT1800I,41
    ///  1,BASO#,2,0.01,,,,,
    ///  1,BASO%,2,0.20,,,,,
    ///  1,EO#,2,0.04,,,,,
    ///  1,EO%,2,0.70,,,,,
    ///  1,HCT,2,38.00,,,,,
    ///  1,HFR,2,0,,,,,
    ///  1,HGB,2,128.00,,,,,
    ///  1,IRF,2,0,,,,,
    ///  1,LFR,2,0,,,,,
    ///  1,LYMPH#,2,1.52,,,,,
    ///  1,LYMPH%,2,27.70,,,,,
    ///  1,MCH,2,30.00,,,,,
    ///  1,MCHC,2,337.00,,,,,
    ///  1,MCV,2,89.20,,,,,
    ///  1,MFR,2,0,,,,,
    ///  1,MONO#,2,0.44,,,,,
    ///  1,MONO%,2,8.00,,,,,
    ///  1,MPV,2,9.80,,,,,
    ///  1,NEUT#,2,3.48,,,,,
    ///  1,NEUT%,2,63.40,,,,,
    ///  1,NRBC#,2,0,,,,,
    ///  1,NRBC%,2,0,,,,,
    ///  1,P-LCR,2,23.50,,,,,
    ///  1,PCT,2,23.00,,,,,
    ///  1,PDW,2,11.40,,,,,
    ///  1,PLT,2,234.00,,,,,
    ///  1,RBC,2,4.26,,,,,
    ///  1,RDW-CV,2,12.70,,,,,
    ///  1,RDW-SD,2,40.80,,,,,
    ///  1,RET#,2,0,,,,,
    ///  1,RET%,2,0,,,,,
    ///  1,WBC,2,5.49,,,,,
    ///  3,,HPLT,D:\測試圖片\00000009999_151026145540_HPLT.gif,2
    ///  3,,HRBC,D:\測試圖片\00000009999_151026145540_HRBC.gif,2
    ///  3,,SBASO,D:\測試圖片\00000009999_151026145540_SBASO.gif,2
    ///  3,,SDIFF,D:\測試圖片\00000009999_151026145540_SDIFF.gif,2
    ///  3,,SNRBC,D:\測試圖片\00000009999_151026145540_SNRBC.gif,2
    ///  3,,SPLT,D:\測試圖片\00000009999_151026145540_SPLT.gif,2
    ///  3,,SPLT-O,D:\測試圖片\00000009999_151026145540_SPLT-O.gif,2
    ///  3,,SRET,D:\測試圖片\00000009999_1510265540_SRET.gif,2
    ///  3,,SRET-E,D:\測試圖片\00000009999_151026145540_SRET-E.gif,2
    ///  9,41
    ///  ]<para/>
    ///</說明>
    ///<修改記錄>
    ///    [修改時間:本次修改時間]<para/>
    ///    [修改內容:本次修改內容]<para/>
    ///</修改記錄>
    ///<修改記錄>
    ///    [修改時間:本次修改時間]<para/>
    ///    [修改內容:本次修改內容]<para/>
    ///</修改記錄>
    ///</summary>
    [Remark(Remark = "西施美康帶圖片的處理,處理數據格式。\n0,2015-10-26,00:00:00,9999,XT1800I,41\n1,BASO#,2,0.01,,,,,\n1,BASO%,2,0.20,,,,,\n3,,HPLT,D:\\測試圖片\00000009999_151026145540_HPLT.gif,2")]
    public class DealImage : BaseDeal, IPreDeal
    {
        /// <summary>
        /// 存流水號
        /// </summary>
        private static string episNo = "";

        /// <summary>
        /// 儀器代碼
        /// </summary>
        private static string machCode = "";

        /// <summary>
        /// 前處理
        /// </summary>
        /// <param name="result">結果</param>
        /// <param name="machID">儀器ID</param>
        /// <param name="dealProcess">處理程序</param>
        /// <param name="index">當前文件的第幾行</param>
        /// <param name="fileName">當前讀取的文件全名</param>
        /// <returns></returns>
        public bool PreDeal(string result, string machID, string dealProcess, int index, string fileName)
        {
            string[] strArr = result.Split(',');
            if (strArr != null && strArr.Length > 0)
            {
                //第一行數據時清空流水號
                if (index == 0)
                {
                    episNo = "";
                    machCode = "";
                }
                if (index == -1)
                {
                    DealData("", machID, episNo, dealProcess, index);
                }
                if (strArr[0] == "0")
                {
                    //第一行數據提取流水號
                    episNo = result.Split(',')[3];
                    machCode = result.Split(',')[5];
                    DealData(DealNotSeeChar(result + "," + machCode), machID, episNo, dealProcess, index);
                    return false;
                }
                else if (strArr[0] == "1" || strArr[0] == "4" || strArr[0] == "9")
                {
                    DealData(DealNotSeeChar(result + "," + machCode), machID, episNo, dealProcess, index);
                    return false;
                }
                else if (strArr[0] == "3")
                {
                    //得到配置的處理程序處理數據
                    try
                    {
                        //圖片路徑
                        string imgPath = strArr[3];
                        if (System.IO.File.Exists(imgPath))
                        {
                            string ftpPath = "";
                            //得到ftp
                            FtpService ftp = GetFtpHelper(machID, dealProcess, out ftpPath);
                            //上傳圖片
                            ftp.Upload(imgPath);
                            System.IO.FileInfo fInfo = new System.IO.FileInfo(imgPath);
                            //保存圖片
                            SaveImg(machID, episNo, strArr[2], ftpPath.Split('^')[3] + fInfo.Name, dealProcess);
                        }
                        else
                        {
                            LIS.Core.Util.LogUtils.WriteDebugLog("文件不存在:" + imgPath);
                        }
                    }
                    catch (Exception ex)
                    {
                        LIS.Core.Util.LogUtils.WriteExceptionLog("獲得數據處理程序失敗", ex);
                    }
                    return false;
                }
            }
            return true;
        }

        /// <summary>
        /// 處理數據庫數據
        /// </summary>
        /// <param name="row">當前行數據</param>
        /// <param name="machID">儀器ID</param>
        /// <param name="dealProcess">處理程序</param>
        /// <param name="index">當前數據的第幾行</param>
        /// <param name="otherPara">其他參數</param>
        /// <returns></returns>
        public bool PreDealDataBase(System.Data.DataRow row, string machID, string dealProcess, int index, string otherPara)
        {
            throw new NotImplementedException();
        }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PreDeal.Interface;
using PreDeal.Attributes;
using System.IO;
using PreDeal.Ftp;

namespace PreDeal.UPDeal
{
    ///<summary  NoteObject="Class">
    /// [功能描述:愛康唐篩上傳糖篩數據] <para/>
    /// [創建者:zlz] <para/>
    /// [創建時間:2015年10月25日] <para/>
    ///<說明>
    ///  [說明:默認的處理,配置改實現時實現讀一行傳一行的默認實現]<para/>
    ///</說明>
    ///<修改記錄>
    ///    [修改時間:本次修改時間]<para/>
    ///    [修改內容:本次修改內容]<para/>
    ///</修改記錄>
    ///<修改記錄>
    ///    [修改時間:本次修改時間]<para/>
    ///    [修改內容:本次修改內容]<para/>
    ///</修改記錄>
    ///</summary>
    [Remark(Remark = "默認的處理,配置改實現時實現讀一行傳一行的默認實現")]
    public class UpAiKangTangShai : BaseDeal, IUPPreDeal, IPreDeal
    {
        /// <summary>
        /// 前處理
        /// </summary>
        /// <param name="labno">檢驗號</param>
        /// <param name="labnoInfo">標本信息</param>
        /// <param name="patInfo">患者信息</param>
        /// <returns>是否繼續後處理,true是,false否</returns>
        public bool UPPreDeal(string labno, string labnoInfo, string patInfo, string upPara, string machID, string dealProcess)
        {
            LIS.DAL.ORM.EntityManager.EntityManagerImpl manager = new LIS.DAL.ORM.EntityManager.EntityManagerImpl("OTAccessBaseDbFactory");
            string[] infoArr = patInfo.Split('~');
            string err;
            //認爲m層組裝了sql語句
            if (infoArr.Length > 1 && infoArr[1] != "")
            {
                LIS.Core.Util.LogUtils.WriteDebugLog("插入唐篩數據");
                LIS.Core.Util.LogUtils.WriteDebugLog("執行SQL:" + infoArr[1]);
                bool ret = manager.ExecUnSelectSQL(infoArr[1], out err);
                if (err != "")
                {
                    LIS.Core.Util.LogUtils.WriteDebugLog("插入唐篩數據出錯:" + err);
                    return false;
                }
                return true;
            }
            string sql = "insert into InputTable(Rep_No,Pat_Zip,Rep_Date,Pat_Name,Pat_Birthday,Pat_Addr,Pat_tel,Pat_Weight,Pat_Index,Rep_SampleDate,It_HCG,Pat_GestWeek,Pat_GestDay,Rep_Methor) values('{0}','{1}','{2}','{3}','{4}','{5}','{6}','{7}','{8}','{9}','{10}','{11}','{12}','{13}')";
            string[] patArr = patInfo.Split('^');
            string[] labArr = labnoInfo.Split(',');
            string LisPatientID = patArr[8];
            if (LisPatientID == "")
            {
                LisPatientID = labno;
            }
            string LisPatientName = patArr[9];
            string LisBirthday = patArr[13].Split(' ')[0];
            string LisSampleID = labno+"^"+patArr[28];
            string LisSamplingDate = patArr[0];
            string LisTestDate = patArr[0].Split(' ')[0];
            string LisDoctorName = patArr[6];
            string LisLocation = patArr[5];
            sql = String.Format(sql, LisSampleID, patArr[28], LisTestDate, LisPatientName, LisBirthday, patArr[29], patArr[30], patArr[31], patArr[32], LisTestDate, patArr[33], patArr[34], patArr[35], patArr[36]);
            bool ret1 = manager.ExecUnSelectSQL(sql,out err);
            if (err != "")
            {
                LIS.Core.Util.LogUtils.WriteDebugLog("插入唐篩數據出錯:"+err);
                return false;
            }
            return true;
        }

        bool IPreDeal.PreDeal(string result, string machID, string dealProcess, int index, string fileName)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// 處理數據庫
        /// </summary>
        /// <param name="row"></param>
        /// <param name="machID"></param>
        /// <param name="dealProcess"></param>
        /// <param name="index"></param>
        /// <param name="otherPara"></param>
        /// <returns></returns>
        bool IPreDeal.PreDealDataBase(System.Data.DataRow row, string machID, string dealProcess, int index, string otherPara)
        {
            try
            {
                LIS.Core.Util.LogUtils.WriteDebugLog("繪製上傳唐篩圖片");
                string episNo = row["ColA"].ToString();
                string T21 = "1:" + row["ColL"].ToString();
                string T18 = "1:" + row["ColM"].ToString();
                string Name21 = DrawTangSaiImg("1:270", "T21", T21, "1:690", episNo);
                LIS.Core.Util.LogUtils.WriteDebugLog("生成圖片文件:" + Name21);
                string Name18 = DrawTangSaiImg("1:350", "T18", T18, "1:6200", episNo);
                LIS.Core.Util.LogUtils.WriteDebugLog("生成圖片文件:" + Name18);
                string ftpPath = "";
                //得到ftp
                FtpService ftp = GetFtpHelper(machID, dealProcess, out ftpPath);
                LIS.Core.Util.LogUtils.WriteDebugLog("獲得FTP地址:" + ftpPath);
                if (File.Exists(Name21))
                {
                    System.IO.FileInfo fInfo21 = new System.IO.FileInfo(Name21);
                    //上傳圖片
                    ftp.Upload(Name21);
                    System.IO.File.Delete(Name21);
                    //保存圖片
                    SaveImg(machID, episNo, "T21", ftpPath.Split('^')[3] + fInfo21.Name, dealProcess);
                }
                if (File.Exists(Name18))
                {
                    System.IO.FileInfo fInfo18 = new System.IO.FileInfo(Name18);
                    //上傳圖片
                    ftp.Upload(Name18);
                    System.IO.File.Delete(Name18);
                    //保存圖片
                    SaveImg(machID, episNo, "T18", ftpPath.Split('^')[3] + fInfo18.Name, dealProcess);
                }
            }
            catch (Exception ex)
            {
                LIS.Core.Util.LogUtils.WriteExceptionLog("處理唐篩圖片異常", ex);
            }
            return true;
        }
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章