Autor Téma: AT příkazy z modemu - parsing v Delphi  (Přečteno 888 krát)

Offline Jirka

  • Hrdina
  • ****
  • Příspěvků: 390
  • Karma: 9
    • Verze Delphi: XE2
AT příkazy z modemu - parsing v Delphi
« kdy: 02-03-2021, 13:02:31 »
Zdravím.
Nenapověděl mi někdo cestu jak efektivně parsovat response  AT příkazy  (například došlá SMS zpráva).
Případně zda již existuje nějaký parser v Delphi nebo aspoň v C# 

Offline Radek Červinka

  • Administrátoři
  • Padawan
  • *****
  • Příspěvků: 2827
  • Karma: 105
    • Verze Delphi: D2007, DXE + 2 poslední
    • O Delphi v češtině
Re:AT příkazy z modemu - parsing v Delphi
« Odpověď #1 kdy: 02-03-2021, 14:33:55 »
Třeba https://github.com/Zeus64/alcinoe/blob/master/source/ALGSMComm.pas
Embarcadero MVP - Czech republic

Offline Radek Červinka

  • Administrátoři
  • Padawan
  • *****
  • Příspěvků: 2827
  • Karma: 105
    • Verze Delphi: D2007, DXE + 2 poslední
    • O Delphi v češtině
Re:AT příkazy z modemu - parsing v Delphi
« Odpověď #2 kdy: 02-03-2021, 14:35:25 »
Nebo hledej klicove slovo PDU, bohuzel ti nemuzu dat nas kod.
Embarcadero MVP - Czech republic

Offline Jirka

  • Hrdina
  • ****
  • Příspěvků: 390
  • Karma: 9
    • Verze Delphi: XE2
Re:AT příkazy z modemu - parsing v Delphi
« Odpověď #3 kdy: 02-03-2021, 18:09:43 »
Třeba https://github.com/Zeus64/alcinoe/blob/master/source/ALGSMComm.pas
Pro začátek to je určitě dobré ...
Díky
Docela mě zaujalo tamější vytvoření serial portu (jestli to tedy serial je...)

Offline Jirka

  • Hrdina
  • ****
  • Příspěvků: 390
  • Karma: 9
    • Verze Delphi: XE2
Re:AT příkazy z modemu - parsing v Delphi
« Odpověď #4 kdy: 10-03-2021, 20:08:09 »
Nebo hledej klicove slovo PDU, bohuzel ti nemuzu dat nas kod.

To samozřejmě chápu.


Ale velmi by mi pomohla rada jak spolehlivě parsovat  příchozí data v thread.execute

Doposud  jsem pracoval  s datovou větou <STX> ...... <ETX>
a se strukturou těch <CR> <LF> se nějak peru aniž bych zatím vítězil :-)

Nějaký parsing jsem i stvořil, ale bohužel,  pokud někdo třeba na SIM zavolá,  tak mi rozhodí ten můj parsující systém ..  :-\



       repeat
           if   MainSockKlient.WaitingData >0 then
       begin
      NactenaData:=MainSockKlient.RecvPacket(5000);
       if MainsockKlient.lastError<>0 then break;

      // tady by mělo nasledovat parsovani  a další zpracování...
         ProvedParsingAZpracuj(NactenaData)

     end;
        sleep(20);
   until false;

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 3139
  • Karma: 137
    • Verze Delphi: D2007, XE3, DX10
