**Технології індустрії 4.0. Лабораторний практикум. ** Автор і лектор: Олександр Пупена
| <- до лаборних робіт | на основну сторінку курсу |
|---|---|
Завдання лабораторної роботи навчитися основам роботи з Grafana у парі з базою даних часових рядів Influxdb.

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

Рис.2. Форма реєстрації на порталі Grafana
finish setup
I'm already familiar with Grafana. Skip setup щоб перейти на Grafana Cloud.
Grafana з порталу Grafana Cloud треба через My Account ->плитка Grafana -> Launch.

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

API TOKENS: пункт меню Load Data -> API Tokens.Access to firstbucket from Grafana. В розділі Resourses для firstbucket оберіть опції читання та запису.
Рис.4. Налаштування токена доступу

Запис.1. Генерація API токена для доступу до бакету “firstbucket”
Connections/Data Sources (шестерня зліва внизу).
Рис.5. Налаштування Grafana
Add new data source.
В якості джерела даних оберіть InfluxDB.
InfluxDB.flux.
Запис.2. Створення джерела даних в Grafana
У попередній лабораторній роботі в якості перегляду даних в InfluxDB використоувалася мова fluxQL (SQL подібна мова запитів). У цій та наступній роботі використоуватиметься більша потужна мова Flux.
Cluster URL з налаштувань організації в Influxdb UI (див лабораторну роботу Influx).
Запис.3. Створення джерела даних в Grafana
Basic auth повинна бути деактивованаOrganization ID з налаштувань організації в Influxdb UI (Influxdb UI -> пункт меню Account -> Organization settings -> Organization ID).firstbucket.Save & test.Після цього, якщо підключення вдалося, виведеться напис: “datasource is working. 1 buckets found”

UaCPPServer та node-red, тобто відновіть запис даних з OPC UA сервера в influxdb, який було налаштовано в попередніх лабораторних роботах по Influxdb.
New->FolderLab7.Create.Після створення директорії, за замовчуванням, відкриваються дашбоарди, які зберігаються в даній папці. Оскільки вона пуста, пропонується створити новий дашбоард.
+ Create Dashboard+ Add visualization, це додасть одну панель візуалізаціїSelect Data Source виберіть InfluxDBMain - для цього натисніть кнопку Save у правому верхньому кутку

Рис.6. Збереження дашбоарду
Для навігації між різними директоріями та дашбоардами використовується головний пункт меню Dashboards
Lab7, відкрийте дашбоард Main.Main, Ви також створили одну панель. Наразі вона немає жодних налаштувань і містить опис Panel Title. Використовуючи меню перейдіть в режим редагування.
Рис.7. Перехід в редагування панелі
Time series.30 хвилин.
Рис.8. Редагування панелі
Data source) встановлено InfluxDB (під час конфігурування джерела даних InfluxDB ми означили його як джерело даних за замовчуванням). В іншому випадку оберіть InfluxDB з випадального списку.
Рис.9. Редагування панелі Data Source
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)
Детальніше мова flux буде розглядатися в наступній лабораторній роботі. Тут трохи прокоментуємо що саме відбувається в цьому коді. Спочатку з бакета firstbucket вибираються дані, які далі обробляються в конвеєрній обробці, яка позначається |>. Спочатку вказується діапазон вибірки по часу, потім йде фільтрація даних за службовим полем _measurement, field, та тегом device (один з вказаних по or). З вибраними даними відбувається агрегація, де за кожну хвилину розраховується середнє і видається результат.
Apply.
Рис.10. Редагування панелі

