diff --git a/assets/images/report_images/0_docker_build_first_run.png b/assets/images/report_images/0_docker_build_first_run.png
new file mode 100644
index 0000000..a6c09ae
Binary files /dev/null and b/assets/images/report_images/0_docker_build_first_run.png differ
diff --git a/assets/images/report_images/10_grafana_web_3.png b/assets/images/report_images/10_grafana_web_3.png
new file mode 100644
index 0000000..ae723b6
Binary files /dev/null and b/assets/images/report_images/10_grafana_web_3.png differ
diff --git a/assets/images/report_images/1_docker_build_first_run.png b/assets/images/report_images/1_docker_build_first_run.png
new file mode 100644
index 0000000..c2c7470
Binary files /dev/null and b/assets/images/report_images/1_docker_build_first_run.png differ
diff --git a/assets/images/report_images/2_mqtt_run.png b/assets/images/report_images/2_mqtt_run.png
new file mode 100644
index 0000000..27c28f9
Binary files /dev/null and b/assets/images/report_images/2_mqtt_run.png differ
diff --git a/assets/images/report_images/3_sim_run.png b/assets/images/report_images/3_sim_run.png
new file mode 100644
index 0000000..152d472
Binary files /dev/null and b/assets/images/report_images/3_sim_run.png differ
diff --git a/assets/images/report_images/4_mqtt_run_listening.png b/assets/images/report_images/4_mqtt_run_listening.png
new file mode 100644
index 0000000..295f183
Binary files /dev/null and b/assets/images/report_images/4_mqtt_run_listening.png differ
diff --git a/assets/images/report_images/5_infra_run.png b/assets/images/report_images/5_infra_run.png
new file mode 100644
index 0000000..9f82da4
Binary files /dev/null and b/assets/images/report_images/5_infra_run.png differ
diff --git a/assets/images/report_images/6_infa_from_broker.png b/assets/images/report_images/6_infa_from_broker.png
new file mode 100644
index 0000000..ac94123
Binary files /dev/null and b/assets/images/report_images/6_infa_from_broker.png differ
diff --git a/assets/images/report_images/7_grafana_web_1.png b/assets/images/report_images/7_grafana_web_1.png
new file mode 100644
index 0000000..c3f8b00
Binary files /dev/null and b/assets/images/report_images/7_grafana_web_1.png differ
diff --git a/assets/images/report_images/8_grafana_web_2.png b/assets/images/report_images/8_grafana_web_2.png
new file mode 100644
index 0000000..f00f01c
Binary files /dev/null and b/assets/images/report_images/8_grafana_web_2.png differ
diff --git a/assets/images/report_images/9_grafana_queries.png b/assets/images/report_images/9_grafana_queries.png
new file mode 100644
index 0000000..b154106
Binary files /dev/null and b/assets/images/report_images/9_grafana_queries.png differ
diff --git a/report.md b/report.md
new file mode 100644
index 0000000..a342f89
--- /dev/null
+++ b/report.md
@@ -0,0 +1,232 @@
+# Отчёт
+## Студент Зайков Матвей, группа 5142704/30801
+
+
+# 1. Разработка Simulator для генерации данных
+В файле ```sensor.py``` создадим новый тип датчиков Acceleration, способный измерять величину ускорения.
+
+```python
+class Acceleration(Sensor):
+ step = 0
+
+ def __init__(self, name):
+ super().__init__(name)
+ self.type = "acceleration"
+
+ def generate_new_value(self):
+ import math
+ self.value = 7 * math.sin(self.step)
+```
+
+Код клиента из ```main.py```, который подключается к mqtt брокеру и публикует сообщения:
+```python
+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"])
+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
+ 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
+while True:
+ sensor.generate_new_value()
+ ret = client1.publish("sensors/" + sensor.type + "/" + sensor.name, sensor.get_data()) # publish
+ time.sleep(period)
+```
+
+В Dockerfile укажем следующие инструкции для создания образа:
+```
+FROM python:alpine3.19
+WORKDIR /app
+COPY requirements.txt .
+RUN pip install -r requirements.txt
+COPY . .
+CMD ["python", "main.py"]
+```
+
+В ```requirements.txt``` укажем:
+```
+paho_mqtt==1.6.1
+```
+
+Добавим текущего пользователя машины в группу docker с помощью
+```
+sudo usermod -aG docker $USER
+```
+Выполним это на трёх машинах для client, gateway и server
+
+Теперь можно приступать к билду образа:
+```
+docker build -t matveeey/data-simulator .
+```
+
+
+
+Сборка прошла успешно. Можно переходить к следующему этапу.
+
+# 2. Запуск Mosquitto брокера
+Для настройки MQTT необходимо создать конфиг mosquitto.conf:
+```
+listener 1883
+allowanonymous true
+```
+Создадим docker-compose.yml для gateway:
+```
+version: '3'
+services:
+ broker:
+ image: eclipse-mosquitto
+ container_name: broker
+ volumes:
+ - ./mosquitto/mosquitto.conf:/mosquitto/config/mosquitto.conf
+ ports:
+ - "1883:1883"
+```
+Настроим нужный нам проброс пакетов:
+```
+sudo iptables -A OUTPUT -o enp0s8 -p tcp --syn --dport 1883 -m conntrack --ctstate NEW,ESTABLISHED,RELATED -j ACCEPT
+sudo iptables -A OUTPUT -o enp0s9 -p tcp --syn --dport 1883 -m conntrack --ctstate NEW,ESTABLISHED,RELATED -j ACCEPT
+sudo iptables -A INPUT -i enp0s8 -p tcp --syn --dport 1883 -m conntrack --ctstate NEW,ESTABLISHED,RELATED -j ACCEPT
+sudo iptables -A INPUT -i enp0s9 -p tcp --syn --dport 1883 -m conntrack --ctstate NEW,ESTABLISHED,RELATED -j ACCEPT
+```
+И сохраним настройки под рутом
+```
+iptables-save > /etc/iptables/rules.v4
+ip6tables-save > /etc/iptables/rules.v6
+```
+Запустим наш контейнер:
+
+
+
+Брокер запущен и работает.
+
+Теперь запустим на клиенте симуляторы датчиков:
+
+
+
+На брокер прилетают пакеты:
+
+
+
+
+# 2. Отображение данных
+## Telegraf
+Настроим Telegraf, который будет подписываться на MQTT с данными от датчиков:
+В telegraf.conf добавим строчку
+```
+servers = ["tcp://192.168.0.104:1883"] # адрес vm с mqtt-брокером
+```
+
+## InfluxDB
+Используем образ influxdb:1.8
+Настроим конфиг ```influxdb-init.iql```, указав название таблицы sensors:
+
+```
+CREATE database sensors
+CREATE USER telegraf WITH PASSWORD 'telegraf' WITH ALL PRIVILEGES
+```
+
+## Grafana
+Данные берутся из db из influx. В конфиге ```default.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.yml```:
+```
+version: "3"
+services:
+ influxdb:
+ image: influxdb:1.8
+ container_name: influxdb
+ volumes:
+ - ./influxdb/scripts:/docker-entrypoint-initdb.d
+ - influx_data:/var/lib/influxdb
+ networks:
+ - server-net
+ telegraf:
+ image: telegraf
+ container_name: telegraf
+ volumes:
+ - ./telegraf:/etc/telegraf:ro
+ restart: unless-stopped
+ networks:
+ - server-net
+ grafana:
+ image: grafana/grafana
+ container_name: grafana
+ volumes:
+ - grafana_data:/var/lib/grafana
+ - ./grafana/:/etc/grafana/
+
+ environment:
+ - GF_SECURITY_ADMIN_USER=admin
+ - GF_SECURITY_ADMIN_PASSWORD=admin
+ - GF_USERS_ALLOW_SIGN_UP=false
+ restart: unless-stopped
+ ports:
+ - 3000:3000
+ networks:
+ - server-net
+
+
+volumes:
+ influx_data: {}
+ grafana_data: {}
+
+networks:
+ server-net: {}
+```
+
+
+
+
+Логи из брокера:
+
+
+
+Переходим по 192.168.0.18:3000 и логинимся дефолтными admin/admin:
+
+
+
+
+В источниках присутствует InfluxDB:
+
+
+
+
+Настроим запросы:
+
+
+
+Итоговый дашборд:
+
+
+
diff --git a/vms/client/simulator/docker-compose.yml b/vms/client/simulator/docker-compose.yml
index b9e08bb..8afe8cb 100644
--- a/vms/client/simulator/docker-compose.yml
+++ b/vms/client/simulator/docker-compose.yml
@@ -2,23 +2,30 @@ version: "3"
services:
temp_sensor:
- image: antonaleks/data-simulator
+ image: matveeey/simulator:latest
environment:
- - SIM_HOST=192.168.1.1
+ - SIM_HOST=192.168.0.17
- SIM_NAME=TIRCAHL24
- SIM_PERIOD=5
- SIM_TYPE=temperature
pressure_sensor:
- image: antonaleks/data-simulator
+ image: matveeey/simulator:latest
environment:
- - SIM_HOST=192.168.1.1
+ - SIM_HOST=192.168.0.17
- SIM_NAME=PIRCAHL11
- SIM_PERIOD=10
- SIM_TYPE=pressure
current_sensor:
- image: antonaleks/data-simulator
+ image: matveeey/simulator:latest
environment:
- - SIM_HOST=192.168.1.1
+ - SIM_HOST=192.168.0.17
- SIM_NAME=A0_CURRENT
- SIM_PERIOD=1
- SIM_TYPE=current
+ acceleration_sensor:
+ image: matveeey/simulator:latest
+ environment:
+ - SIM_HOST=192.168.0.17
+ - SIM_NAME=ACC0
+ - SIM_PERIOD=15
+ - SIM_TYPE=acceleration
diff --git a/vms/client/simulator/entity/__pycache__/__init__.cpython-310.pyc b/vms/client/simulator/entity/__pycache__/__init__.cpython-310.pyc
new file mode 100644
index 0000000..6f711e3
Binary files /dev/null and b/vms/client/simulator/entity/__pycache__/__init__.cpython-310.pyc differ
diff --git a/vms/client/simulator/entity/__pycache__/sensor.cpython-310.pyc b/vms/client/simulator/entity/__pycache__/sensor.cpython-310.pyc
new file mode 100644
index 0000000..23f1c44
Binary files /dev/null and b/vms/client/simulator/entity/__pycache__/sensor.cpython-310.pyc differ
diff --git a/vms/client/simulator/entity/sensor.py b/vms/client/simulator/entity/sensor.py
index 922fea5..78309d2 100644
--- a/vms/client/simulator/entity/sensor.py
+++ b/vms/client/simulator/entity/sensor.py
@@ -52,3 +52,14 @@ def generate_new_value(self):
import math
self.value = math.sin(self.step)
self.step = self.step + 1
+
+class Acceleration(Sensor):
+ step = 0
+
+ def __init__(self, name):
+ super().__init__(name)
+ self.type = "acceleration"
+
+ def generate_new_value(self):
+ import math
+ self.value = 7 * math.sin(self.step)
diff --git a/vms/client/simulator/main.py b/vms/client/simulator/main.py
index 4d17730..935120e 100644
--- a/vms/client/simulator/main.py
+++ b/vms/client/simulator/main.py
@@ -9,18 +9,20 @@
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}
+sensors = {"temperature": Temperature, "pressure": Pressure, "current": Current, "acceleration": Acceleration}
def on_publish(client, userdata, result): # create function for callback
print(f"data published {userdata}")
pass
-
+print(f'broker: {broker}')
+print(f'Sim port: {port}')
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
+
while True:
sensor.generate_new_value()
ret = client1.publish("sensors/" + sensor.type + "/" + sensor.name, sensor.get_data()) # publish
diff --git a/vms/gateway/mosquitto/docker-compose.yml b/vms/gateway/mosquitto/docker-compose.yml
new file mode 100644
index 0000000..021332b
--- /dev/null
+++ b/vms/gateway/mosquitto/docker-compose.yml
@@ -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"
\ No newline at end of file