Skip to main content
Version: 0.24.1

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:

  1. Create a gRPC connection to the server.
  2. Create an instance of the UpdateNetworkStateClient using your gRPC connection.
  3. Use your UpdateNetworkStateClient to update the state of the network.

Creating a gRPC channel

The channel gRPC channel can be directly from the gPRC 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:

import com.zepben.evolve.streaming.grpc.GrpcChannel;
import io.grpc.ManagedChannelBuilder;

var channel = new 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.

import com.zepben.evolve.streaming.mutations.UpdateNetworkStateClient;

var client = new 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.

note

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.

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));

If you have multiple batches to send, you can pass a stream/sequence of them rather than calling setCurrentStates multiple times

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.
);

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.

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));

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.

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));

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.

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));

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.

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));

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 - The mRID of the event could not be found in the network hosted by this server.
    • StateEventDuplicateMrid - The mRID of an item being added to the network is already in use.
    • StateEventInvalidMrid - The mRID of the item being addressed in the event is of a different type than expected. e.g. You can't remove a Jumper with an mRID that belongs to a Cut.
    • StateEventUnsupportedPhasing - You tried to specify phases that do not make sense to the item being updated. When using the default phasing of NONE you will never receive this error. Until un-ganged switching is supported, this error will be returned for all events that specify phases.
    • StateEventUnsupportedMrid - The mRID 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.*

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
}
});
}