TI40

**Технології індустрії 4.0. Лабораторний практикум. ** Автор і лектор: Олександр Пупена

<- до лаборних робіт на основну сторінку курсу
   

Лабораторна робота №10. Основи роботи з Grafana.

Завдання лабораторної роботи навчитися основам роботи з Grafana у парі з базою даних часових рядів Influxdb.

Порядок виконання лабораторної роботи

1.Створення безкоштовного облікового запису на Grafana Cloud Portal

Рис.1. Портал Grafana Cloud Portal

Рис.2. Форма реєстрації на порталі Grafana

Рис.3. Запуск Grafana з порталу Grafana Cloud Portal

2.Створення джерела даних в Grafana

2.1. Генерація API токена для доступу до бакету “firstbucket” в Influxdb з Grafana

Рис.4. Налаштування токена доступу

Запис.1. Генерація API токена для доступу до бакету “firstbucket”

2.2. Створення джерела даних Influxdb в Grafana

Рис.5. Налаштування Grafana

Запис.2. Створення джерела даних в Grafana

Запис.3. Створення джерела даних в Grafana

2.3. Відновлення запису даних в influxdb

3.Створення першого Dashboard

3.1. Створення загальної директорії для зберігання дашбоардів лабораторної роботи

3.2. Створення дашбоарду

Після створення директорії, за замовчуванням, відкриваються дашбоарди, які зберігаються в даній папці. Оскільки вона пуста, пропонується створити новий дашбоард.

Рис.6. Збереження дашбоарду

3.3. Навігація в Grafana

Для навігації між різними директоріями та дашбоардами використовується пункт меню Dashboards -> Browse.

3.4. Створення та редагування інформаційної панелі (Panel)

Рис.7. Створення панелі

3.4.1. Налаштування візуалізації Time series для відображення температур (усереднені значення щохвилини) всіх кондиціонерів за останні 30 хвилин

Рис.8. Редагування панелі

Рис.9. Редагування панелі

from(bucket: "firstbucket")
  |> range(start: v.timeRangeStart, stop: v.timeRangeStop)
  |> filter(fn: (r) => r["_measurement"] == "Building")
  |> filter(fn: (r) => r["_field"] == "Temperature")
  |> filter(fn: (r) => r["device"] == "AirConditioner_1" or r["device"] == "AirConditioner_10" or r["device"] == "AirConditioner_2" or r["device"] == "AirConditioner_3" or r["device"] == "AirConditioner_4" or r["device"] == "AirConditioner_5" or r["device"] == "AirConditioner_6" or r["device"] == "AirConditioner_7" or r["device"] == "AirConditioner_8" or r["device"] == "AirConditioner_9")
  |> aggregateWindow(every: 1m, fn: mean, createEmpty: false)

Рис.10. Редагування панелі

Запис.4. Створення панелі, збереження дашбоарду

Рис.11. Період оновлення дашбоарду

Запис.5. Налаштування властивості override

Запис.6. Зміна часового діапазону для відображення

3.5. Налаштування посилань дашбоарду

Запис.7. Посилання на дашбоард в Influxdb UI

Рис.12. Налаштування дашбоарду

Рис.13. Налаштування лінку дашбоарду

Рис.14. Повернення до дашбоарду, перевірка роботи лінку

3.6. Налаштування змінної дашбоарду для динамічного вибору кондиціонера для відображення на панелі (аналогічно до змінних Influxdb)

3.6.1. Ознайомлення із можливостями Explore

Для відлагодження запитів до баз даних, Grafana надає окремий інструмент Explore.

Рис.15. Explore

Рис.16. Explore

import "influxdata/influxdb/v1"
v1.tagValues(bucket: "firstbucket", tag: "device", predicate: (r) => true, start: -1y)

Рис.16. Результат запиту

3.6.1. Створення змінної device дашбоарду Main
import "influxdata/influxdb/v1"
v1.tagValues(bucket: "firstbucket", tag: "device", predicate: (r) => true, start: -1y)

Рис.17. Налаштування змінної дашбоарду

|> filter(fn: (r) => r["device"] == "AirConditioner_1" or r["device"] == "AirConditioner_10" or r["device"] == "AirConditioner_2" or r["device"] == "AirConditioner_3" or r["device"] == "AirConditioner_4" or r["device"] == "AirConditioner_5" or r["device"] == "AirConditioner_6" or r["device"] == "AirConditioner_7" or r["device"] == "AirConditioner_8" or r["device"] == "AirConditioner_9")

на

|> filter(fn: (r) => r["device"]  =~ /^${device:regex}$/ )

Звернення до змінної реалізується за допомогою $+назва змінної. Щоб забезпечити множинний вибір девайсів для відображення на графіку, окрім звернення до змінної безпосередньо – застосували регулярний вираз.

Запис.8. Перевірка роботи змінних дашбоарду

3.7. Налаштування візуалізації Stat для відображення останнього значення температури в числовому вигляді

Рис.18. Дашбоард Main

4.Створення дашбоарду журнал подій – Events

4.1. Організація запису змін станів кондиціонерів в Influxdb

