package oculusPrime;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.FileChannel;
import java.util.Collection;
import java.util.Set;
import developer.*;
import org.jasypt.util.password.ConfigurablePasswordEncryptor;
import org.opencv.core.Core;
import org.red5.server.adapter.MultiThreadedApplicationAdapter;
import org.red5.server.api.IConnection;
import org.red5.server.api.Red5;
import org.red5.server.api.service.IServiceCapableConnection;
import developer.depth.Mapper;
import developer.image.OpenCVMotionDetect;
import developer.image.OpenCVObjectDetect;
import developer.image.OpenCVUtils;
import oculusPrime.State.values;
import oculusPrime.commport.ArduinoPower;
import oculusPrime.commport.ArduinoPrime;
import oculusPrime.commport.PowerLogger;
/** red5 application */
public class Application extends MultiThreadedApplicationAdapter {
public enum streamstate { stop, camera, camandmic, mic }
public enum camquality { low, med, high, custom }
public enum driverstreamstate { stop, mic, pending, disabled }
public static final String VIDEOSOUNDMODELOW = "low";
public static final String VIDEOSOUNDMODEHIGH = "high";
public static final int STREAM_CONNECT_DELAY = 2000;
private static final int GRABBERRELOADTIMEOUT = 5000;
public static final int GRABBERRESPAWN = 8000;
public static final String ARM = "arm";
public static final String UBUNTU1604 = "16.04";
public static final String LOCALHOST = "127.0.0.1";
private ConfigurablePasswordEncryptor passwordEncryptor = new ConfigurablePasswordEncryptor();
protected boolean initialstatuscalled = false;
private boolean pendingplayerisnull = true;
public IConnection grabber = null; // flash client on robot, camera capture (optional)
private IConnection player = null; // client, typically remote flash plugin or air app
private String authtoken = null;
private String salt = null;
private Settings settings = Settings.getReference();
private BanList banlist = BanList.getRefrence();
private State state = State.getReference();
protected LoginRecords loginRecords = null;
private IConnection pendingplayer = null;
protected SystemWatchdog watchdog = null;
private AutoDock docker = null;
public Video video = null;
public ArduinoPrime comport = null;
public ArduinoPower powerport = null;
public TelnetServer commandServer = null;
public static developer.depth.OpenNIRead openNIRead = null;
public static developer.depth.ScanUtils scanUtils = null;
private developer.Navigation navigation = null;
public static byte[] framegrabimg = null;
public static BufferedImage processedImage = null;
public static BufferedImage videoOverlayImage = null;
private Red5Client red5client = null;
public IConnection relayclient = null;
public Network network = null;
public Application() {
super();
state.set(values.osarch, System.getProperty("os.arch"));
Util.log("\n==============Oculus Prime Java Start Arch:"+state.get(values.osarch)+"===============", this);
PowerLogger.append("\n==============Oculus Prime Java Start===============", this);
passwordEncryptor.setAlgorithm("SHA-1");
passwordEncryptor.setPlainDigest(true);
loginRecords = new LoginRecords(this);
DashboardServlet.setApp(this);
FrameGrabHTTP.setApp(this);
initialize();
}
@Override
public boolean appConnect(IConnection connection, Object[] params) {
authtoken = null;
// TODO: testing avconv/ffmpeg stream accept all non-auth LAN connections
// if (banlist.knownAddress(connection.getRemoteAddress()) && params.length==0) {
// Util.log("localhost/LAN/known netstream connect, no params", this);
// return true;
// }
// always accept local avconv/ffmpeg
if (params.length==0 && connection.getRemoteAddress().equals("127.0.0.1") ) {
grabber = Red5.getConnectionLocal(); // TODO: cause of unknown bug? dumpframegrabs sometimes connects after initial video source
return true;
}
// always accept relayclient avconv/ffmpeg
if (params.length==0 && state.exists(values.relayclient)) {
if (connection.getRemoteAddress().equals(state.get(values.relayclient)) ) {
grabber = Red5.getConnectionLocal();
if (settings.getBoolean(ManualSettings.useflash)) {
driverCallServer(PlayerCommands.messageclients, "relay server in use, setting "useflash" set to false");
Util.log("setting useflash false", this);
settings.writeSettings(ManualSettings.useflash, Settings.FALSE);
}
return true;
}
}
if (params.length==0) return false;
String logininfo[] = ((String) params[0]).split(" ");
// always accept local grabber (flash)
if ((connection.getRemoteAddress()).equals("127.0.0.1") && logininfo[0].equals("")) return true;
// disallow normal connection if relay server active
if (state.exists(values.relayserver)) return false;
// TODO: if banned, but cookie exists??
if(banlist.isBanned(connection.getRemoteAddress())) return false;
// test for cookie auth
if (logininfo.length == 1) {
String username = logintest("", logininfo[0]);
if (username != null) {
state.set(State.values.pendinguserconnected, username);
banlist.clearAddress(connection.getRemoteAddress());
return true;
}
}
// test for user/pass/remember
if (logininfo.length > 1) {
String encryptedPassword = (passwordEncryptor.encryptPassword(logininfo[0] + salt + logininfo[1])).trim();
if (logintest(logininfo[0], encryptedPassword) != null) {
if (logininfo[2].equals("remember")) {
authtoken = encryptedPassword;
}
state.set(State.values.pendinguserconnected, logininfo[0]);
banlist.clearAddress(connection.getRemoteAddress());
return true;
}
}
banlist.loginFailed(connection.getRemoteAddress(), logininfo[0]);
return false;
}
@Override
public void appDisconnect(IConnection connection) {
if(connection==null) { return; }
if (connection.equals(player)) {
String str = state.get(State.values.driver) + " disconnected";
Util.log("appDisconnect(): " + str,this);
messageGrabber(str, "connection awaiting connection");
loginRecords.signoutDriver();
//if autodocking, keep autodocking
if (!state.getBoolean(State.values.autodocking) &&
!(state.exists(values.navigationroute) && !state.exists(values.nextroutetime)) ) {
if (!state.get(State.values.driverstream).equals(driverstreamstate.pending.toString())) {
if (state.get(State.values.stream) != null) {
if (!state.get(State.values.stream).equals(streamstate.stop.toString())) {
publish(streamstate.stop);
}
}
if (comport.isConnected()) {
comport.setSpotLightBrightness(0);
comport.floodLight(0);
comport.stopGoing();
}
if (!state.get(State.values.driverstream).equals(driverstreamstate.stop.toString())
&& !state.get(values.driverstream).equals(driverstreamstate.disabled.toString())) {
state.set(State.values.driverstream, driverstreamstate.stop.toString());
grabberPlayPlayer(0);
messageGrabber("playerbroadcast", "0");
}
}
// this needs to be before player = null
if (state.get(State.values.pendinguserconnected) != null) {
assumeControl(state.get(State.values.pendinguserconnected));
state.delete(State.values.pendinguserconnected);
return;
}
}
player = null;
connection.close();
if (state.exists(values.relayclient)) {
IServiceCapableConnection t = (IServiceCapableConnection) relayclient;
t.invoke("playerDisconnect");
}
}
if (connection.equals(grabber)) {
grabber = null;
if (!settings.getBoolean(ManualSettings.useflash)) return;
// flash only
// wait a bit, see if still no grabber, THEN reload
new Thread(new Runnable() {
public void run() {
try {
Thread.sleep(GRABBERRESPAWN);
if (grabber == null) {
grabberInitialize();
}
} catch (Exception e) {
Util.printError(e);
}
}
}).start();
return;
}
if (connection.equals(relayclient)) {
relayclient = null;
state.delete(values.relayclient);
Util.log("relay client disconnected", this);
if (state.exists(values.driver)) //messageplayer("relay client disconnected", "connection", "connected");
driverCallServer(PlayerCommands.driverexit, null);
if (!state.get(values.stream).equals(streamstate.stop.toString()))
driverCallServer(PlayerCommands.streammode, streamstate.stop.toString());
return;
}
state.delete(State.values.pendinguserconnected);
//TODO: extend IConnection class, associate loginRecord (to get passenger info)
// currently no username info when passenger disconnects
}
// called by flash
public void grabbersignin(String mode) {
if (mode.equals("init")) {
state.delete(State.values.stream);
} else {
// state.set(State.values.stream, Application.streamstate.stop.toString());
driverCallServer(PlayerCommands.state, State.values.stream.toString() + " " +
Application.streamstate.stop.toString());
}
grabber = Red5.getConnectionLocal();
String str = "awaiting connection";
if (state.get(State.values.driver) != null) {
str = state.get(State.values.driver) + " connected";
}
str += " stream " + state.get(State.values.stream);
messageGrabber("connected to subsystem", "connection " + str);
Util.log("grabber signed in from " + grabber.getRemoteAddress(), this);
if (state.get(State.values.driverstream).equals(driverstreamstate.mic.toString())) {
grabberPlayPlayer(1);
messageGrabber("playerbroadcast", "1");
}
// eliminate any other grabbers
Collection<Set<IConnection>> concollection = getConnections();
for (Set<IConnection> cc : concollection) {
for (IConnection con : cc) {
if (con instanceof IServiceCapableConnection && con != grabber && con != player
&& (con.getRemoteAddress()).equals("127.0.0.1")) {
con.close();
}
}
}
// set video, audio quality mode in grabber flash, depending on server/client OS
String videosoundmode=state.get(State.values.videosoundmode);
if (videosoundmode == null) videosoundmode=VIDEOSOUNDMODEHIGH;
setGrabberVideoSoundMode(videosoundmode);
Util.systemCall(System.getenv("RED5_HOME")+"/flashsymlink.sh");
}
public void killGrabber() {
if (settings.getBoolean(ManualSettings.useflash)) Util.systemCall("pkill chrome"); // TODO: use PID
}
/** */
public void initialize() {
settings.writeFile();
salt = settings.readSetting("salt");
if (settings.readSetting("user0") == null) {
driverCallServer(PlayerCommands.new_user_add, "oculus robot");
// String p = "oculus" + salt + "robot"; // default
// String encryptedPassword = passwordEncryptor.encryptPassword(p);
// settings.newSetting("user0", "oculus");
// settings.newSetting("pass0", encryptedPassword);
}
comport = new ArduinoPrime(this); // note: blocking
powerport = new ArduinoPower(this); // note: blocking
state.set(State.values.httpport, settings.readRed5Setting("http.port"));
initialstatuscalled = false;
pendingplayerisnull = true;
if (!settings.readSetting(GUISettings.telnetport).equals(Settings.DISABLED.toString()))
commandServer = new TelnetServer(this);
if (settings.getBoolean(ManualSettings.developer.name())) {
openNIRead = new developer.depth.OpenNIRead();
scanUtils = new developer.depth.ScanUtils();
}
// OpenCV, requires restart if ubuntu 14.04 running, with jar file targeted at 16.04 was present
OpenCVUtils ocv = new OpenCVUtils(this);
ocv.loadOpenCVnativeLib();
if (ocv.jarfiledeleted) restart();
if (settings.getBoolean(GUISettings.navigation)) {
navigation = new developer.Navigation(this);
navigation.runAnyActiveRoute();
}
Util.setSystemVolume(settings.getInteger(GUISettings.volume));
state.set(State.values.volume, settings.getInteger(GUISettings.volume));
// use relay server if set
if (!settings.readSetting(GUISettings.relayserver).equals(Settings.DISABLED)) {
red5client = new Red5Client(this); // connects to remote server
red5client.connectToRelay();
}
if (state.get(values.osarch).equals(ARM))
settings.writeSettings(ManualSettings.useflash, Settings.FALSE);
if (!settings.getBoolean(ManualSettings.useflash))
state.set(values.driverstream, driverstreamstate.disabled.toString());
else
state.set(State.values.driverstream, driverstreamstate.stop.toString());
grabberInitialize();
state.set(State.values.lastusercommand, System.currentTimeMillis()); // must be before watchdog
docker = new AutoDock(this, comport, powerport);
// below network stuff should be called before SystemWatchdog (prevent redundant updates)
// Util.updateExternalIPAddress();
// Util.updateLocalIPAddress();
network = new Network(this);
Util.log("prime folder: " + Util.countMbytes(".") + " mybtes, " + Util.diskFullPercent() + "% used", this);
watchdog = new SystemWatchdog(this);
Util.debug("application initialize done", this);
}
// called by remote relay client
public void setRelayClient() {
IConnection c = Red5.getConnectionLocal();
if (c instanceof IServiceCapableConnection) {
relayclient = c;
state.set(values.relayclient, c.getRemoteAddress());
Util.log("relayclient connected from: " + state.get(values.relayclient), this);
if (authtoken != null) {
IServiceCapableConnection sc = (IServiceCapableConnection) relayclient;
sc.invoke("relayCallClient", new Object[] { "writesetting",
GUISettings.relayserverauth.toString()+" "+authtoken });
}
if (state.exists(values.driver)) {
player.close();
player = null;
loginRecords.signoutDriver();
driverCallServer(PlayerCommands.publish, streamstate.stop.toString());
}
}
}
// called by remote relayclient
public void relayPing() {
Util.debug("ping from relayclient", this); // TODO: testing
if (relayclient == null) {
Util.log("error,relayclient null", this); // TODO: testing
return;
}
IServiceCapableConnection sc = (IServiceCapableConnection) relayclient;
sc.invoke("relayPong", new Object[] { });
}
// called by remote Red5Client.sendToRelay()
public void fromRelayClient(Object[] params) {
if ( !Red5.getConnectionLocal().equals(relayclient)) return;
String[] s= new String[params.length-1];
switch (params[0].toString()) {
case "messageplayer":
for (int i=1; i<params.length; i++) if (params[i]!=null) s[i-1]=params[i].toString();
messageplayer(s[0],s[1],s[2]);
break;
case "sendplayerfunction":
for (int i=1; i<params.length; i++) if (params[i]!=null) s[i-1]=params[i].toString();
sendplayerfunction(s[0], s[1]);
break;
case "grabberSetStream":
grabberSetStream(params[1].toString());
}
}
private void grabberInitialize() {
// String host = LOCALHOST;
// if (!settings.readSetting(ManualSettings.relayserver).equals(Settings.DISABLED))
// host = settings.readSetting(ManualSettings.relayserver);
video = new Video(this);
// non flash, no gui
if (!settings.getBoolean(ManualSettings.useflash)) video.initAvconv();
else {
// if (host.equals(LOCALHOST)) grabber_launch("");
// else grabber_launch("?host="+host);
grabber_launch("");
}
}
public void grabber_launch(final String str) {
new Thread(new Runnable() {
public void run() {
try {
// stream = "stop";
String address = "127.0.0.1:" + state.get(State.values.httpport);
Runtime.getRuntime().exec("google-chrome " + address + "/oculusPrime/server.html"+str);
} catch (Exception e) {
Util.printError(e);
}
}
}).start();
}
/**
* called by remote flash
* */
public void playersignin() {
// set video, audio quality mode in grabber flash, depending on server/client OS
String videosoundmode=VIDEOSOUNDMODELOW;
if (player != null) { // pending connection
pendingplayer = Red5.getConnectionLocal();
pendingplayerisnull = false;
if (pendingplayer instanceof IServiceCapableConnection) {
IServiceCapableConnection sc = (IServiceCapableConnection) pendingplayer;
String str = "connection PENDING user " + state.get(State.values.pendinguserconnected);
if (authtoken != null) {
// System.out.println("sending store cookie");
str += " storecookie " + authtoken;
authtoken = null;
}
str += " someonealreadydriving " + state.get(State.values.driver);
// this has to be last to above variables are already set in java script
sc.invoke("message", new Object[] { null, "green", "multiple", str });
str = state.get(State.values.pendinguserconnected) + " pending connection from: "
+ pendingplayer.getRemoteAddress();
Util.log("playersignin(): " + str,this);
messageGrabber(str, null);
sc.invoke("videoSoundMode", new Object[] { videosoundmode });
}
} else { // driver connected
player = Red5.getConnectionLocal();
state.set(State.values.driver, state.get(State.values.pendinguserconnected));
state.delete(State.values.pendinguserconnected);
String conn = "connected";
if (state.exists(values.relayclient)) conn="relay";
String str = "connection "+conn+" user " + state.get(values.driver);
if (authtoken != null) {
str += " storecookie " + authtoken;
authtoken = null;
}
str += " streamsettings " + streamSettings();
messageplayer(state.get(State.values.driver) + " connected to OCULUS PRIME", "multiple", str);
initialstatuscalled = false;
str = state.get(State.values.driver) + " connected from: " + player.getRemoteAddress();
messageGrabber(str, "connection " + state.get(State.values.driver) + " connected");
Util.log("playersignin(), " + str, this);
loginRecords.beDriver();
if (settings.getBoolean(GUISettings.loginnotify)) {
saySpeech("lawg inn " + state.get(State.values.driver));
}
IServiceCapableConnection sc = (IServiceCapableConnection) player;
sc.invoke("videoSoundMode", new Object[] { videosoundmode });
Util.log("player video sound mode = "+videosoundmode, this);
// state.delete(State.values.controlsinverted);
watchdog.lastpowererrornotify = null; // new driver not notified of any errors yet
if (state.exists(values.relayclient)) {
IServiceCapableConnection t = (IServiceCapableConnection) relayclient;
t.invoke("playerSignIn", new Object[] { state.get(values.driver)});
}
}
}
public void driverCallServer(PlayerCommands fn, String str) {
playerCallServer(fn, str, true);
}
/**
* called by remote flash
* */
public void playerCallServer(String fn, String str) {
if (fn == null) return;
if (fn.equals("")) return;
PlayerCommands cmd = null;
try {
cmd = PlayerCommands.valueOf(fn);
} catch (Exception e) {
Util.debug("playerCallServer() command not found:" + fn, this);
messageplayer("error: unknown command, "+fn,null,null);
return;
}
if (cmd != null) playerCallServer(cmd, str, false);
}
@SuppressWarnings("incomplete-switch")
public void playerCallServer(PlayerCommands fn, String str, boolean passengerOverride) {
if (PlayerCommands.requiresAdmin(fn) && !passengerOverride) {
if ( ! loginRecords.isAdmin()){
Util.debug("playerCallServer(), must be an admin to do: " + fn.name() + " curent driver: " + state.get(State.values.driver), this);
return;
}
}
// track last user command
if(fn != PlayerCommands.statuscheck && !passengerOverride)
state.set(State.values.lastusercommand, System.currentTimeMillis());
// if acting as relay server, forward commands
if (state.exists(values.relayclient) && !PlayerCommands.nonRelayCommands(fn)) {
IServiceCapableConnection sc = (IServiceCapableConnection) relayclient;
sc.invoke("relayCallClient", new Object[] { fn, str });
return;
}
String[] cmd = null;
if(str!=null) cmd = str.split(" ");
switch (fn) {
case chat: chat(str) ;return;
case beapassenger: beAPassenger(str);return;
case assumecontrol: assumeControl(str); return;
}
// must be driver/non-passenger for all commands below
if (Red5.getConnectionLocal() != player && player != null && !passengerOverride) {
Util.log("passenger, command dropped: " + fn.toString(), this);
return;
}
switch (fn) {
case move: {
if (settings.getBoolean(GUISettings.navigation)) navigation.navdockactive = false;
if (state.exists(State.values.navigationroute) && !passengerOverride &&
str.equals(ArduinoPrime.direction.stop.toString())) {
messageplayer("navigation route "+state.get(State.values.navigationroute)+" cancelled by stop", null, null);
navigation.navlog.newItem(NavigationLog.INFOSTATUS, "Route cancelled by user",
Navigation.routestarttime, null, state.get(values.navigationroute),
Navigation.consecutiveroute, 0);
navigation.cancelAllRoutes();
}
else if (state.exists(State.values.roscurrentgoal) && !passengerOverride && str.equals(ArduinoPrime.direction.stop.toString())) {
Navigation.goalCancel();
messageplayer("navigation goal cancelled by stop", null, null);
}
if (!passengerOverride && watchdog.redocking) watchdog.redocking = false;
move(str);
break;
}
case battstats: messageplayer(state.get(State.values.batteryinfo), "battery", state.get(State.values.batterylife)); break;
case cameracommand:
if (state.getBoolean(State.values.autodocking)) {
messageplayer("command dropped, autodocking", null, null);
return;
}
comport.camCommand(ArduinoPrime.cameramove.valueOf(str));
break;
// case camtiltfast: comport.cameraToPosition(Integer.parseInt(str)); break;
case camtilt: comport.camtilt(Integer.parseInt(str)); break;
case getdrivingsettings:getDrivingSettings();break;
case drivingsettingsupdate:drivingSettingsUpdate(str);break;
case getemailsettings: getEmailSettings(); break;
case emailsettingsupdate: emailSettingsUpdate(str); break;
case motionenabletoggle:motionEnableToggle();break;
case clicksteer:clickSteer(str);break;
case streamsettingscustom: streamSettingsCustom(str);break;
case streamsettingsset:streamSettingsSet(str);break;
case driverexit: appDisconnect(player); break;
case playerbroadcast: playerBroadCast(str); break;
case password_update: account("password_update", str); break;
case new_user_add: account("new_user_add", str); break;
case user_list: account("user_list", ""); break;
case delete_user: account("delete_user", str); break;
case statuscheck: statusCheck(str); break;
case extrauser_password_update: account("extrauser_password_update", str); break;
case username_update: account("username_update", str); break;
case disconnectotherconnections: disconnectOtherConnections(); break;
case showlog: showlog(str); break;
case publish: publish(streamstate.valueOf(str)); break;
case record: // record [true | false] optionalfilename
if(str == null) break;
if(str.startsWith("true ")) video.record("true", str.substring(4).trim().replace(" ", "_"));
if(str.equals("true") || str.equals("false")) video.record(str);
break;
case autodockcalibrate: docker.autoDock("calibrate " + str); break;
case redock: watchdog.redock(str); break;
case restart: restart(); break;
case powershutdown: powerport.shutdown(); break;
case reboot: reboot(); break;
case systemshutdown: powerdown(); break;
case softwareupdate: softwareUpdate(str); break;
// case muterovmiconmovetoggle: muteROVMicOnMoveToggle(); break;
case quitserver: shutdownApplication(); break;
case setstreamactivitythreshold: setStreamActivityThreshold(str); break;
case email: new SendMail(str, this); break;
case uptime: messageplayer(state.getUpTime() + " ms", null, null); break;
case memory: messageplayer(Util.memory(), null, null); break;
case who: messageplayer(loginRecords.who(), null, null); break;
case loginrecords: messageplayer(loginRecords.toString(), null, null); break;
case messageclients: messageplayer(str, null,null); Util.log("messageclients: "+str,this); break;
case dockgrab:
if (str!=null) if (str.equals(AutoDock.HIGHRES)) docker.lowres = false;
docker.dockGrab(AutoDock.dockgrabmodes.start, 0, 0);
docker.lowres = true;
break;
case dockgrabtest:
if (str.equals(AutoDock.HIGHRES)) docker.lowres = false; // ?
docker.dockGrab(AutoDock.dockgrabmodes.test, 0, 0);
docker.lowres = true; // ?
break;
case rssadd: RssFeed feed = new RssFeed(); feed.newItem(str); break;
case nudge: nudge(str); break;
case state:
String s[] = str.split(" ");
if (s.length == 2) { // two args
if (s[0].equals("delete")) state.delete(s[1]);
else state.set(s[0], s[1]);
}
else if (s.length > 2) { // 2nd arg has spaces
String stateval = "";
for (int i=1; i<s.length; i++) stateval += s[i]+" ";
state.set(s[0], stateval.trim());
}
else {
if (s[0].matches("\\S+")) { // one arg
messageplayer("<state> "+s[0]+" "+state.get(s[0]), null, null);
} else { // no args
messageplayer("<state> "+state.toString(), null, null);
}
}
break;
case writesetting:
if (settings.readSetting(cmd[0]) == null) {
settings.newSetting(cmd[0], cmd[1]);
messageplayer("new setting: " + cmd[1], null, null);
} else {
settings.writeSettings(cmd[0], cmd[1]);
messageplayer(cmd[0] + " " + cmd[1], null, null);
}
settings.writeFile();
break;
case readsetting:
messageplayer("setting "+cmd[0]+" "+settings.readSetting(cmd[0]),null,null);
break;
case speed:
comport.speedset(str);
messageplayer("speed set: " + str, "speed", str.toUpperCase());
break;
case left:
case right:
if (!state.getBoolean(State.values.motionenabled.name())) {
messageplayer("motion disabled", "motion", "disabled");
break;
}
if (state.getBoolean(State.values.autodocking.name())) {
messageplayer("command dropped, autodocking", null, null);
break;
}
moveMacroCancel();
comport.rotate(ArduinoPrime.direction.valueOf(fn.toString()), Integer.parseInt(str));
messageplayer(ArduinoPrime.direction.valueOf(fn.toString())+" " + str+"°", "motion", "moving");
break;
case forward:
case backward:
if (!state.getBoolean(State.values.motionenabled.name())) {
messageplayer("motion disabled", "motion", "disabled");
break;
}
if (state.getBoolean(State.values.autodocking.name())) {
messageplayer("command dropped, autodocking", null, null);
break;
}
moveMacroCancel();
comport.movedistance(ArduinoPrime.direction.valueOf(fn.toString()),Double.parseDouble(str));
messageplayer(ArduinoPrime.direction.valueOf(fn.toString())+" " + str+"m", "motion", "moving");
break;
case arcmove:
if (!state.getBoolean(values.motionenabled) || state.getBoolean(values.autodocking)) return;
moveMacroCancel();
String[] metersdegrees = str.split(" ");
comport.arcmove(Double.parseDouble(metersdegrees[0]), Integer.parseInt(metersdegrees[1]));
break;
case odometrystart: comport.odometryStart(); break;
case odometryreport: comport.odometryReport(); break;
case odometrystop: comport.odometryStop(); break;
case lefttimed: comport.turnLeft(Integer.parseInt(str)); break;
case righttimed: comport.turnRight(Integer.parseInt(str)); break;
case forwardtimed: comport.goForward(Integer.parseInt(str)); break;
case systemcall:
Util.log("received: " + str,this);
messageplayer("system command received", null, null);
Util.systemCall(str);
break;
case serverbrowser:
grabber_launch(str);
break;
case docklineposupdate:
settings.writeSettings(GUISettings.vidctroffset, str);
messageplayer("vidctroffset set to : " + str, null, null);
break;
case motorsreset:
comport.reset();
messageplayer("resetting malg board", null, null);
break;
case speech:
messageplayer("synth voice: " + str, null, null);
messageGrabber("synth voice: " + str, null);
saySpeech(str);
break;
case setsystemvolume:
Util.setSystemVolume(Integer.parseInt(str));
messageplayer("ROV volume set to "+str+"%", null, null);
state.set(State.values.volume, str);
break;
case opennisensor:
if(str.equals("on")) {
if (openNIRead.startDepthCam()) {
// if (!state.getBoolean(State.values.odometry)) comport.odometryStart();
}
else
messageplayer("roslaunch already running, abort", null, null);
}
else {
openNIRead.stopDepthCam();
// if (state.getBoolean(State.values.odometry)) comport.odometryStop();
}
messageplayer("openNI camera "+str, null, null);
break;
case videosoundmode:
setGrabberVideoSoundMode(str);
break;
case spotlightsetbrightness: // deprecated, maintained for mobile client compatibility
case spotlight:
comport.setSpotLightBrightness(Integer.parseInt(str));
messageplayer("spotlight brightness set to "+str+"%", "light", str);
break;
case floodlight:
comport.floodLight(Integer.parseInt(str));
messageplayer("floodLight brightness set to "+str+"%", "floodlight", str);
break;
case fwdflood:
comport.fwdflood(Integer.parseInt(str));
messageplayer("forward floodLight brightness set to "+str+"%", "fwdflood", str);
break;
case autodock:
docker.autoDock(str);
break;
case getlightlevel:
docker.getLightLevel(); break;
case dock:
docker.dock();
break;
case strobeflash:
String mode = "on";
int duration = 0;
int intensity = 0;
if (str != null) {
String[] STR = str.split(" ");
mode = STR[0];
if (STR.length >= 3) {
duration = Integer.parseInt(STR[1]);
intensity = Integer.parseInt(STR[2]);
}
}
comport.strobeflash(mode, duration, intensity);
messageplayer("strobeflash "+str, null, null);
break;
case powerreset:
messageplayer("resetting power board", null, null);
powerport.reset();
break;
case powercommand:
messageplayer("powercommand: "+str, null, null);
powerport.powercommand(str);
break;
case malgcommand:
if (!passengerOverride) messageplayer("malgcommand: "+str, null, null);
comport.malgcommand(str);
break;
case erroracknowledged:
if (str.equals("true")) {
Util.log("power error acknowledged",this);
Util.log("power error acknowledged","Application_power");
if (watchdog.powererrorwarningonly) {
powerport.clearWarningErrors();
watchdog.lastpowererrornotify = null;
}
}
else {
Util.log("power error purposefully dismissed",this);
}
break;
case block:
banlist.addBlockedFile(str);
break;
case unblock:
banlist.removeblockedFile(str);
break;
case roslaunch:
if (Ros.launch(str))
messageplayer("roslaunch "+str+".launch", null, null);
else
messageplayer("roslaunch already running", null, null);
break;
case savewaypoints:
Ros.savewaypoints(str);
messageplayer("waypoints saved", null, null);
break;
case gotowaypoint:
if (navigation != null) navigation.gotoWaypoint(str);
break;
case startnav:
if (navigation != null) navigation.startNavigation();
break;
case stopnav:
if (navigation != null) navigation.stopNavigation();
break;
case gotodock:
if (navigation != null) navigation.dock();
break;
case saveroute:
if (navigation != null) navigation.saveRoute(str);
messageplayer("route saved", null, null);
break;
case runroute:
if (navigation != null) {
navigation.navlog.newItem(NavigationLog.INFOSTATUS, "Route activated by user",
System.currentTimeMillis(), null, str, Navigation.consecutiveroute, 0);
navigation.runRoute(str);
}
break;
case cancelroute:
if (navigation != null && state.exists(values.navigationroute)) {
navigation.navlog.newItem(NavigationLog.INFOSTATUS, "Route cancelled",
Navigation.routestarttime, null, state.get(values.navigationroute),
Navigation.consecutiveroute, 0);
navigation.cancelAllRoutes();
}
break;
case startmapping:
if (navigation != null) navigation.startMapping();
break;
case savemap:
if (navigation != null) navigation.saveMap();
break;
case clearmap: Mapper.clearMap();
break;
case motiondetect: new OpenCVMotionDetect(this).motionDetectGo(); break;
case motiondetectcancel: state.delete(State.values.motiondetect); break;
case motiondetectstream: new OpenCVMotionDetect(this).motionDetectStream(); break;
case sounddetect: video.sounddetect(str); break;
case objectdetect: new OpenCVObjectDetect(this).detectGo(str); break;
case objectdetectcancel: state.delete(values.objectdetect); break;
case objectdetectstream: new OpenCVObjectDetect(this).detectStream(str); break;
// case framegrabtofile: messageplayer(FrameGrabHTTP.saveToFile(str), null, null); break;
case framegrabtofile: // allow extra name to be added
// final String c = str.trim();
Util.debug("framegrabtofile(): length = " + cmd.length, this);
if(cmd.length == 2) {
FrameGrabHTTP.saveToFile(cmd[0], cmd[1]); // ?mode=processedImgJPG
Util.debug("framegrabtofile(mode, fname): " + cmd[0] + " " + cmd[1], this);
}
if(cmd.length == 1) {
FrameGrabHTTP.saveToFile(cmd[0]); // ?mode=processedImgJPG
Util.debug("framegrabtofile(mode): "+cmd[0], this);
}
if(cmd.length == 0){
FrameGrabHTTP.saveToFile(null); // default filename
Util.debug("framegrabtofile(default):", this);
}
break;
case log: Util.log("log: "+str, this); break;
case settings: messageplayer(settings.toString(), null, null); break;
case cpu:
String cpu = String.valueOf(Util.getCPU());
if(cpu != null) state.set(values.cpu, cpu);
break;
case waitforcpu: watchdog.waitForCpuThread(); break;
// dev tool only
case test:
try {
Util.log("testing", this.getClass().getEnclosingMethod().toString());
} catch (Exception e) { Util.printError(e); }
break;
case jpgstream:
if (str== null) str="";
if (str.equals(streamstate.stop.toString())) {
state.delete(values.jpgstream);
break;
}
if (str.equals("")) str = AutoDock.HIGHRES;
new OpenCVUtils(this).jpgStream(str);
// opencvutils.jpgStream(str);
break;
case deletelogs:
if( !state.equals(values.dockstatus, AutoDock.DOCKED)) {
Util.log("archiving busy, must be docked, skipping.. ", null);
break;
}
Util.deleteLogFiles();
break;
case archivelogs:
// if( !state.equals(values.dockstatus, AutoDock.DOCKED)) {
// Util.log("archiving busy, must be docked, skipping.. ", null);
// break;
// }
Util.archiveLogs();
break;
case streammode: // TODO: testing ffmpeg/avconv streaming
grabberSetStream(str);
break;
case calibraterotation:
new Calibrate(this).calibrateRotation();
break;
case relayconnect:
if (red5client == null) red5client = new Red5Client(this);
if (!str.equals("")) { red5client.connectToRelay(str); break; }
red5client.connectToRelay();
// TODO: stop any running streams
break;
case relaydisable:
driverCallServer(PlayerCommands.writesetting, GUISettings.relayserver.toString()+" "+Settings.DISABLED);
driverCallServer(PlayerCommands.writesetting, GUISettings.relayserverauth.toString()+" "+Settings.DISABLED);
// break omitted on purpose
case relaydisconnect:
driverCallServer(PlayerCommands.publish, Application.streamstate.stop.toString()); // TODO: server doesn't get stream stop
if (state.exists(values.relayserver))
red5client.relayDisconnect();
else if (state.exists(values.relayclient)) {
IServiceCapableConnection rc = (IServiceCapableConnection) relayclient;
rc.invoke("disconnect");
state.delete(values.relayclient);
driverCallServer(PlayerCommands.publish, Application.streamstate.stop.toString()); // TODO: server doesn't get stream stop
}
break;
case networksettings:
network.getNetworkSettings();
break;
case networkconnect:
// if (state.exists(values.relayserver) || state.exists(values.relayclient))
// driverCallServer(PlayerCommands.relaydisconnect, null);
network.connectNetwork(str);
break;
}
}
/** put all commands here */
public enum grabberCommands {
streammode, saveandlaunch, populatesettings, systemcall, chat, dockgrabbed, autodock,
restart, checkforbattery, factoryreset, shutdown, streamactivitydetected;
@Override
public String toString() {
return super.toString();
}
}
/**
* turn string input to command id
*
* @param fn
* is the funct ion to call
* @param str
* is the parameters to pass on to the function.
*/
public void grabberCallServer(String fn, String str) {
grabberCommands cmd = null;
try {
cmd = grabberCommands.valueOf(fn);
} catch (Exception e) {
return;
}
if (cmd == null) return;
else grabberCallServer(cmd, str);
}
/**
* distribute commands from grabber
*
* @param cmd
* is the function to call in xxxxxx.swf ???
* @param str
* is the parameters to pass on to the function.
*/
@SuppressWarnings("incomplete-switch")
public void grabberCallServer(final grabberCommands cmd, final String str) {
switch (cmd) {
case streammode:
grabberSetStream(str);
break;
case systemcall:
Util.systemCall(str);
break;
case chat:
chat(str);
break;
case dockgrabbed:
docker.autoDock("dockgrabbed " + str);
state.set(State.values.dockgrabbusy.name(), false);
break;
// case autodock:
// docker.autoDock(str);
// break;
case restart:
restart();
break;
case shutdown:
shutdownApplication();
break;
case streamactivitydetected:
streamActivityDetected(str);
break;
}
}
/**
* set state and message all connected clients with stream status
* @param str
*/
private void grabberSetStream(String str) {
state.set(State.values.stream, str);
if (!settings.getBoolean(ManualSettings.useflash) && str.equals(streamstate.camandmic.toString()))
str = str+"_2";
final String stream = str;
messageGrabber("streaming " + stream, "stream " + stream);
Util.log("streaming " + stream, this);
new Thread(new Runnable() {
public void run() {
try {
// notify all passengers and driver
Thread.sleep(STREAM_CONNECT_DELAY);
// if (stream.equals(streamstate.camandmic)); Thread.sleep(STREAM_CONNECT_DELAY*2); // longer delay required doesn't help
Collection<Set<IConnection>> concollection = getConnections();
for (Set<IConnection> cc : concollection) {
for (IConnection con : cc) {
if (con instanceof IServiceCapableConnection
&& con != grabber
&& !(con == pendingplayer && !pendingplayerisnull)) {
IServiceCapableConnection n = (IServiceCapableConnection) con; // all CLIENTS
n.invoke("message", new Object[] { "streaming " + stream, "green", "stream", stream });
Util.debug("message all players: streaming " + stream +" stream " +stream,this);
}
}
}
// set stream on relayserver if necessary
if (state.exists(values.relayserver)) {
Util.delay(1000); // allow extra time for avconv to connect to remote server
red5client.sendToRelay("grabberSetStream", new Object[]{state.get(values.stream)});
}
} catch (Exception e) {
Util.printError(e);
}
}
}).start();
}
private void setGrabberVideoSoundMode(String str) {
if (!settings.getBoolean(ManualSettings.useflash)) return;
if (state.getBoolean(State.values.autodocking.name())) {
messageplayer("command dropped, autodocking", null, null);
return;
}
if (state.get(State.values.stream) == null) {
messageplayer("stream control unavailable, server may be in setup mode", null, null);
return;
}
long timeout = System.currentTimeMillis() + GRABBERRELOADTIMEOUT;
while (!(grabber instanceof IServiceCapableConnection) && System.currentTimeMillis() < timeout ) { Util.delay(10); }
if (!(grabber instanceof IServiceCapableConnection))
Util.log("setGrabberVideoSoundMode() error grabber reload timeout", this);
IServiceCapableConnection sc = (IServiceCapableConnection) grabber;
sc.invoke("videoSoundMode", new Object[]{str});
state.set(State.values.videosoundmode, str);
Util.log("grabber video sound mode = " + str, this);
}
public void publish(streamstate mode) {
if (state.getBoolean(State.values.autodocking.name())) {
messageplayer("command dropped, autodocking", null, null);
return;
}
if (state.get(State.values.stream) == null) {
messageplayer("stream control unavailable, server may be in setup mode", null, null);
return;
}
if (state.get(State.values.record) == null)
state.set(State.values.record, Application.streamstate.stop.toString());
// if recording and mode changing, kill recording
if (state.exists(values.stream)) {
if (!mode.equals(streamstate.valueOf(state.get(values.stream))) && !state.get(values.record).equals(streamstate.stop.toString()))
video.record(Settings.FALSE);
}
ArduinoPrime.checkIfInverted();
String current = settings.readSetting(GUISettings.vset);
String vals[] = (settings.readSetting(current)).split("_");
int width = Integer.parseInt(vals[0]);
int height = Integer.parseInt(vals[1]);
int fps = Integer.parseInt(vals[2]);
int quality = Integer.parseInt(vals[3]);
if (!settings.getBoolean(ManualSettings.useflash)) {
video.publish(mode, width, height, fps);
return;
}
// flash
try {
// commands: camandmic camera mic stop
long timeout = System.currentTimeMillis() + GRABBERRELOADTIMEOUT;
while (!(grabber instanceof IServiceCapableConnection) && System.currentTimeMillis() < timeout ) { Util.delay(10); }
if (!(grabber instanceof IServiceCapableConnection))
Util.log("publish() error grabber reload timeout", this);
IServiceCapableConnection sc = (IServiceCapableConnection) grabber;
sc.invoke("publish", new Object[] { mode.toString(), width, height, fps, quality });
messageplayer("command received: publish " + mode.toString(), null, null);
Util.log("publish: " + mode.toString(), this);
} catch (NumberFormatException e) {
Util.log("publish() error " + e.getMessage(),this);
Util.printError(e);
}
}
// private void muteROVMicOnMoveToggle() {
// if (settings.getBoolean(GUISettings.muteonrovmove)) {
//// state.set(State.values.muteOnROVmove, false);
// settings.writeSettings(GUISettings.muteonrovmove.toString(), "false");
// messageplayer("mute ROV onmove off", null, null);
// } else {
//// state.set(State.values.muteOnROVmove, true);
// settings.writeSettings(GUISettings.muteonrovmove.toString(), "true");
// messageplayer("mute ROV onmove on", null, null);
// }
// }
public boolean frameGrab() {
return frameGrab("");
}
/** */
public boolean frameGrab(String res) {
if(state.getBoolean(State.values.framegrabbusy.name()) ||
!(state.get(State.values.stream).equals(Application.streamstate.camera.toString()) ||
state.get(State.values.stream).equals(Application.streamstate.camandmic.toString()))) {
messageplayer("stream unavailable or framegrab busy", null, null);
return false;
}
if (settings.getBoolean(ManualSettings.useflash)) {
if (grabber instanceof IServiceCapableConnection) {
IServiceCapableConnection sc = (IServiceCapableConnection) grabber;
if (res.equals(AutoDock.LOWRES)) sc.invoke("framegrabMedium", new Object[]{});
else sc.invoke("framegrab", new Object[]{});
state.set(State.values.framegrabbusy.name(), true);
}
}
else video.framegrab(res);
// Util.debug("framegrab start at: "+System.currentTimeMillis(), this);
return true;
}
/**
* for compatibility with legacy grabber swfs
*/
// public void frameGrabbed() {
// String current = settings.readSetting(GUISettings.vset);
// String vals[] = (settings.readSetting(current)).split("_");
// int width = Integer.parseInt(vals[0]);
// int height = Integer.parseInt(vals[1]);
// frameGrabbed(width, height);
// }
/** called by Flash oculusPrime_grabber.swf after writing data to shared object file
* linux only for now
**/
public void frameGrabbed(int width, int height) {
try {
// read file into bytebuffer
FileInputStream file = new FileInputStream("/run/shm/oculusPrimeFlashSO/framegrab.sol");
FileChannel ch = file.getChannel();
int size = (int) ch.size();
ByteBuffer frameData = ByteBuffer.allocate( size );
ch.read(frameData.order(ByteOrder.BIG_ENDIAN));
ch.close();
file.close();
// int width=640;
// int height=480;
if (settings.readSetting(GUISettings.vset).equals("vmed") ||
settings.readSetting(GUISettings.vset).equals("vlow")) { // failed, switch to highres if avail and try again
width=320;
height=240;
}
// int headersize = 1228843 - (640*480*4);
int headersize = size - (width*height*4)-1;
frameData.position(headersize); // skip past header
boolean invalid = true;
processedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
for(int y=0; y<height; y++) {
for (int x=0; x<width; x++) {
int rgb = frameData.getInt(); // argb ok for png only
if (rgb != 0) invalid = false;
rgb = rgb & 0x00ffffff; // can't have alpha channel if want to jpeg out
processedImage.setRGB(x, y, rgb);
}
}
if (invalid) Util.log("error, framegrab invalid", this);
state.set(State.values.framegrabbusy.name(), false);
} catch (Exception e) { Util.printError(e); }
// Util.debug("framegrab finished at: "+System.currentTimeMillis(), this);
}
/** called by Flash oculusPrime_grabber.swf after writing data to shared object file
* linux only for now
**/
public void mediumFrameGrabbed() {
try {
// read file into bytebuffer
FileInputStream file = new FileInputStream("/run/shm/oculusPrimeFlashSO/framegrabMedium.sol");
FileChannel ch = file.getChannel();
int size = (int) ch.size();
ByteBuffer frameData = ByteBuffer.allocate( size );
ch.read(frameData.order(ByteOrder.BIG_ENDIAN));
ch.close();
file.close();
int width = 320;
int height = 240;
// int headersize = 307248 - (width*height*4);
int headersize = size - (width*height*4) -1;
frameData.position(headersize); // skip past header
boolean invalid = true;
processedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
for(int y=0; y<height; y++) {
for (int x=0; x<width; x++) {
int rgb = frameData.getInt(); // argb ok for png only
if (rgb != 0) invalid = false;
rgb = rgb & 0x00ffffff; // can't have alpha channel if want to jpeg out
processedImage.setRGB(x, y, rgb);
}
}
if (invalid) Util.log("error, framegrab empty", this);
state.set(State.values.framegrabbusy.name(), false);
} catch (Exception e) { Util.printError(e); }
// Util.debug("mediumframegrab finished at: "+System.currentTimeMillis(), this);
}
public void messageplayer(String str, String status, String value) {
if (state.exists(values.relayserver)) {
red5client.sendToRelay("messageplayer", new Object[] {str, status, value});
}
if (player instanceof IServiceCapableConnection) {
IServiceCapableConnection sc = (IServiceCapableConnection) player;
sc.invoke("message", new Object[] { str, "green", status, value });
}
if(commandServer!=null) {
if(str!=null){
if(! str.equals("status check received")) // basic ping from client, ignore
commandServer.sendToGroup(TelnetServer.MSGPLAYERTAG + " " + str);
}
if (status !=null) {
commandServer.sendToGroup(TelnetServer.MSGPLAYERTAG + " <status> " + status + " " + value);
}
}
if(str!=null){
if(! str.equals("status check received")) // basic ping from client, ignore
Util.debug("messageplayer: "+str+", "+status+", "+value, this);
}
}
public void sendplayerfunction(String fn, String params) {
if (player instanceof IServiceCapableConnection) {
IServiceCapableConnection sc = (IServiceCapableConnection) player;
sc.invoke("playerfunction", new Object[] { fn, params });
}
if (state.exists(values.relayserver)) {
red5client.sendToRelay("sendplayerfunction", new Object[]{fn, params});
}
}
public void saySpeech(String str) {
Util.debug("SPEECH sayspeech: " + str, this);
try {
String strarr[] = {"espeak",str};
Runtime.getRuntime().exec(strarr);
} catch (IOException e) { Util.printError(e); }
}
private void getEmailSettings() {
String str = settings.readSetting(GUISettings.email_smtp_server) + " "
+ settings.readSetting(GUISettings.email_smtp_port) + " "
+ settings.readSetting(GUISettings.email_username) + " "
+ settings.readSetting(GUISettings.email_password) + " " // display as dots
+ settings.readSetting(GUISettings.email_from_address) + " "
+ settings.readSetting(GUISettings.email_to_address);
sendplayerfunction("emailsettingsdisplay", str);
}
private void emailSettingsUpdate(String str) {
String s[] = str.split(" ");
settings.writeSettings(GUISettings.email_smtp_server, s[0]);
settings.writeSettings(GUISettings.email_smtp_port, s[1]);
settings.writeSettings(GUISettings.email_username, s[2]);
settings.writeSettings(GUISettings.email_password, s[3]);
settings.writeSettings(GUISettings.email_from_address, s[4]);
settings.writeSettings(GUISettings.email_to_address, s[5]);
messageplayer("email settings updated", null, null);
}
private void getDrivingSettings() {
if (loginRecords.isAdmin()) {
String str = comport.speedslow + " " + comport.speedmed + " "
+ comport.nudgedelay + " " + comport.maxclicknudgedelay
+ " " + comport.maxclickcam
+ " " + comport.fullrotationdelay + " " + comport.onemeterdelay + " "
+ settings.readSetting(GUISettings.steeringcomp.name()) + " "
+ ArduinoPrime.CAM_HORIZ + " " + ArduinoPrime.CAM_REVERSE;
sendplayerfunction("drivingsettingsdisplay", str);
}
}
private void drivingSettingsUpdate(String str) {
if (loginRecords.isAdmin()) {
String comps[] = str.split(" ");
comport.speedslow = Integer.parseInt(comps[0]);
settings.writeSettings(GUISettings.speedslow, Integer.toString(comport.speedslow));
comport.speedmed = Integer.parseInt(comps[1]);
settings.writeSettings(GUISettings.speedmed, Integer.toString(comport.speedmed));
comport.nudgedelay = Integer.parseInt(comps[2]);
settings.writeSettings(GUISettings.nudgedelay, Integer.toString(comport.nudgedelay));
comport.maxclicknudgedelay = Integer.parseInt(comps[3]);
settings.writeSettings(GUISettings.maxclicknudgedelay, Integer.toString(comport.maxclicknudgedelay));
comport.maxclickcam = Integer.parseInt(comps[4]);
settings.writeSettings(GUISettings.maxclickcam,Integer.toString(comport.maxclickcam));
comport.fullrotationdelay = Integer.parseInt(comps[5]);
settings.writeSettings(GUISettings.fullrotationdelay, Integer.toString(comport.fullrotationdelay));
comport.onemeterdelay = Integer.parseInt(comps[6]);
settings.writeSettings(GUISettings.onemeterdelay, Integer.toString(comport.onemeterdelay));
comport.setSteeringComp(comps[7]);
settings.writeSettings(GUISettings.steeringcomp, comps[7]);
comport.setCameraStops(Integer.parseInt(comps[8]), Integer.parseInt(comps[9]));
String s = comport.speedslow + " " + comport.speedmed + " "
+ comport.nudgedelay + " " + comport.maxclicknudgedelay
+ " " + comport.maxclickcam
+ " " + comport.fullrotationdelay
+ " " + comport.onemeterdelay + " " + comport.steeringcomp + " "
+ ArduinoPrime.CAM_HORIZ + " " + ArduinoPrime.CAM_REVERSE;
messageplayer("driving settings set to: " + s, null, null);
}
}
public void message(String str, String status, String value) {
messageplayer(str, status, value);
}
private void moveMacroCancel() {
if (state.getBoolean(State.values.docking.name())) {
String str = "";
if (!state.equals(State.values.dockstatus, AutoDock.DOCKED)) {
state.set(State.values.dockstatus, AutoDock.UNDOCKED);
str += "dock " + AutoDock.UNDOCKED;
}
messageplayer("docking cancelled", "multiple", str);
state.set(State.values.docking, false);
// powerport.manualSetBatteryUnDocked();
}
}
private void statusCheck(String s) {
if (initialstatuscalled == false || s.equals("intial")) {
initialstatuscalled = true;
// build string
String str = "";
if (comport != null) {
String spd = "FAST";
if (state.getInteger(State.values.motorspeed) == comport.speedmed) spd = "MED";
if (state.getInteger(State.values.motorspeed) == comport.speedslow) spd = "SLOW";
String mov = "STOPPED";
if (!state.getBoolean(State.values.motionenabled)) mov = "DISABLED";
if (state.getBoolean(State.values.moving)) mov = "MOVING";
str += " speed " + spd + " cameratilt " + state.get(State.values.cameratilt) + " motion " + mov;
str += " light " + state.get(State.values.spotlightbrightness);
str += " floodlight " + state.get(State.values.floodlightlevel);
}
str += " vidctroffset " + settings.readSetting(GUISettings.vidctroffset);
str += " rovvolume " + settings.readSetting(GUISettings.volume);
str += " stream " + state.get(State.values.stream);
if (!state.get(values.driverstream).equals(driverstreamstate.disabled.toString()))
str += " selfstream " + state.get(State.values.driverstream);
// str += " pushtotalk " + settings.readSetting("pushtotalk");
if (loginRecords.isAdmin()) str += " admin true";
if (state.get(State.values.dockstatus) != null) str += " dock "+ state.get(State.values.dockstatus);
if (settings.getBoolean(ManualSettings.developer)) str += " developer true";
if (settings.getBoolean(GUISettings.navigation)) str += " navigation "+state.get(values.navsystemstatus);
String videoScale = settings.readSetting("videoscale");
if (videoScale != null) str += " videoscale " + videoScale;
str += " battery " + state.get(State.values.batterylife);
if (state.exists(values.record)) str += " record " + state.get(values.record);
messageplayer("status check received", "multiple", str.trim());
} else {
if (s.equals("battcheck")) {
messageplayer("status check received", "battery", state.get(State.values.batterylife));
} else { // ping only
messageplayer("status check received",null, null);
}
}
}
private void streamSettingsCustom(String str) {
settings.writeSettings(GUISettings.vset, "vcustom");
settings.writeSettings(GUISettings.vcustom, str);
String s = "custom stream set to: " + str;
if (!state.get(State.values.stream).equals(Application.streamstate.stop.toString()) &&
!state.getBoolean(State.values.autodocking)) {
publish(streamstate.valueOf(state.get(State.values.stream).toString()));
s += "<br>restarting stream";
}
messageplayer(s, null, null);
Util.log("stream changed to " + str,this);
}
private void streamSettingsSet(String str) {
settings.writeSettings(GUISettings.vset, "v" + str);
String s = "stream set to: " + str;
if (!state.get(State.values.stream).equals(Application.streamstate.stop.toString()) &&
!state.getBoolean(State.values.autodocking)) {
publish(streamstate.valueOf(state.get(State.values.stream).toString()));
s += "<br>restarting stream";
}
messageplayer(s, null, null);
Util.log("stream changed to " + str, this);
}
private String streamSettings() {
String result = "";
result += settings.readSetting("vset") + "_";
result += settings.readSetting("vlow") + "_" + settings.readSetting("vmed") + "_";
result += settings.readSetting("vhigh") + "_" + settings.readSetting("vfull") + "_";
result += settings.readSetting("vcustom");
return result;
}
private void restart() {
messageplayer("restarting server application", null, null);
int b = settings.getInteger(ManualSettings.restarted); // count java restarts vs booting
settings.writeSettings(ManualSettings.restarted, Integer.toString(b+1));
// THIS in developer mode, or just warning?
// if(settings.getInteger(ManualSettings.restarted) > 10){
// Util.log("restart called but reboot needed, going down..", this);
// write file as restart flag for script
File f = new File(Settings.redhome + Util.sep + "restart");
if (!f.exists()) try { f.createNewFile(); } catch (Exception e) {}
shutdownApplication();
}
private void reboot() {
Util.log("rebooting system", this);
PowerLogger.append("rebooting system", this);
powerport.writeStatusToEeprom();
killGrabber(); // prevents error dialog on chrome startup
settings.writeSettings(ManualSettings.restarted, "0");
if (navigation != null) { // TODO: << condition required?
if (state.exists(values.odomlinearpwm)) {
settings.writeSettings(ManualSettings.odomlinearpwm,
String.valueOf((int) comport.unVoltsComp(state.getDouble(values.odomlinearpwm))));
}
if (state.exists(values.odomturnpwm)) {
settings.writeSettings(ManualSettings.odomturnpwm,
String.valueOf((int) comport.unVoltsComp(state.getDouble(values.odomturnpwm))));
}
}
Util.delay(1000);
// if (!state.get(values.osarch).equals(ARM)) {
// Util.systemCall(Settings.redhome + Util.sep + "systemreboot.sh");
// }
// else Util.systemCall("/usr/bin/sudo /sbin/shutdown -r now");
Util.systemCall(Settings.redhome + Util.sep + "systemreboot.sh");
}
private void powerdown() { // typically called with powershutdown so has to happen quick, skip usual shutdown stuff
Util.log("powering down system", this);
PowerLogger.append("powering down system", this);
powerport.writeStatusToEeprom();
killGrabber(); // prevents error dialog on chrome startup
Util.delay(1000);
// if (!state.get(values.osarch).equals(ARM)) {
// Util.systemCall(Settings.redhome + Util.sep + "systemshutdown.sh");
// }
// else Util.systemCall("/usr/bin/sudo /sbin/shutdown -h now");
Util.systemCall(Settings.redhome + Util.sep + "systemshutdown.sh");
}
private void shutdownApplication() {
Util.log("shutting down application", this);
PowerLogger.append("shutting down application", this);
if(commandServer!=null) {
commandServer.sendToGroup(TelnetServer.TELNETTAG + " shutdown");
commandServer.close();
}
if (powerport.isConnected()) powerport.writeStatusToEeprom();
PowerLogger.close();
if (navigation != null) {
if (!state.get(State.values.navsystemstatus).equals(Ros.navsystemstate.stopped.toString()))
navigation.stopNavigation();
if (state.exists(values.odomlinearpwm)) {
settings.writeSettings(ManualSettings.odomlinearpwm,
String.valueOf((int) comport.unVoltsComp(state.getDouble(values.odomlinearpwm))));
}
if (state.exists(values.odomturnpwm)) {
settings.writeSettings(ManualSettings.odomturnpwm,
String.valueOf((int) comport.unVoltsComp(state.getDouble(values.odomturnpwm))));
}
}
if (! settings.getBoolean(ManualSettings.debugenabled)) killGrabber();
Util.systemCall(Settings.redhome + Util.sep + "red5-shutdown.sh");
}
private void move(final String str) {
if (str.equals(ArduinoPrime.direction.stop.name())) {
if (state.getBoolean(State.values.autodocking))
docker.autoDockCancel();
state.set(values.calibratingrotation, false);
comport.stopGoing();
moveMacroCancel();
message("command received: " + str, "motion", "STOPPED");
return;
}
if (state.getBoolean(State.values.autodocking)) {
messageplayer("command dropped, autodocking", null, null);
return;
}
if (str.equals(ArduinoPrime.direction.forward.toString())) {
if (!state.getBoolean(State.values.motionenabled)) state.set(State.values.motionenabled, true);
comport.goForward();
}
if (!state.getBoolean(State.values.motionenabled)) {
messageplayer("motion disabled (try forward)", "motion", "DISABLED");
return;
}
moveMacroCancel();
ArduinoPrime.direction dir = ArduinoPrime.direction.valueOf(str);
switch (dir) {
case backward: comport.goBackward(); break;
case right: comport.turnRight(); break;
case left: comport.turnLeft();
default: break;
}
messageplayer("command received: " + str, "motion", "MOVING");
}
private void nudge(String str) {
if (str == null) return;
if (!state.getBoolean(State.values.motionenabled)) {
messageplayer("motion disabled (try forward)", "motion", "disabled");
return;
}
if (state.getBoolean(State.values.autodocking)) {
messageplayer("command dropped, autodocking", null, null);
return;
}
comport.nudge(ArduinoPrime.direction.valueOf(str));
messageplayer("command received: nudge " + str, null, null);
if (state.getBoolean(State.values.docking) || state.getBoolean(State.values.autodocking)) moveMacroCancel();
}
private void motionEnableToggle() {
if (state.getBoolean(State.values.motionenabled)) {
state.set(State.values.motionenabled, false);
messageplayer("motion disabled", "motion", "disabled");
} else {
state.set(State.values.motionenabled, true);
messageplayer("motion enabled", "motion", "enabled");
}
}
private void clickSteer(String str) {
if (str == null) return;
if (!state.getBoolean(State.values.motionenabled)) {
messageplayer("motion disabled (try forward)", "motion", "disabled");
return;
}
if (state.getBoolean(State.values.autodocking)) {
messageplayer("command dropped, autodocking", null, null);
return;
}
moveMacroCancel();
String[] xy = str.split(" ");
comport.clickSteer(Integer.parseInt(xy[0]), Integer.parseInt(xy[1]));
}
public void messageGrabber(String str, String status) {
Util.debug("TO grabber flash: " + str + ", " + status, this);
if (grabber instanceof IServiceCapableConnection) {
IServiceCapableConnection sc = (IServiceCapableConnection) grabber;
sc.invoke("message", new Object[] { str, status });
}
if(commandServer != null) {
if(str!=null) commandServer.sendToGroup(TelnetServer.MSGGRABBERTAG + " " + str);
if (status != null) commandServer.sendToGroup(TelnetServer.MSGGRABBERTAG + " <status> " + status );
}
}
private String logintest(String user, String pass) {
int i;
String value = "";
String returnvalue = null;
if (user.equals("")) {
i = 0;
while (true) {
value = settings.readSetting("pass" + i);
if (value == null) {
break;
} else {
if (value.equals(pass)) {
returnvalue = settings.readSetting("user" + i);
break;
}
}
i++;
}
} else {
i = 0;
while (true) {
value = settings.readSetting("user" + i);
if (value == null) {
break;
} else {
if (value.equals(user)) {
if ((settings.readSetting("pass" + i)).equals(pass)) {
returnvalue = user;
}
break;
}
}
i++;
}
}
return returnvalue;
}
/** */
private void assumeControl(String user) {
messageplayer("controls hijacked", "hijacked", user);
if(player==null) return;
if(pendingplayer==null) { pendingplayerisnull = true; return; }
String con = "connected";
if (state.exists(values.relayclient)) {
IServiceCapableConnection t = (IServiceCapableConnection) relayclient;
t.invoke("playerSignIn", new Object[]{state.get(values.driver)});
con = "relay";
}
IConnection tmp = player;
player = pendingplayer;
pendingplayer = tmp;
state.set(State.values.driver, user);
String str = "connection "+con+" streamsettings " + streamSettings();
messageplayer(state.get(State.values.driver) + " connected to OCULUS", "multiple", str);
str = state.get(State.values.driver) + " connected from: " + player.getRemoteAddress();
Util.log("assumeControl(), " + str,this);
messageGrabber(str, null);
initialstatuscalled = false;
pendingplayerisnull = true;
loginRecords.beDriver();
if (settings.getBoolean(GUISettings.loginnotify)) {
saySpeech("lawg inn " + state.get(State.values.driver));
}
}
/** */
private void beAPassenger(String user) {
String stream = state.get(State.values.stream);
pendingplayerisnull = true;
String str = user + " added as passenger";
messageplayer(str, null, null);
Util.log(str,this);
messageGrabber(str, null);
if (!stream.equals("stop")) {
Collection<Set<IConnection>> concollection = getConnections();
for (Set<IConnection> cc : concollection) {
for (IConnection con : cc) {
if (con instanceof IServiceCapableConnection
&& con != grabber && con != player) {
IServiceCapableConnection sc = (IServiceCapableConnection) con;
sc.invoke("message", new Object[] { "streaming " + stream, "green", "stream", stream }); }
}
}
}
loginRecords.bePassenger(user);
if (settings.getBoolean(GUISettings.loginnotify)) {
saySpeech("passenger lawg inn f" + user);
}
}
/**
* Broadcast remote web client microphone through robot speaker
* @param str mode (stop, mic, pending)
*
* need to reload webcam capture webpage on robot, and remote web page to enable
* enhanced mic, then reload both again when turning off mic
*
* reload grabber, restart video stream if necessary
* wait
* reload remote client
*
*/
private void playerBroadCast(final String str) {
if (player instanceof IServiceCapableConnection) {
if (str.equals(driverstreamstate.mic.toString())) { // player mic
if (state.get(State.values.driverstream).equals(driverstreamstate.mic.toString())) return;
String vals[] = "320_240_8_85".split("_"); // TODO: nuke this, for audio only
final int width = Integer.parseInt(vals[0]);
final int height = Integer.parseInt(vals[1]);
final int fps = Integer.parseInt(vals[2]);
final int quality = Integer.parseInt(vals[3]);
final streamstate mode = streamstate.valueOf(state.get(State.values.stream));
state.set(State.values.driverstream, driverstreamstate.pending.toString());
new Thread(new Runnable() {
public void run() {
try {
messageplayer("starting self mic, reloading page", null, null);
// reload grabber page with enhanced mic
messageGrabber("loadpage", "server.html?broadcast"); // reload page
Thread.sleep(STREAM_CONNECT_DELAY);
// restart stream if necessary
if (!mode.equals(streamstate.stop)) {
publish(mode);
Thread.sleep(STREAM_CONNECT_DELAY);
}
// reload driver page with enhanced mic
messageplayer(null, "loadpage","?broadcast");
Thread.sleep(STREAM_CONNECT_DELAY*3);
// start driver mic
IServiceCapableConnection sc = (IServiceCapableConnection) player;
sc.invoke("publish", new Object[] { str, width, height, fps, quality, false });
state.set(State.values.driverstream, driverstreamstate.mic.toString());
Thread.sleep(50);
messageplayer("self mic on", "selfstream",state.get(State.values.driverstream));
Thread.sleep(STREAM_CONNECT_DELAY);
grabberPlayPlayer(1);
} catch (Exception e) {
Util.printError(e);
}
}
}).start();
} else { // player broadcast stop/off
if (state.get(State.values.driverstream).equals(driverstreamstate.stop.toString())) return;
final streamstate mode = streamstate.valueOf(state.get(State.values.stream));
state.set(State.values.driverstream, driverstreamstate.pending.toString());
new Thread(new Runnable() {
public void run() {
try {
messageplayer("stopping self mic, reloading page", null, null);
messageGrabber("loadpage", "server.html"); // reload page normal mic
Thread.sleep(STREAM_CONNECT_DELAY);
// restart stream if necessary
if (!mode.equals(streamstate.stop)) {
publish(mode);
Thread.sleep(STREAM_CONNECT_DELAY);
}
messageplayer(null, "loadpage","?");
Thread.sleep(STREAM_CONNECT_DELAY);
state.set(State.values.driverstream, driverstreamstate.stop.toString());
messageplayer("self mic off", "selfstream",state.get(State.values.driverstream));
} catch (Exception e) {
Util.printError(e);
}
}
}).start();
}
}
}
private void grabberPlayPlayer(int nostreams) {
if (grabber instanceof IServiceCapableConnection) {
IServiceCapableConnection sc = (IServiceCapableConnection) grabber;
sc.invoke("play", new Object[] { nostreams });
}
}
private void account(String fn, String str) {
if (fn.equals("password_update")) passwordChange(state.get(State.values.driver), str);
if (fn.equals("new_user_add")) {
String message = "";
Boolean oktoadd = true;
String u[] = str.split(" ");
if (!u[0].matches("\\w+")) {
message += "error: username must be letters/numbers only ";
oktoadd = false;
}
if (!u[1].matches("\\w+")) {
message += "error: password must be letters/numbers only ";
oktoadd = false;
}
int i = 0;
String s;
while (true) {
s = settings.readSetting("user" + i);
if (s == null) break;
if ((s.toUpperCase()).equals((u[0]).toUpperCase())) {
message += "ERROR: user name already exists ";
oktoadd = false;
}
i++;
}
// add check for existing user, user loop below to get i while you're at it
if (oktoadd) {
message += "added user " + u[0];
settings.newSetting("user" + i, u[0]);
String p = u[0] + salt + u[1];
String encryptedPassword = passwordEncryptor.encryptPassword(p);
settings.newSetting("pass" + i, encryptedPassword);
}
messageplayer(message, null, null);
}
if (fn.equals("user_list")) {
int i = 1;
String users = "";
String u;
while (true) {
u = settings.readSetting("user" + i);
if (u == null) {
break;
} else {
users += u + " ";
}
i++;
}
sendplayerfunction("userlistpopulate", users);
}
if (fn.equals("delete_user")) {
int i = 1;
int usernum = -1;
int maxusernum = -1;
String[] allusers = new String[999];
String[] allpasswords = new String[999];
String u;
while (true) {
// read & store all users+passwords, note number to be deleted, and max number
u = settings.readSetting("user" + i);
if (u == null) {
maxusernum = i - 1;
break;
}
if (u.equals(str)) {
usernum = i;
}
allusers[i] = u;
allpasswords[i] = settings.readSetting("pass" + i);
i++;
}
if (usernum > 0) {
i = usernum;
while (i <= maxusernum) { // delete user to be delted + all after
settings.deleteSetting("user" + i);
settings.deleteSetting("pass" + i);
i++;
}
i = usernum + 1;
while (i <= maxusernum) { // shuffle remaining past deleted one, down one
settings.newSetting("user" + (i - 1), allusers[i]);
settings.newSetting("pass" + (i - 1), allpasswords[i]);
i++;
}
}
messageplayer(str + " deleted.", null, null);
}
if (fn.equals("extrauser_password_update")) {
String s[] = str.split(" ");
passwordChange(s[0], s[1]);
}
if (fn.equals("username_update")) {
String u[] = str.split(" ");
String message = "";
Boolean oktoadd = true;
if (!u[0].matches("\\w+")) {
message += "error: username must be letters/numbers only ";
oktoadd = false;
}
int i = 1;
String s;
while (true) {
s = settings.readSetting("user" + i);
if (s == null) {
break;
}
if ((s.toUpperCase()).equals(u[0].toUpperCase())) {
message += "error: user name already exists ";
oktoadd = false;
}
i++;
}
String encryptedPassword = (passwordEncryptor.encryptPassword(state.get(State.values.driver) + salt + u[1])).trim();
if (logintest(state.get(State.values.driver), encryptedPassword) == null) {
message += "error: wrong password";
oktoadd = false;
}
if (oktoadd) {
message += "username changed to: " + u[0];
messageplayer("username changed to: " + u[0], "user", u[0]);
settings.writeSettings("user0", u[0]);
state.set(State.values.driver, u[0]);
String p = u[0] + salt + u[1];
encryptedPassword = passwordEncryptor.encryptPassword(p);
settings.writeSettings("pass0", encryptedPassword);
} else {
messageplayer(message, null, null);
}
}
}
private void passwordChange(final String user, final String pass) {
Util.debug(user + " " + pass, this);
String message = "password updated";
if (pass.matches("\\w+")) {
String p = user + salt + pass;
String encryptedPassword = passwordEncryptor.encryptPassword(p);
int i = 0;
String u;
while (true) {
u = settings.readSetting("user" + i);
if (u == null) {
break;
} else {
if (u.equals(user)) {
settings.writeSettings("pass" + i, encryptedPassword);
break;
}
}
i++;
}
} else {
message = "error: password must be alpha-numeric with no spaces";
}
messageplayer(message, null, null);
}
private void disconnectOtherConnections() {
if (loginRecords.isAdmin()) {
int i = 0;
Collection<Set<IConnection>> concollection = getConnections();
for (Set<IConnection> cc : concollection) {
for (IConnection con : cc) {
if (con instanceof IServiceCapableConnection
&& con != grabber && con != player) {
con.close();
i++;
}
}
}
messageplayer(i + " passengers eliminated", null, null);
}
}
private void chat(String str) {
Collection<Set<IConnection>> concollection = getConnections();
for (Set<IConnection> cc : concollection) {
for (IConnection con : cc) {
if (con instanceof IServiceCapableConnection && con != grabber
&& !(con == pendingplayer && !pendingplayerisnull)) {
IServiceCapableConnection n = (IServiceCapableConnection) con;
n.invoke("message", new Object[] { str, "yellow", null, null });
}
}
}
Util.log("chat: " + str,this);
messageGrabber("<CHAT>" + str, null);
if(str!=null) if (commandServer != null) {
str = str.replaceAll("</?i>", "");
commandServer.sendToGroup(TelnetServer.TELNETTAG+" chat from "+ str);
}
}
private void showlog(String str) {
int lines = 100; //default
if (!str.equals("")) { lines = Integer.parseInt(str); }
String header = "last "+ Integer.toString(lines) +" line(s) from "+Settings.stdout+" :<br>";
sendplayerfunction("showserverlog", header + Util.tail(lines));
}
private void softwareUpdate(String str) {
if (str.equals("check")) {
messageplayer("checking for new software...", null, null);
Updater updater = new Updater();
double currver = updater.getCurrentVersion();
String fileurl = updater.checkForUpdateFile();
double newver = updater.versionNum(fileurl);
if (newver > currver) {
String message = "New version available: v." + newver + "\n";
if (currver == -1) {
message += "Current software version unknown\n";
} else {
message += "Current software is v." + currver + "\n";
}
message += "Do you want to download and install?";
messageplayer("new version available", "softwareupdate",
message);
} else {
messageplayer("no new version available", null, null);
}
}
if (str.equals("download")) {
messageplayer("downloading software update...", null, null);
new Thread(new Runnable() {
public void run() {
Updater up = new Updater();
final String fileurl = up.checkForUpdateFile();
Util.log("downloading url: " + fileurl,this);
Downloader dl = new Downloader();
if (dl.FileDownload(fileurl, "update.zip", "download")) {
messageplayer("update download complete, unzipping...",
null, null);
// this is a blocking call
if (dl.unzipFolder("download"+Util.sep+"update.zip", "webapps"))
messageplayer("done.", "softwareupdate",
"downloadcomplete");
// not needed now is unpacked
dl.deleteDir(new File(Settings.redhome+Util.sep+"download"));
} else {
messageplayer("update download failed", null, null);
}
}
}).start();
}
if (str.equals("versiononly")) {
double currver = new Updater().getCurrentVersion();
String msg = "";
if (currver == -1)
msg = "version unknown";
else
msg = "version: v." + currver;
messageplayer(msg, null, null);
}
}
public void factoryReset() {
final String backup = "conf"+Util.sep+"backup_oculus_settings.txt";
// backup
new File(Settings.settingsfile).renameTo(new File(backup));
// delete it, build on startup
new File(Settings.settingsfile).delete();
restart();
}
private void setStreamActivityThreshold(String str) {
String val[] = str.split("\\D+");
if (val.length != 2) { return; }
Integer videoThreshold = Integer.parseInt(val[0]);
Integer audioThreshold = Integer.parseInt(val[1]);
String stream = state.get(State.values.stream);
state.delete(State.values.streamactivity);
state.set(State.values.streamactivitythreshold, str);
if (videoThreshold != 0 || audioThreshold != 0) {
if (state.get(State.values.videosoundmode).equals(VIDEOSOUNDMODEHIGH)) {
setGrabberVideoSoundMode(VIDEOSOUNDMODELOW); // videosoundmode needs to be low to for activity threshold to work
if (stream != null) {
if (!stream.equals(streamstate.stop.toString())) { // if stream already running,
publish(streamstate.valueOf(stream)); // restart, in low mode
}
}
}
if (stream != null) {
if (stream.equals(streamstate.stop.toString())) {
if (audioThreshold == 0 && videoThreshold != 0) { publish(streamstate.camera); }
else if (audioThreshold != 0 && videoThreshold == 0) { publish(streamstate.mic); }
else { publish(streamstate.camandmic); }
}
}
state.set(State.values.streamactivityenabled.name(), System.currentTimeMillis());
}
else { // 0 0, disable streamActivityDetected()
state.delete(State.values.streamactivityenabled);
state.delete(State.values.streamactivitythreshold);
}
long timeout = System.currentTimeMillis() + GRABBERRELOADTIMEOUT;
while (!(grabber instanceof IServiceCapableConnection) && System.currentTimeMillis() < timeout ) { Util.delay(10); }
if (!(grabber instanceof IServiceCapableConnection))
Util.log("setStreamActivityThreshold() error grabber reload timeout", this);
IServiceCapableConnection sc = (IServiceCapableConnection) grabber;
sc.invoke("setActivityThreshold", new Object[]{videoThreshold, audioThreshold});
messageplayer("stream activity set to: " + str, null, null);
}
private void streamActivityDetected(String str) {
if (! state.exists(State.values.streamactivityenabled)) return;
// to catch false audio detect on driver login... TODO: find root cause, not just this patch
if (str.split(" ")[0].equals("audio")) { // note: video deprecated
int audiodetected = Integer.valueOf(str.split(" ")[1]);
int audiothreshold = Integer.valueOf(state.get(values.streamactivitythreshold).split(" ")[1]);
// Util.log(audiodetected+ " "+audiothreshold, this);
if (audiodetected < audiothreshold) {
setStreamActivityThreshold(state.get(values.streamactivitythreshold)); // restarts stream
return;
}
}
if (System.currentTimeMillis() > state.getLong(State.values.streamactivityenabled) + 5000.0) {
messageplayer("streamactivity: "+str, "streamactivity", str);
setStreamActivityThreshold("0 0"); // disable
state.set(State.values.streamactivity, str); // needs to be after disable, method deletes state val
}
}
}