Интерфейс лабораторной информационной системы для Remisol 2000 Data Manager - PullRequest
0 голосов
/ 10 июня 2009

Мне нужно разработать интерфейс между Лабораторной информационной системой (LIS), разработанной в .NET, и Remisol 2000 Data Manager, который представляет собой API-интерфейс для систем лабораторного инструментария, разработанный Beckman Coulter Inc. Идея состоит в том, чтобы получить результаты теста программно в LIS.

Есть ли в сети какие-либо ресурсы, которые могут дать мне старт? Я предполагаю, что мне нужно открыть 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);
    }
}

1 Ответ

1 голос
/ 27 октября 2009

Я сделал интерфейс для системы ЛИМС аналогично лабораторным приборам (в моем случае, термоциклеры ).

Я не знаю о конкретных приборах, которые вы упомянули, но многие лабораторные приборы используют последовательный интерфейс какой-либо формы. Физический уровень может быть rs232 (если инструмент предназначен для автономного существования на стенде) или rs485 (если существует несколько инструментов, которые необходимо объединить в конфигурации «гирляндной цепи»). Уровень протокола может быть довольно большим разнообразием простых шаблонов сообщений / ответов. Некоторые из них на самом деле являются стандартами (ASTM 1394), другие - «домашние» задания, которые состоят из простых блоков байтов с кодами операций, данными и контрольной суммой. Что бы это ни было, вам понадобится хорошая документация, если у вас нет библиотек API, которые вы можете использовать. Возможно, вам придется звонить по телефону, чтобы получить этот материал, он не всегда доступен в Интернете.

Одна из проблем, с которой вы столкнетесь, заключается в том, что серверы, на которых работают системы LIMS, часто находятся где-то в центре обработки данных, а ваши инструменты - в лаборатории. Хуже того, на серверах нет последовательных портов, а на инструментах нет Ethernet.

Чтобы обойти это, вам нужно использовать «серверы последовательных терминалов» или «серверы последовательных устройств» (например ... ссылка ). Это небольшие металлические блоки, которые принимают Ethernet-трафик и направляют его на один или несколько последовательных портов (порты можно настроить как rs232 или rs422 или rs485). На сервере вы устанавливаете драйвер, который делает эти порты на удаленном сервере терминалов действительными портами для серверного приложения. Кроме того, вы также можете направить данные в / из определенного сокета TCP / IP на определенный последовательный порт.

Если вы заставите его работать, это довольно аккуратный полезный проект, который экономит много времени. Удачи!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...