Профиль должен быть заполнен на русском языке кириллицей. Заполнение профиля заведомо ложными или некорректными данными - причина возможного отказа в регистрации на форуме.

Радиационный монитор,OPC-сервер,SCADA - проблемы взаимосвязи

Обсуждение вопросов, не относящихся ни к одному из других подразделов

Автор темы
hugo
здесь недавно
здесь недавно
Сообщения: 52
Зарегистрирован: 24 янв 2011, 15:01
Ф.И.О.: Поздеев Василий Николаевич

Радиационный монитор,OPC-сервер,SCADA - проблемы взаимосвязи

Сообщение hugo » 20 дек 2012, 10:22

Добрый день!
Мужчины, помогите - хотя бы где искать и с чего начинать.

Проблема следующая:
Снизу у нас имеется радиационный монитор, который по своему собственному протоколу передает данные.
Сверху у нас имеется SCADA (WinCC), которой необходимо получить информацию по этому протоколу.

Описание протокола есть, описание следующего характера:
"Рад. монитор шлет на заданный IP адрес и порт фрейм данных, который состоит из: заголовок пакета и тело пакета.
Заголовок пакета = длина пакета(4 байта) + тип пакета(1 байт) + резерв (2 байта).
Тело пакета = ..тоже сколько то там байт"

Вопрос довольно общий - как мне этот пакет получить (распознать - уже потом, пока хотя бы так) и отобразить информацию в SCADE? OPC-сервера для данного устройства поставщик не предоставил.


Автор темы
hugo
здесь недавно
здесь недавно
Сообщения: 52
Зарегистрирован: 24 янв 2011, 15:01
Ф.И.О.: Поздеев Василий Николаевич

Re: Радиационный монитор,OPC-сервер,SCADA - проблемы взаимос

Сообщение hugo » 20 дек 2012, 13:52

хм... появилась идея использовать UniOPC сервер.
Вроде, для него можно написать свой dll для нестандартного протокола


LexSL
здесь недавно
здесь недавно
Сообщения: 42
Зарегистрирован: 16 дек 2011, 14:13
Ф.И.О.: Михайлов Алексей
Поблагодарили: 1 раз

Re: Радиационный монитор,OPC-сервер,SCADA - проблемы взаимос

Сообщение LexSL » 21 дек 2012, 11:08

Я для устройств со своим собственным протоколом пишу либо приложение (работающее как служба), которое через объект HMIRuntime (библиотека с типами в CCHMIRuntime.dll) пишет значения напрямую в теги WinCC. Это если надо быстро сварганить обмен, естественно, приложение реализует протокол с устройством.
А по хорошему, да, Вы правы, нужон OPC/
P.S забыл написать - в C# делаю, но это не критично...COM - он и в Африке COM


LexSL
здесь недавно
здесь недавно
Сообщения: 42
Зарегистрирован: 16 дек 2011, 14:13
Ф.И.О.: Михайлов Алексей
Поблагодарили: 1 раз

Re: Радиационный монитор,OPC-сервер,SCADA - проблемы взаимос

Сообщение LexSL » 21 дек 2012, 12:33

Вот накидал, примерно ... естественно сам попробовать не могу :) , у меня поток виснет на строке socket.Accept(); ждет... и даже после закрытия и вызова Thread.Abort() остается в памяти.
будут результаты, хоть какие - отпишите, интересен итог..

[spoiler=класс для радиационного монитора RAD_CLASS.cs]

Код: Выделить всё

using System;
using System.Timers;
using System.Runtime.InteropServices;
using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace RAD_TCP
{
    //это будут приинятые данные
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    struct RADSystemData
    {
        public UInt32 LengthPacket;
        public byte typePacket;
        public float reserv;
        //здесь надо расписать структуру получаемых данных - главное не ошибится сколько байт
        public float value1;
        public float value2;
        public float value3;
    }

    class RAD
    {
        int port;
        int validTimeout;
        public bool running = false;
        public RADData CurrentData = null;
        Thread RADThread;
        public Socket socket = null;

        System.Diagnostics.EventLog appLog;

        public RAD(int port, int validTimeout)
        {
            this.port = port;
            this.validTimeout = validTimeout;
            appLog = new System.Diagnostics.EventLog();
            appLog.Source = "RAD_DataProvider";
        }

        public void Start()
        {
            appLog.WriteEntry("Start RAD MOnitor");
            RADThread = new Thread(listner);
            RADThread.Start();
        }

        public void Stop()
        {
            running = false;
            if (!RADThread.Join(2000)) RADThread.Abort();
        }

        void listner()
        {
           
            try
            {
                //создаем сокет
                socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                //привязываем сокет к порту
                socket.Bind(new IPEndPoint(IPAddress.Any, port));
                //стартуем прослушку
                socket.Listen(0);
                running = true;
                Socket s = null;
                byte[] buffer = new byte[Marshal.SizeOf(typeof(RADSystemData))];
                int cntByte;

                while (running)
                {
                    //ждем пока приконектится клиент
                    try
                    {
                        if (s == null) s = socket.Accept();
                        //читаем данные от клиента
                        //получаем данные из буфера сокета и выводим на экран
                        cntByte = s.Receive(buffer); //читаем буфер сокета
                        if (cntByte >= Marshal.SizeOf(typeof(RADSystemData))) //если прочитали достаточно, то заполняем структуру RADSystemData
                        {
                            if (CurrentData == null)
                            {
                                CurrentData = new RADData(buffer);
                                CurrentData.SetValidTimeout(validTimeout);
                            }
                            else CurrentData.SetData(buffer);
                        }
                    }
                    catch (Exception ex)
                    {
                        appLog.WriteEntry(ex.Message);
                        if (s != null)
                        {
                            s.Close();
                            s = null;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                appLog.WriteEntry(ex.Message);
            }
            if (socket != null) socket.Close();
        }
    }

    class RADData
    {
        public RADSystemData data;
        bool dataIsValid = false;
        System.Timers.Timer validTimer;
        //int validTimeout;

        public RADData(byte[] buf)
        {
            validTimer = null;
            SetData(buf);
        }

        public void SetValidTimeout(int timeout)
        {
            if (timeout > 0)
            {
                if (validTimer == null)
                {
                    validTimer = new System.Timers.Timer();
                    validTimer.Elapsed += OnTimedEvent;
                }
                validTimer.Enabled = false;
                validTimer.Interval = timeout;
                validTimer.Enabled = true;
            }
            else
            {
                if (validTimer != null)
                {
                    validTimer.Enabled = false;
                    validTimer.Dispose();
                    validTimer = null;
                }
            }
        }

        private void OnTimedEvent(object source, ElapsedEventArgs e)
        {
           
            dataIsValid = false;
            validTimer.Enabled = false;
        }

        public void SetData(byte[] buf)
        {
            GCHandle pHandle = GCHandle.Alloc(buf, GCHandleType.Pinned);
            data = (RADSystemData)Marshal.PtrToStructure(pHandle.AddrOfPinnedObject(), typeof(RADSystemData));
            pHandle.Free();
            if (validTimer != null)
            {
                validTimer.Enabled = false;
                validTimer.Enabled = true;
            }
            dataIsValid = true;
        }

    }
}
[/spoiler]

[spoiler=использование Form1.cs]

Код: Выделить всё

using System;
using System.Windows.Forms;
using CCHMIRUNTIME;

namespace RAD_TCP
{
    public partial class Form1 : Form
    {
        private RAD rad_mon = new RAD(1001 /*порт - укажите нужный!!!!*/,5000 /*интервал чтения мс*/);
        private HMIRuntime runtimeWinCC;
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            rad_mon.Start();
            runtimeWinCC = new HMIRuntime();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            rad_mon.Stop();
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (rad_mon.running) rad_mon.Stop();
        }

        private void button3_Click(object sender, EventArgs e)
        {
            if (rad_mon.CurrentData != null)
            {
                //теги TAG1 и TAG2 должны быть созданы в WinCC и быть float, сам рантайм WinCC - запущен
                runtimeWinCC.Tags["TAG1"].Write(rad_mon.CurrentData.data.value1, HMIWriteType.hmiWriteAsync);
                runtimeWinCC.Tags["TAG2"].Write(rad_mon.CurrentData.data.value2, HMIWriteType.hmiWriteAsync);
            }
        }
    }
}
[/spoiler]


Автор темы
hugo
здесь недавно
здесь недавно
Сообщения: 52
Зарегистрирован: 24 янв 2011, 15:01
Ф.И.О.: Поздеев Василий Николаевич

Re: Радиационный монитор,OPC-сервер,SCADA - проблемы взаимос

Сообщение hugo » 24 дек 2012, 07:51

спасибо, будем пробовать

Но раньше нового года уже не получится :)


Вернуться в «Общие вопросы»



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 1 гость