Saving btmon output - java

This is my first post here, although I've been reading stuff here for quite some time :)
I'm currently doing my bachelor thesis in computer science where we're doing an Indoors-positioning thing with iBeacons and Bluetooth. Where the device "being found" is currently a Raspberry Pi due to complications with smartphones.
I've got a bit of a problem with the btmon command on my Raspberry Pi. The full structure of our program is as follows:
Scan for bluetooth devices (iBeacons)
Save the output result <---- Here's the problem
Filter the desired data
Send to server node
As this is a part of a program we're building, the commands are executed through Java code that executes the terminal command, and returns the output as a String. The method looks like this:
private String executeCommand(String command) {
StringBuffer output = new StringBuffer();
Process p;
try {
p = Runtime.getRuntime().exec(command);
p.waitFor();
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
while ((line = reader.readLine()) != null) {
output.append(line + "\r\n");
}
} catch (Exception e) {
e.printStackTrace();
}
return output.toString();
}
I've got everything working when using another command (such as ifconfig) so the method works for ordinary commands, but I can't get it to work with btmon.
The full command I'm trying to run is this:
sudo btmon & sudo hcitool lescan
It seems to me as if btmon is running as a different process/runtime which would explain why the above Java code doesn't catch its output. I've been trying to "get" the btmon runtime but have failed to do so, and I've been trying to use ProcessBuilder with inheritIO() to change it's output source but couldn't get that to work either...
I've been googling this for a couple of days by now, and I've bumped into a couple of Python scripts that I can't get to work either (probably because I've never used Python before ^^).
So, in short: How do I save the output of sudo btmon & sudo hcitool lescan? Preferably to a String through Java code, but saving it as a file would also work!
Thanks in advance! :)

I got the same problem and spent many days to solve this issue. The key point was Thread and not using &. Here is what I discovered:
& literally runs in the background. Change sudo btmon & to sudo btmon
Use Thread.
Thread 1 - start btmon (You can get result this Thread)
Thread 2 - start hcitool lescan
(btmon should first - because "lescan" occur hci events so btmon can get them) Summary - do not use & and use independent thread.

Related

Recreating Linux traceroute for an Android app

I am extremely new the Android app development and Stack Overflow. I am trying to recreate traceroute in an Android app since Android devices do not come with traceroute by default. I've encountered a couple stack overflow posts talking about solutions to this, but I have still run into challenges.
Traceroute on android - the top post on this thread links an Android Studio project that implements traceroute using ping. If I understand the algorithm correctly, it continually pings the destination IP, incrementing the time-to-live field to obtain information about intermediary routers. I've tried to recreate this behavior, but for certain values of TTL, the ping stalls and doesn't retrieve any router information. I'm not really sure why this happens. Here's a quick demo function I spun up... at some point in the loop the pings stall.
public static void smallTracerouteDemoShowingThatTheProgramStallsAtCertainTTLs() {
try {
String host = "google.com";
int maxTTL = 20;
for (int i = 1; i < maxTTL; i++) {
// Create a process that executes the ping command
Process p = Runtime.getRuntime().exec("ping -c 1 -t " + i + " " + host);
// Get a buffered reader with the information returned by the ping
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
// Convert the BufferedReader to a string
String dataReturnedByPing = "";
for (String line; (line = br.readLine()) != null; dataReturnedByPing += "\n"+line);
// Print out information about each TTL
System.out.println("TTL = " + i + " out of " + maxTTL);
System.out.println(dataReturnedByPing);
System.out.println("========================================");
}
} catch (Exception e) {
e.printStackTrace();
}
}
how to run traceroute command through your application? - The solution on this thread suggests using BusyBox. I've not used BusyBox as yet, but it seems like I would have to embed BusyBox into my app to get things to work. After doing some research it looks like BusyBox provides numerous Linux commands through one executable. I'm a bit hesitant to explore this option because I really only need the traceroute command. In addition, I know that Android targets a few different CPU architectures, and I'm not sure if one executable will support them all.
I've also run into a github repository that takes another approach to running traceroute:
https://github.com/wangjing53406/traceroute-for-android - In this repository the author embeds the traceroute source code into the project and uses the NDK to build the source code along with the rest of his app. I really like this approach because it feels the most "correct." It uses a built traceroute instead of a Java-based implementation, so you can't find yourself in a situation where the Java implementation gives you one thing and the actual traceroute gives you another. When I open this project to experiment with it, my build fails. The top line says:
org.gradle.initialization.ReportedException: org.gradle.internal.exceptions.LocationAwareException: A problem occurred configuring root project 'traceroute-for-android-master'.
Any help on why this happens or ways to troubleshoot it would be fantastic.
For reference, the minimum SDK I am targeting is API 21 and I am running on Android Studio 3.3.0.
So, at this point I'm stumped. If you were trying to make an app that would let you execute traceroute commands, how would you do it? I really like the NDK approach because it guarantees you're getting true traceroute behavior. If you have any guides to getting that set up for my Android version/SDK, I would appreciate if you would post them. If you'd take another approach I'd to hear about it as well.
Thank you in advance.

