Initial commit of Java wrappers.

The JNI bindings are built directly into the shared library.  In the gradle
build, all built shared libraries are embedded into the generated jar.

Java bindings may be disabled via -DWITHOUT_JAVA (cmake) or -PskipJava=true
(gradle).

TODO:
- getEntryInfo() and RPC are not yet implemented.
- The cmake build doesn't integrate the built objects into the jar.
- The Java client and server tests are not built (but have been manually
  tested).

This has not yet been tested on Windows.
This commit is contained in:
Peter Johnson
2015-08-28 12:35:04 -07:00
parent 9c576b10d0
commit a990859db6
16 changed files with 2807 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,17 @@
package edu.wpi.first.wpilibj.networktables;
public class ConnectionInfo {
final String remote_id;
final String remote_name;
final int remote_port;
final long last_update;
final int protocol_version;
ConnectionInfo(String remote_id, String remote_name, int remote_port, long last_update, int protocol_version) {
this.remote_id = remote_id;
this.remote_name = remote_name;
this.remote_port = remote_port;
this.last_update = last_update;
this.protocol_version = protocol_version;
}
}

View File

@@ -0,0 +1,735 @@
package edu.wpi.first.wpilibj.networktables;
import edu.wpi.first.wpilibj.tables.*;
import java.io.*;
import java.util.*;
/**
* A network table that knows its subtable path.
*
*/
public class NetworkTable implements ITable, IRemote {
/**
* The path separator for sub-tables and keys
*
*/
public static final char PATH_SEPARATOR = '/';
/**
* The default port that network tables operates on
*/
public static final int DEFAULT_PORT = 1735;
private static boolean client = false;
private static boolean running = false;
private static int port = DEFAULT_PORT;
private static String ipAddress = null;
private static String persistentFilename = "networktables.ini";
private synchronized static void checkInit() {
if (running)
throw new IllegalStateException(
"Network tables has already been initialized");
}
/**
* initializes network tables
*/
public synchronized static void initialize() {
checkInit();
if (client)
NetworkTablesJNI.startClient(ipAddress, port);
else
NetworkTablesJNI.startServer(persistentFilename, ipAddress, port);
running = true;
}
/**
* set that network tables should be a server
* This must be called before initalize or getTable
*/
public synchronized static void setServerMode() {
checkInit();
client = false;
}
/**
* set that network tables should be a client
* This must be called before initalize or getTable
*/
public synchronized static void setClientMode() {
checkInit();
client = true;
}
/**
* set the team the robot is configured for (this will set the ip address that
* network tables will connect to in client mode)
* This must be called before initalize or getTable
* @param team the team number
*/
public synchronized static void setTeam(int team) {
setIPAddress("10." + (team / 100) + "." + (team % 100) + ".2");
}
/**
* @param address the adress that network tables will connect to in client
* mode
*/
public synchronized static void setIPAddress(final String address) {
checkInit();
ipAddress = address;
}
/**
* @param port the port number that network tables will connect to in client
* mode or listen to in server mode
*/
public synchronized static void setPort(int aport) {
checkInit();
port = aport;
}
/**
* Gets the table with the specified key. If the table does not exist, a new
*table will be created.<br>
* This will automatically initialize network tables if it has not been
*already
*
* @param key
* the key name
* @return the network table requested
*/
public synchronized static NetworkTable getTable(String key) {
if (!running)
initialize();
if (key.isEmpty())
return new NetworkTable(key);
return new NetworkTable(PATH_SEPARATOR + key);
}
private final String path;
NetworkTable(String path) {
this.path = path;
}
public String toString() { return "NetworkTable: " + path; }
public boolean isConnected() {
ConnectionInfo[] conns = NetworkTablesJNI.getConnections();
return conns.length > 0;
}
public boolean isServer() {
return !client;
}
private class ListenerBase {
public int uid;
}
private class ConnectionListenerAdapter extends ListenerBase implements NetworkTablesJNI.ConnectionListenerFunction {
private final IRemote targetSource;
private final IRemoteConnectionListener targetListener;
public ConnectionListenerAdapter(IRemote targetSource, IRemoteConnectionListener targetListener) {
this.targetSource = targetSource;
this.targetListener = targetListener;
}
public void apply(int uid, boolean connected, ConnectionInfo conn) {
if (connected)
targetListener.connected(targetSource);
else
targetListener.disconnected(targetSource);
}
}
private final Hashtable<IRemoteConnectionListener,ConnectionListenerAdapter> connectionListenerMap = new Hashtable<IRemoteConnectionListener,ConnectionListenerAdapter>();
public synchronized void addConnectionListener(IRemoteConnectionListener listener,
boolean immediateNotify) {
ConnectionListenerAdapter adapter = connectionListenerMap.get(listener);
if (adapter != null)
throw new IllegalStateException("Cannot add the same listener twice");
adapter = new ConnectionListenerAdapter(this, listener);
adapter.uid = NetworkTablesJNI.addConnectionListener(adapter, immediateNotify);
connectionListenerMap.put(listener, adapter);
}
public synchronized void removeConnectionListener(IRemoteConnectionListener listener) {
ConnectionListenerAdapter adapter = connectionListenerMap.get(listener);
if (adapter != null) {
NetworkTablesJNI.removeConnectionListener(adapter.uid);
connectionListenerMap.remove(listener);
}
}
public void addTableListener(ITableListener listener) {
addTableListener(listener, false);
}
private class TableListenerAdapter extends ListenerBase implements NetworkTablesJNI.EntryListenerFunction {
private final int prefixLen;
private final ITable targetSource;
private final ITableListener targetListener;
public TableListenerAdapter(int prefixLen, ITable targetSource, ITableListener targetListener) {
this.prefixLen = prefixLen;
this.targetSource = targetSource;
this.targetListener = targetListener;
}
public void apply(int uid, String key, Object value, boolean isNew) {
String relativeKey = key.substring(prefixLen);
if (relativeKey.indexOf(PATH_SEPARATOR) != -1)
return;
targetListener.valueChanged(targetSource, relativeKey, value, isNew);
}
}
private final Hashtable<ITableListener,List<ListenerBase>> listenerMap = new Hashtable<ITableListener,List<ListenerBase>>();
public synchronized void addTableListener(ITableListener listener,
boolean immediateNotify) {
List<ListenerBase> adapters = listenerMap.get(listener);
if (adapters == null) {
adapters = new ArrayList<ListenerBase>();
listenerMap.put(listener, adapters);
}
TableListenerAdapter adapter =
new TableListenerAdapter(path.length() + 1, this, listener);
adapter.uid = NetworkTablesJNI.addEntryListener(path + PATH_SEPARATOR, adapter, immediateNotify);
adapters.add(adapter);
}
private class KeyListenerAdapter extends ListenerBase implements NetworkTablesJNI.EntryListenerFunction {
private final String relativeKey;
private final String fullKey;
private final ITable targetSource;
private final ITableListener targetListener;
public KeyListenerAdapter(String relativeKey, String fullKey, ITable targetSource, ITableListener targetListener) {
this.relativeKey = relativeKey;
this.fullKey = fullKey;
this.targetSource = targetSource;
this.targetListener = targetListener;
}
public void apply(int uid, String key, Object value, boolean isNew) {
if (!key.equals(fullKey))
return;
targetListener.valueChanged(targetSource, relativeKey, value, isNew);
}
}
public synchronized void addTableListener(String key, ITableListener listener,
boolean immediateNotify) {
List<ListenerBase> adapters = listenerMap.get(listener);
if (adapters == null) {
adapters = new ArrayList<ListenerBase>();
listenerMap.put(listener, adapters);
}
String fullKey = path + PATH_SEPARATOR + key;
KeyListenerAdapter adapter =
new KeyListenerAdapter(key, fullKey, this, listener);
adapter.uid = NetworkTablesJNI.addEntryListener(fullKey, adapter, immediateNotify);
adapters.add(adapter);
}
private class SubListenerAdapter extends ListenerBase implements NetworkTablesJNI.EntryListenerFunction {
private final int prefixLen;
private final ITable targetSource;
private final ITableListener targetListener;
private final Set<String> notifiedTables = new HashSet<String>();
public SubListenerAdapter(int prefixLen, ITable targetSource, ITableListener targetListener) {
this.prefixLen = prefixLen;
this.targetSource = targetSource;
this.targetListener = targetListener;
}
public void apply(int uid, String key, Object value, boolean isNew) {
String relativeKey = key.substring(prefixLen);
int endSubTable = relativeKey.indexOf(PATH_SEPARATOR);
if (endSubTable == -1)
return;
String subTableKey = relativeKey.substring(0, endSubTable);
if (notifiedTables.contains(subTableKey))
return;
notifiedTables.add(subTableKey);
targetListener.valueChanged(targetSource, subTableKey, targetSource.getSubTable(subTableKey), true);
}
}
public synchronized void addSubTableListener(final ITableListener listener) {
List<ListenerBase> adapters = listenerMap.get(listener);
if (adapters == null) {
adapters = new ArrayList<ListenerBase>();
listenerMap.put(listener, adapters);
}
SubListenerAdapter adapter =
new SubListenerAdapter(path.length() + 1, this, listener);
adapter.uid = NetworkTablesJNI.addEntryListener(path + PATH_SEPARATOR, adapter, true);
adapters.add(adapter);
}
public synchronized void removeTableListener(ITableListener listener) {
List<ListenerBase> adapters = listenerMap.get(listener);
if (adapters != null) {
for (int i = 0; i < adapters.size(); ++i)
NetworkTablesJNI.removeEntryListener(adapters.get(i).uid);
adapters.clear();
}
}
/**
* Returns the table at the specified key. If there is no table at the
* specified key, it will create a new table
*
* @param key
* the key name
* @return the networktable to be returned
*/
public ITable getSubTable(String key) {
return new NetworkTable(path + PATH_SEPARATOR + key);
}
/**
* Checks the table and tells if it contains the specified key
*
* @param key
* the key to be checked
*/
public boolean containsKey(String key) {
return NetworkTablesJNI.containsKey(path + PATH_SEPARATOR + key);
}
public boolean containsSubTable(String key) {
String subtablePrefix = path + key + PATH_SEPARATOR;
//List keys = node.getEntryStore().keys();
//for (int i = 0; i < keys.size(); ++i) {
// if (((String)keys.get(i)).startsWith(subtablePrefix))
// return true;
//}
return false;
}
/**
* Maps the specified key to the specified value in this table. The key can
* not be null. The value can be retrieved by calling the get method with a
* key that is equal to the original key.
*
* @param key
* the key
* @param value
* the value
*/
public void putNumber(String key, double value) {
NetworkTablesJNI.putDouble(path + PATH_SEPARATOR + key, value);
}
/**
* Returns the key that the name maps to.
*
* @param key
* the key name
* @return the key
* @throws TableKeyNotDefinedException
* if the specified key is null
*/
public double getNumber(String key) throws TableKeyNotDefinedException {
return NetworkTablesJNI.getDouble(path + PATH_SEPARATOR + key);
}
/**
* Returns the key that the name maps to. If the key is null, it will return
* the default value
*
* @param key
* the key name
* @param defaultValue
* the default value if the key is null
* @return the key
*/
public double getNumber(String key, double defaultValue) {
return NetworkTablesJNI.getDouble(path + PATH_SEPARATOR + key, defaultValue);
}
/**
* Maps the specified key to the specified value in this table. The key can
* not be null. The value can be retrieved by calling the get method with a
* key that is equal to the original key.
*
* @param key
* the key
* @param value
* the value
*/
public void putString(String key, String value) {
NetworkTablesJNI.putString(path + PATH_SEPARATOR + key, value);
}
/**
* Returns the key that the name maps to.
*
* @param key
* the key name
* @return the key
* @throws TableKeyNotDefinedException
* if the specified key is null
*/
public String getString(String key) throws TableKeyNotDefinedException {
return NetworkTablesJNI.getString(path + PATH_SEPARATOR + key);
}
/**
* Returns the key that the name maps to. If the key is null, it will return
* the default value
*
* @param key
* the key name
* @param defaultValue
* the default value if the key is null
* @return the key
*/
public String getString(String key, String defaultValue) {
return NetworkTablesJNI.getString(path + PATH_SEPARATOR + key, defaultValue);
}
/**
* Maps the specified key to the specified value in this table. The key can
* not be null. The value can be retrieved by calling the get method with a
* key that is equal to the original key.
*
* @param key
* the key
* @param value
* the value
*/
public void putBoolean(String key, boolean value) {
NetworkTablesJNI.putBoolean(path + PATH_SEPARATOR + key, value);
}
/**
* Returns the key that the name maps to.
*
* @param key
* the key name
* @return the key
* @throws TableKeyNotDefinedException
* if the specified key is null
*/
public boolean getBoolean(String key) throws TableKeyNotDefinedException {
return NetworkTablesJNI.getBoolean(path + PATH_SEPARATOR + key);
}
/**
* Returns the key that the name maps to. If the key is null, it will return
* the default value
*
* @param key
* the key name
* @param defaultValue
* the default value if the key is null
* @return the key
*/
public boolean getBoolean(String key, boolean defaultValue) {
return NetworkTablesJNI.getBoolean(path + PATH_SEPARATOR + key, defaultValue);
}
/**
* Maps the specified key to the specified value in this table. The key can
* not be null. The value can be retrieved by calling the get method with a
* key that is equal to the original key.
*
* @param key
* the key
* @param value
* the value
*/
public void putBooleanArray(String key, boolean[] value) {
NetworkTablesJNI.putBooleanArray(path + PATH_SEPARATOR + key, value);
}
/**
* Returns the key that the name maps to.
*
* @param key
* the key name
* @return the key
* @throws TableKeyNotDefinedException
* if the specified key is null
*/
public boolean[] getBooleanArray(String key) throws TableKeyNotDefinedException {
return NetworkTablesJNI.getBooleanArray(path + PATH_SEPARATOR + key);
}
/**
* Returns the key that the name maps to. If the key is null, it will return
* the default value
*
* @param key
* the key name
* @param defaultValue
* the default value if the key is null
* @return the key
*/
public boolean[] getBooleanArray(String key, boolean[] defaultValue) {
return NetworkTablesJNI.getBooleanArray(path + PATH_SEPARATOR + key, defaultValue);
}
/**
* Maps the specified key to the specified value in this table. The key can
* not be null. The value can be retrieved by calling the get method with a
* key that is equal to the original key.
*
* @param key
* the key
* @param value
* the value
*/
public void putNumberArray(String key, double[] value) {
NetworkTablesJNI.putDoubleArray(path + PATH_SEPARATOR + key, value);
}
/**
* Returns the key that the name maps to.
*
* @param key
* the key name
* @return the key
* @throws TableKeyNotDefinedException
* if the specified key is null
*/
public double[] getNumberArray(String key) throws TableKeyNotDefinedException {
return NetworkTablesJNI.getDoubleArray(path + PATH_SEPARATOR + key);
}
/**
* Returns the key that the name maps to. If the key is null, it will return
* the default value
*
* @param key
* the key name
* @param defaultValue
* the default value if the key is null
* @return the key
*/
public double[] getNumberArray(String key, double[] defaultValue) {
return NetworkTablesJNI.getDoubleArray(path + PATH_SEPARATOR + key, defaultValue);
}
/**
* Maps the specified key to the specified value in this table. The key can
* not be null. The value can be retrieved by calling the get method with a
* key that is equal to the original key.
*
* @param key
* the key
* @param value
* the value
*/
public void putStringArray(String key, String[] value) {
NetworkTablesJNI.putStringArray(path + PATH_SEPARATOR + key, value);
}
/**
* Returns the key that the name maps to.
*
* @param key
* the key name
* @return the key
* @throws TableKeyNotDefinedException
* if the specified key is null
*/
public String[] getStringArray(String key) throws TableKeyNotDefinedException {
return NetworkTablesJNI.getStringArray(path + PATH_SEPARATOR + key);
}
/**
* Returns the key that the name maps to. If the key is null, it will return
* the default value
*
* @param key
* the key name
* @param defaultValue
* the default value if the key is null
* @return the key
*/
public String[] getStringArray(String key, String[] defaultValue) {
return NetworkTablesJNI.getStringArray(path + PATH_SEPARATOR + key, defaultValue);
}
/**
* Maps the specified key to the specified value in this table. The key can
* not be null. The value can be retrieved by calling the get method with a
* key that is equal to the original key.
*
* @param key the key name
* @param value the value to be put
*/
public void putValue(String key, Object value) {
if (value instanceof Boolean)
NetworkTablesJNI.putBoolean(path + PATH_SEPARATOR + key, ((Boolean)value).booleanValue());
else if (value instanceof Double)
NetworkTablesJNI.putDouble(path + PATH_SEPARATOR + key, ((Double)value).doubleValue());
else if (value instanceof String)
NetworkTablesJNI.putString(path + PATH_SEPARATOR + key, (String)value);
else if (value instanceof byte[])
NetworkTablesJNI.putRaw(path + PATH_SEPARATOR + key, (byte[])value);
else if (value instanceof boolean[])
NetworkTablesJNI.putBooleanArray(path + PATH_SEPARATOR + key, (boolean[])value);
else if (value instanceof double[])
NetworkTablesJNI.putDoubleArray(path + PATH_SEPARATOR + key, (double[])value);
else if (value instanceof String[])
NetworkTablesJNI.putStringArray(path + PATH_SEPARATOR + key, (String[])value);
}
/**
* Returns the key that the name maps to.
* NOTE: If the value is a double, it will return a Double object,
* not a primitive. To get the primitive, use getDouble
*
* @param key
* the key name
* @return the key
* @throws TableKeyNotDefinedException
* if the specified key is null
*/
public Object getValue(String key) throws TableKeyNotDefinedException {
return NetworkTablesJNI.getValue(path + PATH_SEPARATOR + key);
}
/**
* Returns the key that the name maps to. If the key is null, it will return
* the default value
* NOTE: If the value is a double, it will return a Double object,
* not a primitive. To get the primitive, use getDouble
*
* @param key
* the key name
* @param defaultValue
* the default value if the key is null
* @return the key
*/
public Object getValue(String key, Object defaultValue) {
return NetworkTablesJNI.getValue(path + PATH_SEPARATOR + key, defaultValue);
}
/** The persistent flag value. */
public static final int PERSISTENT = 1;
/**
* Sets flags on the specified key in this table. The key can
* not be null.
*
* @param key the key name
* @param flags the flags to set
*/
public void setFlags(String key, int flags) {
NetworkTablesJNI.setEntryFlags(path + PATH_SEPARATOR + key, flags);
}
/**
* Returns the flags for the specified key.
*
* @param key
* the key name
* @return the flags, or 0 if the key is not defined
*/
public int getFlags(String key) {
return NetworkTablesJNI.getEntryFlags(path + PATH_SEPARATOR + key);
}
/*
* Deprecated Methods
*/
/**
* @deprecated
* Maps the specified key to the specified value in this table.
* The key can not be null.
* The value can be retrieved by calling the get method with a key that is
* equal to the original key.
* @param key the key
* @param value the value
* @throws IllegalArgumentException if key is null
*/
public void putInt(String key, int value) { putNumber(key, value); }
/**
* @deprecated
* Returns the value at the specified key.
* @param key the key
* @return the value
* @throws TableKeyNotDefinedException if there is no value mapped to by the
* key
* @throws IllegalArgumentException if the value mapped to by the key is not
* an int
* @throws IllegalArgumentException if the key is null
*/
public int getInt(String key) throws TableKeyNotDefinedException {
return (int)getNumber(key);
}
/**
* @deprecated
* Returns the value at the specified key.
* @param key the key
* @param defaultValue the value returned if the key is undefined
* @return the value
* @throws NetworkTableKeyNotDefined if there is no value mapped to by the key
* @throws IllegalArgumentException if the value mapped to by the key is not
* an int
* @throws IllegalArgumentException if the key is null
*/
public int getInt(String key, int defaultValue) throws TableKeyNotDefinedException {
try {
return (int)getNumber(key);
} catch (NoSuchElementException ex) {
return defaultValue;
}
}
/**
* @deprecated
* Maps the specified key to the specified value in this table.
* The key can not be null.
* The value can be retrieved by calling the get method with a key that is
* equal to the original key.
* @param key the key
* @param value the value
* @throws IllegalArgumentException if key is null
*/
public void putDouble(String key, double value) {
putNumber(key, value);
}
/**
* @deprecated
* Returns the value at the specified key.
* @param key the key
* @return the value
* @throws NoSuchEleNetworkTableKeyNotDefinedmentException if there is no
* value mapped to by the key
* @throws IllegalArgumentException if the value mapped to by the key is not a
* double
* @throws IllegalArgumentException if the key is null
*/
public double getDouble(String key) throws TableKeyNotDefinedException {
return getNumber(key);
}
/**
* @deprecated
* Returns the value at the specified key.
* @param key the key
* @param defaultValue the value returned if the key is undefined
* @return the value
* @throws NoSuchEleNetworkTableKeyNotDefinedmentException if there is no
* value mapped to by the key
* @throws IllegalArgumentException if the value mapped to by the key is not a
* double
* @throws IllegalArgumentException if the key is null
*/
public double getDouble(String key, double defaultValue) {
return getNumber(key, defaultValue);
}
}

