2009-06-10 14 views
0

.NETで開発されたラボ情報システム(LIS)とBeckman製のラボ計測システム用APIであるRemisol 2000 Data Managerの間のインターフェースを開発する必要があります。 Coulter Inc.の考え方は、テスト結果をプログラム的にLISに取り込むことです。実験室情報システムインターフェースRemisol 2000データマネージャー

私にスタートを許すリソースがウェブ上にありますか?私はSocketを開く必要があると推測しますが、ドキュメントでは、Synchron LX20、Synchron CX7、ASTM、ASTMH2、およびLIS Gen.S.のようなプロトコルのメッセージ構造についてのみ記述しています。

これらはすべてシリアルプロトコルを使用しています。

using System; 
using System.IO.Ports; 
using System.Threading; 

public class ClientToBeckmanDL2000 
{ 
    static bool _continue; 
    static SerialPort _serialPort; 
    static bool keepRetrying = true; 

    public static void Main() 
    { 

     CreateNewSerialPortAndOpenIt(); 

     SendAndReceiveMessagesInALoop(); 

     CloseTheSerialPort(); 
    } 

    private static void CloseTheSerialPort() 
    { 
     _serialPort.Close(); 
    } 

    private static void SendAndReceiveMessagesInALoop() 
    { 
     StringComparer stringComparer = StringComparer.OrdinalIgnoreCase; 
     string outputMessage, inputMessage; 
     _continue = true; 
     DateTime startTime, endTime; 
     TimeSpan diffInSeconds; 
     int retryCounter = 0; 


     Console.WriteLine("Type QUIT to exit"); 

     try 
     { 
      while (_continue) 
      { 
       outputMessage = Console.ReadLine(); 

       _serialPort.WriteLine(
         String.Format("{0}", outputMessage)); 

       if (outputMessage.Equals("ENQ") || outputMessage.Equals("<ENQ>") || 
        outputMessage.Equals("EOT SOH") || outputMessage.Equals("<EOT> <SOH>") || 
        outputMessage.Equals("<EOT><SOH>")) 
       { 
        while (keepRetrying.Equals(true)) 
        { 
         startTime = DateTime.Now; 
         inputMessage = string.Empty; 

         inputMessage = GetResponseFromServerInALoop(); 



         endTime = DateTime.Now; 
         diffInSeconds = endTime - startTime; 

         // if the time for response crosses 15 seconds keep retrying 
         if (diffInSeconds.Seconds > 15) 
         { 
          retryCounter++; 
          keepRetrying = true; 
          Console.WriteLine("Retrying..." + retryCounter.ToString()); 
          Console.WriteLine(" "); 
          if (retryCounter > 7) 
          { 
           keepRetrying = false; 
           Console.WriteLine("Tried more than 7 times . Line down. Please try again later..."); 
           break; 
          } 


         } 
         else 
          if (inputMessage.ToString().Length > 0 && (inputMessage.Equals("STX"))) 
          { 
           Console.WriteLine("Response is " + inputMessage.ToString() + " The Remisol server is bidding for line. Try to send your message later ... "); 
           keepRetrying = false; 
          } 
          else 
           if (inputMessage.ToString().Length > 0 && (!inputMessage.Equals("ACK") && !inputMessage.Equals("NAK") && !inputMessage.Equals("STX"))) 
           { 
            Console.WriteLine("Response is " + inputMessage.ToString() + " It should be ACK or NAK or STX. Try again ... "); 
            keepRetrying = false; 
           } 
           else 
            if (inputMessage.ToString().Length > 0 && (inputMessage.Equals("NAK"))) 
            { 
             Console.WriteLine("Response is " + inputMessage.ToString() + " It should be ACK. Try again ... "); 
             keepRetrying = false; 
            } 
            else 
            { 
             Console.WriteLine("Please key in [00,800,01]97<CR><LF> to check Remisol.."); 
             keepRetrying = false; 
            } 
         if (keepRetrying.Equals(true)) 
         { 
          _serialPort.WriteLine(String.Format("{0}", outputMessage)); 
         } 
        } 
       } 
       else 
        if (outputMessage.Equals("[00,800,01]97<CR><LF>")) 
        { 
         do 
         { 
          inputMessage = _serialPort.ReadLine(); 
          System.Threading.Thread.Sleep(1000); 
          keepRetrying = false; 
          Console.WriteLine(inputMessage); 

         } while (inputMessage.Equals(null)); 

         Console.WriteLine("Response is " + inputMessage.ToString()); 
        } 
       if (stringComparer.Equals("quit", outputMessage)) 
       { 
        _continue = false; 
       } 

      } 
     } 
     catch (Exception) { } 
    } 

