Skip to content

Commit

Permalink
Merge pull request #646 from AustinShalit/ntSource
Browse files Browse the repository at this point in the history
Add NetworkTableSource
  • Loading branch information
AustinShalit authored Aug 27, 2016
2 parents a700892 + fc680f8 commit a9659d0
Show file tree
Hide file tree
Showing 26 changed files with 651 additions and 36 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,7 @@ bower_components
**/generated
*/generated_tests
/bin/

### NetworkTables
networktables.ini
networktables.ini.bak
4 changes: 4 additions & 0 deletions core/src/main/java/edu/wpi/grip/core/GripCoreModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import edu.wpi.grip.core.sources.HttpSource;
import edu.wpi.grip.core.sources.ImageFileSource;
import edu.wpi.grip.core.sources.MultiImageFileSource;
import edu.wpi.grip.core.sources.NetworkTableEntrySource;
import edu.wpi.grip.core.util.ExceptionWitness;
import edu.wpi.grip.core.util.GripMode;

Expand Down Expand Up @@ -144,6 +145,9 @@ public <I> void hear(TypeLiteral<I> type, TypeEncounter<I> encounter) {
install(new FactoryModuleBuilder()
.implement(HttpSource.class, HttpSource.class)
.build(HttpSource.Factory.class));
install(new FactoryModuleBuilder()
.implement(NetworkTableEntrySource.class, NetworkTableEntrySource.class)
.build(NetworkTableEntrySource.Factory.class));

install(new FactoryModuleBuilder().build(ExceptionWitness.Factory.class));
}
Expand Down
5 changes: 5 additions & 0 deletions core/src/main/java/edu/wpi/grip/core/Source.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import edu.wpi.grip.core.sources.HttpSource;
import edu.wpi.grip.core.sources.ImageFileSource;
import edu.wpi.grip.core.sources.MultiImageFileSource;
import edu.wpi.grip.core.sources.NetworkTableEntrySource;
import edu.wpi.grip.core.util.ExceptionWitness;

