Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add NetworkTableSource #646

Merged
merged 9 commits into from
Aug 27, 2016
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this a protected field?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed in person


/**
* 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();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this be generic?

Copy link
Member Author

@AustinShalit AustinShalit Aug 3, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I want NetworkReceiver to not care what kind of object it gets. This means GRIP will handle any mismatch in NetworkTableEntrySource instead of NetworkReceiver


/**
* 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);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this be generic?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


/**
* 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,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should have Javadoc.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The other methods in the class do not have any Javadoc. Should I add for all of them?

String defaultValue) {
return new SocketHint.Builder<String>(String.class)
.identifier(identifier)
.initialValue(defaultValue)
.build();
}
}
}
Loading