Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
f9eba5e
Update README.md
Liudmi1a May 29, 2025
6f6c1e9
Delete vms directory
Liudmi1a May 29, 2025
7f5c05e
Delete guide directory
Liudmi1a May 29, 2025
a0ae558
Delete assets directory
Liudmi1a May 29, 2025
c41b1ab
Add files via upload
Liudmi1a May 29, 2025
ac6cba1
Create dummy
Liudmi1a May 29, 2025
a1e04f8
Add files via upload
Liudmi1a May 29, 2025
e64f6e3
Delete test.txt
Liudmi1a May 29, 2025
49d5ba0
Delete papka directory
Liudmi1a May 29, 2025
739c009
Delete .gitignore
Liudmi1a May 29, 2025
5d0dc50
Update README.md
Liudmi1a May 29, 2025
6f0174a
Create client
Liudmi1a May 29, 2025
6b7e320
Delete vm/client
Liudmi1a May 29, 2025
86a5d41
Create Dockerfile
Liudmi1a May 29, 2025
dee7371
Delete vm/client directory
Liudmi1a May 29, 2025
19e44d6
Create t
Liudmi1a May 29, 2025
ca7f71c
Create Dockerfile
Liudmi1a May 29, 2025
0831a8c
Delete vm/t
Liudmi1a May 29, 2025
c317720
Create docker-compose.yml
Liudmi1a May 29, 2025
dc80894
Create dicker-compose.yml
Liudmi1a May 29, 2025
d830610
Delete vm/client/dicker-compose.yml
Liudmi1a May 29, 2025
5498e12
Create docker-compose.yml
Liudmi1a May 29, 2025
26bcc03
Create sensor.py
Liudmi1a May 29, 2025
bf190cc
Update sensor.py
Liudmi1a May 29, 2025
76e09cc
Create main.py
Liudmi1a May 29, 2025
28356b4
Create requirements.txt
Liudmi1a May 29, 2025
cf1b3c5
Create gateway
Liudmi1a May 29, 2025
dc9344e
Delete vm/gateway
Liudmi1a May 29, 2025
a6ed4a8
Create docker-compose.yml
Liudmi1a May 29, 2025
cb7f532
Update docker-compose.yml
Liudmi1a May 29, 2025
f9c7372
Create mqtt.json
Liudmi1a May 29, 2025
21643e0
Delete vm/server/grafana/provisioning/mqtt.json
Liudmi1a May 29, 2025
4e5cfdf
Create telegraf.conf
Liudmi1a May 29, 2025
3f19e26
Create REPORT.md
Liudmi1a May 29, 2025
4be4cc9
Update REPORT.md
Liudmi1a May 29, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .gitignore

This file was deleted.

5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@

Необходимо развернуть следующую систему:

