Commit cbed3616 authored by Sebastian Böhm's avatar Sebastian Böhm
Browse files

update documentation

parent 35fb7dbb
......@@ -2,6 +2,8 @@
The following project contains a small edge-IoT simulator.
## Components and Architecture
Components:
* `core`: IoT device simulators, e.g., `temperature` simulator
......@@ -11,15 +13,14 @@ Components:
Architecture:
```bash
web <-> core <-> queue <-> mqtt_publisher
web <-> core <-> queue <-> mqtt_client
```
Details:
* `web`: The web application has a reference to the core services (e.g., temperature) and has currently two endpoints:
* `web`: The web application has a reference to the core services (e.g., temperature) and has currently three endpoints:
* `/`: Dashboard which shows the latest temperature value
* `/temperature`: Returns the latest temperature value as json
* `core, queue, mqtt_publisher`: The core services (e.g., `temperature`) are decoupled from the `mqtt_publisher` by a shared memory `threadsafe` queue. The `mqtt_publisher` forwards the message with a corresponding topic and payload.
* `/cpu-load`: Returns a UI to manage CPU load jobs
* `core, queue, mqtt_client`: The core services (e.g., `temperature`, `cpu-load`) are decoupled from the `mqtt_client` by a shared memory `threadsafe` queue. The `mqtt_client` forwards the message with a corresponding topic and payload.
For example:
......@@ -34,7 +35,89 @@ temperature <-> TemperatureMeasurement (timestamp=XXX,value=XXX,unit=XXX)
queue
^
|
mqtt_publisher.client.publish(MqttMessage.topic, MqttMessage.payload)
mqtt_client.client.publish(MqttMessage.topic, MqttMessage.payload)
```
Other available services follow the same decoupled architecture.
## Services
## TemperatureService (`core.temperature_svc.py`)
This service is continuously transmitting temperature values to an mqtt endpoint.
### HTTP-Endpoints:
* (UI) `/` \[GET\]: Current temperature value
* (API) `/temperature` \[GET\]: Current temperature value as json
### MQTT-Topics:
**TemperatureMessage:** `sensors/<MQTT_CLIENT_ID>/data`
```json
{
"timestamp": 1637751270.438974,
"value": 33,
"unit": "celsius"
}
```
## CPULoadService (`core.cpu_load_svc`)
This service allow to stress the CPU of the edge device for a period of time.
It is possible to define the duration and the target load for the cpu.
For example, all logical cores can be utilized to run at 50% CPU utilization for 15min.
### HTTP_Endpoints
* (UI) `/` `/cpu-load`: Allow to create new cpu load jobs and to manage already existing ones
### MQTT_TOPICS
**Request Creation of CPULoadJobAllCores:** `services/cpuLoadSvc/<MQTT_CLIENT_ID>/jobs/create/req`
```json
{
"duration": 200,
"target_load": 0.50
}
```
**Response Creation of CPULoadJobAllCores:** `services/cpuLoadSvc/<MQTT_CLIENT_ID>/jobs/create/res`
On Success:
```json
{
"duration": 200,
"target_load": 0.50
}
```
On Error:
```json
{
"error": "Illegal message received: ('Duration must be between 30 and 3600',)"
}
```
**Request Reading current QueuedCPULoadJobAllCores:** `services/cpuLoadSvc/<MQTT_CLIENT_ID>/jobs/read/req`
Payload intentionally left blank.
**Response Reading current QueuedCPULoadJobAllCores:** `services/cpuLoadSvc/<MQTT_CLIENT_ID>/jobs/read/res`
```json
{
"duration": 60,
"target_load": 0.55,
"id": 1,
"pid": 596,
"state": "RUNNING"
}
```
All components can easily be configured with the following `.env` file with should be present in the root of this project.
......@@ -54,15 +137,34 @@ MQTT_MAX_CONNECT_RETRIES=5
MQTT_RECONNECT_TIMEOUT=30
MQTT_CLIENT_ID=ab444537-cf67-47aa-a5ef-3548292e225b
MQTT_PUBLISH_QOS=2
MQTT_SUBSCRIBE_QOS=2
MQTT_TOPIC_PUBLISHER=publisher
MQTT_TOPIC_PUBLISHER_STATE=state
# core
MQTT_TOPIC_REQ_TYPE_CREATE=create/req
MQTT_TOPIC_RES_TYPE_CREATE=create/res
MQTT_TOPIC_REQ_TYPE_READ=read/req
MQTT_TOPIC_RES_TYPE_READ=read/res
## temperature
MQTT_TOPIC_SENSORS=sensors
MQTT_TOPIC_SENSORS_DATA=data
## cpu
MQTT_TOPIC_SERVICES=services
MQTT_TOPIC_CPU_LOAD_SERVICE=cpuLoadSvc
MQTT_TOPIC_CPU_LOAD_SERVICE_DATA=jobs
CPU_LOAD_SVC_MIN_DURATION_SECONDS=30
CPU_LOAD_SVC_MAX_DURATION_SECONDS=3600
CPU_LOAD_SVC_MIN_TARGET_LOAD=0.25
CPU_LOAD_SVC_MAX_TARGET_LOAD=0.75
# web
WEB_HOSTNAME=localhost
```
## Prerequisites
......@@ -88,17 +190,17 @@ You should see the following output:
```bash
11/11/2021 02:48:48 PM main Please any key to interrupt...
11/11/2021 02:48:48 PM mqtt_publisher Successfully started mqtt publisher...
11/11/2021 02:48:48 PM mqtt_client Successfully started mqtt publisher...
11/11/2021 02:48:48 PM temperature_svc Successfully started temperature sensor...
11/11/2021 02:48:48 PM temperature_svc New value measured {"timestamp": 1636638528.2080338, "value": 26, "unit": "celsius"}
11/11/2021 02:48:48 PM app Successfully started WebbApp...
11/11/2021 02:48:48 PM mqtt_publisher Error establishing connection to localhost:1883[Errno 111] Connection refused
11/11/2021 02:48:48 PM mqtt_publisher mqtt publisher received shutdown signal
11/11/2021 02:48:48 PM mqtt_client Error establishing connection to localhost:1883[Errno 111] Connection refused
11/11/2021 02:48:48 PM mqtt_client mqtt publisher received shutdown signal
11/11/2021 02:48:51 PM temperature_svc New value measured {"timestamp": 1636638531.2109501, "value": 20, "unit": "celsius"}
11/11/2021 02:48:54 PM temperature_svc New value measured {"timestamp": 1636638534.2141488, "value": 7, "unit": "celsius"}
11/11/2021 02:48:57 PM temperature_svc New value measured {"timestamp": 1636638537.2166193, "value": 59, "unit": "celsius"}
11/11/2021 02:48:58 PM main Unknown error occurred: Could not establish the connection to the mqtt broker
11/11/2021 02:48:58 PM mqtt_publisher mqtt publisher received shutdown signal
11/11/2021 02:48:58 PM mqtt_client mqtt publisher received shutdown signal
11/11/2021 02:48:58 PM temperature_svc Temperature service received shutdown signal...
11/11/2021 02:48:58 PM app WebApp received shutdown signal....
11/11/2021 02:48:58 PM main Wait for graceful termination...
......@@ -115,21 +217,21 @@ You should see the following output:
```bash
11/11/2021 02:55:39 PM main Please any key to interrupt...
11/11/2021 02:55:39 PM mqtt_publisher Successfully started mqtt publisher...
11/11/2021 02:55:39 PM mqtt_client Successfully started mqtt publisher...
11/11/2021 02:55:39 PM temperature_svc Successfully started temperature sensor...
11/11/2021 02:55:39 PM temperature_svc New value measured {"timestamp": 1636638939.4815965, "value": 46, "unit": "celsius"}
11/11/2021 02:55:39 PM app Successfully started WebbApp...
11/11/2021 02:55:39 PM mqtt_publisher Publisher connected with result code 0
11/11/2021 02:55:39 PM mqtt_publisher Successfully published message {"timestamp": 1636638939.4815965, "value": 46, "unit": "celsius"}
11/11/2021 02:55:39 PM mqtt_client Publisher connected with result code 0
11/11/2021 02:55:39 PM mqtt_client Successfully published message {"timestamp": 1636638939.4815965, "value": 46, "unit": "celsius"}
11/11/2021 02:55:42 PM temperature_svc New value measured {"timestamp": 1636638942.4844544, "value": 14, "unit": "celsius"}
11/11/2021 02:55:42 PM mqtt_publisher Successfully published message {"timestamp": 1636638942.4844544, "value": 14, "unit": "celsius"}
11/11/2021 02:55:42 PM mqtt_client Successfully published message {"timestamp": 1636638942.4844544, "value": 14, "unit": "celsius"}
11/11/2021 02:55:45 PM temperature_svc New value measured {"timestamp": 1636638945.4878645, "value": 36, "unit": "celsius"}
11/11/2021 02:55:45 PM mqtt_publisher Successfully published message {"timestamp": 1636638945.4878645, "value": 36, "unit": "celsius"}
11/11/2021 02:55:45 PM mqtt_client Successfully published message {"timestamp": 1636638945.4878645, "value": 36, "unit": "celsius"}
^C11/11/2021 02:55:48 PM main Received user's shutdown signal...
11/11/2021 02:55:48 PM mqtt_publisher mqtt publisher received shutdown signal
11/11/2021 02:55:48 PM mqtt_client mqtt publisher received shutdown signal
11/11/2021 02:55:48 PM temperature_svc New value measured {"timestamp": 1636638948.4884603, "value": 1, "unit": "celsius"}
11/11/2021 02:55:48 PM mqtt_publisher Successfully published message {"timestamp": 1636638948.4884603, "value": 1, "unit": "celsius"}
11/11/2021 02:55:48 PM mqtt_publisher mqtt publisher received shutdown signal
11/11/2021 02:55:48 PM mqtt_client Successfully published message {"timestamp": 1636638948.4884603, "value": 1, "unit": "celsius"}
11/11/2021 02:55:48 PM mqtt_client mqtt publisher received shutdown signal
11/11/2021 02:55:48 PM temperature_svc Temperature service received shutdown signal...
11/11/2021 02:55:48 PM app WebApp received shutdown signal....
11/11/2021 02:55:48 PM main Wait for graceful termination...
......
......@@ -144,8 +144,8 @@ class MessageBroker(threading.Thread):
created_cpu_load_job = self.cpu_load_svc.create_cpu_load_job(json_cpu_load_job_all_cores['duration'], json_cpu_load_job_all_cores['target_load'])
self.publisher_queue.put(MqttMessage(topic_cpuLoadSvc_cpuLoadJob_create_res, MqttSuccessMessage(created_cpu_load_job)))
except (ValueError, JSONDecodeError) as e:
error_message = 'Illegal message received: ' + str(e.args)
except (ValueError, JSONDecodeError, KeyError) as e:
error_message = 'Illegal message received: ' + str(e)
self.logger.error(error_message)
self.publisher_queue.put(MqttMessage(topic_cpuLoadSvc_cpuLoadJob_read_res, MqttErrorMessage(error_message)))
......
......@@ -8,13 +8,13 @@
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
<title>Hello, world!</title>
<title>Edge-IoT Simulator - CPU-Load!</title>
</head>
<body>
<div class="container px-4">
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container-fluid">
<a class="navbar-brand" href="#">Edge-IoT Simulator</a>
<a class="navbar-brand" href="/dashboard">Edge-IoT Simulator</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
......
<!doctype html>
<title>IoT Simulator Dashboard</title>
<body>
<h1>Temperature Service</h1>
<h2>Edge</h2>
<p>Timestamp: {{ TemperatureMeasurement.timestamp }} </p>
<p>Value: {{ TemperatureMeasurement.value }} </p>
<p>Unit: {{ TemperatureMeasurement.unit }}</p>
<br />
<form>
<div class="form-example">
<label for="name">Average Latency (10 requests):</label>
<input type="text" name="latency" id="latency"> <i>ms</i>
</div>
</form>
<button onclick="myFunction()">Check latency</button>
<br />
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
<title>Edge-IoT Simulator - CPU-Load!</title>
</head>
<body>
<div class="container px-4">
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container-fluid">
<a class="navbar-brand" href="#">Edge-IoT Simulator</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="/">Temperature</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/cpu-load">CPU-Load</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="row gx-5">
<div class="col">
<div class="p-3 border">
<h2>Temperature Service</h2>
<p>Timestamp: {{ TemperatureMeasurement.timestamp }} </p>
<p>Value: {{ TemperatureMeasurement.value }} </p>
<p>Unit: {{ TemperatureMeasurement.unit }}</p>
<form>
<div class="form-example">
<label for="name">Average Latency (10 requests):</label>
<input type="text" name="latency" id="latency"> <i>ms</i>
</div>
</form>
<button onclick="myFunction()">Check latency</button>
</div>
</div>
</div>
<div class="col">
<div class="p-3 border">
<h3>MQTT Info</h3>
<p>Host: {{ MqttStatistics.host }}</p>
<p>Port: {{ MqttStatistics.port }}</p>
<p>Connection status: {{ MqttStatistics.status }}</p>
<p>Published messages: {{ MqttStatistics.message_counter }} </p>
</div>
</div>
<script>
function myFunction() {
total_simulation_time = 0;
......@@ -35,11 +76,4 @@
document.getElementById('latency').value = total_simulation_time / interactions;
};
</script>
<br />
<br />
<h3>MQTT Info</h3>
<p>Host: {{ MqttStatistics.host }}</p>
<p>Port: {{ MqttStatistics.port }}</p>
<p>Connection status: {{ MqttStatistics.status }}</p>
<p>Published messages: {{ MqttStatistics.message_counter }} </p>
</body>
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment