diff --git a/assets/images/MQTT-docker-compose.png b/assets/images/MQTT-docker-compose.png new file mode 100644 index 0000000..7e7b5b5 Binary files /dev/null and b/assets/images/MQTT-docker-compose.png differ diff --git a/assets/images/MQTT-docker_run.png b/assets/images/MQTT-docker_run.png new file mode 100644 index 0000000..d6b816a Binary files /dev/null and b/assets/images/MQTT-docker_run.png differ diff --git a/assets/images/dashboard.png b/assets/images/dashboard.png new file mode 100644 index 0000000..8ddb737 Binary files /dev/null and b/assets/images/dashboard.png differ diff --git a/assets/images/docker-compose-simulator.png b/assets/images/docker-compose-simulator.png new file mode 100644 index 0000000..d35375a Binary files /dev/null and b/assets/images/docker-compose-simulator.png differ diff --git a/assets/images/example_run.png b/assets/images/example_run.png new file mode 100644 index 0000000..9bd3ecf Binary files /dev/null and b/assets/images/example_run.png differ diff --git a/assets/images/example_run_logs.png b/assets/images/example_run_logs.png new file mode 100644 index 0000000..9f61b98 Binary files /dev/null and b/assets/images/example_run_logs.png differ diff --git a/assets/images/example_run_with_error.png b/assets/images/example_run_with_error.png new file mode 100644 index 0000000..1d518e3 Binary files /dev/null and b/assets/images/example_run_with_error.png differ diff --git a/assets/images/grafana-influx-test.png b/assets/images/grafana-influx-test.png new file mode 100644 index 0000000..68fad83 Binary files /dev/null and b/assets/images/grafana-influx-test.png differ diff --git a/assets/images/grafana-login.png b/assets/images/grafana-login.png new file mode 100644 index 0000000..f0cba04 Binary files /dev/null and b/assets/images/grafana-login.png differ diff --git a/assets/images/grafana-new-view.png b/assets/images/grafana-new-view.png new file mode 100644 index 0000000..18285d9 Binary files /dev/null and b/assets/images/grafana-new-view.png differ diff --git a/assets/images/image-data-simulator.png b/assets/images/image-data-simulator.png new file mode 100644 index 0000000..362fea2 Binary files /dev/null and b/assets/images/image-data-simulator.png differ diff --git a/assets/images/query.png b/assets/images/query.png new file mode 100644 index 0000000..f9a4792 Binary files /dev/null and b/assets/images/query.png differ diff --git a/assets/images/telegraf-influx-grafana.png b/assets/images/telegraf-influx-grafana.png new file mode 100644 index 0000000..cd8edcd Binary files /dev/null and b/assets/images/telegraf-influx-grafana.png differ diff --git a/vms/client/simulator/Dockerfile b/vms/client/simulator/Dockerfile index eb66b3a..a2d5ef7 100644 --- a/vms/client/simulator/Dockerfile +++ b/vms/client/simulator/Dockerfile @@ -1,6 +1,6 @@ -FROM python:alpine3.19 +FROM python:alpine3.19 WORKDIR /app COPY requirements.txt . RUN pip install -r requirements.txt COPY . . -CMD ["python", "main.py"] +CMD ["python", "main.py"] \ No newline at end of file diff --git a/vms/client/simulator/docker-compose.yml b/vms/client/simulator/docker-compose.yml index b9e08bb..6d07fe5 100644 --- a/vms/client/simulator/docker-compose.yml +++ b/vms/client/simulator/docker-compose.yml @@ -2,23 +2,44 @@ version: "3" services: temp_sensor: - image: antonaleks/data-simulator + image: annagajna/data-simulator environment: - - SIM_HOST=192.168.1.1 - - SIM_NAME=TIRCAHL24 - - SIM_PERIOD=5 + - SIM_HOST=192.168.0.101 + - SIM_NAME=TEMP1 + - SIM_PERIOD=2 - SIM_TYPE=temperature pressure_sensor: - image: antonaleks/data-simulator + image: annagajna/data-simulator environment: - - SIM_HOST=192.168.1.1 - - SIM_NAME=PIRCAHL11 - - SIM_PERIOD=10 + - SIM_HOST=192.168.0.101 + - SIM_NAME=PRESS1 + - SIM_PERIOD=2 - SIM_TYPE=pressure current_sensor: - image: antonaleks/data-simulator + image: annagajna/data-simulator environment: - - SIM_HOST=192.168.1.1 - - SIM_NAME=A0_CURRENT - - SIM_PERIOD=1 + - SIM_HOST=192.168.0.101 + - SIM_NAME=CURRENT1 + - SIM_PERIOD=2 - SIM_TYPE=current + co_sensor: + image: annagajna/data-simulator + environment: + - SIM_HOST=192.168.0.101 + - SIM_NAME=CO1 + - SIM_PERIOD=2 + - SIM_TYPE=carbon_oxid + temp_sensor_2: + image: annagajna/data-simulator + environment: + - SIM_HOST=192.168.0.101 + - SIM_NAME=TEMP2 + - SIM_PERIOD=4 + - SIM_TYPE=temperature + co_sensor_2: + image: annagajna/data-simulator + environment: + - SIM_HOST=192.168.0.101 + - SIM_NAME=CO2 + - SIM_PERIOD=6 + - SIM_TYPE=carbon_oxid \ No newline at end of file diff --git a/vms/client/simulator/entity/sensor.py b/vms/client/simulator/entity/sensor.py index 922fea5..65200ae 100644 --- a/vms/client/simulator/entity/sensor.py +++ b/vms/client/simulator/entity/sensor.py @@ -1,54 +1,11 @@ -import random - - -class Sensor: - value: float - name: str - type: str - - def __init__(self, name): - self.name = name - - def generate_new_value(self): - pass - - def get_data(self): - return self.value - - def __str__(self): - return {"type": self.type, "name": self.name, "value": self.value} - - -class Temperature(Sensor): - step = 25 - - def __init__(self, name): - super().__init__(name) - self.type = "temp" - - def generate_new_value(self): - self.value = random.random() + self.step - - -class Pressure(Sensor): - step = 55 - - def __init__(self, name): - super().__init__(name) - self.type = "pressure" - - def generate_new_value(self): - self.value = random.random() + self.step - 56.48 + 25 * 7 - - -class Current(Sensor): +class CO(Sensor): step = 0 - - def __init__(self, name): + + def __init__(self,name): super().__init__(name) - self.type = "current" - + self.type = "carbon oxid" + def generate_new_value(self): - import math - self.value = math.sin(self.step) - self.step = self.step + 1 + self.value = self.step * 1e6 + self.step = self.step + 0.001 + \ No newline at end of file diff --git a/vms/client/simulator/main.py b/vms/client/simulator/main.py index 4d17730..d2639c0 100644 --- a/vms/client/simulator/main.py +++ b/vms/client/simulator/main.py @@ -5,11 +5,12 @@ 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} + +sensors = {"temperature": Temperature, "pressure": Pressure, "current": Current, "carbon_oxid": CO} def on_publish(client, userdata, result): # create function for callback @@ -24,4 +25,4 @@ def on_publish(client, userdata, result): # create function for callback while True: sensor.generate_new_value() ret = client1.publish("sensors/" + sensor.type + "/" + sensor.name, sensor.get_data()) # publish - time.sleep(period) + time.sleep(period) \ No newline at end of file diff --git a/vms/gateway/docker-compose.yml b/vms/gateway/docker-compose.yml new file mode 100644 index 0000000..869e743 --- /dev/null +++ b/vms/gateway/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 diff --git a/vms/gateway/mosquitto/mosquitto.conf b/vms/gateway/mosquitto/mosquitto.conf index c8348ac..daa4137 100644 --- a/vms/gateway/mosquitto/mosquitto.conf +++ b/vms/gateway/mosquitto/mosquitto.conf @@ -1,2 +1,2 @@ listener 1883 -allow_anonymous true +allow_anonymous true \ No newline at end of file diff --git a/vms/server/infra/docker-compose.yml b/vms/server/infra/docker-compose.yml index 94e705e..ff420db 100644 --- a/vms/server/infra/docker-compose.yml +++ b/vms/server/infra/docker-compose.yml @@ -33,7 +33,6 @@ services: networks: - server-net - volumes: influx_data: {} grafana_data: {} diff --git a/vms/server/infra/grafana/provisioning/dashboards/mqtt.json b/vms/server/infra/grafana/provisioning/dashboards/mqtt.json index ec65ac0..03b6880 100644 --- a/vms/server/infra/grafana/provisioning/dashboards/mqtt.json +++ b/vms/server/infra/grafana/provisioning/dashboards/mqtt.json @@ -3,7 +3,10 @@ "list": [ { "builtIn": 1, - "datasource": "-- Grafana --", + "datasource": { + "type": "datasource", + "uid": "grafana" + }, "enable": true, "hide": true, "iconColor": "rgba(0, 211, 255, 1)", @@ -21,6 +24,7 @@ "editable": true, "fiscalYearStartMonth": 0, "graphTooltip": 0, + "id": 1, "links": [], "liveNow": false, "panels": [ @@ -35,6 +39,184 @@ "mode": "palette-classic" }, "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "fillOpacity": 80, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineWidth": 1, + "scaleDistribution": { + "type": "linear" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ppm" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 8, + "x": 0, + "y": 0 + }, + "id": 3, + "options": { + "barRadius": 0, + "barWidth": 0.97, + "fullHighlight": false, + "groupWidth": 0.7, + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "orientation": "auto", + "showValue": "auto", + "stacking": "none", + "tooltip": { + "mode": "single", + "sort": "none" + }, + "xTickLabelRotation": 0, + "xTickLabelSpacing": 0 + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "P4B5EB7AC8565B06F" + }, + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "measurement": "mqtt_consumer", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "topic::tag", + "operator": "=", + "value": "sensors/carbon oxid/CO1" + } + ] + }, + { + "datasource": { + "type": "influxdb", + "uid": "P4B5EB7AC8565B06F" + }, + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "hide": false, + "measurement": "mqtt_consumer", + "orderByTime": "ASC", + "policy": "default", + "refId": "B", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "topic::tag", + "operator": "=", + "value": "sensors/carbon oxid/CO2" + } + ] + } + ], + "title": "Panel: CO", + "type": "barchart" + }, + { + "datasource": { + "type": "influxdb", + "uid": "P4B5EB7AC8565B06F" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, @@ -46,14 +228,151 @@ "tooltip": false, "viz": false }, - "lineInterpolation": "linear", + "insertNulls": false, + "lineInterpolation": "smooth", + "lineStyle": { + "fill": "solid" + }, "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "auto", - "spanNulls": false, + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "line" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "dark-red", + "value": null + }, + { + "color": "red", + "value": -0.5 + }, + { + "color": "red", + "value": 0.5 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 8, + "y": 0 + }, + "id": 6, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "P4B5EB7AC8565B06F" + }, + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "measurement": "mqtt_consumer", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "topic::tag", + "operator": "=", + "value": "sensors/current/CURRENT1" + } + ] + } + ], + "title": "Panel: Current (Time series)", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "P4B5EB7AC8565B06F" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "smooth", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": true, "stacking": { "group": "A", "mode": "none" @@ -75,22 +394,24 @@ "value": 80 } ] - } + }, + "unit": "celsius" }, "overrides": [] }, "gridPos": { - "h": 9, - "w": 12, + "h": 8, + "w": 8, "x": 0, - "y": 0 + "y": 7 }, "id": 2, "options": { "legend": { "calcs": [], "displayMode": "list", - "placement": "bottom" + "placement": "bottom", + "showLegend": true }, "tooltip": { "mode": "single", @@ -103,7 +424,20 @@ "type": "influxdb", "uid": "P4B5EB7AC8565B06F" }, - "groupBy": [], + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], "measurement": "mqtt_consumer", "orderByTime": "ASC", "policy": "default", @@ -116,35 +450,327 @@ "value" ], "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "topic::tag", + "operator": "=", + "value": "sensors/temp/TEMP1" + } + ] + }, + { + "datasource": { + "type": "influxdb", + "uid": "P4B5EB7AC8565B06F" + }, + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "hide": false, + "measurement": "mqtt_consumer", + "orderByTime": "ASC", + "policy": "default", + "refId": "B", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "topic::tag", + "operator": "=", + "value": "sensors/temp/TEMP2" + } + ] + } + ], + "title": "Panel: Temperatures", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "P4B5EB7AC8565B06F" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "dark-red", + "value": null + }, + { + "color": "green", + "value": -0.5 + }, + { + "color": "orange", + "value": 0.5 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 4, + "x": 8, + "y": 7 + }, + "id": 5, + "options": { + "minVizHeight": 75, + "minVizWidth": 75, + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true, + "sizing": "auto" + }, + "pluginVersion": "10.4.2", + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "${DS_INFLUXDB_V1}" + }, + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "hide": false, + "measurement": "mqtt_consumer", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "topic::tag", + "operator": "=", + "value": "sensors/current/CURRENT1" + } + ] + } + ], + "title": "Panel: Current (Gauge)", + "type": "gauge" + }, + { + "datasource": { + "type": "influxdb", + "uid": "P4B5EB7AC8565B06F" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic-by-name" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "smooth", + "lineStyle": { + "fill": "solid" + }, + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "always", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "pressurepa" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 12, + "y": 7 + }, + "id": 4, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "10.4.2", + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "P4B5EB7AC8565B06F" + }, + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "measurement": "mqtt_consumer", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" } ] ], "tags": [ { - "key": "topic", + "key": "topic::tag", "operator": "=", - "value": "sensors/current/A0_CURRENT" + "value": "sensors/pressure/PRESS1" } ] } ], - "title": "Panel Title", + "title": "Panel: Pressure", "type": "timeseries" } ], - "schemaVersion": 35, - "style": "dark", + "refresh": "", + "schemaVersion": 39, "tags": [], "templating": { "list": [] }, "time": { - "from": "now-5m", + "from": "now-2m", "to": "now" }, "timepicker": {}, "timezone": "", - "title": "New dashboard", - "version": 0, + "title": "My dashboard", + "uid": "bdift4lxq3vgge", + "version": 8, "weekStart": "" } \ No newline at end of file diff --git a/vms/server/infra/telegraf/telegraf.conf b/vms/server/infra/telegraf/telegraf.conf index ddd8b05..4a9c173 100644 --- a/vms/server/infra/telegraf/telegraf.conf +++ b/vms/server/infra/telegraf/telegraf.conf @@ -8558,7 +8558,7 @@ password = "telegraf" # "telegraf/+/mem", # "sensors/#", # ] -servers = ["tcp://192.168.26.1:1883"] # адрес vm с mqtt-брокером +servers = ["tcp://192.168.0.101:1883"] # адрес vm с mqtt-брокером topics = [ "sensors/#" ]