[
    {
        "id": "40ebca3949a03fc6",
        "type": "inject",
        "z": "42cdb79f439ee463",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": true,
        "onceDelay": 0.1,
        "topic": "",
        "payloadType": "date",
        "x": 110,
        "y": 200,
        "wires": [
            [
                "deed70ad5094bdfe"
            ]
        ]
    },
    {
        "id": "deed70ad5094bdfe",
        "type": "function",
        "z": "42cdb79f439ee463",
        "name": "multiplesubscribe",
        "func": "msg.payload=10000;\nfor(i=1;i<11;i++){\n   msg.topic=`ns=3;s=AirConditioner_${i}.State`;\n   node.send(msg);\n    }\n",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 290,
        "y": 200,
        "wires": [
            [
                "1c7613ca498e131c"
            ]
        ]
    },
    {
        "id": "1c7613ca498e131c",
        "type": "OpcUa-Client",
        "z": "42cdb79f439ee463",
        "endpoint": "501a96153c7c8d57",
        "action": "subscribe",
        "deadbandtype": "a",
        "deadbandvalue": 1,
        "time": "1",
        "timeUnit": "s",
        "certificate": "n",
        "localfile": "",
        "localkeyfile": "",
        "securitymode": "None",
        "securitypolicy": "None",
        "folderName4PKI": "",
        "name": "",
        "x": 500,
        "y": 200,
        "wires": [
            [
                "500d758fa01f947b"
            ]
        ]
    },
    {
        "id": "500d758fa01f947b",
        "type": "switch",
        "z": "42cdb79f439ee463",
        "name": "",
        "property": "topic",
        "propertyType": "msg",
        "rules": [
            {
                "t": "cont",
                "v": "ns=3;s=AirConditioner",
                "vt": "str"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 1,
        "x": 615,
        "y": 200,
        "wires": [
            [
                "8c90ebf4b87e9109"
            ]
        ],
        "l": false
    },
    {
        "id": "8c90ebf4b87e9109",
        "type": "function",
        "z": "42cdb79f439ee463",
        "name": "",
        "func": "let str=\"\";\nlet obj={};\nstr=msg.topic.replace(\"ns=3;s=\",\"\");\nobj.device=str.replace(\".State\",\"\");\nobj.fields={State:msg.payload};\nobj.timestamp=msg.serverTimestamp;\nmsg={};\nmsg.payload=obj;\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 675,
        "y": 200,
        "wires": [
            [
                "a153c3bec6acf22a"
            ]
        ],
        "l": false
    },
    {
        "id": "a153c3bec6acf22a",
        "type": "join",
        "z": "42cdb79f439ee463",
        "name": "",
        "mode": "custom",
        "build": "array",
        "property": "payload",
        "propertyType": "msg",
        "key": "topic",
        "joiner": "\\n",
        "joinerType": "str",
        "accumulate": false,
        "timeout": "1",
        "count": "",
        "reduceRight": false,
        "reduceExp": "",
        "reduceInit": "",
        "reduceInitType": "num",
        "reduceFixup": "",
        "x": 775,
        "y": 200,
        "wires": [
            [
                "0ba540df0fcba817"
            ]
        ],
        "l": false
    },
    {
        "id": "0ba540df0fcba817",
        "type": "function",
        "z": "42cdb79f439ee463",
        "name": "msgtoinflux",
        "func": "let datastore=[];\nconst State = new Map([\n  [0, 'Вимкнено'],\n  [1, 'Увімкнено'],\n  ]);\nclass sample {\n  constructor(payload) {\n    this.data={\n        measurement:'Building_log',\n        tags: {\n            device: payload.device,\n        },\n        fields: {message:payload.device+\" \"+State.get(payload.fields.State)},\n        timestamp: new Date(payload.timestamp).getTime()\n    }\n  }\n}\nfor (let i=0; i<msg.payload.length;i++){\n    dataobj=new sample(msg.payload[i]);\n    datastore.push(dataobj.data);\n}\nmsg.payload = {\n    bucket:'firstbucket',\n    precision: 'ms',\n    data:datastore,\n};\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 930,
        "y": 200,
        "wires": [
            [
                "260f8e645e064f0c"
            ]
        ]
    },
    {
        "id": "501a96153c7c8d57",
        "type": "OpcUa-Endpoint",
        "endpoint": " opc.tcp://DESKTOP-E871FG5:48010",
        "secpol": "None",
        "secmode": "None",
        "login": false
    }
]

Рис.19. Нові вузли для node-red

Імпортовані вузли забезпечуються опитування стану 10-ти кондиціонерів і запис цього стану у вигляді текстового повідомлення в той самий бакет Influxdb (firstbucket) проте в інший measurementBuilding_log.

4.2. Створення дашбоарду Events

Рис.20. Посилання на дашбоард Main

&var-device=AirConditioner_1&var-device=AirConditioner_10&var-device=AirConditioner_2

Запис.9. Створення дашбоарду Events

from(bucket: "firstbucket")
  |> range(start: -1y)
  |> filter(fn: (r) => r["_measurement"] == "Building_log")
  |> filter(fn: (r) => r["_field"] == "message")
  |> group(columns:["_field"])
  |> sort(columns: ["_time"], desc: true) 
  |> drop(columns:["_measurement"])

Рис.21. Data link комірки таблиці

Запис.10. Генерація подій (вкл/викл кондиціонер)

5.Створення анотацій

5.1. Створення анотації вручну

Анотації дозволяють робити помітки на графіку з прив’язкою до часу, щоб забезпечити контекст.

Запис.11. Ручне створення анотацій

5.2. Створення автоматичних анотацій з прив’язкою до подій з журналу подій

from(bucket: "firstbucket")
  |> range(start: v.timeRangeStart, stop: v.timeRangeStop)
  |> filter(fn: (r) => r["_measurement"] == "Building_log")
  |> filter(fn: (r) => r["device"] =~ /^${device:regex}$/)
  |> filter(fn: (r) => r["_field"] == "message")

6.Означення стартового дашбоарду

Рис.22. Додавання дашбоарду до улюблених

Таким чином дашбоард додано до улюблених.

Рис.23. Налаштування акаунта

7.Повноекранний режим

Рис.24. Повноекранний режим

Щоб видалити дашбоард, потрібно перейти в його налаштування і натиснути кнопку Delete. Видаляти не потрібно, довідкова інформація.