import com.google.common.collect.ImmutableList;
Expand Down Expand Up @@ -111,6 +112,8 @@ public static class SourceFactoryImpl implements SourceFactory {
MultiImageFileSource.Factory multiImageFactory;
@Inject
HttpSource.Factory httpFactory;
@Inject
NetworkTableEntrySource.Factory networkTableEntryFactory;

@Override
public Source create(Class<?> type, Properties properties) throws IOException {
Expand All @@ -122,6 +125,8 @@ public Source create(Class<?> type, Properties properties) throws IOException {
return multiImageFactory.create(properties);
} else if (type.isAssignableFrom(HttpSource.class)) {
return httpFactory.create(properties);
} else if (type.isAssignableFrom(NetworkTableEntrySource.class)) {
return networkTableEntryFactory.create(properties);
} else {
throw new IllegalArgumentException(type + " was not a valid type");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,10 @@ protected void configure() {
bind(ROSNetworkPublisherFactory.class)
.annotatedWith(Names.named("rosManager"))
.to(ROSManager.class);

// Network receiver bindings
bind(MapNetworkReceiverFactory.class)
.annotatedWith(Names.named("ntManager"))
.to(NTManager.class);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package edu.wpi.grip.core.operations.network;


/**
* A factory to create {@link NetworkReceiver NetworkRecievers}.
*/
@FunctionalInterface
public interface MapNetworkReceiverFactory {
NetworkReceiver create(String path);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package edu.wpi.grip.core.operations.network;

import java.util.function.Consumer;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;

/**
* Manages the interface between the {@link PublishAnnotatedOperation} and the actual network
* protocol implemented by a specific {@link Manager}.
*/
public abstract class NetworkReceiver implements AutoCloseable {

protected final String path;

/**
* Create a new NetworkReceiver with the specified path.
*
* @param path The path of the object to get
*/
public NetworkReceiver(String path) {
checkNotNull(path, "Path cannot be null");
checkArgument(!path.isEmpty(), "Path cannot be an empty string");
this.path = path;
}

/**
* Get the value of the object.
*
* @return The value of this NetworkReceiver
*/
public abstract Object getValue();

/**
* Add a listener to the NetworkReceiver item.
*
* @param consumer The consumer to call when this item has a update
*/
public abstract void addListener(Consumer<Object> consumer);

/**
* Close the network reciever. This should not throw an exception.
*/
public abstract void close();
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import edu.wpi.grip.core.operations.network.Manager;
import edu.wpi.grip.core.operations.network.MapNetworkPublisher;
import edu.wpi.grip.core.operations.network.MapNetworkPublisherFactory;
import edu.wpi.grip.core.operations.network.MapNetworkReceiverFactory;
import edu.wpi.grip.core.operations.network.NetworkReceiver;
import edu.wpi.grip.core.settings.ProjectSettings;
import edu.wpi.grip.core.util.GripMode;

Expand All @@ -19,13 +21,15 @@
import edu.wpi.first.wpilibj.tables.ITable;

import java.io.File;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.inject.Inject;

import static com.google.common.base.Preconditions.checkNotNull;
Expand All @@ -34,18 +38,18 @@
* This class encapsulates the way we map various settings to the global NetworkTables state.
*/
@Singleton
public class NTManager implements Manager, MapNetworkPublisherFactory {
public class NTManager implements Manager, MapNetworkPublisherFactory, MapNetworkReceiverFactory {
/*
* Nasty hack that is unavoidable because of how NetworkTables works.
*/
private static final AtomicInteger publisherCount = new AtomicInteger(0);
private static final AtomicInteger count = new AtomicInteger(0);

/**
* Information from: https://github.com/PeterJohnson/ntcore/blob/master/src/Log.h and
* https://github.com/PeterJohnson/ntcore/blob/e6054f543a6ab10aa27af6cace855da66d67ee44
* /include/ntcore_c.h#L39
*/
private static final Map<Integer, Level> ntLogLevels = ImmutableMap.<Integer, Level>builder()
protected static final Map<Integer, Level> ntLogLevels = ImmutableMap.<Integer, Level>builder()
.put(40, Level.SEVERE)
.put(30, Level.WARNING)
.put(20, Level.INFO)
Expand Down Expand Up @@ -120,11 +124,69 @@ public void updateSettings(ProjectSettingsChangedEvent event) {

@Override
public <P> MapNetworkPublisher<P> create(Set<String> keys) {
// Keep track of ever publisher created.
publisherCount.getAndAdd(1);
// Keep track of every publisher created.
count.getAndAdd(1);
return new NTPublisher<>(keys);
}

@Override
public NetworkReceiver create(String path) {
count.getAndAdd(1);
return new NTReceiver(path);
}

private static final class NTReceiver extends NetworkReceiver {

private int entryListenerFunctionUid;
private Object object = false;
private final List<Consumer<Object>> listeners = new LinkedList<>();

protected NTReceiver(String path) {
super(path);
addListener();

synchronized (NetworkTable.class) {
NetworkTable.initialize();
}
}

private void addListener() {
entryListenerFunctionUid = NetworkTablesJNI.addEntryListener(path,
(uid, key, value, flags) -> {
object = value;
listeners.forEach(c -> c.accept(object));
},
ITable.NOTIFY_IMMEDIATE
| ITable.NOTIFY_NEW
| ITable.NOTIFY_UPDATE
| ITable.NOTIFY_DELETE
| ITable.NOTIFY_LOCAL);
}

@Override
public void addListener(Consumer<Object> consumer) {
listeners.add(consumer);
}

@Override
public Object getValue() {
return object;
}

@Override
public void close() {
NetworkTablesJNI.removeEntryListener(entryListenerFunctionUid);

synchronized (NetworkTable.class) {
// This receiver is no longer used.
if (NTManager.count.addAndGet(-1) == 0) {
// We are the last resource using NetworkTables so shut it down
NetworkTable.shutdown();
}
}
}
}

private static final class NTPublisher<P> extends MapNetworkPublisher<P> {
private final ImmutableSet<String> keys;
private Optional<String> name = Optional.empty();
Expand Down Expand Up @@ -184,8 +246,8 @@ public void close() {
}
synchronized (NetworkTable.class) {
// This publisher is no longer used.
if (NTManager.publisherCount.addAndGet(-1) == 0) {
// We are the last publisher so shut it down
if (NTManager.count.addAndGet(-1) == 0) {
// We are the last resource using NetworkTables so shut it down
NetworkTable.shutdown();
}
}
Expand Down
8 changes: 8 additions & 0 deletions core/src/main/java/edu/wpi/grip/core/sockets/SocketHints.java
Original file line number Diff line number Diff line change
Expand Up @@ -193,5 +193,13 @@ public static SocketHint<Number> createNumberSocketHint(final String identifier,
defaultValue) {
return createNumberSocketHintBuilder(identifier, defaultValue).build();
}

public static SocketHint<String> createStringSocketHint(final String identifier,
String defaultValue) {
return new SocketHint.Builder<String>(String.class)
.identifier(identifier)
.initialValue(defaultValue)
.build();
}
}
}
Loading

0 comments on commit a9659d0

Please sign in to comment.