UCEF TimeSync Federation Tutorial - SCU-Smart-Grid-CPS/smart-grid-energy-simulation-research GitHub Wiki
In this tutorial, we will improve upon the timestep project by making everything run on a single step. You may have noticed that the timestep has a pattern like this:
However, this in a physical sense means that the data from socket takes a whole timestep to arrive at processor and control, then another timestep for the processor data based on that socket data to reach control. For a real-time system such as a smart grid, it will be no longer relevant by the time the socket gets the data back several timesteps later. Thus, we want it to do everything in just one timestep like this:
A working example code can be found in the tutorials folder as timesync demo
The procedure:
- Open the WebGME from timestep and click on one of the C2WInteractionRoot objects you want to have occur without a time delay.
- Under Property Editor -> Order, change "timestamp" to "receive"
- Repeat for all other C2WInteractionRoot objects you want to have occur without a time delay. In this demo, these are sockToProc, sockToCtrl, procToCtrl. Do NOT change ctrlToSock.
- In Eclipse or other Java editor, make the following changes:
- In control.java, processor.java, and socket.java, at the top, add the import line:
import org.cpswt.utils.CpswtUtils;
- Socket does not receive an interaction without time delay, but it sends one to processor and one to control, both containing the variable sockTime.
- Processor both receives a no-delay interaction from socket containing sockTime, and sends one to control with two variables, sockTime and procTime.
- Control receives two no-delay interactions, one from socket and one from processor. The interaction sent to socket has a time delay.
Sending a no-delay interaction
In the java file for the federate sending a no-delay interaction:
In the send interaction below "Set the interaction's parameters," remove the part , currentTime + getLookAhead()
For example,
Before: vsockToProc.sendInteraction(getLRC(), currentTime + getLookAhead());
After: vsockToProc.sendInteraction(getLRC());
Repeat for each no-delay interaction.
Receiving a no-delay interaction
In the java file for the federate receiving a no-delay interaction:
-
For each no-delay interaction, create a boolean. Declare with:
private boolean variableName = false;
-
We need to set these variables to true when the interaction is received. Find the
handleInteractionClass
methods (there is one for each interaction). After the log.info line in one of them, set one of the booleans to true using the linevariableName = true;
. Repeat for the otherhandleInteractionClass
using each boolean only once. -
Next, we add a while loop that tells it to wait before sending new data until the boolean(s) are true, so it received the interactions. Immediately above the big block of commented code that says "Set the interaction's parameters," add the following:
while (!receivedSimTime) { log.info("waiting to receive SimTime..."); synchronized (lrc) { lrc.tick(); } checkReceivedSubscriptions(); if (!receivedSimTime) { CpswtUtils.sleep(1000); } }
If there are multiple, can modify the code to allow for multiple booleans at once rather than pasting several while loops.
while (!receivedSimTime || !recProc) {
log.info("waiting to receive SimTime...");
synchronized (lrc) {
lrc.tick();
}
checkReceivedSubscriptions();
if (!receivedSimTime || !recProc) {
CpswtUtils.sleep(1000);
}
}
- If the booleans are not reset to false again, on the next timestep it still will read true and will not get reset. To fix this, set each variable to false right after the while loop with:
variableName = false;
Compile, run, check:
Compile and run the code as done before. You will need to repeat the bash build-all.sh step. Look at the output or log file for control and compare to the previous version.