Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > IT форум > Помощь студентам
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 22.11.2012, 09:53   #1
DMBS
 
Регистрация: 19.11.2012
Сообщений: 4
По умолчанию Расшифровке кода (Delphi). Cерверное приложение.

Здесь клиент SCADA Tracemode посылает запрос на сервер "RX from SCADA port" и получает ответ от сервера "TX from SCADA port"
Реальный запрос и ответ выглядят так
На сервер приходит запрос от SCADA по протоколу modbus
Rx from Scada port 64006 1A 00 00 00 00 06 02 04 00 04 00 01
Cервер высылает ответ
TX from Scada port 64006 1A 00 00 00 00 05 02 04 04 00 E2
где E2 это к примеру значение с датчика.

Код:
procedure TfMain.ssForSkadaClientRead(Sender: TObject; //вызываем процедуру в момент принятия данных от клиента.
  Socket: TCustomWinSocket);
var
   Text : string;
  wI:Word;
  cRSchar: char;
  st:string;
  zs: string;
  ___st:string;
  Buf: array[0..1000] of byte;
  as1: array [0 .. 255] of byte;
  adr: integer;
  i:integer;
  j,uL,u1:byte;
begin
   Text := socket.ReceiveText;        // Переменной Text присваиваем принятое от клиента сообщения (строку запроса от SCADA в протоколе Modbus)

   st := '';
  for wI:=0 to  Length(Text)-1 do
   begin
    //cRSchar:=Form1.ApdComPort1.GetChar;
    cRSchar:=Text[wI+1];
    Buf[wI]:=ord(cRSchar);
    as1[wI+1]:=ord(cRSchar);
    st := st + inttohex((ord(cRSchar)),2) + ' ';
   end;
  DateTimeToString(___st,'hh:nn:ss:zzz',time);
  fMain.lbLog.Items.Add(___st + ' Rx from SKADA port '+inttostr(Socket.LocalPort)+' : '+ st);/выводим строку запроса
  if (fMain.lbLog.Items.Count > 1000) then  fMain.lbLog.Items.Delete(0);
  adr:=0;
  for i:=0 to MAX_TERMINALS do
  begin
    if terminals[i].portForSkada <> 0 then
      if (Socket.LocalPort = terminals[i].portForSkada) then
        begin
          adr:= terminals[i].adr;
        end;
        if terminals[i].active = true then terminals[i].values[23]:= 1;
        if terminals[i].active = false then terminals[i].values[23]:= 0;
  end;

  for i:=0 to MAX_TERMINALS do
  begin
    if terminals[i].adr = adr then
    begin
     begin
      st:='';
      zs:='';
      for  j:=1 to 5 do
//вот здесь несовсем понятно что идет дальше
        begin
         st:=st+char(as1[j]);
         zs:=zs + inttohex((ord(char(as1[j]))),2) + ' ';
        end;
      st:=st+char(as1[12]*2+3);
      zs:=zs + inttohex((ord(char(as1[12]*2+3))),2) + ' ';
      st:=st+char(as1[7]);
      zs:=zs + inttohex((ord(char(as1[7]))),2) + ' ';
      st:=st+char(as1[8]);
      zs:=zs + inttohex((ord(char(as1[8]))),2) + ' ';
      //st:=st+char(as1[12]*2);
      //zs:=zs + inttohex((ord(char(as1[12]*2))),2) + ' ';
      st:=st+char(as1[10]);
      zs:=zs + inttohex((ord(char(as1[10]))),2) + ' ';
      uL:=0;
      for u1:=0 to as1[12]-1 do
        begin
          //st:=st+char(TermParam[10,as1[10]+uL] shr 8);
          st:=st+char(terminals[i].values[as1[10]+uL] shr 8);
          zs:=zs + inttohex((ord(char(terminals[i].values[as1[10]+uL] shr 8))),2) + ' ';
          //st:=st+char(TermParam[10,as1[10]+uL]);uL:=uL+1;
          st:=st+char(terminals[i].values[as1[10]+uL]);
          zs:=zs + inttohex((ord(char(terminals[i].values[as1[10]+uL]))),2) + ' ';
          uL:=uL+1;
        end;
      socket.SendText(st);//отсылаем клиенту текстовое сообщение в виде строки.

      DateTimeToString(___st,'hh:nn:ss:zzz',time);
      fMain.lbLog.Items.Add(___st + ' Tx for SKADA port '+inttostr(Socket.LocalPort)+' : '+ zs);/выводим ответ в SCADA
      if (fMain.lbLog.Items.Count > 1000) then  fMain.lbLog.Items.Delete(0);
     end;
    end;
  end;