    private static string GetResponseFromServerInALoop() 
    { 
     string inputMessage = string.Empty; 


     do { 
      inputMessage = _serialPort.ReadLine(); 

      System.Threading.Thread.Sleep(10); 
      keepRetrying = false; 
      Console.WriteLine(inputMessage); 

     } 
     while (inputMessage.Equals(string.Empty)); 

     return inputMessage; 
    } 

    private static void CreateNewSerialPortAndOpenIt() 
    { 
     _serialPort = new SerialPort(); 

     // Allow the user to set the appropriate properties. 
     _serialPort.PortName = SetPortName(_serialPort.PortName); 
     _serialPort.BaudRate = SetPortBaudRate(_serialPort.BaudRate); 
     _serialPort.Parity = SetPortParity(_serialPort.Parity); 
     _serialPort.DataBits = SetPortDataBits(_serialPort.DataBits); 
     _serialPort.StopBits = SetPortStopBits(_serialPort.StopBits); 
     _serialPort.Handshake = SetPortHandshake(_serialPort.Handshake); 

     // Set the read/write timeouts 
     //_serialPort.ReadTimeout = 0; -- this is being commented since this testing program needs to run for long time without timeouts. The default is anyway 0 which is infinite timeouts 
     //_serialPort.WriteTimeout = 500000; -- this too is being commented out since it needs to run infinitely for test 

     _serialPort.Open(); 
    } 


    public static string SetPortName(string defaultPortName) 
    { 
     string portName; 

     Console.WriteLine("Available Ports:"); 
     foreach (string s in SerialPort.GetPortNames()) 
     { 
      Console.WriteLine(" {0}", s); 
     } 

     Console.Write("COM port({0}): ", defaultPortName); 
     portName = Console.ReadLine(); 

     if (portName == "") 
     { 
      portName = defaultPortName; 
     } 
     return portName; 
    } 

    public static int SetPortBaudRate(int defaultPortBaudRate) 
    { 
     string baudRate; 

     Console.Write("Baud Rate({0}): ", defaultPortBaudRate); 
     baudRate = Console.ReadLine(); 

     if (baudRate == "") 
     { 
      baudRate = defaultPortBaudRate.ToString(); 
     } 

     return int.Parse(baudRate); 
    } 

    public static Parity SetPortParity(Parity defaultPortParity) 
    { 
     string parity; 

     Console.WriteLine("Available Parity options:"); 
     foreach (string s in Enum.GetNames(typeof(Parity))) 
     { 
      Console.WriteLine(" {0}", s); 
     } 

     Console.Write("Parity({0}):", defaultPortParity.ToString()); 
     parity = Console.ReadLine(); 

     if (parity == "") 
     { 
      parity = defaultPortParity.ToString(); 
     } 

     return (Parity)Enum.Parse(typeof(Parity), parity); 
    } 

    public static int SetPortDataBits(int defaultPortDataBits) 
    { 
     string dataBits; 

     Console.Write("Data Bits({0}): ", defaultPortDataBits); 
     dataBits = Console.ReadLine(); 

     if (dataBits == "") 
     { 
      dataBits = defaultPortDataBits.ToString(); 
     } 

     return int.Parse(dataBits); 
    } 

