Update Network State Client
The UpdateNetworkStateClient
will allow you to interact with a server running the UpdateNetworkStateService
(e.g. EWB). It provides an object-oriented
wrapper for the gRPC library, with the ability to update information about the state of the network. This is done with the following 3 steps:
- Create a gRPC connection to the server.
- Create an instance of the
UpdateNetworkStateClient
using your gRPC connection. - Use your
UpdateNetworkStateClient
to update the state of the network.
Creating a gRPC channel
The channel gRPC channel can be directly from the gRPC library, or the channel wrapped in our GrpcChannel
helper, which implements the AutoClosable
interface
and performs shutdown operations for you. At its most basic, this can be achieved with:
- Java
- Kotlin
import com.zepben.evolve.streaming.grpc.GrpcChannel;
import io.grpc.ManagedChannelBuilder;
var channel = new GrpcChannel(ManagedChannelBuilder.forAddress(host, port).usePlaintext().build());
import com.zepben.evolve.streaming.grpc.GrpcChannel
import io.grpc.ManagedChannelBuilder
val channel = GrpcChannel(ManagedChannelBuilder.forAddress(host, port).usePlaintext().build())
For more in depth options for using a gRPC channel, see the gRPC documentation, or look up a tutorial.
Using a gRPC channel with your client
Using your gRPC channel with the UpdateNetworkStateClient
is as simple as passing it to the constructor.
- Java
- Kotlin
import com.zepben.evolve.streaming.mutations.UpdateNetworkStateClient;
var client = new UpdateNetworkStateClient(channel);
import com.zepben.evolve.streaming.mutations.UpdateNetworkStateClient
val client = UpdateNetworkStateClient(channel)
Using your client to update the network state
Now that you have a client, you can use it to update the state of the network on the connected server.
Updating current network state
The current state of the network can be updated using the setCurrentStates
function on the UpdateNetworkStateClient
. All events passed in the same list will
be executed as a batch.
The current implementation only supports updating the current state of switches. In the future we will add more functionality such as cuts and jumpers.
Updating current switch state
The current state of switches can be updating by passing a SwitchStateEvent
to the setCurrentStates
function.
- Java
- Kotlin
import com.zepben.evolve.streaming.data.SwitchStateEvent;
import com.zepben.evolve.streaming.mutations.UpdateNetworkStateClient;
import java.time.LocalDateTime;
import java.util.List;
var event1 = new SwitchStateEvent("event1", LocalDateTime.now(), "switch_id_1", SwitchAction.OPEN);
var response = client.setCurrentStates(1, List.of(event1));
import com.zepben.evolve.streaming.data.SwitchStateEvent
import com.zepben.evolve.streaming.mutations.UpdateNetworkStateClient
val event1 = SwitchStateEvent("event1", LocalDateTime.now(), "switch_id_1", SwitchAction.OPEN)
val response = client.setCurrentStates(1, listOf(event1))
If you have multiple batches to send, you can pass a stream/sequence of them rather than calling setCurrentStates
multiple times
- Java
- Kotlin
import com.zepben.evolve.streaming.data.SwitchStateEvent;
import com.zepben.evolve.streaming.mutations.UpdateNetworkStateClient;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Stream;
var event1 = new SwitchStateEvent("event1", LocalDateTime.now(), "switch_id_1", SwitchAction.OPEN);
var event2 = new SwitchStateEvent("event2", LocalDateTime.now(), "switch_id_2", SwitchAction.CLOSE);
var batches = Stream.of(
new UpdateNetworkStateClient.SetCurrentStatesRequest(1, List.of(event1)),
new UpdateNetworkStateClient.SetCurrentStatesRequest(2, List.of(event2))
);
client.setCurrentStates(batches).forEach(response ->
// Process your responses here. You will get a response per batch.
);
import com.zepben.evolve.streaming.data.SwitchStateEvent
import com.zepben.evolve.streaming.mutations.UpdateNetworkStateClient
import java.time.LocalDateTime
val event1 = SwitchStateEvent("event1", LocalDateTime.now(), "switch_id_1", SwitchAction.OPEN)
val event2 = SwitchStateEvent("event2", LocalDateTime.now(), "switch_id_2", SwitchAction.CLOSE)
val batches = sequenceOf(
UpdateNetworkStateClient.SetCurrentStatesRequest(1, listOf(event1)),
UpdateNetworkStateClient.SetCurrentStatesRequest(2, listOf(event2))
)
client.setCurrentStates(batches).forEach { response ->
// Process your responses here. You will get a response per batch.
}
Adding cuts
You can add a cut to an AC line segment by passing an AddCutEvent
to the setCurrentStates
function. This can be done with both individual events, and
batches of events as shown above.
- Java
- Kotlin
import com.zepben.evolve.streaming.data.AddCutEvent;
import com.zepben.evolve.streaming.mutations.UpdateNetworkStateClient;
import java.time.LocalDateTime;
import java.util.List;
var event1 = new AddCutEvent("event1", LocalDateTime.now(), "cut_id_1", "acls_id_1");
var response = client.setCurrentStates(1, List.of(event1));
import com.zepben.evolve.streaming.data.AddCutEvent
import com.zepben.evolve.streaming.mutations.UpdateNetworkStateClient
val event1 = AddCutEvent("event1", LocalDateTime.now(), "cut_id_1", "acls_id_1")
val response = client.setCurrentStates(1, listOf(event1))
Removing cuts
You can remove previously added cuts by passing a RemoveCutEvent
to the setCurrentStates
function. This can be done with both individual events, and batches
of events as shown above.
- Java
- Kotlin
import com.zepben.evolve.streaming.data.RemoveCutEvent;
import com.zepben.evolve.streaming.mutations.UpdateNetworkStateClient;
import java.time.LocalDateTime;
import java.util.List;
var event1 = new RemoveCutEvent("event1", LocalDateTime.now(), "cut_id_1");
var response = client.setCurrentStates(1, List.of(event1));
import com.zepben.evolve.streaming.data.RemoveCutEvent
import com.zepben.evolve.streaming.mutations.UpdateNetworkStateClient
val event1 = RemoveCutEvent("event1", LocalDateTime.now(), "cut_id_1")
val response = client.setCurrentStates(1, listOf(event1))
Adding jumpers
You can add a jumper between two pieces of equipment by passing an AddJumperEvent
to the setCurrentStates
function. This can be done with both individual
events, and batches of events as shown above.
- Java
- Kotlin
import com.zepben.evolve.streaming.data.AddJumperEvent;
import com.zepben.evolve.streaming.data.JumperConnection;
import com.zepben.evolve.streaming.mutations.UpdateNetworkStateClient;
import java.time.LocalDateTime;
import java.util.List;
var event1 = new AddJumperEvent("event1", LocalDateTime.now(), "jumper_id_1", new JumperConnection("acls_id_1"), new JumperConnection("acls_id_2"));
var response = client.setCurrentStates(1, List.of(event1));
import com.zepben.evolve.streaming.data.AddJumperEvent
import com.zepben.evolve.streaming.mutations.UpdateNetworkStateClient
val event1 = AddJumperEvent("event1", LocalDateTime.now(), "jumper_id_1", JumperConnection("acls_id_1"), JumperConnection("acls_id_2"))
val response = client.setCurrentStates(1, listOf(event1))
Removing jumpers
You can remove previously added jumpers by passing a RemoveJumperEvent
to the setCurrentStates
function. This can be done with both individual events, and
batches of events as shown above.
- Java
- Kotlin
import com.zepben.evolve.streaming.data.RemoveJumperEvent;
import com.zepben.evolve.streaming.mutations.UpdateNetworkStateClient;
import java.time.LocalDateTime;
import java.util.List;
var event1 = new RemoveJumperEvent("event1", LocalDateTime.now(), "jumper_id_1");
var response = client.setCurrentStates(1, List.of(event1));
import com.zepben.evolve.streaming.data.RemoveJumperEvent
import com.zepben.evolve.streaming.mutations.UpdateNetworkStateClient
val event1 = RemoveJumperEvent("event1", LocalDateTime.now(), "jumper_id_1")
val response = client.setCurrentStates(1, listOf(event1))
Batch result responses
Each batch will receive its own response, which will be one of the following:
BatchSuccessful
- Indicates that all events in the batch were processed successfully. Events that are ignored because they set the state to one that is already present, or are skipped due to a later event applying the opposite action, will be marked as successful.BatchFailure
- Indicates at least one event in the batch could not be applied. Each event that failed will indicate why it failed, some of which will have more impact than others.StateEventUnknownMrid
- ThemRID
of the event could not be found in the network hosted by this server.StateEventDuplicateMrid
- ThemRID
of an item being added to the network is already in use.StateEventInvalidMrid
- ThemRID
of the item being addressed in the event is of a different type than expected. e.g. You can't remove aJumper
with anmRID
that belongs to aCut
.StateEventUnsupportedPhasing
- You tried to specify phases that do not make sense to the item being updated. When using the default phasing ofNONE
you will never receive this error. Until un-ganged switching is supported, this error will be returned for all events that specify phases.StateEventUnsupportedMrid
- ThemRID
provided can't be used to perform the given action even though it is of the correct type. e.g. Trying to open/close a switch in a voltage level that hasn't been implemented in the server.
BatchNotProcessed
- Indicates the entire batch was ignored because the message ID of the batch was prior to the last processed batch.
You can check the type of response or failure by check against the types from com.zepben.evolve.streaming.data.*
- Java
- Kotlin
import com.zepben.evolve.streaming.data.BatchFailure;
import com.zepben.evolve.streaming.data.StateEventUnknownMrid;
if (response instanceof BatchFailure) {
var batchFailure = (BatchFailure) response;
batchFailure.getPartialFailure(); // Will be true if all event failed, otherwise false.
batchFailure.getFailures().forEach((failure) -> {
if (failure instanceof StateEventUnknownMrid) {
// Process failure
}
});
}
when (response) {
is BatchFailure -> {
response.partialFailure // Will be true if all event failed, otherwise false.
response.failures.forEach { failure ->
when (failure) {
is StateEventUnknownMrid -> // Process failure
// process other failure types
}
}
}
// process other response types
}