end;
DMBS вне форума Ответить с цитированием
Старый 22.11.2012, 12:29   #2
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Во-первых: Неужели у тебя нет ОРС сервера для твоего девайса? Или хоть маломальского провайдера, драйвера т.д.? Не может такого быть, чтоб девайс был без ПО вообще. Мануалы что пишут?

Во-вторых: Тот дамп что ты представил - это ведь поток байт, уже переведенный в 16-тиричку заботливым сниффером, или девайсина вот прямо так и передает в виде текста?
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 22.11.2012, 12:48   #3
DMBS
 
Регистрация: 19.11.2012
Сообщений: 4
По умолчанию

OPC сервера нету,По писалось от руки вообще))и сдавалось заказчику ,некакой документации нету.До сих пор даже при эксплуатации сервера вылетает ошибка acess violation. Суть примерно такова . Имеется данный сервер . Имеются терминалы(клиенты)к который подключены датчики давления.Посылки от терминалов передаются по каналу GSM /GPRS на сервер.Каждая посылка имеет свой Код.Код 22 означает ,что данные пришедшие на сервер записывались бы в Базу данных.А посылка имеющая код 25 -это мгновенные значения с терминалом-Она бы отправлялась в SCADA на визуализацию. Посылка от терминала имеет такой вид
На сервер от терминала приходит посылка вида 08:31:35 812 from Terminal:45 00 50 13 00 22 31 07 DC 0B 16 08 1F 04 00 00 00 00 E2 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00.....Где (22) код посылки,07-04 время, E2 значение с датчика
DMBS вне форума Ответить с цитированием
Старый 22.11.2012, 13:09   #4
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Т.е. по факту тебе приходит не массив байт а именно строка, которую и нужно разбирать, верно?
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 22.11.2012, 13:33   #5
DMBS
 
Регистрация: 19.11.2012
Сообщений: 4
По умолчанию

да,вот код сервера на принятие данных от терминала(клиента.)Мне нужно сделать чтобы посылка с code 25 , уходила в SCADA а с code 22 писалась бы в базу данных.
Код:
procedure TfMain.ssForTerminalsClientRead(Sender: TObject;
  Socket: TCustomWinSocket);/вызываем процедуру в момент принятия данных от клиента
var
  Text : string;
  wI:Word;
  cRSchar: char;
  st:string;
  ___st:string;
  Buf: array[0..1000] of byte;
  Buf1: array[0..20] of byte;
  adr: integer;
  i, j :integer;

  t:integer;
  year,month,day,hour,minute,second:integer;

  myDate : TDateTime;
  myYear, myMonth, myDay : Word;
  myHour, myMin, mySec, myMilli : Word;


  ass : array[0..12] of byte;
  str, zss : string;

begin
// здесь принимаем пакеты от клиентов
   Text := socket.ReceiveText;

   if Length(Text) <> 12 then begin
     st := '';
     for wI:=0 to  Length(Text)-1 do
     begin
       //cRSchar:=Form1.ApdComPort1.GetChar;
       cRSchar:=Text[wI+1];
       Buf[wI]:=ord(cRSchar);
       st := st + inttohex((ord(cRSchar)),2) + ' ';
     end;

     DateTimeToString(___st,'hh:nn:ss:zzz',time);
     fMAin.lbLog.Items.Add(___st + 'From Terminal: '+ st);//вывод строки в лог 

     if (fMAin.lbLog.Items.Count > 1000) then  fMAin.lbLog.Items.Delete(0);

     //len:=Buf[0]+Buf[1]*256;
     adr:=Buf[3]+Buf[4]*256;
     code:=Buf[5];

     if (code = 1) then exit;

     for i:=0 to MAX_TERMINALS do
     begin
       if terminals[i].adr = adr then
       begin
         if  terminals[i].socket <> socket then
         begin
           terminals[i].socket := socket;
           terminals[i].active := true;
           terminals[i].adr := adr;
           terminals[i].setDate := false;
           //fMain.lbTerminals.Items.Delete(i);
           fMain.lbTerminals.Items[i]:= inttostr(i+1)+'. '+terminals[i].name+' , ' + inttostr(terminals[i].adr) + '         Терминал Подключен';
           //fMain.lbTerminals.Items.Add(inttostr(i+1)+'. '+terminals[i].name+' , ' + inttostr(terminals[i].adr) + '         Терминал Подключен.');
         end;

       end;
     end;
     t:=0;
     if not terminals[t].setDate then
     begin
       Buf1[0]:=14;
       Buf1[1]:=0;
       Buf1[2]:=0;
       Buf1[3]:=0;
       Buf1[4]:=0;
       Buf1[5]:=$1B;
       Buf1[6]:=0;
       myDate:=Now;
       DecodeDateTime(myDate, myYear, myMonth, myDay, myHour, myMin, mySec, myMilli);
       Buf1[7]:=myYear mod 256;
       Buf1[8]:=myYear div 256;
       Buf1[9]:=myMonth;
       Buf1[10]:=myDay;
       Buf1[11]:=myHour;
       Buf1[12]:=myMin;
       Buf1[13]:=mySec;
       terminals[t].socket.SendBuf(Buf1,14);
       terminals[t].setDate:=True;
     end;

