Forum Delphi.cz

Delphi => Obecné => Téma založeno: Jirka 02-03-2021, 13:02:31

Název: AT příkazy z modemu - parsing v Delphi
Přispěvatel: Jirka 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# 
Název: Re:AT příkazy z modemu - parsing v Delphi
Přispěvatel: Radek Červinka 02-03-2021, 14:33:55
Třeba https://github.com/Zeus64/alcinoe/blob/master/source/ALGSMComm.pas
Název: Re:AT příkazy z modemu - parsing v Delphi
Přispěvatel: Radek Červinka 02-03-2021, 14:35:25
Nebo hledej klicove slovo PDU, bohuzel ti nemuzu dat nas kod.
Název: Re:AT příkazy z modemu - parsing v Delphi
Přispěvatel: Jirka 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...)
Název: Re:AT příkazy z modemu - parsing v Delphi
Přispěvatel: Jirka 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;
Název: Re:AT příkazy z modemu - parsing v Delphi
Přispěvatel: pf1957 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.  
Název: Re:AT příkazy z modemu - parsing v Delphi
Přispěvatel: Jirka 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 ..
Název: Re:AT příkazy z modemu - parsing v Delphi
Přispěvatel: Jirka 12-03-2021, 17:38:14

while Data<>sz do

Mohu se zeptat jakou ulohu ma promenna "sz" ?
Název: Re:AT příkazy z modemu - parsing v Delphi
Přispěvatel: pf1957 12-03-2021, 18:04:27
Mohu se zeptat jakou ulohu ma promenna "sz" ?
To je literal definujici prazdny string tj. ''
Název: Re:AT příkazy z modemu - parsing v Delphi
Přispěvatel: Jirka 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á ..


Název: Re:AT příkazy z modemu - parsing v Delphi
Přispěvatel: pf1957 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.


Název: Re:AT příkazy z modemu - parsing v Delphi
Přispěvatel: Jirka 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
Název: Re:AT příkazy z modemu - parsing v Delphi
Přispěvatel: pf1957 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
Název: Re:AT příkazy z modemu - parsing v Delphi
Přispěvatel: Jirka 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 (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 ?
Název: Re:AT příkazy z modemu - parsing v Delphi
Přispěvatel: pf1957 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.

Název: Re:AT příkazy z modemu - parsing v Delphi
Přispěvatel: Jirka 19-03-2021, 14:42:28
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

No nazdar :-)

Díky bohu mě se v praxi bude jednat v 80 % odesílání SMS  a 20%   přijimání  SMS.
Takže mě jde hlavně o to, že když budu v dávce odesilat SMS tak během toho odchytit nevyžádané oznámení (RING, CLIP atd.) a odfiltrovat tak
aby mi to nenarušilo vyhodnocení   komunikace SMS, například jestli  mi přišel '> ' 
Název: Re:AT příkazy z modemu - parsing v Delphi
Přispěvatel: pf1957 19-03-2021, 14:51:28
odesilat SMS tak během toho odchytit nevyžádané oznámení (RING, CLIP atd.)
CLIP se da u nekterych vypnout, jestli RING uz si nepamatuju. Ale je otazka, jestli to ma pracovat jen s vybranymi/otestovanymi zarizenimi nebo by to melo fungovat s kde cim.