    public static StopBits SetPortStopBits(StopBits defaultPortStopBits) 
    { 
     string stopBits; 

     Console.WriteLine("Available Stop Bits options:"); 
     foreach (string s in Enum.GetNames(typeof(StopBits))) 
     { 
      Console.WriteLine(" {0}", s); 
     } 

     Console.Write("Stop Bits({0}):", defaultPortStopBits.ToString()); 
     stopBits = Console.ReadLine(); 

     if (stopBits == "") 
     { 
      stopBits = defaultPortStopBits.ToString(); 
     } 

     return (StopBits)Enum.Parse(typeof(StopBits), stopBits); 
    } 

    public static Handshake SetPortHandshake(Handshake defaultPortHandshake) 
    { 
     string handshake; 

     Console.WriteLine("Available Handshake options:"); 
     foreach (string s in Enum.GetNames(typeof(Handshake))) 
     { 
      Console.WriteLine(" {0}", s); 
     } 

     Console.Write("Stop Bits({0}):", defaultPortHandshake.ToString()); 
     handshake = Console.ReadLine(); 

     if (handshake == "") 
     { 
      handshake = defaultPortHandshake.ToString(); 
     } 

     return (Handshake)Enum.Parse(typeof(Handshake), handshake); 
    } 
} 
+0

上記のそれぞれについて、それぞれのタイプのプロトコルを定義します。シリアル、tcp-ipベース、x25などです。それを最初に定義します。 –

+0

Synchron CX7にはシリアルインターフェースがあります。 –

+0

これらはすべてシリアルプロトコルを使用しているはずです。 – Chakra

答えて

1

私は(私の場合は、thermocyclers)ラボ機器にLIMSシステムのための同様のインターフェースをやりました。

あなたが言及した特定の装置についてはわかりませんが、多くのラボ装置は何らかの形式のシリアルインターフェイスを使用しています。物理レイヤーはrs232(ベンチでスタンドアロンで使用する場合)またはrs485(デイジーチェーン構成で複数の楽器を一緒に使用する必要がある場合)のいずれかになります。プロトコルレベルは、非常に幅広い単純なメッセージ/応答パターンにすることができます。これらの中には実際には標準(ASTM 1394)のものもあれば、オペコード、データ、チェックサムを持つ単純なバイトブロックで構成される「自家製」のものもあります。それが何であれ、使用できるAPIライブラリがない場合は、適切なドキュメントが必要です。あなたはこのようなものを得るために電話をかけなければならないかもしれませんが、いつもインターネットで利用できるとは限りません。

問題の1つは、LIMSシステムを実行するサーバーが、しばしばどこかのデータセンターにあり、計測器がラボにあることです。さらに悪いことに、サーバーにはシリアルポートがなく、計測器にはイーサネットがありません。

この問題を回避するには、「シリアルターミナルサーバー」または「シリアルデバイスサーバー」(たとえば、link)を使用します。これらは、イーサネットトラフィックを受け取り、1つ以上のシリアルポート(ポートはrs232またはrs422またはrs485として設定できます)にルーティングする小さなメタルボックスです。サーバー上で、リモートターミナルサーバーのこれらのポートをサーバーアプリケーションの実際のポートとして表示するドライバをインストールします。また、特定のTCP/IPソケットとの間でデータを特定のシリアルポートにルーティングすることもできます。

これを動作させると、時間を大幅に節約できる非常にうまくやりがいのあるプロジェクトです。がんばろう!

+0

クライアントプログラムのコードを今質問に追加しました。私はクライアントとサーバーを接続するrs232ケーブルを使用しています。同じクライアントプログラムは、ASTMHサーバーのように動作する「ダミー」サーバープログラムで動作します。私はそれをRemissolサーバーのPCに接続し、EOT SOHまたはENQメッセージを送信すると失敗します。 – Chakra

+1

"ACK"と "STX"は実際にASCII文字であり、3文字の文字列ではないことを認識しています。 – Angelo

+0

だから、ENQのような文字列を送信し、ACKのような文字列を待つ代わりに、ENQのASCIIを送信し、ACKのASCIIを期待する必要がありますか? – Chakra