I setup using Java using BlueJ and Bluetooth using Blueman on my RaspberryPI and am using the BlueCove API.
I took the example RemoteDeviceDiscovery from:
http://bluecove.org/bluecove/apidocs/overview-summary.html#DeviceDiscovery
When I run the example from within BlueJ I get:
"
wait for device inquiry to complete...
Device Inquiry completed!
0 device(s) found
"
and when I run from the terminal window using:
pi#raspberrypi ~/java/bluetooth_jar $ /usr/lib/jvm/jdk-8-oracle-arm-vfp-hflt/jre/bin/java -jar bluetooth_jar.jar
I get:
"
BlueCove version 2.1.1-SNAPSHOT on bluez
BluetoothStateException exception: javax.bluetooth.BluetoothStateException: Bluetooth Device is not ready. [1] Operation not permitted
BlueCove stack shutdown completed
"
Why the exception is not thrown when using BlueJ I don't understand but from the commandline it appears unable to detect nearby devices because the device is not ready. However, I don't understand this error message since I can send files using Blueman Manager to nearby a Android tablet and Win7 laptop.
import java.io.IOException;
import java.util.ArrayList;
import javax.bluetooth.*;
/**
* Minimal Device Discovery example.
*/
public class RemoteDeviceDiscovery {
protected ArrayList<RemoteDevice> devicesDiscovered = new ArrayList();
protected final Object inquiryCompletedEvent = new Object();
public RemoteDeviceDiscovery()
{
DiscoveryListener listener = new MyDiscoveryListener();
synchronized(inquiryCompletedEvent) {
try
{
LocalDevice local = LocalDevice.getLocalDevice();
local.setDiscoverable(DiscoveryAgent.GIAC);
DiscoveryAgent discoveryAgent = local.getDiscoveryAgent();
// note: GIAC: The inquiry access code for General/Unlimited Inquiry Access Code (GIAC).
boolean startedInquiry = discoveryAgent.startInquiry(DiscoveryAgent.GIAC, listener);
if (startedInquiry)
{
System.out.println("wait for device inquiry to complete...");
inquiryCompletedEvent.wait();
System.out.println(devicesDiscovered.size() + " device(s) found");
}
}
catch ( BluetoothStateException e)
{
System.out.println("BluetoothStateException exception: " + e);
}
catch (InterruptedException e)
{
System.out.println("InterruptedException exception: " + e);
}
}
}
public static void main(String[] args)
{
RemoteDeviceDiscovery rmd = new RemoteDeviceDiscovery();
}
class MyDiscoveryListener implements DiscoveryListener
{
public MyDiscoveryListener()
{
}
public void deviceDiscovered(RemoteDevice btDevice, DeviceClass cod) {
System.out.println("Device " + btDevice.getBluetoothAddress() + " found");
devicesDiscovered.add(btDevice);
try {
System.out.println(" name " + btDevice.getFriendlyName(false));
} catch (IOException cantGetDeviceName) {
}
}
public void inquiryCompleted(int discType) {
System.out.println("Device Inquiry completed!");
synchronized(inquiryCompletedEvent){
inquiryCompletedEvent.notifyAll();
}
}
public void serviceSearchCompleted(int transID, int respCode) {
}
public void servicesDiscovered(int transID, ServiceRecord[] servRecord) {
}
} // class MyDiscoveryListener
} // class RemoteDeviceDiscovery
Discovered that if I run the jar with superuser rights then it works as expected:
pi#raspberrypi ~ sudo /java/bluetooth_jar $ /usr/lib/jvm/jdk-8-oracle-arm-vfp-hflt/jre/bin/java -jar bluetooth_jar.jar
with output:
BlueCove version 2.1.1-SNAPSHOT on bluez
wait for device inquiry to complete...
Device C4850852975B found
name GMSEED-PC
Device Inquiry completed!
1 device(s) found
BlueCove stack shutdown completed
and if I start BlueJ as superuser from the commandline rather than through the desktop menu item Menu|Programming|BlueJ; ie:
pi#raspberrypi ~ $ sudo bluej
and then the example app gives the same output.
Related
I am using "selenium-java.jar" file to open chrome headless drivers.
Now we are using threads to open headless chrome. Now what happens if there is any error then sometime threads quits without closing browser.
So i want to implement a solution that if any headless chrome is ideal for last 20 minutes then close/quit it.
I searched on google and i found may solution which is around selenium server standalone like this https://github.com/seleniumhq/selenium/issues/1106
My problem is i cannot switch to standalone server now so i have to figure out solution with current library.
So is there any way to close all headless chrome browsers which are idle for last 20 minutes?
Please guide.
I use selenium-java.jar with TestNg and whilst I don't run headless browsers I do clean up after a test run in the TestNg aftermethod, which is not quite the same as your 20 min wait, but might be of help.
When running tests on a windows OS I check for to see if the process is running by name and terminate it:
public final class OsUtils
{
private static final String TASKLIST = "tasklist";
private static final String KILL = "taskkill /F /IM ";
public static final String IE_EXE = "iexplore.exe";
public static final String CHROME_EXE = "chrome.exe";
public static final String EDGE_EXE = "MicrosoftEdge.exe";
public static final String FIREFOX_EXE = "firefox.exe";
public static boolean isProcessRunning(String processName)
{
Process process;
try
{
process = Runtime.getRuntime().exec(TASKLIST);
}
catch (IOException ex)
{
Logger.error("Error on get runtime" + ex.getMessage());
return false;
}
String line;
try ( BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); )
{
while ((line = reader.readLine()) != null) {
if (line.contains(processName)) {
Logger.log("Process found");
return true;
}
}
}
catch (IOException ex)
{
Logger.error("Error on check for process " + processName + ": " + ex.getMessage());
}
return false;
}
public static void killProcessIfRunning(String processName)
{
Logger.log("Trying to kill process: " + processName);
try
{
if (isProcessRunning(processName))
{
Runtime.getRuntime().exec(KILL + processName);
}
}
catch (IOException ex)
{
Logger.error("Error on kill process " + processName+ ": " + ex.getMessage());
}
}
...
}
When running Safari on macmini I have a similar kill command (which works for both Safari proper and also the technology preview):
public static void killSafariProcess()
{
Logger.log("Trying to kill Safari processes if running.");
try
{
Process p = Runtime.getRuntime().exec(new String[]{"bash","-c","ps ux | grep -i app/Contents/MacOs/Safari | grep -v grep | awk '{print $2}' | xargs kill -9"});
}
catch (IOException ex)
{
Logger.error("Error on kill Safari processes: " + ex.getMessage());
}
}
The custom Logger class just uses System.out.println(message)
You can probably do some analysis on the start time of the different processes that match your driver criteria. I don't think it's going to tell you how long it's been idle, but you can probably assume that if it's been running for 20 mins (assuming your test should successfully complete within minutes) that it's probably orphaned.
I found this answer that shows how you can use Java to get a list of processes and see their start time. From there you should be able to find all of the drivers that are old and kill them.
An alternative might be to use Powershell to get the processes, start time, and deal with it in that way. It just depends on what you are looking for. Here's an answer to get you started down this path.
You could subclass ChromeDriver and implement your own proxy class with a timer to quit after 20 minutes idle time:
public class TimedChromeDriver extends ChromeDriver {
Timer timeOut;
private void initTimer() {
timeOut = new Timer();
}
private void startTimer() {
timeOut.cancel();
timeOut.schedule(
new TimerTask() {
#Override
public void run() {
quit();
}
},
20 * 60 * 1000);
}
public TimedChromeDriver() {
initTimer();
}
#Override
public void get(String url) {
super.get(url);
startTimer();
}
// override every method of WebDriver and ChromeDriver in the same way
}
This will only work if your Java VM is not terminated before the timer is triggered. The garbage collector could also interfere. Overriding the finalize method is deprecated.
I would invest some analysis effort into your threads quitting ungracefully. This would solve your problems at the source.
I have a java project, which complied into an executable jar file v-agent-exe.jar. This jar is a log server, log rows is sent to it for processing.
I can execute it by using this command:
`java -jar v-agent-exe.jar -a watch -f config.ini`.
After executed, this jar file will create a ServerSocket at port 1235 and listen for incoming data from clients. After data received, the program will process the data and send the result back to the client. When I execute the jar from CMD windows, the processing is working perfect.
Now I am trying to wrap the Jar file as a Windows service (I am using Windows 10). I created a "Windows service project"
in Visual studio like below:
- Caller class have call() method to execute the jar file using process.
- AgentService is the service, which execute Caller->call() in another thread.
- Program is the main entry to load AgentService.
Caller.cs
public class Caller
{
static Process proc;
public Process GetProcess(){
return proc;
}
public void call() {
try
{
String dir = AppDomain.CurrentDomain.BaseDirectory;
proc = new Process
{
StartInfo = new ProcessStartInfo
{
WorkingDirectory = dir,
FileName = "java.exe",
Arguments = #"-jar v-agent-exe.jar -a watch -f config.ini",
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
RedirectStandardInput = true,
CreateNoWindow = true
}
};
proc.Start();
while (!proc.StandardError.EndOfStream)
{
string line = proc.StandardError.ReadLine();
}
}
catch (Exception ex) {
VAgentService.writeLog("Error when call process: " + ex.Message);
}
}
}
AgentService
public partial class AgentService : ServiceBase
{
private string jarPath;
private string iniPath;
static Process proc;
Caller caller;
public AgentService()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
writeLog("On start");
try
{
caller = new Caller();
writeLog("Prepare to launch thread");
Thread t = new Thread(new ThreadStart(caller.call));
t.Start();
}
catch (Exception ex)
{
EventLog.WriteEntry("Demo error: " + ex.Message);
}
}
protected override void OnStop()
{
proc = caller.GetProcess();
if (proc != null && !proc.HasExited)
{
proc.Kill();
}
else
{
...
}
}
}
Program.cs
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main(String[] args)
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new AgentService()
};
ServiceBase.Run(ServicesToRun);
}
}
After build the the service project, I have AgentService.exe.
I install it to my system using:
sc create VAgentLogging binpath= %CD%\AgentService.exe depend= lmhosts start= auto
After start the service in service.msc, I can telnet to port "1235" which the java process is listening (I am sure about
only the jar running in this port). According to the
log of java program, it still can received some part of data but seem like it cannot send back to client or something,
which cause the followed process cannot be done.
I think my problem is: the jar file can executed as standalone but somehow it sucks when wrapped under my service project.
I haven't posted the jar's code yet because I think the error is related to the Windows service project. If you need the java code, please tell me and I will update it here.
Any help would be appreciated.
I've been banging my head on this all day, read everything I can find, followed the JDK source around, no luck in finding out the gory details about HOW or WHERE java looks to obtain data on a midi device and determines what's what.
I'm trying to capture midi messages through my NI Audio 8 DJ MIDI IN port, but, java isn't "seeing" the MIDI IN port, only the out, which I have successfully used to send midi with. I also get the same results with an M-Audio USB UNO midi device: MidiSystem.getMidiDeviceInfo() only "sees" the output port.
I have verified the operation of the MIDI IN port with:
amidi -p hw:2,0 -d
and sending it some signals. Works fine.
getMaxTransmitters() returns zero.
MidiSystem.getMidiDeviceInfo() shows only one entry for both devices: Audio8DJ [hw:2,0] or Interface [hw:2,0]
The code below works fine for a Receiver and I think is only the bits I need to verify that getTransmitter() grabs the port, since it just works for the other and everything works fine, up I get a MidiUnavailableException / Transmitter not available exception.
I've even taken the getMaxReceivers() trap out because I was just trying to see if the device only offered up the one entry and sorted it out, but no.
public static Transmitter getMidiIn () {
if (midiIn == null){
devices = MidiSystem.getMidiDeviceInfo();
for(MidiDevice.Info info: devices){
System.out.println("device class " + info.getClass());
MidiDevice device;
try{
device = MidiSystem.getMidiDevice(info);
if (info.toString().equals("Audio8DJ [hw:2,0]")){
if (device.getMaxTransmitters() != 0){
try{
device.open();
System.out.println("max transmitters:" + device.getMaxTransmitters());
midiIn = device.getTransmitter();
System.out.println("Found a transmitter: "+ midiIn);
break;
} catch (Exception e){
e.printStackTrace();
}
}
}
} catch (MidiUnavailableException e1){
e1.printStackTrace();
}
}
}
return midiIn;
}
So the thing that's getting me here is this: alsa lists only one entry in amidi -l and when I specify that as a port to dump, it works fine. Java gets that same text entry and can't sort out the MIDI IN, assigning it the com.sun.media.sound.MidiOutDeviceProvider class so it leaves me wondering just how does, or where does Java figure out what a device has to offer and why isn't it seeing the input port that alsa is seeing.
I'm coding with eclipse Version: 3.8.1 IDE with JDK1.6, on a linux mint OS, .
I'll be happy to provide anything asked for. Thanks for reading!
The solution to java seeing the transmitter was in the version of JDK being used, though unfortunately at this time, I do not have an answer as to why for the failure, just that one version worked and suits my needs for the time being. If I find that answer, I will edit this answer.
Of the three versions I was switching between for testing, jdk1.8.0_60, jdk1.7.0_80, jdk1.6.0_45, 1.7 did not experience the error and successfully obtained a transmitter from my device. I found this out, and that privileges were not the cause of my specific issue, by compiling and running some code I found suitable for command line execution that attempts to obtain the transmitter, prints out midi data sent to it, and modified it a little ...
import javax.sound.midi.MidiDevice;
import javax.sound.midi.MidiMessage;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.MidiUnavailableException;
import javax.sound.midi.Receiver;
public class MidiInputTest {
public MidiDevice input;
public MidiDevice output;
public static void main(String[] args) {
new MidiInputTest().start();
}
public void start() {
init(); // initialize your midi input device
// system dependent
try {
output.open(); // From midi device
MyReceiver myrcvr = new MyReceiver();
MidiSystem.getTransmitter().setReceiver(myrcvr);
} catch (Exception e) {
e.printStackTrace();
System.exit(0);
}
}
private class MyReceiver implements Receiver {
Receiver rcvr;
public MyReceiver() {
try {
this.rcvr = MidiSystem.getReceiver();
} catch (MidiUnavailableException mue) {
mue.printStackTrace();
}
}
#Override
public void send(MidiMessage message, long timeStamp) {
byte[] b = message.getMessage();
if (b[0] != (byte)254) {
System.out.println((b[0] & 0xff) + " " + (b[1] & 0xff));
}
//rcvr.send(message, timeStamp); // will send out what ever you receive
}
#Override
public void close() {
rcvr.close();
}
}
public void init() {
MidiDevice.Info[] devices;
devices = MidiSystem.getMidiDeviceInfo();
try{
for (MidiDevice.Info info: devices) {
MidiDevice device;
device = MidiSystem.getMidiDevice(info);
System.out.println("MidiDevice.Info="+info + "\n" + "maxTransmitters="+device.getMaxTransmitters());
// I put the specific device I want to connect to behind an if gate here to avoid connecting to something I do not
if (info.toString().equals("Interface [hw:2,0,0]") && device.getMaxTransmitters() != 0) {
System.out.println(" Name: " + info.toString() +
", Decription: " +
info.getDescription() +
", Vendor: " +
info.getVendor());
output = MidiSystem.getMidiDevice(info);
if (! output.isOpen()) {
output.open();
}
}
}
} catch (MidiUnavailableException mue) {
mue.printStackTrace();
}
}
}
To run this from the command line choose a version of JDK you have installed, compile and run it with those specific versions substituting jdk1.7.0_80 for the distro you wish to test.
/opt/java-jdk/jdk1.7.0_80/bin/javac MidiInputTest.java
/opt/java-jdk/jdk1.7.0_80/bin/java -cp . MidiInputTest
Though I haven't been able to verify it, Java Sound is apparently responsible for figuring out what is available for java's use from your MIDI architecture.
Thank you Mike Harris for sending me down the right path of testing on the command line, and jim829 over at java-forums.org for the example code for the command line.
I had this problem which was caused by multiple instances of device info with the same name reterned by MidiSystem.getMidiDeviceInfo(). Basically when you call MidiSystem.getMidiDevice(Info) if you're unlucky it'll return the one without the transmitter. I'm not sure why it does this but only one instance has transmitters, (I think one might be for in and one out but, not sure). By first getting just the devices that have transmitters and then selecting from these, with the desired info, it worked for me. Hope that helps
public ArrayList<MidiDevice> getTransmitterDevices() {
MidiDevice.Info[] deviceInfo = MidiSystem.getMidiDeviceInfo();
ArrayList<MidiDevice> transmitterDevices = new ArrayList<>();
for(int i=0;i<deviceInfo.length;i++) {
try {
MidiDevice device = MidiSystem.getMidiDevice(deviceInfo[i]);
if(device.getMaxTransmitters()!=0) {
transmitterDevices.add(device);
}
} catch (MidiUnavailableException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return transmitterDevices;
}
//Somewhere else
//choose appropriate info somehow
MidiDevices<ArrayList> transmitterDevices = getTransmitterDevices();
for(MidiDevice tmp : transmitterDevices) {
if(tmp.getDeviceInfo().equals(info)) {
try {
midiController = tmp;
Transmitter transmitter = midiController.getTransmitter();
// something that implements receiver
midiReceiver = new MidiReceiver();
transmitter.setReceiver(midiReceiver);
midiController.open();
System.out.println("controller set ok");
} catch (MidiUnavailableException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
I am trying to start/stop an Endpoint web service in a separate thread from my main program with the click of a button. Starting works fine, i am able to access all my WebMethods without issue. The problem is, when i click the stop button to try and stop the web service endpoint, i get an exception and i don't know what it is. I am new to Java as well.
Thanks in advance.
Excetion thrown at 'ep.stop()':
WebService Running On: http://0.0.0.0:9898/
Exception in thread "Thread-0" java.lang.NullPointerException
at com.sun.xml.internal.ws.transport.http.server.ServerMgr.removeContext(Unknown Source)
at com.sun.xml.internal.ws.transport.http.server.HttpEndpoint.stop(Unknown Source)
at com.sun.xml.internal.ws.transport.http.server.EndpointImpl.stop(Unknown Source)
at com.simba.Server.startWebSrv(Server.java:27)
at com.simba.Server.run(Server.java:13)
Server class:
import javax.xml.ws.Endpoint;
public class Server extends Thread {
public volatile boolean active = true;
private Endpoint ep;
private String ip = "0.0.0.0";
public void run(){
ep = Endpoint.publish("http://" + ip + ":9898/", new SWS());
startWebSrv();
}
private void startWebSrv(){
synchronized(this){
try {
while (active) {
System.out.println("WebService Running On: http://" + ip + ":9898/");
wait();
}
}catch (InterruptedException e) {
e.printStackTrace();
}finally{
if(!active){
ep.stop();
System.out.println("WebService Stopped!");
}
}
}
}
}
How i am attempting to stop the service/thread from my main program:
MenuItem mntmToggleWebservice = new MenuItem(menu_4, SWT.NONE);
mntmToggleWebservice.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
synchronized(srv){
srv.active = false;
srv.notifyAll();
}
}
});
mntmToggleWebservice.setText("Toggle WebService");
Problem solved!
Don't use '0.0.0.0'. For some reason, creating the service on '0.0.0.0' works (uses the machine's actual ip), but Endpoint.stop() doesn't not play well with it.
Instead I just used 'System.getEvn('COMPUTERNAME')' and create the service with the machine name.
You can use the "input" to block the run of program
public class ServiceMain {
private static void DoNothing() {
}
public static void main(String[] args) {
String address = "http://127.0.0.1:7775/hb";
Endpoint ep = Endpoint.publish(address, new ServiceImp());
Scanner scanIn=new Scanner(System.in);
System.out.println("Web Service Release Successfully!");
while(!scanIn.next().equals("stop")){
DoNothing();
}
scanIn.close();
ep.stop();
System.out.println("Web Service Close Successfully!");
}
}
Hi I created sample jmdns serviceListner, When i run it , It should continue to list services as it finds, But with this my program, It list few services when run and after that it does not list any service. And i have dns-sd in my google chrome browser, So when i browse services in chrome, at that time my program list other services, Otherwise my program doesn't list services. I don't get why ServiceListner itself doesn't detect any subsequent events.
public static void main(String[] args) throws Exception {
String type = "_my-app._tcp.local.";
Enumeration<NetworkInterface> ifc = NetworkInterface.getNetworkInterfaces();
while (ifc.hasMoreElements()) {
NetworkInterface anInterface = ifc.nextElement();
if (anInterface.isUp()) {
Enumeration<InetAddress> addr = anInterface.getInetAddresses();
while (addr.hasMoreElements()) {
InetAddress address = addr.nextElement();
final JmDNS jmdns = JmDNS.create(address, type);
ServiceListenerClass aClass = new ServiceListenerClass();
jmdns.addServiceListener(type, aClass);
}
}
}
}
public static class ServiceListenerClass implements ServiceListener {
public void serviceAdded(ServiceEvent event) {
event.getDNS().requestServiceInfo(event.getType(), event.getName(), true);
}
public void serviceRemoved(ServiceEvent event) {
System.out.println((count--) + " " + event.getInfo().getName());
}
public void serviceResolved(ServiceEvent event) {
System.out.println((count++) + " :Res: " + event.getInfo().getName() + " " + event.getInfo().getPort() + " " + event.getInfo().getApplication()
+ " " + event.getInfo().getDomain() + " " + event.getInfo().getKey());
}
}
I had a similar problem two.
The problem might come from your firewall settings.
In my case the javaw.exe had access to all incoming calls but could not send anything to anyone as the firewall blocked it.
Try turning of the firewall to test you programm and to be shure thats not the firewall causing the problem.
Same issue here. Starting java with the following argument solved it for me:
-Djava.net.preferIPv4Stack=true