Skip to content
Snippets Groups Projects
Commit 38692dcb authored by Joakim Oscarsson's avatar Joakim Oscarsson
Browse files

Init

parents
No related branches found
No related tags found
No related merge requests found
env/**
venv/**
.vscode/**
lib/Helics-*
**.log
**.png
log/**
__pycache__/**
src/__pycache__/**
data/__pycache__/**
*/data/__pycache__/**
src/__pycache__/**.pyc
**/__pycache__
data/processed/__pycache__/**
README.md 0 → 100644
# CloudBatteryAttack Simulator
## NOTE, YOU NEED TO ADD DATA TO THE DATA FOLDER FOR THE SIMULATOR TO WORK.
This simulator is the result of the following master's thesis:
Cyberattack Evaluation of Cloud-controlled Energy Storage
The simulator design can be seen in the Figure below. The modules and connections are described further down.
![The simulator design model](res/SIv4.svg)
## Modules of the simulator
The simulator currently consists of 6 different modules:
- Grid
- Sensor
- Network
- Controller
- Battery
- GUI
### Grid
The Grid module receives power (positive or negative) from the Battery module, and this power is added or subtracted from the internal produciton value, trying to match the consumption (that is read from a file with real-world data).
The Grid gets a list of consumption values from one of the files located in **@/data/processed** which it uses to calculate the frequency. The frequency is calculated by a function located in the **lib** directory of the **src** folder. The calculated frequency is published to the Sensor module.
### Sensor
The sensor gets the frequency from the Grid module by a subscription and forwards that frequency measurement over the Network module as a message (using endpoints). The sensor has an interval parameter specifying how often it should send the frequency measurement over the network. It is implemented as a counter for the number of packets reaching it.
### Network
The Network module is probably the most complicated module in terms of communication. It has one endpoint for receiving messages and another for sending messages. Over these endpoints there is a filter for delaying packets and another filter for dropping packets.
Just like a normal network, packets flow through the module and when packets flow they can be delayed, dropped, altered, replayed etc. This is where most of the cyberattacks occur (with the exception of Load Altering attacks).
The Network module has two big pieces of logic, one for config messages and one for normal messages. Normal messages can also be recorded to stage a replay attack.
### Controller
The Controller gets a frequency reading from the Sensor and inserts the measurement into a controller that generates a control signal. This signal is then sent to the Battery over the Network, indicating how much power should be pushed or pulled from the Grid.
The control signal is currently produced by a PID controller but can easily be changed for any other algorithm that bases its output on the frequency error (current - nominal frequency).
The Controller also receives status messages from the Battery every time it sends control signals. The status message currently consists of the battery's State of Charge.
### Battery
The Battery base how much power to send to the Grid by the control signal received from the Controller. The power can be both positive (pushing power to the grid, i.e. discharging) and negative (pulling power from the grid, i.e. charging).
### GUI
The GUI starts two threads, one for the graphical interface, and one for the HELICS simulation handling the communication of config messages with the rest of the simulator. The GUI defines everything that is visible on the screen and also the logic behind the attack script.
# Installing the simulator
To install the simulator, execute install.ps1 (Windows) or install.sh (Linux) (tested on Ubuntu server 22.04)
# Running the simulator
To run the simulator, execute run.ps1 (Windows) or run.sh (Linux).
## Configuration parameters
The system has many parameters; they are given initial values via the *initial_parameters.json* file, but can also be changed by either the input fields in the **GUI** or via an external script called *attack.py*. Upon any changes, the updated JSON is broadcasted from the **GUI** module's main thread and is parsed by all other module instances to update their internal configuration.
The parameters can currently be used to configure the Battery, Sensor, Grid, and the different Network instances. What the configuration parameters do and how they are used is explained below
### Grid parameters
The Grid module defines five parameters: production_delay, consumption_scaling_factor, and three parameters part of the load_altering group.
Load Altering (or LA) is a cyberattack where the grid power is altered by attacker-controlled devices (external to the simulator system). The parameters for simulating LA are:
- offset (MW): a positive or negative bias added to the consumption power before being fed into the simulation
- randomness (MW): at each time step, adds a random value from the uniform distribution ['-randomness', 'randomness'] to the consumption before it is fed into the simulation
- interval: an integer that defines at what times the power is altered. An interval of 0 means no attack, an interval of 1 means altering occurs at every time-step, an interval of 2 means every other time-step, and so on.
The production_delay parameter, if set to a non-zero value, causes the grid production to match the consumption data but with a delay of 'production_delay' seconds. This can be thought of as the large power plants slowly following the consumption curve but taking time to adapt.
Finally, the consumption_scaling_factor is used to scale the consumption that is fed into the simulator (by default we are using the entire power consumption of Sweden in July 2023 so scaling it down with a factor < 1 into the size of a town's distribution grid could aid in making the simulation more realistic).
### Network parameters
"sensor_to_controller_network": {
"delay_min": 0.0,
"delay_max": 0.0,
"drop_rate": 0.0,
"FDI": {
"interval": 0,
"offset": 0.0,
"randomness": 0.0,
"base": 0.0,
"scaling_factor": 1.0
},
"replay" : {
"amount": 0,
"wait": 0
}
},
The user can specify a uniform span of delays, packet drop rate, FDI attacks and replay attacks.
The FDI paramters works in the following way:
- Interval: 1 mean that every packet is modified, 2 means every other etc.
- Offset: Adds or subtracts a constant value.
- Randomness: Adds or subtracts a random value between [-randomness, +randomness].
- Base: Sends a constant value.
- Scaling Factor: Scales the value with a constant.
The Replay parameters works in the following way:
- Amount: How many packets to record from the moment the update button is pressed (or when simulator starts if set in initial_parameters.json)
- Wait: How many packets to wait before replaying after recording is finished.
### Other parameters
"use_attack_script": false,
"consumption_data_name": "consumption_20ms_short_cubic_average_window10_july_23",
"battery": {"balancing_power": 2.0, "capacity": 2.0},
"sensor": {"interval": 50},
"pid_controller": {"kp": 2.0, "ki": 2.0, "kd": 0.0},
The other parameters works in the following way:
- use_attack_script: Tells the simulator if it should use a user created script to modify simulator config parameters.
- consumption_data_name: Where to fetch consumption data from (to the Grid module)
- Battery.balancing_power: The maximum and minimum battery power.
- Battery.capacity: Battery MWh.
- Sensor.interval: How often the sensor should send frequency measurements to the Controller.
- pid_Controller: The PID tunings.
# HELICS
The simulator is built using the co-simulation framework HELICS. It allows execution and coordination of multiple different "subsimulators" and handles the global time and communication between them so that they can interact. In our project, all of the "subsimulators" are small snippets of python code, but due to the nature of the HELICS framework they are relatively easy to replace with more sophisticated simulators. The documentation for HELICS is located at:
https://docs.helics.org/en/latest/
And the github and examples which we drew inspiration from is located at:
https://github.com/GMLC-TDC/HELICS-Examples
Copyright (c) 2017-2019, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC.
All rights reserved.
The file *advanced_default_runner.json* is parsed by the HELICS broker for starting up the simulator (we use a single HELICS broker). This file defines how the modules are executed (as separate processes) and what HELICS configuration files are defined for each module (located in the **config** directory). The files in the **config** directory are parsed by each module process to configure time properties and inputs/outputs to other modules among other things (see HELICS documentation).
In HELICS, module instances (so-called federates) can communicate in two ways: through endpoints (messages) or through values (publish, subscribe). HELICS messages are used to simulate packet-based communication (i.e. over a network), while HELICS values are used for continuous non-packetized connections (such as Power flow).
The general execution flow of each module instance can be seen in the Figure.
![HELICS execution flow](res/flowchart_simulator_federate.svg)
\ No newline at end of file
{
"name": "advanced_default",
"broker": true,
"federates": [
{
"directory": "./config",
"exec": "python -u ../src/Sensor.py",
"host": "localhost",
"name": "Sensor"
},
{
"directory": "./config",
"exec": "python -u ../src/Controller.py",
"host": "localhost",
"name": "Controller"
},
{
"directory": "./config",
"exec": "python -u ../src/Battery.py",
"host": "localhost",
"name": "Battery"
},
{
"directory": "./config",
"exec": "python -u ../src/Grid.py",
"host": "localhost",
"name": "Grid"
},
{
"directory": "./config",
"exec": "python -u ../src/GUI.py",
"host": "localhost",
"name": "GUI"
},
{
"directory": "./config",
"exec": "python -u ../src/Network.py SensorToControllerNetworkConfig.json",
"host": "localhost",
"name": "SensorToControllerNetwork"
},
{
"directory": "./config",
"exec": "python -u ../src/Network.py ControllerToBatteryNetworkConfig.json",
"host": "localhost",
"name": "ControllerToBatteryNetwork"
},
{
"directory": "./config",
"exec": "python -u ../src/Network.py BatteryToControllerNetworkConfig.json",
"host": "localhost",
"name": "BatteryToControllerNetwork"
}
]
}
{
"use_attack_script": false,
"consumption_data_name": "consumption_20ms_short_cubic_average_window10_july_23",
"battery": {"balancing_power": 2.0, "capacity": 2.0},
"sensor": {"interval": 50},
"grid": {
"load_altering": {
"offset": 0.0,
"randomness": 0.0,
"interval": 0
},
"production_delay" : 0,
"consumption_scaling_factor" : 0.02
},
"pid_controller": {"kp": 2.0, "ki": 1.0, "kd": 0.0},
"sensor_to_controller_network": {
"delay_min": 0.0,
"delay_max": 0.0,
"drop_rate": 0.0,
"FDI": {
"interval": 0,
"offset": 0.0,
"randomness": 0.0,
"base": 0.0,
"scaling_factor": 1.0
},
"replay" : {
"amount": 0,
"wait": 0
}
},
"controller_to_battery_network": {
"delay_min": 0.0,
"delay_max": 0.0,
"drop_rate": 0.0,
"FDI": {
"interval": 0,
"offset": 0.0,
"randomness": 0.0,
"base": 0.0,
"scaling_factor": 1.0
},
"replay" : {
"amount": 0,
"wait": 0
}
},
"battery_to_controller_network": {
"delay_min": 0.0,
"delay_max": 0.0,
"drop_rate": 0.0,
"FDI": {
"interval": 0,
"offset": 0.0,
"randomness": 0.0,
"base": 0.0,
"scaling_factor": 1.0
},
"replay" : {
"amount": 0,
"wait": 0
}
}
}
\ No newline at end of file
# This script interactively explains how to install the simulator
# on a windows system. It could benefit from being automated in the future
Write-Host "Download and Install python3 from the official website"
Write-Host "(NOT MICROSOFT STORE) and add it to PATH:"
Write-Host " https://www.python.org/downloads/"
Read-Host 'Press RETURN to continue'
Write-Host "Open a new powershell and verify that the python Tkinter library was included"
Write-Host "using the following command (otherwise it needs to be installed separately):"
Write-Host " python.exe -c 'import tkinter'"
Read-Host 'Press RETURN to continue'
Write-Host "[Optional: create and enter a python virtual environment first]"
Write-Host "Then install python modules used in the project with the following command:"
Write-Host " pip install -r requirements.txt"
Read-Host 'Press RETURN to continue'
Write-Host "Download and Install HELICS 3.4 from the GitHub and add HELICS executables to PATH:"
Write-Host " https://github.com/GMLC-TDC/HELICS/releases/download/v3.4.0/Helics-3.4.0-win64.exe"
\ No newline at end of file
#!/bin/bash
# Script for installation on a debian-based linux system
# (but probably easy to adapt to other distributions)
echo "Install system packages (differs between distros)"
sudo apt install wget python3 python3-virtualenv python3-tk
printf '\n\n%s\n' "Create and enter python virtual environment"
virtualenv -p /usr/bin/python3 venv
source venv/bin/activate
printf '\n\n%s\n' "Installing python dependencies (pip)"
pip install -r requirements.txt
printf '\n\n%s\n' "Installing HELICS 3.4"
mkdir -p lib
cd lib
wget https://github.com/GMLC-TDC/HELICS/releases/download/v3.4.0/Helics-3.4.0-Linux-x86_64.tar.gz
tar xvzf Helics-*
rm *.tar.gz
cd ..
printf '\n\n%s\n' "Adding Helics to system PATH (assumes bash)"
echo "export PATH=\$PATH:$PWD/lib/Helics-3.4.0-Linux-x86_64/bin" >> $HOME/.bashrc
source $HOME/.bashrc
helics_broker --version
File suppressed by a .gitattributes entry or the file's encoding is unsupported.
echo "Running HELICS simulation..."
helics.exe run --path="advanced_default_runner.json"
\ No newline at end of file
run.sh 0 → 100644
#!/bin/bash
echo "Running HELICS simulation..."
helics run --path="advanced_default_runner.json"
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment