**Технології
індустрії 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->Folder
Lab7
.Create
.Після створення директорії, за замовчуванням, відкриваються дашбоарди, які зберігаються в даній папці. Оскільки вона пуста, пропонується створити новий дашбоард.
+ Create Dashboard
+ Add visualization
, це додасть одну панель візуалізаціїSelect Data Source
виберіть InfluxDB
Main
- для цього натисніть кнопку 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
на правій бічній панелі:
Temperature
All
Ascending
Table
Right
Last
Line
, Line interpolation: Smooth
3
Left
Temperature
Celsium (°C)
2
red
, значення 72
Thresholds -> Show thresholds: As lines
Встановіть налаштування на вкладці Overrides
: назва трендів замість “Temperature AirConditioner_1, … , Temperature AirConditioner_10” – Air Conditioner1, ... , Air Conditioner 10
відповідно. Для цього:
+ Add field override
Field with name
Temperature AirConditioner_1
+ Add override property
Air 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
Налаштуйте загальні настройки змінної наступним чином:
Query
device
Device
У налаштуваннях запиту 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}
device
8
Calculate
Last*
None
Celsium (°C)
1
From thresholds
Thresholds -> 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
.
Events
Main
виберіть кондиціонери 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
:Events
Header 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
.Налаштуйте анотацію наступним чином:
Event
InfluxDB
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")
Save dashboard
Main
.Main
.Main
.Рис.22. Додавання дашбоарду до улюблених
Таким чином дашбоард додано до улюблених.
Profile
Preferences
.Lab7/ Main
.Save
.Рис.23. Налаштування акаунта
Home
Grafana. (Бокове меню Dashboards -> Home)Enable kiosk mode
Рис.24. Перехід в повноекранний режим
ESC
.