A jeste pozor na odesilani SMS s pozadavkem na potvrzeni: SMS v GSM siti pouzivaji signalni kanal, ktery je poloduplexni, takze kdyz odesilas batch a SMSC ti do toho zacne posilat dorucenky, obcas se to vlivem poloduplexu rozpadne, takze je treba resend jak na tvoji strane, tak na strane SMSC, ktere navic pouziva exponencialne rostouci prodlevy u retry, takze se ty dorucenky pak mohou trousit docela s velkym zpozdenim.
Název: Re:AT příkazy z modemu - parsing v Delphi
Přispěvatel: Radek Červinka 19-03-2021, 15:27:20
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 (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 ?

Celkem by mohl zafungovat AT+CFUN=1 ( u nekterych modemu to pouzivame, ale celkove jak pise PF je to magie).
Kukni sem: https://m2msupport.net/m2msupport/atcfun-set-phone-functionality/
Název: Re:AT příkazy z modemu - parsing v Delphi
Přispěvatel: Jirka 19-03-2021, 17:55:16
Celkem by mohl zafungovat AT+CFUN=1 ( u nekterych modemu to pouzivame, ale celkove jak pise PF je to magie).
Možnosti  +CFUN: (0,1,4,6,7,8),(0-1)
Aktuální nastavení  +CFUN: 1,0
Název: Re:AT příkazy z modemu - parsing v Delphi
Přispěvatel: Jirka 23-03-2021, 20:43:20
Řekl by mi někdo která syntaxe je správná ? Díky
Modem Cinterion
Příkaz AT
Odpověd AT<cr><cr><lf>OK<cr><lf>

Modem SIMCOM   - model SIM900
Příkaz AT
Odpověd AT<cr><lf><cr><lf>OK<cr><lf>



Název: Re:AT příkazy z modemu - parsing v Delphi
Přispěvatel: pf1957 23-03-2021, 21:38:42
Vypni si echo
Název: Re:AT příkazy z modemu - parsing v Delphi
Přispěvatel: Jirka 23-03-2021, 21:50:37
Vypni si echo

Echo bych si rád ponechal, ale ted jsem díval do https://drive.google.com/file/d/0B4B30jzMyzG8aUpIOVpRVFpaTXM/view (https://drive.google.com/file/d/0B4B30jzMyzG8aUpIOVpRVFpaTXM/view)
a píší že stačí pro odeslání AT zadat jen <CR>  a já zadával <CR><LF> stejně jako do modemu Cinetrion (prý bývalý Siemens)  a tam mi to procházelo.
Název: Re:AT příkazy z modemu - parsing v Delphi
Přispěvatel: pf1957 24-03-2021, 06:13:15
a píší že stačí pro odeslání AT zadat jen <CR>  a já zadával <CR><LF> stejně jako do modemu Cinetrion (prý bývalý Siemens)  a tam mi to procházelo.
No jasne, protoze echo slouzi pro pripad, ze zadavas prikazy z klavesnice a tam prikaz ukoncujes klavesou Enter, ktera posila samotne CR, coz je spravna syntaxe prikazu. Na to, jestli modem akceptuje i LF bych se nespolehal.

Ale protoze se z prapodivnych duvodu na nekterych platformach jako oddelovac radku prezila posloupnost CR+LF z doby el. psacich stroju, kde se skutecne jednim znakem (CR) sepnula spojka, ktera tahla vozik doprava a dalsim (LF) se pootacelo valcem a u nekterych stroju se to z duvodu zrychleni operace posilalo obracene tj. LF+CR, tak je v tom bordel.

V jedne z prvnich odpovedi jsem ti psal, ze LF pri prijmu vypoustime a jako oddelovac radku pouzivame jen CR. Prikazy zadavane modemu ukoncujeme jen CR.

Název: Re:AT příkazy z modemu - parsing v Delphi
Přispěvatel: Jirka 24-03-2021, 09:30:43
Tu informaci o používání <CR><LF> jako celku jsem někde odchytil  a tak jsem to bral jako požadované pravidlo

Citace
No jasne, protoze echo slouzi pro pripad, ze zadavas prikazy z klavesnice a tam prikaz ukoncujes klavesou Enter, ktera posila samotne CR, coz je spravna syntaxe prikazu. Na to, jestli modem akceptuje i LF bych se nespolehal.

Už jsem to  předělal na čisté <CR>  , jak jsem včera večer zjistil , tak i Cinterion v dokumentaci uvádí pro ukončení příkazu čisté  <CR>

Citace
V jedne z prvnich odpovedi jsem ti psal, ze LF pri prijmu vypoustime a jako oddelovac radku pouzivame jen CR. Prikazy zadavane modemu ukoncujeme jen CR.

Tu filtraci jsem na začátku taky používal ale dělalo mi to bordel, tak jsem to filtrovani vynechal  - ale je klidně možné že ten "bordel" mi dělalo to přidávané <LF>
Název: Re:AT příkazy z modemu - parsing v Delphi
Přispěvatel: Jirka 26-03-2021, 10:58:36
Na odeslaní SMS používám Synaser.SendString()
Pokud posílam text SMS bez nového odstavce tak je vše v pořádku
ale pokud zadám Enter,
memo komponenta mi tam vkládá<CR><LF> tak  to skončí na timeoutu,
vypadá to tak že SendString odešle tu část textu před odstavcem  a s tím zbytkem má problém.
Je nějaká cesta jak z toho ven a posílat SMS i s odstavcem ?
Název: Re:AT příkazy z modemu - parsing v Delphi
Přispěvatel: pf1957 26-03-2021, 12:16:58
Na odeslaní SMS používám Synaser.SendString()
Pokud posílam text SMS bez nového odstavce tak je vše v pořádku
ale pokud zadám Enter,
memo komponenta mi tam vkládá<CR><LF> tak  to skončí na timeoutu,
vypadá to tak že SendString odešle tu část textu před odstavcem  a s tím zbytkem má problém.
Pokud tam nejak necarujes, tak to vypada na problem s kompatibilitou modemu, protoze podle GSM 3.38 jsou CR i LF akceptovane znaky a odesilany text se ukoncuje ^Z.

Citace
Je nějaká cesta jak z toho ven a posílat SMS i s odstavcem ?
Opustit Text mode a prejit na PDU, pokud to zarizeni zvlada? My jsme Text mode pouzivali jen tam, kde skutecne nebylo zbyti, protoze modem mel problemy s PDU.



Název: Re:AT příkazy z modemu - parsing v Delphi
Přispěvatel: Jirka 26-03-2021, 12:27:29

Citace
Pokud tam nejak necarujes, tak to vypada na problem s kompatibilitou modemu, protoze podle GSM 3.38 jsou CR i LF akceptovane znaky a odesilany text se ukoncuje ^Z.

Já jsem spíše myslel jestli  ten SendString nenarazí na první CRLF  začne ho zpracovávat a ten zbytek zprávy s tím ^Z. už nevezme a tím pádem to spadne ..

 PDU bych se alepoň v této fázi vyhnul (jsem rád že to mohu ladit v textu a ne  v Hexa a 7bit - což jsem nikdy  nepotkal )
Teď zkouším SendBuffer, ale tam mi neprojde nic ..

 
Název: Re:AT příkazy z modemu - parsing v Delphi
Přispěvatel: pf1957 26-03-2021, 14:21:58
Já jsem spíše myslel jestli  ten SendString nenarazí na první CRLF  začne ho zpracovávat a ten zbytek zprávy s tím ^Z. už nevezme a tím pádem to spadne ..
Vzdy mas zdrojovku ne? SendString vola jen SendBuffer a ten si obsahu nevsima
Název: Re:AT příkazy z modemu - parsing v Delphi
Přispěvatel: Jirka 26-03-2021, 15:15:39
Tady měli podobný problém ...
https://stackoverflow.com/questions/20092649/howto-properly-parse-response-data-received-from-gsm-module/20096236#20096236 (https://stackoverflow.com/questions/20092649/howto-properly-parse-response-data-received-from-gsm-module/20096236#20096236)

Doplněno:    Pomohla náhrada  CRLF za LF
Název: Re:AT příkazy z modemu - parsing v Delphi
Přispěvatel: pf1957 26-03-2021, 19:45:01
Tady měli podobný problém ...
https://stackoverflow.com/questions/20092649/howto-properly-parse-response-data-received-from-gsm-module/20096236#20096236 (https://stackoverflow.com/questions/20092649/howto-properly-parse-response-data-received-from-gsm-module/20096236#20096236)

Doplněno:    Pomohla náhrada  CRLF za LF
Dival jsem se do normy a spravne chovani vypada tak, ze jakmile prijme v datech CR, tak zobrazi dalsi prompt "> " a ceka na dalsi text -> proto ti to zustane viset. Podivej se do GSM 7.05, kde je v kapitole 3.5.6 priklad odesilani textu na nekolik radku v textovem rezimu.
Název: Re:AT příkazy z modemu - parsing v Delphi
Přispěvatel: Radek Červinka 14-04-2021, 16:00:39
Jinak k tomu CFUN a resetu modemu pro zajimavost - https://stackoverflow.com/a/44034293/268106

There seems to be a generally used or defacto standard AT command for turning off and turning on a USB cellular modem.

To turn the modem off use: AT+CFUN=0 and to turn the modem on use: AT+CFUN=1. The AT command must be terminated by a carriage return and it must be sent through the Virtual Serial Port that is assigned to the USB modem.