[megoldva] RXTX olvasott válasz rövid

Fórumok

Sziasztok!

Van egy kódom, ami egy USB relépanelre küld parancsokat és a válaszokat kiolvassa.

Szintakszis:

parancs:

command\r

válasz:

command\r
reply\r
>

tehát visszaküldi a parancsot magát, új sorban a választ, megint új sorban egy > jelet.

A dev PC-men tökéletes, illetve még két virtuális gépen kipróbálva szintén jól működött.

Példa a helyes működésre:

Küldés:

gpio read 0\r

Helyes válasz:

gpio read 0\r
1\r
>

Ami a target gépen jön vissza:

gpio read 0

Magyarán a stream véget ér, és csak az elküldött válasz visszatolásáig jut el.

Maga a kód:

public static String command(String command) throws Exception {
byte[] buffer = new byte[1024];
int len = 0;
out.flush();
try{
out.write(command.getBytes());
out.write('\r');
out.flush();
int data;
Thread.sleep(100);
while (in.available() > 0)
{
data = in.read();
if ( (char) data == '>') {
break;
}
buffer[len++] = (byte) data;
}

} catch (IOException ex){
}
return new String(buffer);
}

Néhány hasznos param:

dev gép:


kernel: 3.11.0-12 generic
java version: 1.7.0_51 OpenJDK IcedTea 2.4.4, 7u51-2.4.4-0ubuntu0.13.10.1

cél gép:

kernel 3.7.1-030701-generic
java version: 1.7.0_55 OpenJDK IcedTea 2.4.7, 7u55-2.4.7-1ubuntu1~0.12.04.2

Mindkét esetben a használt jar: RXTX-2.2-pre2

Nekem valami rendszerszintű változtatásnak tűnik, amit az RXTX natív kódrésze nem jól kezel. Nem vagyok egy túl nagy Java manó, de ez a kód azt csinálja, amit kell (direkt nem nonblocking vagy event vezérelt), viszont sajnos pont a cél rendszeren nem jó.

Bárki bármi ötlet mond, már segített!

Hozzászólások

Kivehetned a try-catchet, hogy kideruljon van -e io exception. Masreszt tehetnel bele sys out println-t (vagy debuggolj), hogy kideruljon azert lep ki a while-bol mert mar nincs mit olvasni vagy mert elerte a '>'-t?

Biztos, hogy ez jol mukodik a dev gepen? Mert szerintem ez a metodus, amit bemasoltal, se nem irja ki a '>'-t a kimenetre, se nem tarolja el a buffer-be.

Tovabba: mi a default character encoding a kulonbozo gepeken? Mert nem adod meg explicit a String kosntruktornak es igy a JVM a system defaultot fogja hasznalni.

Mintha az utolso new String() objektum letrehozasnal a string hossza mint olyan nem adodik rendesen a't. a buffer ugye egy 1024 elemu" to"mb. abbol csinalhasz stringet, de igazabol semmilyen info nem megy a't hogy az tenylegesen milyen hosszu. illetve a buffer[]-ben maga a leza'ro' ">" karakter sem lesz benne, merthogy ugye nem teszed bele.

Voltak benne print-ek, és az alapján sem jutottam közelebb a megoldáshoz. Igazatok van abban, hogy a végén nem ennyire egyszerű a byte array átadása, ez is meg van oldva, csak az bonyolítja a kódot, ami a probléma szempontjából felesleges, ezért gyorsan kicseréltem erre az egy sorra.

Nem az a baj, hogy a > karaktert nem veszi észre, hanem hogy nem is jön be a bufferbe, legalábbis látszólag. Minden egyes read után sysout-olva az látszik, hogy megáll a történet a kiküldött parancs visszaolvasásánál, és kész. Most debuggolom megint, ha találok valami értelmeset, leírom ide. Köszi az eddigi segítséget!

Az in.available-s feltetel nem annyira jo. A soros vonal altalaban definite lassabb mint egy mai modern gep. Mondjuk ezelobbi 9600 baud (kabe 1kbyte/sec), ezutobbi meg ugye joval gyorsabb feldolgozast tesz leheto"ve'. A soros vonal kezelo"k fifo-ja is ve'ges, arra se erdemes bazirozni hogy az mondjuk 16 byte-nal nagyobb.

Egy ilyesmi algoritmus (master-slave UART kommunikacio) tehat inkabb igy nezzen ki":


uart.send(command,command_length);
t0=time();
while ( time() < t0+timeout )
 {  while ( uart.available() )
     {   buffer[len++]=uart.getchar();
     }
    if ( data_is_ready(buffer,len) )
         break;
    dsleep(10.0/baud_rate);
 };
if ( data_is_ready(buffer,len) ) 
   have_fun();
else
   timeout_exception();

Na'lad a data_is_ready() az kabe ilyesmi lehet:


data_is_ready(buffer,len)
 {   if ( 0 < len && buffer[len-1]=='>' )
         return(true);
     else
         return(false);
 }

Nyilvan a mindez megf programnyelven ;] Ha ez a programnyelv tamogat egy C select()-hez hasonlo megoldast, akkor az lenne az igazi. Ha nem, akkor a fenti megoldas sem rossz, a busy wait jellege miatt, tekintve hogy a baudrate meg a szamitogep sebessege kozott van egy jopa'r nagysagrend (mondjuk 5-6).

A timeout-ot meg erdemes ugy beallitani hogy az adott baud rate e's a vart valasz hosszanak a szorzata szorozva mondjuk 40-nel. Marmint ezt akkor ha a hardver azonnal valaszol (ami na'lad eselyes). Pl 9600 baud + 20 karakternyi valasz eseten 1 sec az teljesen jo.

Próbáltad a Thread.sleep-et nagyobbra állítani? Bár a kódból nem derül ki mi is az, de lehet valami lassabb a másik gépen :)

Köszönöm mindenkinek a válaszokat! Teljesen jogos volt az időzítésre hajazás. Majdnem ez volt a gond, de végül mégsem. CR helyett LF CR a sorvége, és ez a dokumentációban nem szerepelt. A különbség amúgy a dev és test PC-k meg az igazi gép között az volt, hogy előbbiek VirtualBox-ban futottak, utóbbi meg fizikai vas. Hogy miért okozott ez így gondot, illetve a fizikai vason miért működött úgy, hogy a parancsot végrehajtotta, csak választ nem küldött, na az rejtély marad, viszont most jó, úgyhogy tanulság leszűrve, a helpet meg köszönöm :)