Save current time range as dashboard default (залишити виставлений часовий діапазон як діапазон дашбоарду за замовчуванням).
Запис.4. Збереження дашбоарду
).
Рис.11. Період оновлення дашбоарду
... та оберіть опцію Edit.Для панелі встановіть наступні налаштування на вкладці All на правій бічній панелі:
TemperatureAllAscendingTableRightLastLine, Line interpolation: Smooth3LeftTemperatureCelsium (°C)2red , значення 72 Thresholds -> Show thresholds: As lines
Встановіть налаштування на вкладці Overrides: назва трендів замість “Temperature AirConditioner_1, … , Temperature AirConditioner_10” – Air Conditioner1, ... , Air Conditioner 10 відповідно. Для цього:
+ Add field overrideField with nameTemperature AirConditioner_1+ Add override propertyAir Conditioner 1
Запис.5. Налаштування властивості override
Apply.
time picker, а також виділенням потрібної області на графіку.
Запис.6. Зміна часового діапазону для відображення
Для відлагодження запитів до баз даних, Grafana надає окремий інструмент Explore.
Explore.
Рис.15. Explore
InfluxDB.
Рис.16. Explore
import "influxdata/influxdb/v1"
v1.tagValues(bucket: "firstbucket", tag: "device", predicate: (r) => true, start: -1y)
Run query.
Рис.16. Результат запиту
device дашбоарду MainЗмінні дають можливість використовувати змінні властивості, якими оперує користувач. У цьому пункті буде створена змінна з іменем device, перелік значень якої буде зчитуватися з бакета, як це було зроблено вище. Далі користувач зможе вибирати одне або кілька значень для фільтрування вибірки.
Main (через пункт меню Browse).Перейдіть до пункту Variables.
Натисніть Add variable
Налаштуйте загальні настройки змінної наступним чином:
QuerydeviceDevice
У налаштуваннях запиту Query options зробіть наступне
Data source – InfluxDB,
import "influxdata/influxdb/v1"
v1.tagValues(bucket: "firstbucket", tag: "device", predicate: (r) => true, start: -1y)
On dashboard load
Рис.17. Налаштування опцій запиту для змінної дашбоарду
Apply.Save dashboard а потім підьвердіть кнопкою save.device в запитіTemperature (через кнопку три крапки на панелі).filter(fn: (r) => r["device"], який наведений нижче|> 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}$/ )
Звернення до змінної реалізується за допомогою $+назва змінної. Щоб забезпечити множинний вибір девайсів для відображення на графіку, окрім звернення до змінної безпосередньо – застосували регулярний вираз.
Apply) та збережіть дашбоард.
Запис.8. Перевірка роботи змінних дашбоарду
Stat для відображення останнього значення температури в числовому виглядіСкопіюйте запит з панелі Temperature.
Add ->Visualisation у верхньому правому куті дашбоарду.Time Series оберіть візуалізацію Stat.Вставте скопійований запит з панелі Temperature.
Для панелі встановіть наступні налаштування на вкладці All:
${device}device8CalculateLast*NoneCelsium (°C)1From thresholdsThresholds -> 72: red
Застосуйте зміни панелі (кнопка Apply) та збережіть дашбоард.

Рис.18. Дашбоард Main
Events[
{
"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
}
]
msgtoinflux з наявним вузлом InfluxDBwrite.
Рис.19. Нові вузли для node-red
Імпортовані вузли забезпечуються опитування стану 10-ти кондиціонерів і запис цього стану у вигляді текстового повідомлення в той самий бакет Influxdb (firstbucket) проте в інший measurement – Building_log.
EventsMain виберіть кондиціонери 1, 10 та 2.Main в блокнот, він знадобиться далі.
Рис.20. Посилання на дашбоард Main
&var-device=AirConditioner_1&var-device=AirConditioner_10&var-device=AirConditioner_2
Lab7 створіть дашбоардОберіть візуалізацію типу Table.
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"])
All:EventsHeader and footer -> Show table header: деактивувати опцію
Для панелі встановіть наступні налаштування на вкладці Overrides:
+Add field Override.field with name.device (base field name).+Add override property.Data Links -> data links.Add link.Main , який був скопійований в блокнот, змінивши налаштування device, тобто:з
https://******.grafana.net/d/*******/main?orgId=1&var-device=AirConditioner_1&var-device=AirConditioner_10&var-device=AirConditioner_2
на
https://******.grafana.net/d/*******/main?orgId=1&var-device=${__value.raw}
*зірочками позначена індивідуальна для кожного частина посилання*
Open in new tab.Save, збережіть дашбоард з назвою Events.
Рис.21. Data link комірки таблиці
UA Expert, викличте метод Stop для зміни станів кількох кондиціонерів. Вручну оновіть дашбоард Events та перегляньте результат.Start (якщо кондиціонер в стопі) або Stop (якщо кондиціонер в старті) для тих же кондиціонерів. Перегляньте результат в дашбоарді.

Запис.10. Генерація подій (вкл/викл кондиціонер)
Main, з активною однією змінною, на назву якої ви натиснули.Анотації дозволяють робити помітки на графіку з прив’язкою до часу, щоб забезпечити контекст.
Main зробіть клік лівою кнопкою миші по графіку на панелі типу Time series .Add annotation.test annotation.Save.
Запис.11. Ручне створення анотацій
Main (шестерня в верхньому правому кутку дашбоарду).Annotations.Add annotation query.Налаштуйте анотацію наступним чином:
EventInfluxDBfrom(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")
Save dashboardMain.Main.Main.
Рис.22. Додавання дашбоарду до улюблених
Таким чином дашбоард додано до улюблених.
Profile
Preferences.Lab7/ Main.Save.
Рис.23. Налаштування акаунта
Home Grafana. (Бокове меню Dashboards -> Home)
Enable kiosk mode
Рис.24. Перехід в повноекранний режим
ESC.