PDA

Просмотр полной версии : Modbus MasterOPC сервер - проблема с unicode



Terminat
03.07.2017, 12:50
Необходимо получить и записать в устройство unicode-строку.

Вводим на самом устройстве строку "1234".
Настраиваем в OPC-сервере тег: типы string, длина 64 байта, формат строки unicode. Запускаем режим исполнения - получаем строку "1".
Меняем формат строки на hex - получаем 3100320033003400 (и далее нули).
Предположительно OPC-сервер интерпретировал строку как ascii и поэтому оборвал ее на первом же нуле.

Как это выглядит с кириллицей: вводим на устройстве "АБВГ", получаем в формате строки unicode строку из 8 кракозямбр, в формате строки hex - 1004110412041304 (и далее нули).
Предположительно OPC-сервер интерпретировал строку как ascii.

Что делать? Версия сервера 4.0.3 Demo.
Кстати, возможность перестановки байт для строк "Старшим байтом вперед" была бы в нашем случае очень удобна, пока приходится делать это вручную в устройстве.

SCADAMaster
03.07.2017, 16:39
Ошибка исправлена - скачайте текущую версию.
Чередование байт для строки сделать нельзя, так как неизвестна ее длина

Terminat
04.07.2017, 11:08
Спасибо, все работает.
Жаль. Длина строки вроде бы указывается в настройках тега.

SCADAMaster
04.07.2017, 11:24
Правильно. Но их может быть больше 8, а чередование байт только для 8 байта.
Можно скриптами менять чередование.

Terminat
04.07.2017, 19:41
Такова текущая реализация, и новшество с шаблоном перестановки из устройства - отличное. Но речь не о произвольном порядке байт, а только об единственном варианте "Старший байт вперед" для строк: применяемое в данном случае устройство строго следует именно этому правилу для всех типов данных. Предполагаю, что это не уникальная ситуация.
Мы, как я писал, выполняем перестановку вручную на устройстве (отдельно для чтения и записи), но думаю, что пример скрипта для MasterSCADA или MasterOPC (что выглядит предпочтительнее) будет многим полезен.

Еще раз - спасибо!

SCADAMaster
04.07.2017, 20:14
Вам нужно просто задом наперед их?
function OnRead()
local str,qual=server.ReadCurrentTag();
if str==nil then return; end;
local NewStr="";
for i=string.len(str),1,-1 do
NewStr=NewStr..string.sub(str,i,i);
end;
server.WriteCurrentTag(str,qual);
end

Terminat
05.07.2017, 10:36
Не совсем, нужно попарно поменять байты местами. Т.е. порядок перестановки 10(3254 и далее до конца строки).

SCADAMaster
05.07.2017, 11:04
В этой строчке:
NewStr=NewStr..string.sub(str,i,i);
sub - это выделение определенного символа строки.
Извлеките каждый символ, а затем склейте строку через оператор .. как вам нужно

Terminat
05.07.2017, 14:54
Увы, вариант вида:

function OnRead()
local str,qual=server.ReadCurrentTag();
if str==nil then return; end;
local NewStr="";
for i=1,string.len(str),2 do
NewStr=NewStr..string.sub(str,i+1,i+1);
NewStr=NewStr..string.sub(str,i,i);
end;
server.WriteCurrentTag(NewStr,qual);
end

- для unicode-строки меняет местами символы, а не байты.
Ладно, вопрос закрыт. Спасибо.