{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Sensor Replay Attack Example" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from IPython.display import display, HTML\n", "display(HTML('\"Open'))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This example demonstrates how to add a sensor replay attack to a scenario -- more information can be found in the [documentation](https://epyt-flow.readthedocs.io/en/stable/tut.events.html#sensor-reading-attacks)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%pip install epyt-flow --quiet" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from epyt_flow.data.benchmarks import load_leakdb_scenarios\n", "from epyt_flow.simulation import ScenarioSimulator, SENSOR_TYPE_NODE_PRESSURE\n", "from epyt_flow.simulation.events import SensorReplayAttack\n", "from epyt_flow.utils import to_seconds, plot_timeseries_data" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Load the first [LeakDB](https://epyt-flow.readthedocs.io/en/stable/epyt_flow.data.benchmarks.html#epyt_flow.data.benchmarks.leakdb.load_scenarios) Hanoi scenario:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "config = load_leakdb_scenarios(scenarios_id=[\"1\"], use_net1=False, verbose=False)[0]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Create a new simulation:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sim = ScenarioSimulator(scenario_config=config)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Set the simulation duration to two days:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sim.set_general_parameters(simulation_duration=to_seconds(days=2))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Add a sensor replay attack -- pressure readings at node \"13\" between 5hrs and 7hrs after simulation start (time steps 10 - 15) are replaced by the historical readings collected from the first 150min (i.e. first 5 time steps).\n", "\n", "This is done by creating an instance of the [SensorReplayAttack](https://epyt-flow.readthedocs.io/en/stable/epyt_flow.simulation.events.html#epyt_flow.simulation.events.sensor_reading_attack.SensorReplayAttack) class and adding it to the scenarion by calling [add_sensor_reading_event()](https://epyt-flow.readthedocs.io/en/stable/epyt_flow.simulation.html#epyt_flow.simulation.scenario_simulator.ScenarioSimulator.add_sensor_reading_event):" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sensor_replay_attack = SensorReplayAttack(replay_data_time_window_start=0,\n", " replay_data_time_window_end=to_seconds(minutes=150),\n", " start_time=to_seconds(hours=5),\n", " end_time=to_seconds(hours=7),\n", " sensor_id=\"13\",\n", " sensor_type=SENSOR_TYPE_NODE_PRESSURE)\n", "\n", "sim.add_sensor_reading_event(sensor_replay_attack)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Run the entire simulation:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "scada_data = sim.run_simulation()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Retrieve and plot the pressure readings:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "pressure_readings = scada_data.get_data_pressures(sensor_locations=[\"13\"])" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "scada_data.plot_pressures(sensor_locations=[\"13\"])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Readings for time 10 - 15 are same as the first 5 readings!" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "plot_timeseries_data(pressure_readings[:20].T, # The same as the first 5 readings!\n", " x_axis_label=\"Time (30min steps)\",\n", " y_axis_label=\"Pressure in $m$\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Sensor readings WITHOUT the sensor replay attack" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Remove sensor replay attack\n", "scada_data.sensor_reading_events = []\n", "\n", "# Recompute and show final sensor readings\n", "pressure_readings = scada_data.get_data_pressures(sensor_locations=[\"13\"])\n", "plot_timeseries_data(pressure_readings[:20].T,\n", " x_axis_label=\"Time (30min steps)\",\n", " y_axis_label=\"Pressure in $m$\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Do not forget to close the simulation!" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sim.close()" ] } ], "metadata": { "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.20" } }, "nbformat": 4, "nbformat_minor": 2 }