Java jar execution stuck when launched in a process by another java program

This is a very unusual problem I've come across and I'm hoping someone might have some insight on it. I'm on macOS Mojave (10.14.6), using Amazon's JRE Corretto-11.0.9.12.1 (build 11.0.9.1+12-LTS)
I have a program I've written that is something of a scripting engine that we use to do our routine bulk data processing. It takes an xml "script" file which contains the processing directions to execute and a list of input files as arguments. I'll refer to this as the "engine" from this point on. This engine is the backbone of a large portion of our automation. It shows a progress bar while processing to let users know that it is working.
There are 2 programs that use this engine:
One is a thin UI written in Swing, which we use to manually process data; it generates an xml file from the user input and passes it along with the input files and launches the engine in a separate process; the UI itself doesn't process any data.
The other watches a folder on our file server and processes incoming data from our clients daily when a folder is created inside of it so we can rip the data into our database. I'll call this the "importer".
Recently, a problem has come up where the engine becomes stuck while processing. Older versions of the engine did not have this problem, and I'm trying to figure out what exactly changed that caused this to happen, but while I've been trying to do this, our UI and importer programs have been using and older version of the engine. There are new features that we need to use in the new version of the engine, but we can't use it until this problem is solved.
The programs that uses the engine launch it in a process then waits for the result before continuing:
// example command generated from external program
String commandString = "java -jar engine.jar script.xml input_file1.txt input_file2.txt input_file3.txt";
String[] command = {"bash", "-c", commandString};
// I can grab the command from here for debugging
System.out.println(Arrays.toString(command));
ProcessBuilder pb = new ProcessBuilder(command);
// wait for the process to complete before continuing
Process p = pb.start();
p.waitFor();
int result = p.exitValue();
try (BufferedReader e = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
BufferedReader i = new BufferedReader(new InputStreamReader(proc.getInputStream()))) {
String line;
while ((line = e.readLine()) != null) {
System.out.println(line);
}
while ((line = i.readLine()) != null) {
System.out.println(line);
}
}
p.destroy();
// do other stuff
When launched in this way, there is a specific operation that causes the engine to hang. But if I take the command and launch it directly from the command line, the engine runs just fine! This is making it difficult to pin down where exactly the problem is; is it in the engine, or in the other programs? I've spent a couple of days looking for answers and come up with nothing. It's even more frustrating that this problem has appeared seemingly out of nowhere when it was working perfectly before, using the exact code above, for a quite a long time.
The operation where the engine hangs sorts files into folders based on their file names. When I watch my activity monitor while it runs, it's not taxing my resources at all, and disk space isn't an issue. It isn't a file permission issue, as the engine is creating files and folders all the time and in every step leading up to the step where it hangs. And as I said, if I run the command directly from the command line, it creates the folders and sorts the files without issue, to my extreme confusion.
The importer and UI run locally on a station, but the engine jar file lives on our file server, so that it is accessible to every station without individually downloading it everywhere each time there is an update. I thought at first that the issue might lie in the fact that it is being accessed over the network, but the problem occurs even when I use a local copy of the engine on my dev machine, so I have ruled that out. I've also ruled out that it's the JRE, even though we switched to it recently, since the older version of the engine still perform as expected.
There might of course be any reason why your 'engine' program may hang ;-) but certainly it will hang you don't read the its output, and in the right way:
The parent process needs to read the standard output and standard error streams of the child process, given that the child process does generate any substantial amount of output on any of these two channels. This must be done in two separate background threads. If the parent does not read the child's output, then the child process will block as soon as the (small) buffer between the processes is filled up.
The threads should be started as soon as the child process is started, and before the parent calls process.waitFor().
The simplest way to do this is the following:
Process process = processBuilder.start();
InputStream stdout = process.getInputStream();
InputStream stderr = process.getErrorStream();
Thread stdoutThread = new Thread() {
#Override
public void run() {
// read stdout here, e.g.
try {
int c;
while (-1 != (c = stdout.read())) {
// do whatever with c
}
} catch (IOException ioex) {
// ...
}
}
};
Thread stderrThread = new Thread() {
// ... same as for stdout
};
stdoutThread.start();
stderrThread.start();
}
Only after both threads have been started you may wait for the child process and join the threads:
int exitValue = process.waitFor();
stdoutThread.join();
stderrThread.join();
There might be more sophisticated ways to work with background threads using the Concurrency Framework introduced in Java 5, but this basic code gives the idea.

How to execute a linux terminal command from LUAJ?

I want to simply execute a linux terminal command like ls from LuaJ and the result that it will return or anything that returns i want to receive it and will show the names in the Java Gui. I searched but found this but not one with LuaJ.
Is there any function to execute the terminal command from LuaJ ??
There are multiple ways to do this, for one, you can implement it yourself in Java then link it to LuaJ.
LuaFunction command = new OneArgFunction()
{
public LuaValue call(LuaValue cmd)
{
Process p = Runtime.getRuntime().exec("/bin/sh", "-c", cmd.checkstring());
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
int returnCode = p.waitFor();
return LuaValue.valueOf(returnCode);
}
}
globals.set("command", command);
Then in Lua:
local code = command("ls");
The problem with actually getting the output of a command is that you can't just have a fixall solution. For all the system knows you could be calling a program which runs for 2 hours generating constant output, which could be an issue, not to mention if the program requires input. If you know you're only going to use certain functions you can make a dirty version of above function to capture the output from the stream and return it all instead of the exit code, just don't use it on other processes that don't return quickly. The other alternative is to create a class that wraps the input and output streams from the process and return a coerced version of that class, and manage the input and output from lua.
Lua does have a function that's part of the OsLib called execute(), if execute doesn't exist in your current environment then in Java call:
globals.load(new OsLib());
Before loading the lua code. the os.execute() function returns the status code, and doesn't return the streams, so no way to get the output there. To get around this you can modify the command to pipe the output to a temp file and open it with the io library (new IoLib() if doesn't exist in current environment).
The other option is to use io.openProcess, which also executes the command and returns a file to read the output from.
Resources:
http://luaj.org/luaj/3.0/api/org/luaj/vm2/lib/OsLib.html
http://luaj.org/luaj/3.0/api/org/luaj/vm2/lib/IoLib.html

How to call a bash script from GWT-RPC server (Java)

I want to call a bash script from GWT server
I coded up my first application with GWT/RPC, and I need to call a bash script on the server side (from MyOwnServiceImpl extends RemoteServiceServlet implements MyOwnService).
ProcessBuilder doesn't work
To do that, I confess that I am using java.lang.ProcessBuilder, which is apparently "not supported by GAE" (I just ignored the warning). As it is running on the server side, it seemed to me that it should work anyways. I feel that I am missing something.
Something seems to be preventing the call from being executed, even though the required packages are correctly imported, the binaries are found, the execution doesn't crash. But the call is just not successful (for example even mkdir is not executed on the server).
Related posts weren't much help...
How to execute a Unix shell script via GWT? (does not give a complete answer, and I could not simply comment on the answer)
GWT + ProcessBuilder (mentions precisely the solution I implemented which is not working for me, see above)
Any thoughts on this would be much appreciated, thanks!
In a GWT application without GAE you can use Runtime.getRuntime().exec("some command");
If you want to read out the result of the command, you can use:
Process p = Runtime.getRuntime().exec("A command");
BufferedReader in = new BufferedReader(new InputStreamReader(p.getErrorStream()));
StringBuilder builder = new StringBuilder();
String line = null;
while ((line = in.readLine()) != null) {
builder.append(line + "\n");
}
String result = builder.toString();
If the command above should not work, i guess you have to remove GAE from your project to run a bash script.
you can call bash script with GWT,if your servet side on your computer.
the limit is GAE for secury. no way to cross this limit.

Java & Windows 7: Reliably getting IPv4 netmask?

I've run into a known bug with Java 6 on Windows. My understanding is that the normal way to get the netmask is to look up the network prefix length and do some bit shifts. The problem is that on Windows the prefix length is often returned incorrectly, so we get a 128 when we should get a 24 or 20.
In this solution, it is suggested to put -Djava.net.preferIPv4Stack=true on the Java command line. Unfortunately, on Windows 7, adding that as either a VM parameter or on the Java command line seems to have no effect.
(a) Does anyone know any OTHER work-arounds for this problem that might still work on Windows 7?
(b) Alternatively, is there an entirely different way to get the netmask that is reliable?
Thanks!
P.S. Here is the bug report that pertains to this.
The -Djava.net.preferIPv4Stack=true VM option should work under any OS. Alternatively, it can be put into Java code as System.setProperty("java.net.preferIPv4Stack","true");. Unless, something (library or whatever) is resetting its true state.
The code below displays the subnet mask. On a computer with more than one network connection (like a laptop with a wireless and Cat-5 Ethernet connection) it may write the subnet mask twice because there can be two different IP addresses for the client.
String os = System.getProperty("os.name");
try {
if(os.indexOf("Windows 7")>=0) {
Process process = Runtime.getRuntime().exec("ipconfig");
process.waitFor();
InputStream commandOut= process.getInputStream();
BufferedReader in = new BufferedReader(new InputStreamReader(commandOut));
String line;
while((line = in.readLine()) !=null) {
if(line.indexOf("Subnet Mask")>=0) {
int colon = line.indexOf(":");
System.out.println(line.substring(colon+2));
}
}
}
catch(IOException ioe) { }
catch(java.lang.InterruptedException utoh) { }
On my laptop with both a wired and wireless connection active, I get this output:
255.255.254.0
255.255.254.0
When I turn off my wireless connection, I only see one line of output for the wired Ethernet link, as expected.
Since the problem us just in Windows 7, why not look for an OS specific solution?
I know we can launch windows programs from Java, including the windows command line or bat files. There must be a way to re-direct the output of ipconfig to a text file in windows. Your program should be able to get the subnet mask by calling ipconfig and then reading the output.

Categories