View File

@@ -0,0 +1,22 @@
package edu.wpi.first.wpilibj.networktables;
import edu.wpi.first.wpilibj.tables.TableKeyNotDefinedException;
/**
* An exception throw when the lookup a a key-value fails in a {@link NetworkTable}
*
* @deprecated to provide backwards compatability for new api
*
* @author Mitchell
*
*/
public class NetworkTableKeyNotDefined extends TableKeyNotDefinedException {
/**
* @param key the key that was not defined in the table
*/
public NetworkTableKeyNotDefined(String key) {
super(key);
}
}

View File

@@ -0,0 +1,145 @@
package edu.wpi.first.wpilibj.networktables;
import edu.wpi.first.wpilibj.tables.*;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class NetworkTablesJNI {
static boolean libraryLoaded = false;
static File jniLibrary = null;
static {
if (!libraryLoaded) {
try {
String osname = System.getProperty("os.name");
String resname = "/" + osname + "/" + System.getProperty("os.arch") + "/";
System.out.println("platform: " + resname);
if (osname.startsWith("Windows"))
resname += "ntcore.dll";
else
resname += "libntcore.so";
InputStream is = NetworkTablesJNI.class.getResourceAsStream(resname);
if (is != null) {
// create temporary file
if (System.getProperty("os.name").startsWith("Windows"))
jniLibrary = File.createTempFile("NetworkTablesJNI", ".dll");
else
jniLibrary = File.createTempFile("libNetworkTablesJNI", ".so");
// flag for delete on exit
jniLibrary.deleteOnExit();
OutputStream os = new FileOutputStream(jniLibrary);
byte[] buffer = new byte[1024];
int readBytes;
try {
while ((readBytes = is.read(buffer)) != -1) {
os.write(buffer, 0, readBytes);
}
} finally {
os.close();
is.close();
}
System.load(jniLibrary.getAbsolutePath());
} else {
if (osname.startsWith("Windows"))
System.loadLibrary("ntcore.dll");
else
System.loadLibrary("libntcore.so");
}
} catch (IOException ex) {
ex.printStackTrace();
System.exit(1);
}
libraryLoaded = true;
}
}
public static native boolean containsKey(String key);
public static native int getType(String key);
public static native boolean putBoolean(String key, boolean value);
public static native boolean putDouble(String key, double value);
public static native boolean putString(String key, String value);
public static native boolean putRaw(String key, byte[] value);
public static native boolean putBooleanArray(String key, boolean[] value);
public static native boolean putDoubleArray(String key, double[] value);
public static native boolean putStringArray(String key, String[] value);
public static native void forcePutBoolean(String key, boolean value);
public static native void forcePutDouble(String key, double value);
public static native void forcePutString(String key, String value);
public static native void forcePutRaw(String key, byte[] value);
public static native void forcePutBooleanArray(String key, boolean[] value);
public static native void forcePutDoubleArray(String key, double[] value);
public static native void forcePutStringArray(String key, String[] value);
public static native Object getValue(String key) throws TableKeyNotDefinedException;
public static native boolean getBoolean(String key) throws TableKeyNotDefinedException;
public static native double getDouble(String key) throws TableKeyNotDefinedException;
public static native String getString(String key) throws TableKeyNotDefinedException;
public static native byte[] getRaw(String key) throws TableKeyNotDefinedException;
public static native boolean[] getBooleanArray(String key) throws TableKeyNotDefinedException;
public static native double[] getDoubleArray(String key) throws TableKeyNotDefinedException;
public static native String[] getStringArray(String key) throws TableKeyNotDefinedException;
public static native Object getValue(String key, Object defaultValue);
public static native boolean getBoolean(String key, boolean defaultValue);
public static native double getDouble(String key, double defaultValue);
public static native String getString(String key, String defaultValue);
public static native byte[] getRaw(String key, byte[] defaultValue);
public static native boolean[] getBooleanArray(String key, boolean[] defaultValue);
public static native double[] getDoubleArray(String key, double[] defaultValue);
public static native String[] getStringArray(String key, String[] defaultValue);
public static native void setEntryFlags(String key, int flags);
public static native int getEntryFlags(String key);
public static native void deleteEntry(String key);
public static native void deleteAllEntries();
// public static native EntryInfo[] getEntryInfo(String prefix, int types);
public static native void flush();
public interface EntryListenerFunction {
void apply(int uid, String key, Object value, boolean isNew);
}
public static native int addEntryListener(String prefix, EntryListenerFunction listener, boolean immediateNotify);
public static native void removeEntryListener(int entryListenerUid);
public interface ConnectionListenerFunction {
void apply(int uid, boolean connected, ConnectionInfo conn);
}
public static native int addConnectionListener(ConnectionListenerFunction listener, boolean immediateNotify);
public static native void removeConnectionListener(int connListenerUid);
// public static native void createRpc(String key, byte[] def, IRpc rpc);
public static native byte[] getRpc(String key) throws TableKeyNotDefinedException;
public static native byte[] getRpc(String key, byte[] defaultValue);
public static native int callRpc(String key, byte[] params);
// public static native byte[] getRpcResultBlocking(int callUid);
// public static native byte[] getRpcResultNonblocking(int callUid) throws RpcNoResponseException;
public static native void setNetworkIdentity(String name);
public static native void startServer(String persistFilename, String listenAddress, int port);
public static native void stopServer();
public static native void startClient(String serverName, int port);
public static native void stopClient();
public static native void setUpdateRate(double interval);
public static native ConnectionInfo[] getConnections();
public static native void savePersistent(String filename) throws PersistentException;
public static native String[] loadPersistent(String filename) throws PersistentException; // returns warnings
public static native long now();
public interface LoggerFunction {
void apply(int level, String file, int line, String msg);
}
public static native void setLogger(LoggerFunction func, int minLevel);
}

View File

@@ -0,0 +1,18 @@
package edu.wpi.first.wpilibj.networktables;
import java.io.IOException;
/**
* An exception thrown when persistent load/save fails in a {@link NetworkTable}
*
*/
public class PersistentException extends IOException {
/**
* @param message The error message
*/
public PersistentException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,37 @@
package edu.wpi.first.wpilibj.tables;
/**
* Represents an object that has a remote connection
*
* @author Mitchell
*
*/
public interface IRemote {
/**
* Register an object to listen for connection and disconnection events
*
* @param listener the listener to be register
* @param immediateNotify if the listener object should be notified of the current connection state
*/
public void addConnectionListener(IRemoteConnectionListener listener, boolean immediateNotify);
/**
* Unregister a listener from connection events
*
* @param listener the listener to be unregistered
*/
public void removeConnectionListener(IRemoteConnectionListener listener);
/**
* Get the current state of the objects connection
* @return the current connection state
*/
public boolean isConnected();
/**
* If the object is acting as a server
* @return if the object is a server
*/
public boolean isServer();
}

View File

@@ -0,0 +1,20 @@
package edu.wpi.first.wpilibj.tables;
/**
* A listener that listens for connection changes in a {@link IRemote} object
*
* @author Mitchell
*
*/
public interface IRemoteConnectionListener {
/**
* Called when an IRemote is connected
* @param remote the object that connected
*/
public void connected(IRemote remote);
/**
* Called when an IRemote is disconnected
* @param remote the object that disconnected
*/
public void disconnected(IRemote remote);
}

View File

@@ -0,0 +1,292 @@
package edu.wpi.first.wpilibj.tables;
import java.util.NoSuchElementException;
/**
* A table whose values can be read and written to
*
* @author Mitchell
*
*/
public interface ITable {
/**
* @param key the key to search for
* @return true if the table as a value assigned to the given key
*/
public boolean containsKey(String key);
/**
* @param key the key to search for
* @return true if there is a subtable with the key which contains at least
* one key/subtable of its own
*/
public boolean containsSubTable(String key);
/**
* @param key the name of the table relative to this one
* @return a sub table relative to this one
*/
public ITable getSubTable(String key);
/**
* Gets the value associated with a key as an object
* @param key the key of the value to look up
* @return the value associated with the given key
* @throws TableKeyNotDefinedException if there is no value associated with
* the given key
*/
public Object getValue(String key) throws TableKeyNotDefinedException;
/**
* Put a value in the table
* @param key the key to be assigned to
* @param value the value that will be assigned
* @throws IllegalArgumentException when the value is not supported by the
* table
*/
public void putValue(String key, Object value)
throws IllegalArgumentException;
/**
* Put a number in the table
* @param key the key to be assigned to
* @param value the value that will be assigned
*/
public void putNumber(String key, double value);
/**
* @param key the key to look up
* @return the value associated with the given key
* @throws TableKeyNotDefinedException if there is no value associated with
* the given key
*/
public double getNumber(String key) throws TableKeyNotDefinedException;
/**
* @param key the key to look up
* @param defaultValue the value to be returned if no value is found
* @return the value associated with the given key or the given default value
* if there is no value associated with the key
*/
public double getNumber(String key, double defaultValue);
/**
* Put a string in the table
* @param key the key to be assigned to
* @param value the value that will be assigned
*/
public void putString(String key, String value);
/**
* @param key the key to look up
* @return the value associated with the given key
* @throws TableKeyNotDefinedException if there is no value associated with
* the given key
*/
public String getString(String key) throws TableKeyNotDefinedException;
/**
* @param key the key to look up
* @param defaultValue the value to be returned if no value is found
* @return the value associated with the given key or the given default value
* if there is no value associated with the key
*/
public String getString(String key, String defaultValue);
/**
* Put a boolean in the table
* @param key the key to be assigned to
* @param value the value that will be assigned
*/
public void putBoolean(String key, boolean value);
/**
* @param key the key to look up
* @return the value associated with the given key
* @throws TableKeyNotDefinedException if there is no value associated with
* the given key
*/
public boolean getBoolean(String key) throws TableKeyNotDefinedException;
/**
* @param key the key to look up
* @param defaultValue the value to be returned if no value is found
* @return the value associated with the given key or the given default value
* if there is no value associated with the key
*/
public boolean getBoolean(String key, boolean defaultValue);
/**
* Put a boolean array in the table
* @param key the key to be assigned to
* @param value the value that will be assigned
*/
public void putBooleanArray(String key, boolean[] value);
/**
* @param key the key to look up
* @return the value associated with the given key
* @throws TableKeyNotDefinedException if there is no value associated with
* the given key
*/
public boolean[] getBooleanArray(String key) throws TableKeyNotDefinedException;
/**
* @param key the key to look up
* @param defaultValue the value to be returned if no value is found
* @return the value associated with the given key or the given default value
* if there is no value associated with the key
*/
public boolean[] getBooleanArray(String key, boolean[] defaultValue);
/**
* Put a number array in the table
* @param key the key to be assigned to
* @param value the value that will be assigned
*/
public void putNumberArray(String key, double[] value);
/**
* @param key the key to look up
* @return the value associated with the given key
* @throws TableKeyNotDefinedException if there is no value associated with
* the given key
*/
public double[] getNumberArray(String key) throws TableKeyNotDefinedException;
/**
* @param key the key to look up
* @param defaultValue the value to be returned if no value is found
* @return the value associated with the given key or the given default value
* if there is no value associated with the key
*/
public double[] getNumberArray(String key, double[] defaultValue);
/**
* Put a string array in the table
* @param key the key to be assigned to
* @param value the value that will be assigned
*/
public void putStringArray(String key, String[] value);
/**
* @param key the key to look up
* @return the value associated with the given key
* @throws TableKeyNotDefinedException if there is no value associated with
* the given key
*/
public String[] getStringArray(String key) throws TableKeyNotDefinedException;
/**
* @param key the key to look up
* @param defaultValue the value to be returned if no value is found
* @return the value associated with the given key or the given default value
* if there is no value associated with the key
*/
public String[] getStringArray(String key, String[] defaultValue);
/**
* Add a listener for changes to the table
* @param listener the listener to add
*/
public void addTableListener(ITableListener listener);
/**
* Add a listener for changes to the table
* @param listener the listener to add
* @param immediateNotify if true then this listener will be notified of all
* current entries (marked as new)
*/
public void addTableListener(ITableListener listener,
boolean immediateNotify);
/**
* Add a listener for changes to a specific key the table
* @param key the key to listen for
* @param listener the listener to add
* @param immediateNotify if true then this listener will be notified of all
* current entries (marked as new)
*/
public void addTableListener(String key, ITableListener listener,
boolean immediateNotify);
/**
* This will immediately notify the listener of all current sub tables
* @param listener
*/
public void addSubTableListener(final ITableListener listener);
/**
* Remove a listener from receiving table events
* @param listener the listener to be removed
*/
public void removeTableListener(ITableListener listener);
/*
* Depricated Methods
*/
/**
* @deprecated
* Maps the specified key to the specified value in this table.
* The key can not be null.
* The value can be retrieved by calling the get method with a key that is
* equal to the original key.
* @param key the key
* @param value the value
* @throws IllegalArgumentException if key is null
*/
public void putInt(String key, int value);
/**
* @deprecated
* Returns the value at the specified key.
* @param key the key
* @return the value
* @throws TableKeyNotDefinedException if there is no value mapped to by the
* key
* @throws IllegalArgumentException if the value mapped to by the key is not
* an int
* @throws IllegalArgumentException if the key is null
*/
public int getInt(String key) throws TableKeyNotDefinedException;
/**
* @deprecated
* Returns the value at the specified key.
* @param key the key
* @param defaultValue the value returned if the key is undefined
* @return the value
* @throws NetworkTableKeyNotDefined if there is no value mapped to by the key
* @throws IllegalArgumentException if the value mapped to by the key is not
* an int
* @throws IllegalArgumentException if the key is null
*/
public int getInt(String key, int defaultValue)
throws TableKeyNotDefinedException;
/**
* @deprecated
* Maps the specified key to the specified value in this table.
* The key can not be null.
* The value can be retrieved by calling the get method with a key that is
* equal to the original key.
* @param key the key
* @param value the value
* @throws IllegalArgumentException if key is null
*/
public void putDouble(String key, double value);
/**
* @deprecated
* Returns the value at the specified key.
* @param key the key
* @return the value
* @throws NoSuchEleNetworkTableKeyNotDefinedmentException if there is no
* value mapped to by the key
* @throws IllegalArgumentException if the value mapped to by the key is not a
* double
* @throws IllegalArgumentException if the key is null
*/
public double getDouble(String key) throws TableKeyNotDefinedException;
/**
* @deprecated
* Returns the value at the specified key.
* @param key the key
* @param defaultValue the value returned if the key is undefined
* @return the value
* @throws NoSuchEleNetworkTableKeyNotDefinedmentException if there is no
* value mapped to by the key
* @throws IllegalArgumentException if the value mapped to by the key is not a
* double
* @throws IllegalArgumentException if the key is null
*/
public double getDouble(String key, double defaultValue);
}

View File

@@ -0,0 +1,19 @@
package edu.wpi.first.wpilibj.tables;
/**
* A listener that listens to changes in values in a {@link ITable}
*
* @author Mitchell
*
*/
public interface ITableListener {
/**
* Called when a key-value pair is changed in a {@link ITable}
* WARNING: If a new key-value is put in this method value changed will immediatly be called which could lead to recursive code
* @param source the table the key-value pair exists in
* @param key the key associated with the value that changed
* @param value the new value
* @param isNew true if the key did not previously exist in the table, otherwise it is false
*/
public void valueChanged(ITable source, String key, Object value, boolean isNew);
}

View File

@@ -0,0 +1,20 @@
package edu.wpi.first.wpilibj.tables;
import java.util.NoSuchElementException;
/**
* An exception throw when the lookup a a key-value fails in a {@link ITable}
*
* @author Mitchell
*
*/
public class TableKeyNotDefinedException extends NoSuchElementException {
/**
* @param key the key that was not defined in the table
*/
public TableKeyNotDefinedException(String key) {
super("Unknown Table Key: "+key);
}
}

39
java/test/Client.java Normal file
View File

@@ -0,0 +1,39 @@
import edu.wpi.first.wpilibj.networktables.*;
import edu.wpi.first.wpilibj.tables.*;
public class Client {
private static class MyLogger implements NetworkTablesJNI.LoggerFunction {
public void apply(int level, String file, int line, String msg) {
System.err.println(msg);
}
}
public static void main(String[] args) {
NetworkTablesJNI.setLogger(new MyLogger(), 0);
NetworkTable.setIPAddress("127.0.0.1");
NetworkTable.setPort(10000);
NetworkTable.setClientMode();
NetworkTable nt = NetworkTable.getTable("");
try { Thread.sleep(2000); } catch (InterruptedException e) {}
try {
System.out.println("Got foo: " + nt.getNumber("foo"));
} catch(TableKeyNotDefinedException ex) {
}
nt.putBoolean("bar", false);
nt.setFlags("bar", NetworkTable.PERSISTENT);
nt.putBoolean("bar2", true);
nt.putBoolean("bar2", false);
nt.putBoolean("bar2", true);
nt.putString("str", "hello world");
double[] nums = new double[3];
nums[0] = 0.5;
nums[1] = 1.2;
nums[2] = 3.0;
nt.putNumberArray("numarray", nums);
String[] strs = new String[2];
strs[0] = "Hello";
strs[1] = "World";
nt.putStringArray("strarray", strs);
try { Thread.sleep(10000); } catch (InterruptedException e) {}
}
}

26
java/test/Server.java Normal file
View File

@@ -0,0 +1,26 @@
import edu.wpi.first.wpilibj.networktables.*;
import edu.wpi.first.wpilibj.tables.*;
public class Server {
private static class MyLogger implements NetworkTablesJNI.LoggerFunction {
public void apply(int level, String file, int line, String msg) {
System.err.println(msg);
}
}
public static void main(String[] args) {
NetworkTablesJNI.setLogger(new MyLogger(), 0);
NetworkTable.setIPAddress("127.0.0.1");
NetworkTable.setPort(10000);
NetworkTable.setServerMode();
NetworkTable nt = NetworkTable.getTable("");
try { Thread.sleep(1000); } catch (InterruptedException e) {}
nt.putNumber("foo", 0.5);
nt.setFlags("foo", NetworkTable.PERSISTENT);
nt.putNumber("foo2", 0.5);
nt.putNumber("foo2", 0.7);
nt.putNumber("foo2", 0.6);
nt.putNumber("foo2", 0.5);
try { Thread.sleep(10000); } catch (InterruptedException e) {}
}
}