разбор по кодам
     {if code = $00 then
     begin
       // трансляция в 485 интерфейс.
     end;
     if code = $01 then
     begin
       // пинг
     end;      }

     if code = $21 then
     begin

       //Bu[6]
       terminals[t].countFail:=0;

       //if Buf[7] = 0 then
       //begin
       for i:=0 to 23 do
         terminals[t].values[i] := Buf[8+i*2] + Buf[9+i*2]*256;
//записываем в базу данных
         saveToDB(t);
       end;
     end;
      code:=0;
     if code = $22 then //код архивных значений для записи в бд
     begin
       //Bu[6]
       t:=0;
       terminals[t].countFail:=0;

       if Buf[6] = $31 then
       begin
         year:=Buf[7]*256 + Buf[8];
         month:=Buf[9];
         day:=Buf[10];
         hour:=Buf[11];
         minute:=Buf[12];
         second:=Buf[13];
         if terminals[t].active = true then Buf[60]:= 1;
         for i:=0 to 23 do
           terminals[t].values[i] := Buf[14+i*2] + Buf[15+i*2]*256;
           // записываем в базу данных
           saveToDBDate(t,year,month,day,hour,minute,second);
         end;
       end
DMBS вне форума Ответить с цитированием
Старый 22.11.2012, 13:42   #6
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Я могу предложить тебе только одно:
Сделай переменку типа TStringList. и приходящую строку засовывай в ее свойство DelimidetText. Тогда ты получишь массив слов, которые в строке разделены были пробелом.
Соответственно [9] элемент даст строку 22. Это 16-ричная версия числа, которое в нормальное число (байт если хочешь) можно перевести функцией StrToInt('$'+этот самый элемент);
Код:
st:=TStringList.Create;
...
st.DelimidetText:= эта самая строка
Число:= StrToInt('$'+st[номер по идее в строке]);
Подходит принцип?
Цитата:
По писалось от руки вообще))и сдавалось заказчику ,некакой документации нету.До сих пор даже при эксплуатации сервера вылетает ошибка acess violation.
Мегасоболезную, сам имел дело с NAPOPC, и знаю какая это прелесть, когда с контроллером на "ты" общаться можно )
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 22.11.2012, 13:49   #7
DMBS
 
Регистрация: 19.11.2012
Сообщений: 4
По умолчанию

Спасибо)будем разбираться
DMBS вне форума Ответить с цитированием
Старый 22.11.2012, 21:35   #8
raxp
Старожил
 
Регистрация: 29.09.2009
Сообщений: 9,713
По умолчанию

...и что, в скаде нет поддержки Modbus?
Разработки и научно-технические публикации :: Видеоблог :: Твиттер
Radar systems engineer & Software developer of industrial automation
raxp вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Инъекция своего кода в чужое приложение. Denutrror Общие вопросы Delphi 2 05.11.2012 15:03
Пишем VBS-приложение для преображения кода VB [статья] dab00 JavaScript, Ajax 10 06.10.2012 17:14
Delphi приложение Homadrom Фриланс 3 12.05.2012 13:46
статья - Пишем VBS-приложение для преображения кода VB Pblog Обсуждение статей 0 23.12.2011 17:00
Приложение Delphi RuVarez Общие вопросы Delphi 6 03.09.2010 13:23