Re:AT příkazy z modemu - parsing v Delphi
« Odpověď #5 kdy: 11-03-2021, 09:13:50 »
Ale velmi by mi pomohla rada jak spolehlivě parsovat  příchozí data v thread.execute
Nevim, jestli ti to pomuze, protoze to mame asynchronni tj. event driven, kde se seriovy port obsluhuje pres overlapped I/O a kdyz prijme nova data, tak je plive do dalsi vrstvy. Treba ti to osvetli, co se na tech dratech muze dit a ze parser pracuje s celymi radky. RxDataFilter nahradi znak NUL za mezeru, vypusti znaky LF a 0xFF. Proc vyppousti ten 0xFF po me nechtej po 1/4 stoleti vedet, protoze ten kod pracuje snad se vsemi modemy, ktere se na trhu vyskytly a ma za sebou velky soubor konfiguracnich parametru, ktery se skryva v tech _RxDataXxxx metodach a resi bordel, ktery panoval  v implementacich modemu pred vydanim/respektovanim normy GSM 7.05. Cely kod ti dat nemuzu.
Kód: Delphi [Vybrat]
  1.  //-------------------------------------------------------------------
  2.     procedure   TGenericModem._DataReceived                
  3.                       (ASender:TObject);                          
  4. //--------------------------------------------------------------------
  5.     var
  6.       Data:  ANSIstring;
  7.       Line:  ANSIstring;
  8.       CRidx: integer;
  9.     begin
  10.       if not Enabled then
  11.         exit;
  12.       Data := FRxTmpBuffer+RxDataFilter(Port.RxString);
  13.       FRxTmpBuffer := sz;
  14.       while Data<>sz do
  15.         begin
  16.           CRidx := pos(#13,Data);
  17.           if CRidx<>0 then
  18.             begin
  19.               Line := copy(Data,1,CRidx-1);
  20.               Data := copy(Data,CRidx+1,length(Data)-CRidx);
  21.               IOCLog.Log(ThreadName,cmltInp,''''+Line+#13+'''');
  22.               // pokracovaci radek nevyzadanych dat
  23.               if FRxUnsolLines>0 then
  24.                 begin
  25.                   IOCLog.Log(ThreadName,cmltUns,'Unsolicited response');
  26.                   __RxAddUnsolicited(Line);
  27.                 end
  28.               // potlaceni echa
  29.               else if CompareText(Line,FTxLastCommand)=0 then
  30.                 begin
  31.                   IOCLog.LogRsp(ThreadName,'echo, skipped');
  32.                 end
  33.               // indikace prichoziho hovoru v pripade, ze modem podporuje Voice
  34.               else if _RxDataRing(Line) then
  35.                 begin
  36.                   IOCLog.LogRsp(ThreadName,'ringing');
  37.                   _Ringing;
  38.                 end
  39.               // indikace volajiciho
  40.               else if _RxDataVoice(Line) then
  41.                 begin
  42.                   IOCLog.LogRsp(ThreadName,'Voice data recognized');
  43.                 end
  44.               // nevyzadana data, pozadat o jejich zpracovani
  45.               else if _RxDataUnsolicited(Line) then
  46.                 begin
  47.                   IOCLog.Log(ThreadName,cmltUns,'Unsolicited response');
  48.                   __RxAddUnsolicited(Line);
  49.                 end
  50.               // ignorovana data napr. RING, pokud neni podpora Voice
  51.               else if _RxDataIgnore(Line) then
  52.                 begin
  53.                   IOCLog.LogRsp(ThreadName,'ignored');
  54.                 end
  55.               // odezva na prikaz
  56.               else
  57.                 begin
  58.                   IOCLog.LogRsp(ThreadName,'response');
  59.                   _RxAddResponse(Line);
  60.                 end;
  61.             end
  62.           // Prompt, ktery neni ukoncen CR, napr. '> '. Je zkonvertovan na response
  63.           else if _RxDataPrompt(Data) then
  64.             begin
  65.               IOCLog.Log(ThreadName,cmltInp,''''+Data+'''');
  66.               IOCLog.LogRsp(ThreadName,'prompt');
  67.               _RxAddResponse(Data);
  68.               Data := sz;
  69.             end
  70.           // Fragment dat, docasne zapamatovat
  71.           else
  72.             begin
  73.               FRxTmpBuffer := Data;
  74.               Data := sz;
  75.             end;
  76.         end;
  77.     end;
  78.  

Offline Jirka

  • Hrdina
  • ****
  • Příspěvků: 390
  • Karma: 9
    • Verze Delphi: XE2
Re:AT příkazy z modemu - parsing v Delphi
« Odpověď #6 kdy: 11-03-2021, 15:34:09 »
obsluhuje pres overlapped I/O a kdyz prijme nova data, tak je plive do dalsi vrstvy.

Díky, snad mi to něco přinese ..

Offline Jirka

  • Hrdina
  • ****
  • Příspěvků: 390
  • Karma: 9
    • Verze Delphi: XE2
Re:AT příkazy z modemu - parsing v Delphi
« Odpověď #7 kdy: 12-03-2021, 17:38:14 »

while Data<>sz do

Mohu se zeptat jakou ulohu ma promenna "sz" ?

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 3139
  • Karma: 137
    • Verze Delphi: D2007, XE3, DX10
Re:AT příkazy z modemu - parsing v Delphi
« Odpověď #8 kdy: 12-03-2021, 18:04:27 »
Mohu se zeptat jakou ulohu ma promenna "sz" ?
To je literal definujici prazdny string tj. ''

Offline Jirka

  • Hrdina
  • ****
  • Příspěvků: 390
  • Karma: 9
    • Verze Delphi: XE2
Re:AT příkazy z modemu - parsing v Delphi
« Odpověď #9 kdy: 19-03-2021, 10:48:29 »
Už jsem přešel do fáze základního testování

Mám modem spuštěný  jak  TCP   Server  a posílám na něj z jednoho připojeného   klienta AT   příkazy ve smyčce s časovou prodlevou (třeba  200-1000 milisekund) mezi jednotlivými příkazy.   
Dá se říct že vše funguje, ale v některých případech se mi v odpovědi  vrátí znak "A"  který tam nemá co dělat .  Viz příklad na požadavek IMEI příjde odpověď
Kód: Delphi [Vybrat]
  1. AT+CGSN<cr>A<cr><lf>153605081160638<cr><lf><cr><lf>OK<cr><lf>

Kde může být problém ?
- třeba že moc tlačím na pilu s rychlostí opakování příkazů a  modem posílá něco co by neměl a v normálním provozu nebude ?
- nebo to může být problém modemu jako hardware  (třeba vnitřní komunikace mezi UART a  TCP) ?

.. Problém se vyskytuje  i u další software terminálů  .. takže se dá předpokladát že to modem skutečně posílá ..



Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 3139
  • Karma: 137
    • Verze Delphi: D2007, XE3, DX10
Re:AT příkazy z modemu - parsing v Delphi
« Odpověď #10 kdy: 19-03-2021, 11:50:36 »
- třeba že moc tlačím na pilu s rychlostí opakování příkazů a  modem posílá něco co by neměl a v normálním provozu nebude ?
- nebo to může být problém modemu jako hardware  (třeba vnitřní komunikace mezi UART a  TCP) ?
GSM telefony/modemy, to byvaly sr*cky nejsr*ckovatejsi, nicmene jen u Siemensu jsme pred kazdy command davali 100 ms prodlevu - co to bez ni delalo uz si napamatuju. Nektere byly citlive na rychlost pripojeni, takze jsme meli u nekterych v konfiguraci MAX/FIX DTE speed. Taky nektere nemely rady, kdyz se komunikovalo soucasne ze strany GSM site a soucasne ze strany pocitace - to se klidne cas od casu deadlocknuly a musel jsi jim odpojit napajeni, bezny reset nestacil.

Jestli se tam to A neobjevuje pravidelne, protoze norma 7.07 rika, ze SN je zpravidla jeden radek, ale muze to byt radku vic - zalezi na konkretnim vyrobci, tak bych videl problem na strane toho, kdo si stoupnul mezi TA a Tebe. Ciste pro sychr muzes zkusit, co se stane, kdyz pred kazdym prikazem udelas treba 2 s prodlevu. Jinak si nevzpominam, ze bychom u nektereho telefonu/modemu neco podobneho resili, ale uz je to hafo let, co se tim nekdo zabyval.



Offline Jirka

  • Hrdina
  • ****
  • Příspěvků: 390
  • Karma: 9
    • Verze Delphi: XE2
Re:AT příkazy z modemu - parsing v Delphi
« Odpověď #11 kdy: 19-03-2021, 12:20:13 »
Příkaz v cyklu o vrácení IMEI  a do toho volání na modem  (RING a CLI)

Test 1
200 příkazů v cyklu  - Sleep(250)
Proběhlo 300 čtení přes SockKlient.RecvPacket(5000);
"A" vráceno 2x

Test 2
200 příkazů v cyklu  - Sleep(2000)
Proběhlo 280 čtení přes SockKlient.RecvPacket(5000);
"A" vráceno 0

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 3139
  • Karma: 137
    • Verze Delphi: D2007, XE3, DX10
Re:AT příkazy z modemu - parsing v Delphi
« Odpověď #12 kdy: 19-03-2021, 13:20:19 »
200 příkazů v cyklu  - Sleep(250)
Proběhlo 300 čtení přes SockKlient.RecvPacket(5000);
"A" vráceno 2x
Hm, to tam maji nejakou race condition - to bych se obratil na vyrobce modemu, co k tomu rekne - poslal bych jim I/O log klidne ze vsech 300 cteni

Offline Jirka

  • Hrdina
  • ****
  • Příspěvků: 390
  • Karma: 9
    • Verze Delphi: XE2
Re:AT příkazy z modemu - parsing v Delphi
« Odpověď #13 kdy: 19-03-2021, 14:00:43 »
Hm, to tam maji nejakou race condition - to bych se obratil na vyrobce modemu, co k tomu rekne - poslal bych jim I/O log klidne ze vsech 300 cteni
Tady toto je nějaký Cinteron od https://www.seapraha.cz/produkt/gsm-bgs5-een/?target=popis_produktu
Příští týden si chci pořídit  SIM800L  a vyzkoušet komunikaci tam

Existují  nějaké univerzální AT  příkazy pro "studený restart"  či "tovární" nastavení  modemu ?

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 3139
  • Karma: 137
    • Verze Delphi: D2007, XE3, DX10
Re:AT příkazy z modemu - parsing v Delphi
« Odpověď #14 kdy: 19-03-2021, 14:32:02 »
Existují  nějaké univerzální AT  příkazy pro "studený restart"  či "tovární" nastavení  modemu ?
Vetsina modemu vychazi ze sady prikazu modemu Hayes, s kompatibilitou to byva horsi, takze reference manual ke konkretnimu modemu, pokud existuje. Kdyz se divam do nasich konfiguraci telefonu/modemu, tak jsme vetsinou vychazeli z Resetu, nacteni profile #0, zapnuti ukecaneho rezimu a vypnuti echa (pokud si to dal vypnout), tj. nejaka varianta
Kód: Delphi [Vybrat]
  1. ATZ^MAT&FX3V1E0^M
ale dost se to lisi, treba nejake ty posledni Siemens moduly jsme iniciovali
Kód: Delphi [Vybrat]
  1. ATZ^MATV1E0+CLIP=1^MAT+CMEE=2^M
a separatne jsme nastavovali +FCLASS (faxovani & spol.)

Ale pred tim jsme zavesovali, vyprazdnovali buffery apod., ruzne cekali, v pripade brutalni formy i rusili a vytvareli thready a objekty pro obsluhu portu a teprve nakonec odeslali nejaky rezec z konfigurace jako ty, co jsme uvedl.