SCADA-система SoloScada позволяет самостоятельно описывать обмен с устройством по протоколу TCP/IP.
Порядок действий для работы с протоколом TCP/IP следующий:
- Создайте переменные с типом «константа», в которые будет выводиться данные.
- Создайте скрипт. Условие запуска выберите «В отдельном потоке».
- Создайте сокет, получите его номер. NomerSock:= CreateSocket; Обращаться в потоке к сокету следует только по этому номеру.
- Соединитесь с удаленным компьютером ConnectSocket(NomerSock,'192.168.42.98',32100,3000,10000); //32100 – порт, 3000 – таймаут ожидания ответа при чтении (мс), 10000 - таймаут соединения (мс).
- Организуйте цикл repeat … until Terminated; , где Terminated – означает, что программа завешается и пора выходить. Если цикл не будет организован, скрипт исполнится один раз и закончится.
- В цикле сформируйте последовательность байт и отправьте её в сокет с помощью функции SendToSocket(NomerSock,data);// NomerSock – номер сокета, data – это строка (тип string). Функция SendToSocket проверяет наличие соединения и пытается соединиться автоматически.
- Примите данные из сокета с помощью функции input:=ReadFromSocket(NomerSock);. //Результат принимаем в строковую переменную input
- Проверить длину, контрольную сумму принятых данных, выбрать численное значение из результата, присвоить переменным из п.1 значения.
- Наличие соединения можно контролировать с помощью функции IsSocketConnect. Функция
- Разорвать соединение можно с помощью функции DisConnectSocket.
- В конце скрипта уничтожить сокет DeleteSocket(NomerSock);
//Пример скрипта, работающего с сокетами
//Опрос счетчика СЭТ-4ТМ, ПСЧ-4ТМ через преобразователь Ethernet/RS-485
var NomerSock, //Номер сокета
NaprP,Ci,Ki: Integer; //Коэффициенты для пересчета измерений счетчика
var b: array [1..3] of Integer;
var data, input: string;
var Dr: Float;
NomerSock:= CreateSocket; //Создаём сокет, запоминаем его номер.
ConnectSocket(NomerSock,'192.168.42.98',32100,3000,10000);//Соединяемся с
IP-адресом 192.168.42.98
Ci:=1;
Ki:=1;
repeat
//Запрос на открытие канала счетчика // 1F 01 30 30 30 30 30 20 4E A4
data:=Chr($1F)+Chr($01)+Chr($30)+Chr($30)+Chr($30)+Chr($30)+Chr($30)+Chr($30)+
Chr($30)+Chr($20);
data:=data + CalcModBusCRC(data);//Пристраиваем в конец контрольную сумму ModBus
SendToSocket(NomerSock,data);// Отправляем в сокет пакет
input:=ReadFromSocket(NomerSock);// Читаем ответ из сокета
//WriteStrToFile( StrToHexFormat( input),'mb1.txt'); // Можно вести логи в
файл при желании
if ChechModBusCRC(input) then // Если счетчик ответил правильно
begin
// Зпрос активной мощности P. 1F 08 11 02 0B A3
data:=Chr($1F)+Chr($08)+Chr($11)+Chr($02);
data:=data + CalcModBusCRC(data);
SendToSocket(NomerSock,data);// Отправляем в сокет пакет
input:=ReadFromSocket(NomerSock);// Читаем ответ из сокета
if (ChechModBusCRC(input))and(Length(input)>4) then //Проверяйте на корректность ответа,
чтобы не залезть потом в несуществующий элемент массива!!!
begin
b[1] := ord(input[2]);
b[2] := ord(input[3]);
b[3] := ord(input[4]);
NaprP := b[1] and $80;
if NaprP > 0 then
NaprP := 1
else
NaprP := 0;
b[1] := b[1] and $3F;
Dr := b[1] * ($FFFF + 1) + b[2] * ($FF + 1) + b[3]; // Пересчет значения
Pset4:= (Dr / 10) * Ci * Ki / 1000; //Вывод в переменную Pset4
end
else
SetBadQualityToValue('Pset4'); // Установка плохого качества для переменной,
если ответ неправильный
// Зпрос реактивной мощности // 1F 08 11 05 4A 61 - Q
data:=Chr($1F)+Chr($08)+Chr($11)+Chr($05);
data:=data + CalcModBusCRC(data);
SendToSocket(NomerSock,data);
input:=ReadFromSocket(NomerSock);
if (ChechModBusCRC(input))and(Length(input)>4) then
begin
b[1] := ord(input[2]);
b[2] := ord(input[3]);
b[3] := ord(input[4]);
NaprP := b[1] and $80;
if NaprP > 0 then
NaprP := 1
else
NaprP := 0;
b[1] := b[1] and $3F;
Dr := b[1] * ($FFFF + 1) + b[2] * ($FF + 1) + b[3];
Qset4 := (Dr / 10) * Ci * Ki / 1000
end
else
SetBadQualityToValue('Qset4');
end;
sleep(20);
if IsSocketConnect(NomerSock) then //можно проверить, есть ли
связь с удаленным компьютером
Connect_set4:=1
else
Connect_set4:=0;
until Terminated; //Terminated – означает, что программа завешается
и пора выходить.
//Если цикл не будет организован, скрипт исполнится один раз и закончится.
DisConnectSocket(NomerSock);//Разрываем соединение
DeleteSocket(NomerSock);//Удаляем сокет