Извиняюсь, старый файл выбрал. Вот новый.
http://rgho.st/7QhDKFSYW
Извиняюсь, старый файл выбрал. Вот новый.
http://rgho.st/7QhDKFSYW
Укажите путь к тегу с проблемным скриптом.
ТРМ210-уставка/уставка
Нет такого.
У похожего тип доступа стоит только на чтение.
На скриншоте выделено.
Вложение 25748
Попробуйте вначале скрипта записи добавить строчку:
if server.IsWriteFromScript( )==true then return; end;
Но в версии 3.2.10 эта функция работать перестала - мы с этим разберемся.
Спасибо большое! Пока не заработало.
Добрый день! Возникли некоторые проблемы при опросе опс-сервером архивов. На объекте в программе плк забыл при формировании строки добавить символ =, в результате чего конец строки получается вида "#000512\N\R", вместо "#000=512\N\R"
Соответственно, скрипт
не обработает данные строки.Код:local n,l= string.find(str, "#" ); --флаг разбора символа " #"
if n~=nil and l~=nil then --если найден символ
local str1=string.sub(str,1,n-1 ); --выделяем строку после символа
if TimeVal==nil then --получаем время строки
NoErr,time=pcall(StrToTime,str1); --вызов функции преобразования в безопасном режиме
if NoErr==true and time~=nil then
TimeVal=time; --ошибки нет - сохраняем время
else
Correct=false; --ошибка - строка некорректная
break; --выходим из цикла
end;
else
local k,z= string.find(str1, "=" ); --разбираем остальные элементы после символа "="
if k~=nil and z~=nil then
local str2=string.sub(str1,z+1); --символ найден - выделяем подстроку со значением
local str3=string.sub(str1,1,z-1); --символ найден - выделяем подстроку с номером
elem[str3+1]=str2; --вставляем в таблицу полученный элемент
else
Correct=false;
TimeVal=nil;
break; --символ не найден - ошибка
end;
end;
str=string.sub(str,l+1 ); --выделяем оставшийся кусок строки и дальше разбираем его
end;
Так как объект удаленный, решил скорректировать код скрипта, получив
Этот вариант кода не работает, хотя в терминале вижу корректные и номера и значения переменной в процессе обработки. Но запись при этом в тэги не происходит. Точнее записывается только если значение переменной (val) = 1. Значения же отличные от 1 не записываютсяКод:local n,l= string.find(str, "#" ); --флаг разбора символа " #"
if n~=nil and l~=nil then --если найден символ
local str1=string.sub(str,1,n-1 ); --выделяем строку после символа
if TimeVal==nil then --получаем время строки
NoErr,time=pcall(StrToTime,str1); --вызов функции преобразования в безопасном режиме
if NoErr==true and time~=nil then
TimeVal=time; --ошибки нет - сохраняем время
else
Correct=false; --ошибка - строка некорректная
break; --выходим из цикла
end;
else
local str2=string.sub(str1,1,3); --выделяем подстроку со значением
server.Message("номер найден. sym=",str2);
local str3=string.sub(str1,4); --символ найден - выделяем подстроку с номером
server.Message("значение найдено. val=",str3);
if string.len(str3)<6 then --(для случаев некорректного получения переменной)
elem[str3+1]=str2; --вставляем в таблицу полученный элемент
end;
end;
str=string.sub(str,l+1 ); --выделяем оставшийся кусок строки и дальше разбираем его
end;
Что я делаю не так?
Кусок лога терминала
Скрытый текст:
Проверяйте - записались ли они в таблицу. Добавьте дальше по программе - где происходит запись в теги server.Message, где значения пропадают.
добавил сообщений:
Скрытый текст:
В сообщении скриптов вижу следующее:
Код:12-08-2016 14:58:48.860 объект.архив:Значения=2016-08-05 08:57:30.000 nil nil
12-08-2016 14:58:48.860 объект.архив:вставили элемент в таблицу - 001
12-08-2016 14:58:48.860 объект.архив:значение найдено, val=16
12-08-2016 14:58:48.860 объект.архив:номер найден, 001
12-08-2016 14:58:48.860 объект.архив:найден символ #
12-08-2016 14:58:48.860 объект.архив:найден символ #
12-08-2016 14:58:48.860 объект.архив:Значения=2016-08-05 08:57:29.000 nil nil
12-08-2016 14:58:48.860 объект.архив:вставили элемент в таблицу - 001
12-08-2016 14:58:48.860 объект.архив:значение найдено, val=32
12-08-2016 14:58:48.860 объект.архив:номер найден, 001
12-08-2016 14:58:48.860 объект.архив:найден символ #
12-08-2016 14:58:48.860 объект.архив:найден символ #
12-08-2016 14:58:48.860 объект.архив:Значения=2016-08-05 08:57:28.000 nil nil
12-08-2016 14:58:48.860 объект.архив:вставили элемент в таблицу - 001
12-08-2016 14:58:48.860 объект.архив:значение найдено, val=16
12-08-2016 14:58:48.860 объект.архив:номер найден, 001
12-08-2016 14:58:48.860 объект.архив:найден символ #
12-08-2016 14:58:48.860 объект.архив:найден символ #
12-08-2016 14:58:48.860 объект.архив:Значения=2016-08-05 08:57:26.000 nil 001
12-08-2016 14:58:48.860 объект.архив:Значения=2016-08-05 08:57:26.000 nil 001
12-08-2016 14:58:48.860 объект.архив:записываем значение в тэг, 2
12-08-2016 14:58:48.860 объект.архив:вставили элемент в таблицу - 001
12-08-2016 14:58:48.860 объект.архив:значение найдено, val=1
12-08-2016 14:58:48.860 объект.архив:номер найден, 001
12-08-2016 14:58:48.859 объект.архив:найден символ #
12-08-2016 14:58:48.859 объект.архив:найден символ #
12-08-2016 14:58:48.859 объект.архив:str=16.8.5 8:57:26#0011
2016.8.5 8:57:28#00116
2016.8.5 8:57:29#00132
2016.8.5 8:57:30#00116
Вот тут вы что то напутали:
local str2=string.sub(str1,1,3); --выделяем подстроку со значением
server.Message("номер найден, ",str2);
local str3=string.sub(str1,4); --символ найден - выделяем подстроку с номером
server.Message("значение найдено, val=",str3);
if string.len(str3)<6 then
elem[str3+1]=str2; --вставляем в таблицу полученный элемент
server.Message("вставили элемент в таблицу - ", elem[str3+1]);
end;
str2 - выделяете начало строки, то есть номер, но затем работаете с ним, как будто это значение. Аналогично с str3.
Не знаю, код взят из оригинального скрипта
Он же рабочий, поэтому не пойму, что не так.Код:local k,z= string.find(str1, "=" ); --разбираем остальные элементы по символа "="
if k~=nil and z~=nil then
local str2=string.sub(str1,z+1); --символ найдет - выделяем подстроку со значением
local str3=string.sub(str1,1,z-1); --символ найден - выделяем подстроку с номером
elem[str3+1]=str2; --вставляем в таблицу полученный элемент
Всё, я понял что вы имеете ввиду, спасибо большое за подсказку
Добрый день!
Подскажите пожалуйста. Пишу скрипт на Луа с использованием побитовых операторов. В стандартном интерпретаторе под
Windows для Луа 5.1 отсутствуют библиотеки для работы с битами. Можно ли подключить вашу библиотеку к этому интерпретатору для проверки кода до вставки в OPC сервер (на-пример, кодом вычисляю число, print - проверяю число)?
Или как проверить тоже самое средствами сервера без запуска тегов?
Нет, вставить нашу библиотеку не получится.
Добрый день!
В одном из Ваших примеров по реализации собственных протоколов путем побитового сдвига получаете из 16-битного числа 32-битное. Мне нужно операции побитовых сдвигов производить с 8-битным числом, но данное число должно оставаться 8-битным. Мне нужно заранее объявить переменные 8-битным числом? Как это сделать?
Спасибо.
В Lua нельзя явно указать битность числа.
Но проблема решается очень просто - после сдвига примените маску по "Логическое И" с числом 255 (8 единиц).
Добрый день!
Мне необходимо поменять биты в 8-битном числе, т.е. 7 бит на место 0-бита, 6 бит на место 1-бита и т.д.
Правильный ли следующий код?
local a --число до перестановки бит
local b --нужное число после перестановки бит
for i=0,7,1 do --цикл по битам байта
c=bit.BitFromData(a,i)
b=bit.BitToData(b,c,(-1(i-7)))
return b
end
Спасибо.
Зачем -1 в bittodata?
Примерно так:
function OnInit()
local a=78 --число до перестановки бит
local b=0; --нужное число после перестановки бит
for i=0,7,1 do --цикл по битам байта
c=bit.BitFromData(a,i)
b=bit.BitToData(b,c,7-i)
end
server.Message("b=",b )
end
Спасибо большое!
Добрый день!
Можно ли функцией server.Message вывести число в двоичном виде? В справке информацию не нашел.
Спасибо
Готовой функции, преобразования нет. Примеры кода можно найти:
http://www.programmersforum.ru/showthread.php?t=78385
Спасибо. Жаль конечно. server.Message помогает отлаживать код.
Добрый день. Не планируется внести в сервер возможность сортировки тегов по адресам? Существующая функциональность перемещения тегов по дереву объекта очень сильно тормозит
Ну вообще она уже года 2 как есть.
На вкладке Таблица тегов можно отсортировать адреса.
Или вы имеете ввиду в режиме исполнения?
Как извлечь время из OPC-HDA запроса от клиента, чтобы в скрипте запросить данные из источника за конкретный период, а не весь диапазон?
Наш ОРС сервер не поддерживает такой режим - есть некоторые проблемы при работе с ним.
Мы в наших ОРС серверах поступаем проще - на уровне устройства задается настройка глубины запроса данных, которую может задать пользователь.
Пропустил Ваш ответ. Я имею ввиду при добавлении нового тега: то есть, к примеру, есть 250 тэгов в устройстве. Добавляю новый тэг(и) с адресом, например 112. В таблице тэгов сортирую по адресации и применив групповые операцию меняю остальную адресацию Это работает. Но в устройстве этот тэг остаётся последним, и, соответственно, чтобы он импортировался в скаду 112-м (для визуального удобства), а не 251 нужно в дереве устройства его довольно долго поднимать вверх. Ну или в скаде (там намного быстрее это происходит).
То есть вас интересует поднятие его вверх?
Здесь решения нет - контрол не поддерживает drag and drop. Поэтому только с помощью Shift + Вверх
Спасибо за ответ. Будем выкручиваться.Цитата:
Наш ОРС сервер не поддерживает такой режим - есть некоторые проблемы при работе с ним.
Мы в наших ОРС серверах поступаем проще - на уровне устройства задается настройка глубины запроса данных, которую может задать пользователь.
Все таки есть или нет возможность отловить событие чтения HDA-тега клиентом?
Периодически читать весь массив значений как-то нехорошо:)
Нет, нельзя.
Читайте определенное количество записей при старте.
А дальше можно читать не весь архив, а только свежую часть - сохранить время последней считанной записи и читать с нее.
Добрый день!
Подскажите пожалуйста, есть ли возможность по значению дискретного тега включать в работу и выключать коммуникационный узел, отвечающий за GSM-модем? То есть, необходимо раз в час прочитать несколько значений с удаленного счетчика. Предполагаю, что при появлении этой необходимости, нужно включить узел в работу, чтобы модем установил соединение, прочитать значения в SCADA-систему, а затем выключить узел (модем через некоторое время разорвет соединение из-за отсутствия обмена данных). Попытался сделать это следующим образом:
В узле GSM-модема "Port" (COM-порт) в скрипт добавил функцию:
function Control(b)
if b==true then
server.SetNodeToOnOff(true);
else
server.SetNodeToOnOff(false);
end;
return "OK"
end
Также добавил вспомогательный программный узел - программное устройство - тег "server only" (это собственно флажок чтения данных из счетчика) со скриптом "после чтения тега":
function OnRead()
local res;
val,q=server.ReadCurrentTag();
res=server.RunFunctionFromNodeByName("Port","Contr ol",1,val);
end
Но не работает такая конструкция...
Должна работать.
Нет необходимости выносить отдельный узел. Разместите server.SetNodeToOnOff() в тег типа ServerOnly, в скрипт "Перед записью". Тогда он будет исполнятся, даже если узел выключен.
Большое спасибо! Все заработало!
OPC HDA возвращает качество тега 0x000400C0. Так и должно быть? В спецификациях что-то не нашел.
Вообще это хороший признак качества, но с каким-то оттенком.
Вы сами его формируете? Как вы его определили?
Вот и я об этом. По идее должно быть C0, но это в принципе качество для OPC DA. Вообще OPC HDA качество какая-то мутная тема.
У нас используется несколько OPC HDA серверов разных производителей, все они возвращают при GOOD - C0.
На вашем сервере настроил HDA. Качество сам в скрипте формирую, по вашим примерам (C0). Скада (не MasterSCADA, другого производителя) все читает и пишет в свою БД, только качество BAD.
А 0x000400C0 я увидел под отладчиком, когда начал разбираться в чем дело (у нас есть исходники OPC HDA и OPC DA клиентов для используемой скада, уже не раз они выручали - почему-то несмотря на стандарты каждый программист OPC-сервера считает своим долгом привнести что-то своё).
Сами понимаете что для себя проблему решили, хотелось уточнить - может неправильно интерпретируем коды качества?
Кажется разобрался.
0004 - необработанные (raw) данные, 00C0 - признак GOOD (как в OPC DA).