![image](assets/images/DockerTask.png)
![DockerTask](https://github.com/user-attachments/assets/ad1e1139-a0d5-474e-ac4d-d46df9240ae8)


Симуляторы сенсоров, развернутые в докер контейнерах, публикуют сообщения на Mqtt брокер. Сервис Consumer подписывается на все сообщение,
опубликованные в брокере, и заносит их в базу данных временных рядов. Сервис dashboard отображает графики полученных данных от сервисов.
Expand Down Expand Up @@ -59,5 +60,3 @@
- docker-compose.yml

- report.md - Отчет markdown

P.S. опираться можно на данную [статью](https://coderlessons.com/articles/programmirovanie/raspberry-pi-iot-datchiki-influxdb-mqtt-i-grafana)
134 changes: 134 additions & 0 deletions REPORT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
# Отчёт по работе №2: Практика Docker
**Цель:** создать систему мониторинга системы датчиков с использованием Docker, Mosquitto, InfluxDB, Telegraf и Grafana на трёх виртуальных машинах (далее ВМ).

## Подготовка ВМ
1. Взяты три ВМ из работы №1 (предварительно настроены в формате client, server, gateway).
2. Необходимо установить на каждую ВМ Docker и Docker Compose посредством:
```shell
sudo apt update
sudo apt upgrade -y
sudo apt install -y docker.io
sudo systemctl enable docker
sudo systemctl start docker
docker --version
sudo usermod -aG docker $USER
sudo apt install -y docker-compose
docker-compose --version
```

# Шаг 1: Разработка Simulator для генерации данных

В файле `sensor.py` создаем четвертыht типf датчиков.

Далее в файле `main.py` реализовуем клиента, который подключается к mqtt брокеру и публикует сообщения.

В `Dockerfile`, необходимом для того, что создать образ, указываем следуюещие инструкции:

``` Dockerfile
FROM python:alpine3.19
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["python", "main.py"]
```

Инструкция `FROM` инициализирует новый этап сборки и устанавливает базовый образ для последующих инструкций. `WORKDIR` создает рабочий каталог для последующих инструкций `Dockerfile`. Инструкция `COPY` копирует файл *requirements.txt* из источника в указанное место внутри образа.
Инструкция `RUN`задает команды, которые следует выполнить и поместить в новый образ контейнера. `RUN` описывает команду с аргументами, которую нужно выполнить когда контейнер будет запущен.

Содержимое файла *requirements.txt* приведено ниже:
`paho_mqtt==1.6.1`

*paho_mqtt* предоставляет клиентский класс, который позволяет приложениям подключаться к MQTT-брокеру для публикации сообщений.

После проделанных выше опреаций можно создать образ командой:

`docker build -t luyda/sensor-sim . `

Таким способом мы создали образ, из которого можно развернуть контейнер.

# Шаг 2: Запуск Mosquitto брокера

Для настройки протокола MQTT необходимо создать конфигурационный файл *mosquitto.conf* со следующим содержимымы:

```c
listener 1883
allow_anonymous true
```
Для более удобного запуска брокера создадим файл *docker-compose.yml*.

Теперь создав контейнер посмотрим его логи:
![example_run_logs](https://github.com/user-attachments/assets/79529d5e-a1a1-4f9a-bb6e-ae171fc12bc2)

Брокер же отображает присоединившегося клиента.
![mqtt-docker_run](https://github.com/user-attachments/assets/ac0feb01-6071-4bf4-8a9c-e969bd2aea44)

Теперь можно запустить несколько датчиков. Но перед этим необходимо прописать *docker-compose.yml*:

С помощью команды `docker compose up` запустим контейнеры.

При этом брокер отображает:
![mqtt-docker-compose](https://github.com/user-attachments/assets/67cae960-53c8-42cc-a962-8eb575bdbbed)

# Шаг 3: Получение данных от симулятора
Первоначально необходимо настроить Telegraf, который подписывается на MQTT, где датчики публикуют данные. Данные будут сохраняться в InfluxDB. Отображение информации с датчиков будет происходить при помощи Grafana.

## Telegraf
Перед использованием Telegram необходимо настроить его.
Для этого создадим конфигурационный файл *telegraf.conf*
Тем самым мы настраиваем Telegraf на чтение данных с машины IP адрес которой 192.168.0.101 через порт 1883.

Настройка Telegraf на этом завршена.

## InfluDB

Для создания базы данных необходимо в конфигурационном файле *influxdb-init.iql* прописать следующее:
```sql
CREATE database sensors
CREATE USER telegraf WITH PASSWORD 'telegraf' WITH ALL PRIVILEGES
```

## Grafana

Данные для отображения датчиков берутся из InfluxDB.
Для настройки в конфигурационном файле необходимо прописать следующее:
```yaml
apiVersion: 1
datasources:
- name: InfluxDB_v1
type: influxdb
access: proxy
database: sensors
user: telegraf
url: http://influxdb:8086
jsonData:
httpMode: GET
secureJsonData:
password: telegraf
```

Для запуска всех трех контенйеров воспользуемся docker-compose. создадим файл docker-compose.yml

После чего можно выполнить команду `docker compose up`

# Настройка дашборда
После запуска всех необходимых контейнеров, в браузере переходим по `192.168.0.101:3000`

Для проверки соединения перейдем в Menu -> Connections -> Data sources. Находим в истончиках InfluxDB и проверяем подключение:
![grafana-influxdb-test](https://github.com/user-attachments/assets/db9150a7-259a-4186-94d3-167383dd9e25)

После переходим через Меню в раздел Dashboards, где создаем собственный дашбоард.
![grafana-new-view](https://github.com/user-attachments/assets/ee1b4398-b5e2-4910-b340-9d1a33185fb5)

Для отображения информации с датчиков необходимо создать запрос (query).
![query](https://github.com/user-attachments/assets/3dbd7945-7190-470d-bf3c-f6f1b537e77e)

После создания необходимо количества графиков, отображающих инфомрацию с Simluator, экспортируем дашборд как JSON-файл.

Для этого находим функцию `Share` -> ``Export` -> `Save to file`. Сохраненный файл помещаем в папку `vms\server\infra\grafana\provisioning\dashboards\mqtt.json`

# Пример выполненной работы

![dashboard](https://github.com/user-attachments/assets/f94c4469-4ef2-4c4a-b2bb-9b2c7464bd79)


Binary file removed assets/images/DockerTask.png
Binary file not shown.
114 changes: 0 additions & 114 deletions guide/manual.md

This file was deleted.

2 changes: 0 additions & 2 deletions vms/client/simulator/Dockerfile → vm/client/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,3 @@ FROM python:alpine3.19
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["python", "main.py"]
31 changes: 31 additions & 0 deletions vm/client/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
version: "3"

services:
temp_sensor:
image: luyda/sensor-sim
environment:
- SIM_HOST=192.168.0.101
- SIM_NAME=TEMP1
- SIM_PERIOD=2
- SIM_TYPE=temperature
pressure_sensor:
image: luyda/sensor-sim
environment:
- SIM_HOST=192.168.0.101
- SIM_NAME=PRESS1
- SIM_PERIOD=2
- SIM_TYPE=pressure
current_sensor:
image: luyda/sensor-sim
environment:
- SIM_HOST=192.168.0.101
- SIM_NAME=CURRENT1
- SIM_PERIOD=2
- SIM_TYPE=current
co_sensor:
image: polinazhirakova/data-simulator
environment:
- SIM_HOST=192.168.0.101
- SIM_NAME=CO1
- SIM_PERIOD=2
- SIM_TYPE=carbon_oxid
14 changes: 14 additions & 0 deletions vm/client/enity/sensor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import math
self.value = math.sin(self.step)
self.step = self.step + 1

class CO(Sensor):
step = 0

def __init__(self,name):
super().__init__(name)
self.type = "carbon oxid"

def generate_new_value(self):
self.value = self.step * 1e6
self.step = self.step + 0.001
20 changes: 7 additions & 13 deletions vms/client/simulator/main.py → vm/client/main.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,21 @@
import paho.mqtt.client as paho
from os import environ
import time

from entity.sensor import *

broker = "localhost" if "SIM_HOST" not in environ.keys() else environ["SIM_HOST"]
port = 1883 if "SIM_PORT" not in environ.keys() else int(environ["SIM_PORT"])
port = 1883 if "SIM_PORT" not in environ.keys() else environ["SIM_PORT"]
name = "sensor" if "SIM_NAME" not in environ.keys() else environ["SIM_NAME"]
period = 1 if "SIM_PERIOD" not in environ.keys() else int(environ["SIM_PERIOD"])
type_sim = "temperature" if "SIM_TYPE" not in environ.keys() else environ["SIM_TYPE"]
sensors = {"temperature": Temperature, "pressure": Pressure, "current": Current}


def on_publish(client, userdata, result): # create function for callback
sensors = {"temperature": Temperature, "pressure": Pressure, "current": Current, "carbon_oxid": CO}
def on_publish(client, userdata, result):
print(f"data published {userdata}")
pass


sensor = sensors[type_sim](name=name)
client1 = paho.Client(sensor.name) # create client object
client1.on_publish = on_publish # assign function to callback
client1.connect(broker, port) # establish connection
client1 = paho.Client(sensor.name)
client1.on_publish = on_publish
client1.connect(broker, port)
while True:
sensor.generate_new_value()
ret = client1.publish("sensors/" + sensor.type + "/" + sensor.name, sensor.get_data()) # publish
ret = client1.publish("sensors/" + sensor.type + "/" + sensor.name, sensor.get_data())
time.sleep(period)
File renamed without changes.
9 changes: 9 additions & 0 deletions vm/gateway/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
version: "3"
services:
broker:
image: eclipse-mosquitto
container_name: broker
volumes:
- ./mosquitto/mosquitto.conf:/mosquitto/config/mosquitto.conf
ports:
- "1883:1883"
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ services:
volumes:
- grafana_data:/var/lib/grafana
- ./grafana/:/etc/grafana/

environment:
- GF_SECURITY_ADMIN_USER=admin
- GF_SECURITY_ADMIN_PASSWORD=admin
Expand All @@ -32,11 +31,8 @@ services:
- 3000:3000
networks:
- server-net


volumes:
influx_data: {}
grafana_data: {}

networks:
server-net: {}
server-net: {}
Loading