воскресенье, 16 июня 2019 г.

Запись сигналов UDP в SQL

В предыдущей записи я рассказывал как отправить сигнал с контроллера через UDP, а принять его можно в IBA PDA или, например, в SQL базу данных, как это было сделано у нас. Когда линия стояла, в базе записывалось время начала простоя, время окончания простоя, и потом высчитывалось время продолжительности простоя. Потом всю эту информацию можно было выудить из базы путем формирования отчета за определенный период времени - то есть можно было посчитать сколько простояла линия вчера, или неделю назад. Вот сейчас я хочу рассказать как мы такого добились.
В общем сигнал в контроллере сформирован и благополучно отправляется на сервер SQL каждую секунду. Помимо бита простоя туда же отправляется и другая информация, например текущая скорость агрегата, или все что угодно, любой технологический параметр находящийся в контроллере. Все это отправляется единым массивом данных и наша задача принять все данные, и записать нужные данные в нужные столбцы. Чтобы принять данные по UDP и отправлять их в SQL была написана программа на C#, причем пишется она почти полностью на примерах из интернета, ниже в комментах дам код как я исправил программу из интернета чтобы чтобы просто принимать UDP, остается только прикрутить запись в SQL. Чтобы программа не мешалась и работала постоянно в фоне и никто не вздумал ее закрыть, а также чтобы она работала даже тогда когда ни один юзер не авторизован - мы ее сделали в виде службы при помощи утилиты nssm - очень просто и легко.

Самое интересное было потом сделать заполнение таблицы простоев. Все данные по UDP записываются в базу  в таблицу Raw_data, и каждый раз они сравниваются изменилось ли состояние бита простоя downtime, если изменилось, то добавить в таблицу время начала простоя, а когда агрегат поехал нужно добавить время конца. Вот сам код триггера который добавили в Raw_data:
USE [DB1]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE TRIGGER [dbo].[downtrig] ON [dbo].[Raw_Data]
   AFTER INSERT
AS
DECLARE @Prev_downtime_bit AS BIT
DECLARE @Downtime_bit AS BIT
DECLARE @Downtime_Start AS Datetime
DECLARE @Downtime_com AS nvarchar(20)
DECLARE @Downtime_Stopdur AS Datetime
DECLARE @ID_record AS INT
SET @ID_record = (SELECT ID_record from inserted)
SET @Prev_downtime_bit = (SELECT downtime from Raw_Data where ID_record = @ID_record-1)
SET @Downtime_bit = (SELECT downtime from inserted)

    IF @Prev_downtime_bit=0 AND @Downtime_bit=1
    BEGIN
    INSERT INTO down_table (Downtime_start) VALUES (GETDATE())
    END
       
    IF @Prev_downtime_bit=1 AND @Downtime_bit=0
    BEGIN
    SET @Downtime_Start = (SELECT MAX(Downtime_start) FROM down_table)
    SET @Downtime_Stopdur = (GETDATE()- @Downtime_Start)
    IF @Downtime_Stopdur>'0:01:00'
    BEGIN
    SET @Downtime_com = 'Простой > 60s'
    END
    ELSE
    BEGIN
    SET @Downtime_com = ''
    END
    UPDATE down_table SET Downtime_stop = GETDATE(), Downtime_dur = @Downtime_Stopdur, Comment = @Downtime_com where Downtime_start = @Downtime_Start
    END
Конечно в данном случае код триггера не самое важное, интереснее как раз получить программу приема сигнала по UDP и передачи его в SQL, однако я не могу ею поделиться поскольку она конкретно заточена под нашу систему - там все сигналы расписаны наши и данные для подключения к SQL тоже, если вдруг я смогу сделать более-менее универсальное средство, то я им поделюсь, начинаю работать над этим.

1 комментарий:

  1. Тут находится сама программа только приема UDP на определенный порт, который задается в кофиге. Так же там находится исходный код. Все взято из инета и потому никаких копирайтов, т.к. все легко гуглится, только спасибо авторам.
    https://cloud.mail.ru/public/3jA1/3niH87oub

    ОтветитьУдалить