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!
- 4925 megtekintés
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.
- A hozzászóláshoz be kell jelentkezni
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.
- A hozzászóláshoz be kell jelentkezni
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!
- A hozzászóláshoz be kell jelentkezni
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.
- A hozzászóláshoz be kell jelentkezni
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 :)
- A hozzászóláshoz be kell jelentkezni
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 :)
- A hozzászóláshoz be kell jelentkezni