整合监听程序

背景
由于我们检验对串口仪器已经有成熟的方案。而且是数据库脚本语言通过串口转网口连的。省去了连仪器要配连接电脑的开销,同时不用在电脑部署环境和程序,用脚本调试也方便。对于仪器在电脑生成数据文件的、或者监听对方数据库、或者需要画图的等就不适合用串口转网口走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;
        }
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小乌鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值