Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • master
1 result

Target

Select target project
  • card10/logix
  • annejan/logix
  • kgz/logix
  • pink/logix
  • mot/logix
  • 9R/logix
  • melle/logix
  • jspricke/logix
  • sjn/logix
  • marble/logix
  • audionerd/logix
  • astro/logix
  • genotest/logix
  • _luc/logix
  • C-Tim/logix
  • Superwallah/logix
  • nitram/logix
  • Pixtxa/logix
  • royrobotiks/logix
  • deusfigendi/logix
  • arist/logix
  • LordBonzi/logix
  • Stormwind/logix
  • dag/logix
24 results
Select Git revision
  • master
  • patch-1
  • patch-2
  • patch-3
  • patch-4
5 results
Show changes
Showing
with 2467 additions and 5 deletions
File added
File added
---
title: Tutorials
---
## Getting started
## Micropython
## E-textile
* Photo tutorial for the E-textile card10 workshop at CCCam19 by plusea https://flickr.com/photos/plusea/albums/72157710505658161
* Tutorial for sewable RGB LEDs (LilyPad Pixel Board): [Sewable RGB LEDs Tutorial](/tutorials/sewable_leds)
## ECG
* ECG kit assembly https://card10.badge.events.ccc.de/tutorials/ecg_kit_assembly
## Maintenance and repairs
We dedicated a separate section of card10logix to repair work for the maintenance of your card10: https://card10.badge.events.ccc.de/maintenance
---
title: ECG kit assembly
---
### How-To wire and solder an ECG-Cable for the card10 badge
Stick some insulating tape over the ECG contacts at the bottom of your wristband, since we are replacing this contact area with one of the electrodes.
Cut off the USB-A connector as we don't have use for it
[![cut usb wire](/media/ecg/1-cut-wire.jpg)](/media/ecg/1-cut-wire.jpg)
Slide the big shrinking tube over the USB cable
Separate the wires as shown in the picture
[![usb wire meanings](/media/ecg/wire-meanings.jpg)](/media/ecg/wire-meanings.jpg)
Cut off all wires ecxept for orange and purple
[![cut off unused wires](/media/ecg/cut-off-wires.jpg)](/media/ecg/cut-off-wires.jpg)
Move the two small shrinking tubes over the ECG wires
Solder the ECG wires to the USB wires as shown in the pictures
[![solder ecg usb wires](/media/ecg/3-solder.jpg)](/media/ecg/3-solder.jpg)
Test your ECG setup on your card10 prior the next step
Slide the small shrinking tubes over the soldering connections and apply hot air (e.g. lighter)
[![apply small heat shrink tubes](/media/ecg/4-add-heat-shrink.jpg)](/media/ecg/4-add-heat-shrink.jpg)
[![shrink small heat shrink tubes](/media/ecg/5-shrik-this.jpg)](/media/ecg/5-shrik-this.jpg)
Slide the bigger shrinking tube over the two small ones and also shrink it
[![apply large heat shrink tube](/media/ecg/large-heat-shrink.jpg)](/media/ecg/large-heat-shrink.jpg)
Have fun and hack ECG stuff
[![ecg fertig](/media/ecg/fertig.jpg)](/media/ecg/fertig.jpg)
### Usage
[![ecg usage](/media/ecg/application.jpg)](/media/ecg/application.jpg)
#### ECG
Place the electrodes on your chest as shown in the picture and connect the USB-C connector with the USB symbol downwards. After starting the ECG application on your card10 press the right lower button (RIGHT) to switch over to ECG over USB.
If you want to start logging your ECG data press the lower left button (LEFT) to start and stop logging. Log files are written to the filesystem (ecg-\<time\>.log) and can be transferred to a computer using the boot loader. You can visualize them with Audacity: Use File→Import→Raw Data, select the log file, then use Signed 16-bit PCM, Little Endian, 1 Channel, offset 0, amount 100% and sample rate 128 Hz. Normalize the amplitude by selecting the entire track (Ctrl-A), then use Effect→Amplify and keep the suggested Amplification value.
#### Eye movement detection and muscle activity
To detect eye movements like fast movements to the left or right or to detect REM phase while at sleep, place your electrodes on your temples.
---
title: Los gehts!
hidden: true
---
# Los geht's!
Du hast also gerade dein card10 bekommen. Und jetzt?
## card10 zusammen bauen
[Hier](/en/assembleyourcard10) ist eine schritt-für-schritt-anleitung mit Bildern, um dein card10 zusammen zu bauen.
[Hier](/userguide/assembly.de) ist eine schritt-für-schritt-anleitung mit Bildern, um dein card10 zusammen zu bauen.
## card10 navigation
Es gibt vier Knopfe auf dem card10 _harmonic_ board: Oben links, direkt über dem USB-C-Connector ist der POWER-Knopf. Darunter ist der LEFT Knopf. Die Knöpfe auf der rechten Seite sind näher beieinander. Auf dieser Seite ist der obere Knopf der SELECT-Knopf und der untere der RIGHT Knopf.
<img class="center" alt="Zeichnung des card10 mit Knopf-Namen" src="/media/card10buttons.svg" width="220" height="auto" align="center">
[![Zeichnung des card10 mit Knopf-Namen](/media/card10buttons.svg)](/media/card10buttons.svg)
### Das card10 an und ausschalten
......@@ -37,6 +36,13 @@ Starte dein card10 im USB-Massenspeichermodus, dann kopiere `nickname.txt` auf d
Jetzt halte nach einer App namens 'nickname.py' (TODO: evtl muss diese App zuerst heruntergeladen werden...),
Diese App zeigt dienen Nickname an..
### Apps hinzufügen
Die [hatchery](https://badge.team/) bietet weitere Apps, die andere card10-Nutzer geschrieben haben. Um die Apps auf Deinen card10 zu bekommen,
kannst Du entweder die [App](/app) installieren oder Du lädst sie selbst auf den USB-Massenspeicher: Lade die `tar.gz`-Dateien herunter und entpacke sie (oder lade alle Dateien einzeln).
Versetze Deinen card10 in den [USB-Massenspeicher-Modus](/userguide/general-usage/#installing-apps-via-usb) und kopiere die Dateien dorthin.
Alle Apps sind im `apps`-Ordner abgelegt. Im `apps`-Ordner hat jede App ihren eigenen Ordner, benannt nach dem App-Namen (z.B. `apps/app_name`). Um eine neue App hinzuzufügen, erstelle einen neuen Ordner mit dem Namen der App und lege alle Dateien der App dort ab!
### BLE aktivieren
Zu Anfang ist BLE aus Privatsphäregründen deaktiviert. Wenn du es benutzen möchtest, musst du es zunächst aktivieren.
......
---
title: Getting Started
---
{{% notice info %}}
Deutsche Version: [Los geht’s!](../gettingstarted.de)
{{% /notice %}}
You just received your card10 - what now?
## card10 assembly
[Here](/userguide/assembly)'s a step by step guide with a video and pictures for assembling your card10
## User guide
Have a look at the [General Usage](/userguide/general-usage) section of the [User Guide](/userguide). It will tell you how to:
- Switch the card10 on and off
- Navigate the menu
- Install new apps
- Set your nickname
And much more!
### Setting your nickname
To set your nickname, create a file called `nickname.txt` on your laptop.
Start your card10 in USB storage mode, then copy `nickname.txt` onto the card10. Eject the USB device.
Then briefly press the POWER button to exit the storage mode, and then a second time, to enter the menu.
You can scroll up and down using the LEFT and RIGHT buttons.
Now look for an app called 'nickname.py', select it by pressing the SELECT button.
If you have successfully uploaded a `nickname.txt` file, your nickname will now show up on the display.
You can also upload a `nickname.json` file instead, to get some more options.
Have a look at the [hatchery](https://badge.team/projects/card10_nickname) for more options of the app.
### Basic ECG howto
Have a look at [how to use the ECG](../ecg/).
For better results use [USB-C electrodes](../ecg_kit_assembly/)
## Next
Now it is time to start playing with the card10, writing your own micropython code!
Continue in the [first interhacktions](/interhacktions/firstinterhacktions) section.
{
"__inputs": [
{
"name": "DS_INFLUXDB",
"label": "InfluxDB",
"description": "",
"type": "datasource",
"pluginId": "influxdb",
"pluginName": "InfluxDB"
}
],
"__requires": [
{
"type": "panel",
"id": "gauge",
"name": "Gauge",
"version": ""
},
{
"type": "grafana",
"id": "grafana",
"name": "Grafana",
"version": "7.3.5"
},
{
"type": "panel",
"id": "graph",
"name": "Graph",
"version": ""
},
{
"type": "datasource",
"id": "influxdb",
"name": "InfluxDB",
"version": "1.0.0"
}
],
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": "-- Grafana --",
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"type": "dashboard"
}
]
},
"editable": true,
"gnetId": null,
"graphTooltip": 0,
"id": null,
"links": [],
"panels": [
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "${DS_INFLUXDB}",
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 9,
"w": 12,
"x": 0,
"y": 0
},
"hiddenSeries": false,
"id": 2,
"legend": {
"avg": false,
"current": false,
"max": false,
"min": false,
"show": true,
"total": false,
"values": false
},
"lines": true,
"linewidth": 1,
"nullPointMode": "connected",
"options": {
"alertThreshold": true
},
"percentage": false,
"pluginVersion": "7.3.5",
"pointradius": 2,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"alias": "Temperature",
"groupBy": [
{
"params": [
"$__interval"
],
"type": "time"
},
{
"params": [
"null"
],
"type": "fill"
}
],
"measurement": "air",
"orderByTime": "ASC",
"policy": "default",
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"temperature"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"tags": []
}
],
"thresholds": [],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "Temperature",
"tooltip": {
"shared": true,
"sort": 0,
"value_type": "individual"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"$$hashKey": "object:665",
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"$$hashKey": "object:666",
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
],
"yaxis": {
"align": false,
"alignLevel": null
}
},
{
"datasource": "${DS_INFLUXDB}",
"fieldConfig": {
"defaults": {
"custom": {},
"mappings": [
{
"from": "0",
"id": 1,
"text": "Excellent",
"to": "50",
"type": 2
},
{
"from": "51",
"id": 2,
"text": "Good",
"to": "100",
"type": 2,
"value": ""
},
{
"from": "101",
"id": 3,
"text": "Lightly polluted",
"to": "150",
"type": 2
},
{
"from": "151",
"id": 4,
"text": "Moderately polluted",
"to": "200",
"type": 2,
"value": ""
},
{
"from": "201",
"id": 5,
"text": "Heavily polluted",
"to": "250",
"type": 2
},
{
"from": "251",
"id": 6,
"text": "Severely polluted",
"to": "350",
"type": 2
},
{
"from": "351",
"id": 7,
"text": "Extremely polluted",
"to": "",
"type": 2
}
],
"max": 350,
"min": 0,
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "dark-green",
"value": 51
},
{
"color": "#EAB839",
"value": 101
},
{
"color": "orange",
"value": 151
},
{
"color": "red",
"value": 201
},
{
"color": "rgb(81, 33, 105)",
"value": 251
},
{
"color": "rgb(82, 48, 27)",
"value": 350
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 12,
"y": 0
},
"id": 14,
"options": {
"reduceOptions": {
"calcs": [
"last"
],
"fields": "",
"values": false
},
"showThresholdLabels": false,
"showThresholdMarkers": true
},
"pluginVersion": "7.3.5",
"targets": [
{
"alias": "IAQ",
"groupBy": [
{
"params": [
"$__interval"
],
"type": "time"
},
{
"params": [
"null"
],
"type": "fill"
}
],
"measurement": "air",
"orderByTime": "ASC",
"policy": "default",
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"iaq"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"tags": []
}
],
"timeFrom": null,
"timeShift": null,
"title": "Indoor Air Quality",
"transformations": [],
"type": "gauge"
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "${DS_INFLUXDB}",
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 8,
"w": 12,
"x": 12,
"y": 8
},
"hiddenSeries": false,
"id": 9,
"legend": {
"avg": false,
"current": false,
"max": false,
"min": false,
"show": true,
"total": false,
"values": false
},
"lines": true,
"linewidth": 1,
"nullPointMode": "connected",
"options": {
"alertThreshold": true
},
"percentage": false,
"pluginVersion": "7.3.5",
"pointradius": 2,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"alias": "IAQ",
"groupBy": [
{
"params": [
"$__interval"
],
"type": "time"
},
{
"params": [
"null"
],
"type": "fill"
}
],
"measurement": "air",
"orderByTime": "ASC",
"policy": "default",
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"iaq"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"tags": []
}
],
"thresholds": [],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "Indoor Air Quality",
"tooltip": {
"shared": true,
"sort": 0,
"value_type": "individual"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"$$hashKey": "object:767",
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"$$hashKey": "object:768",
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": "0",
"show": true
}
],
"yaxis": {
"align": false,
"alignLevel": null
}
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "${DS_INFLUXDB}",
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 8,
"w": 12,
"x": 0,
"y": 9
},
"hiddenSeries": false,
"id": 4,
"legend": {
"avg": false,
"current": false,
"max": false,
"min": false,
"show": true,
"total": false,
"values": false
},
"lines": true,
"linewidth": 1,
"nullPointMode": "connected",
"options": {
"alertThreshold": true
},
"percentage": false,
"pluginVersion": "7.3.5",
"pointradius": 2,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"groupBy": [
{
"params": [
"$__interval"
],
"type": "time"
},
{
"params": [
"null"
],
"type": "fill"
}
],
"measurement": "air",
"orderByTime": "ASC",
"policy": "default",
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"humidity"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"tags": []
}
],
"thresholds": [],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "Humidity",
"tooltip": {
"shared": true,
"sort": 0,
"value_type": "individual"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"$$hashKey": "object:111",
"decimals": null,
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"$$hashKey": "object:112",
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
],
"yaxis": {
"align": false,
"alignLevel": null
}
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "${DS_INFLUXDB}",
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 8,
"w": 12,
"x": 12,
"y": 16
},
"hiddenSeries": false,
"id": 10,
"legend": {
"avg": false,
"current": false,
"max": false,
"min": false,
"show": true,
"total": false,
"values": false
},
"lines": true,
"linewidth": 1,
"nullPointMode": "null",
"options": {
"alertThreshold": true
},
"percentage": false,
"pluginVersion": "7.3.5",
"pointradius": 2,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"alias": "CO2",
"groupBy": [
{
"params": [
"$__interval"
],
"type": "time"
},
{
"params": [
"null"
],
"type": "fill"
}
],
"measurement": "air",
"orderByTime": "ASC",
"policy": "default",
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"co2"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"tags": []
}
],
"thresholds": [],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "CO2",
"tooltip": {
"shared": true,
"sort": 0,
"value_type": "individual"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"$$hashKey": "object:855",
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"$$hashKey": "object:856",
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": "0",
"show": true
}
],
"yaxis": {
"align": false,
"alignLevel": null
}
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "${DS_INFLUXDB}",
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 8,
"w": 12,
"x": 0,
"y": 17
},
"hiddenSeries": false,
"id": 6,
"legend": {
"avg": false,
"current": false,
"max": false,
"min": false,
"show": true,
"total": false,
"values": false
},
"lines": true,
"linewidth": 1,
"nullPointMode": "connected",
"options": {
"alertThreshold": true
},
"percentage": false,
"pluginVersion": "7.3.5",
"pointradius": 2,
"points": true,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"alias": "Pressure",
"groupBy": [
{
"params": [
"$__interval"
],
"type": "time"
},
{
"params": [
"null"
],
"type": "fill"
}
],
"measurement": "air",
"orderByTime": "ASC",
"policy": "default",
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"pressure"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"tags": []
}
],
"thresholds": [],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "Pressure",
"tooltip": {
"shared": true,
"sort": 0,
"value_type": "individual"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"$$hashKey": "object:496",
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"$$hashKey": "object:497",
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
],
"yaxis": {
"align": false,
"alignLevel": null
}
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "${DS_INFLUXDB}",
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 8,
"w": 12,
"x": 12,
"y": 24
},
"hiddenSeries": false,
"id": 12,
"legend": {
"avg": false,
"current": false,
"max": false,
"min": false,
"show": true,
"total": false,
"values": false
},
"lines": true,
"linewidth": 1,
"nullPointMode": "connected",
"options": {
"alertThreshold": true
},
"percentage": false,
"pluginVersion": "7.3.5",
"pointradius": 2,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"groupBy": [
{
"params": [
"$__interval"
],
"type": "time"
},
{
"params": [
"null"
],
"type": "fill"
}
],
"measurement": "air",
"orderByTime": "ASC",
"policy": "default",
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"iaq_accuracy"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"tags": []
}
],
"thresholds": [],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "IAQ Accuracy",
"tooltip": {
"shared": true,
"sort": 0,
"value_type": "individual"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"$$hashKey": "object:943",
"format": "short",
"label": null,
"logBase": 1,
"max": "3",
"min": "0",
"show": true
},
{
"$$hashKey": "object:944",
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
],
"yaxis": {
"align": false,
"alignLevel": null
}
}
],
"refresh": false,
"schemaVersion": 26,
"style": "dark",
"tags": [],
"templating": {
"list": []
},
"time": {
"from": "now-6h",
"to": "now"
},
"timepicker": {},
"timezone": "",
"title": "Air",
"uid": "0Kvpw5zRk",
"version": 12
}
\ No newline at end of file
{
"__inputs": [
{
"name": "DS_INFLUXDB",
"label": "InfluxDB",
"description": "",
"type": "datasource",
"pluginId": "influxdb",
"pluginName": "InfluxDB"
}
],
"__requires": [
{
"type": "panel",
"id": "gauge",
"name": "Gauge",
"version": ""
},
{
"type": "grafana",
"id": "grafana",
"name": "Grafana",
"version": "8.0.5"
},
{
"type": "panel",
"id": "graph",
"name": "Graph (old)",
"version": ""
},
{
"type": "datasource",
"id": "influxdb",
"name": "InfluxDB",
"version": "1.0.0"
}
],
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": "-- Grafana --",
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"type": "dashboard"
}
]
},
"editable": true,
"gnetId": null,
"graphTooltip": 0,
"id": null,
"links": [],
"panels": [
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "${DS_INFLUXDB}",
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 8,
"w": 12,
"x": 0,
"y": 0
},
"hiddenSeries": false,
"id": 2,
"interval": "3s",
"legend": {
"avg": false,
"current": false,
"max": false,
"min": false,
"show": true,
"total": false,
"values": false
},
"lines": true,
"linewidth": 1,
"nullPointMode": "null",
"options": {
"alertThreshold": true
},
"percentage": false,
"pluginVersion": "8.0.5",
"pointradius": 2,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"alias": "temperature",
"groupBy": [
{
"params": [
"$interval"
],
"type": "time"
}
],
"measurement": "air",
"orderByTime": "ASC",
"policy": "default",
"query": "SELECT mean(\"temperature\") FROM \"air\" WHERE $timeFilter GROUP BY time($interval)",
"rawQuery": false,
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"temperature"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"tags": []
}
],
"thresholds": [],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "Temperature",
"tooltip": {
"shared": true,
"sort": 0,
"value_type": "individual"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"$$hashKey": "object:665",
"format": "celsius",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"$$hashKey": "object:666",
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
],
"yaxis": {
"align": false,
"alignLevel": null
}
},
{
"datasource": "${DS_INFLUXDB}",
"fieldConfig": {
"defaults": {
"mappings": [
{
"options": {
"from": 0,
"result": {
"text": "Excellent"
},
"to": 50
},
"type": "range"
},
{
"options": {
"from": 51,
"result": {
"text": "Good"
},
"to": 100
},
"type": "range"
},
{
"options": {
"from": 101,
"result": {
"text": "Lightly polluted"
},
"to": 150
},
"type": "range"
},
{
"options": {
"from": 151,
"result": {
"text": "Moderately polluted"
},
"to": 200
},
"type": "range"
},
{
"options": {
"from": 201,
"result": {
"text": "Heavily polluted"
},
"to": 250
},
"type": "range"
},
{
"options": {
"from": 251,
"result": {
"text": "Severely polluted"
},
"to": 350
},
"type": "range"
},
{
"options": {
"from": 351,
"result": {
"text": "Extremely polluted"
},
"to": 0
},
"type": "range"
}
],
"max": 350,
"min": 0,
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "dark-green",
"value": 51
},
{
"color": "#EAB839",
"value": 101
},
{
"color": "orange",
"value": 151
},
{
"color": "red",
"value": 201
},
{
"color": "rgb(81, 33, 105)",
"value": 251
},
{
"color": "rgb(82, 48, 27)",
"value": 350
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 12,
"y": 0
},
"id": 14,
"interval": "3s",
"options": {
"reduceOptions": {
"calcs": [
"last"
],
"fields": "",
"values": false
},
"showThresholdLabels": false,
"showThresholdMarkers": true,
"text": {}
},
"pluginVersion": "8.0.5",
"targets": [
{
"alias": "IAQ",
"groupBy": [],
"measurement": "air",
"orderByTime": "ASC",
"policy": "default",
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"iaq"
],
"type": "field"
}
]
],
"tags": []
}
],
"timeFrom": null,
"timeShift": null,
"title": "Indoor Air Quality",
"transformations": [],
"type": "gauge"
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "${DS_INFLUXDB}",
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 8,
"w": 12,
"x": 0,
"y": 8
},
"hiddenSeries": false,
"id": 4,
"interval": "3s",
"legend": {
"avg": false,
"current": false,
"max": false,
"min": false,
"show": true,
"total": false,
"values": false
},
"lines": true,
"linewidth": 1,
"nullPointMode": "null",
"options": {
"alertThreshold": true
},
"percentage": false,
"pluginVersion": "8.0.5",
"pointradius": 2,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"alias": "humidity",
"groupBy": [
{
"params": [
"$interval"
],
"type": "time"
}
],
"measurement": "air",
"orderByTime": "ASC",
"policy": "default",
"query": "SELECT mean(\"humidity\"), AS \"alias\" FROM \"air\" WHERE $timeFilter GROUP BY time($__interval) fill(null)",
"rawQuery": false,
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"humidity"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"tags": []
}
],
"thresholds": [],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "Humidity",
"tooltip": {
"shared": true,
"sort": 0,
"value_type": "individual"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"$$hashKey": "object:111",
"decimals": null,
"format": "percent",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"$$hashKey": "object:112",
"format": "short",
"label": "",
"logBase": 1,
"max": null,
"min": null,
"show": true
}
],
"yaxis": {
"align": false,
"alignLevel": null
}
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "${DS_INFLUXDB}",
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 8,
"w": 12,
"x": 12,
"y": 8
},
"hiddenSeries": false,
"id": 9,
"interval": "3s",
"legend": {
"avg": false,
"current": false,
"max": false,
"min": false,
"show": true,
"total": false,
"values": false
},
"lines": true,
"linewidth": 1,
"nullPointMode": "null",
"options": {
"alertThreshold": true
},
"percentage": false,
"pluginVersion": "8.0.5",
"pointradius": 2,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"alias": "iaq",
"groupBy": [
{
"params": [
"$interval"
],
"type": "time"
}
],
"measurement": "air",
"orderByTime": "ASC",
"policy": "default",
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"iaq"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"tags": []
}
],
"thresholds": [],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "Indoor Air Quality",
"tooltip": {
"shared": true,
"sort": 0,
"value_type": "individual"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"$$hashKey": "object:767",
"decimals": 0,
"format": "short",
"label": "",
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"$$hashKey": "object:768",
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": "0",
"show": true
}
],
"yaxis": {
"align": false,
"alignLevel": null
}
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "${DS_INFLUXDB}",
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 8,
"w": 12,
"x": 0,
"y": 16
},
"hiddenSeries": false,
"id": 6,
"interval": "3s",
"legend": {
"avg": false,
"current": false,
"max": false,
"min": false,
"show": true,
"total": false,
"values": false
},
"lines": true,
"linewidth": 1,
"nullPointMode": "null",
"options": {
"alertThreshold": true
},
"percentage": false,
"pluginVersion": "8.0.5",
"pointradius": 2,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"alias": "pressure",
"groupBy": [
{
"params": [
"$interval"
],
"type": "time"
}
],
"measurement": "air",
"orderByTime": "ASC",
"policy": "default",
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"pressure"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"tags": []
}
],
"thresholds": [],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "Pressure",
"tooltip": {
"shared": true,
"sort": 0,
"value_type": "individual"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"$$hashKey": "object:496",
"format": "pressurehpa",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"$$hashKey": "object:497",
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
],
"yaxis": {
"align": false,
"alignLevel": null
}
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "${DS_INFLUXDB}",
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 8,
"w": 12,
"x": 12,
"y": 16
},
"hiddenSeries": false,
"id": 10,
"interval": "3s",
"legend": {
"avg": false,
"current": false,
"max": false,
"min": false,
"show": true,
"total": false,
"values": false
},
"lines": true,
"linewidth": 1,
"nullPointMode": "null",
"options": {
"alertThreshold": true
},
"percentage": false,
"pluginVersion": "8.0.5",
"pointradius": 2,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"alias": "co2",
"groupBy": [
{
"params": [
"$interval"
],
"type": "time"
}
],
"measurement": "air",
"orderByTime": "ASC",
"policy": "default",
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"co2"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"tags": []
}
],
"thresholds": [],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "eCO₂",
"tooltip": {
"shared": true,
"sort": 0,
"value_type": "individual"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"$$hashKey": "object:855",
"decimals": 0,
"format": "ppm",
"label": "",
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"$$hashKey": "object:856",
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": "0",
"show": true
}
],
"yaxis": {
"align": false,
"alignLevel": null
}
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "${DS_INFLUXDB}",
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 8,
"w": 12,
"x": 12,
"y": 24
},
"hiddenSeries": false,
"id": 12,
"interval": "3s",
"legend": {
"avg": false,
"current": false,
"max": false,
"min": false,
"show": true,
"total": false,
"values": false
},
"lines": true,
"linewidth": 1,
"nullPointMode": "null",
"options": {
"alertThreshold": true
},
"percentage": false,
"pluginVersion": "8.0.5",
"pointradius": 2,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"alias": "iaq_accuracy",
"groupBy": [
{
"params": [
"$interval"
],
"type": "time"
}
],
"measurement": "air",
"orderByTime": "ASC",
"policy": "default",
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"iaq_accuracy"
],
"type": "field"
},
{
"params": [],
"type": "min"
}
]
],
"tags": []
}
],
"thresholds": [],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "IAQ Accuracy",
"tooltip": {
"shared": true,
"sort": 0,
"value_type": "individual"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"$$hashKey": "object:943",
"decimals": 0,
"format": "short",
"label": null,
"logBase": 1,
"max": "3",
"min": "0",
"show": true
},
{
"$$hashKey": "object:944",
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
],
"yaxis": {
"align": false,
"alignLevel": null
}
}
],
"refresh": false,
"schemaVersion": 30,
"style": "dark",
"tags": [],
"templating": {
"list": []
},
"time": {
"from": "now-6h",
"to": "now"
},
"timepicker": {},
"timezone": "",
"title": "Air",
"uid": "eTj4xDA7k",
"version": 5
}
\ No newline at end of file
---
title: IAQ with Grafana
---
This tutorial will guide you to create a Grafana installation on a Raspberry Pi which
logs temperature, humidity, air pressure and indoor air quality (IAQ) from a card10 badge.
It will look similar to this:
![](grafana.png)
{{% notice warning %}} This guide does not try to secure the installation of all the software packages involved. There might be default passwords still active which are not accounted for here. {{% /notice %}}
The individual steps are:
- Prepare card10
- Turn on Bluetooth
- Turn on BSEC in BME680 app
- Prepare Raspberry Pi 3/4
- Install latest "Raspberry Pi OS Lite" onto an SD card
- Boot Raspberry Pi
- Login
- Change the password via `passwd`
- Configure any network interfaces as needed using `rpi-config`
- `sudo apt update`
- `sudo apt upgrade`
- `sudo reboot`
- `sudo apt install git`
- Install IOTstack
- `git clone https://github.com/SensorsIot/IOTstack.git IOTstack`
- `cd ~/IOTstack`
- `./menu.sh`
- Let it install dependencies
- Restart when asked
- Edit `/etc/group` and add `pi` to the `docker` group: `docker:x:995:root,pi`
- Logout
- Login again, run `menu.sh` again
- Ignore error message because of docker version
- Select "Build Stack"
- Select grafana, influxdb, nodered using space
- Enter the nodered menu to build addons list with the right arrow key
![](iotstack-1-turn-on-nodered.png)
- Press enter
![](iotstack-3-build-addons.png)
- Add `node-red-contrib-generic-ble` using space
![](iotstack-2-select-generic-ble.png)
- Hit enter to build `addons_list.yml`
- Hit escape to go back
- Hit enter to start the build
- Go to "Docker Commands"
- Select "Start stack"
- Wait for containers being built
- Press enter
- Press escape
- Pair card10 to system
- Run `bluetoothctl`
- `scan on`
- Enter Bluetooth menu on card10
- Wait until something like `[NEW] Device CA:4D:10:XX:XX:XX card10-xxxxxx` appears
- `pair CA:4D:10:XX:XX:XX` (replace with MAC that is shown in bluetooth menu)
- Type `yes`, hit yes on card10
- Try again if the pairing fails
- `disconnect`
- `exit`
- Create influx database
- `docker exec -it influxdb influx`
- `create database card10`
- (use card10)
- `create user "nodered" with password 'supersecure'`
- `create user "grafana" with password 'supersecure'`
- `grant all on card10 to nodered`
- `grant all on card10 to grafana`
- `exit`
- Configure grafana
- Go to `<IP of your Raspberry Pi>:3000`
- User `admin`, Password `admin`
- Select a new password
- Add new data source influxdb
![](grafana-1.png)
![](grafana-2.png)
![](grafana-3.png)
- Url: `http://influxdb:8086`
![](grafana-4.png)
- Database: `card10`
- User: `grafana`
- Password: `supersecure`
- Method: GET
![](grafana-5.png)
- Press "Save & test"
![](grafana-6.png)
![](grafana-7.png)
- Import [Air-1641131410916.json](Air-1641131410916.json)
![](grafana-8.png)
- Select the InfluxDB data source you created before
![](grafana-9.png)
- Press Import
- Add card10 in nodered
- Go to `<IP of your Raspberry Pi>:1880`
- Import [card10-iaq-flow.json](card10-iaq-flow.json)
![](nodered-1.png)
![](nodered-2.png)
- Change mac of device to `CA:4D:10:XX:XX:XX` (same as above)
![](nodered-3.png)
![](nodered-4.png)
- Set user of influxdb to `nodered`
- Set password of influxdb to `supersecure`
![](nodered-9.png)
![](nodered-6.png)
![](nodered-7.png)
- Deploy flow
- Reboot (takes some time)
- Check that card10 BLE connection goes to "Active"
You should now see data coming in in the grafana dashboard that you created before under `http://<IP of your Raspberry Pi>:3000`
[
{
"id": "80bdd197.628e3",
"type": "tab",
"label": "card10 - IAQ",
"disabled": false,
"info": ""
},
{
"id": "7b89673.36ec498",
"type": "Generic BLE in",
"z": "80bdd197.628e3",
"name": "",
"genericBle": "4747b82.2030c48",
"useString": false,
"notification": true,
"x": 530,
"y": 240,
"wires": [
[
"7f392681.7d2c4",
"65f9ae64.9e6a5"
]
]
},
{
"id": "60082717.b120b",
"type": "debug",
"z": "80bdd197.628e3",
"name": "",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 810,
"y": 460,
"wires": []
},
{
"id": "500e363f.e031a8",
"type": "inject",
"z": "80bdd197.628e3",
"name": "Disconnect",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": "",
"topic": "disconnect",
"payload": "",
"payloadType": "date",
"x": 120,
"y": 300,
"wires": [
[
"7b89673.36ec498"
]
]
},
{
"id": "1c319748.0abd51",
"type": "inject",
"z": "80bdd197.628e3",
"name": "Connect",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "60",
"crontab": "",
"once": true,
"onceDelay": "",
"topic": "connect",
"payload": "",
"payloadType": "date",
"x": 120,
"y": 140,
"wires": [
[
"7b89673.36ec498"
]
]
},
{
"id": "f3829282.1b7f2",
"type": "inject",
"z": "80bdd197.628e3",
"name": "Start All Notify Events",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "60",
"crontab": "",
"once": true,
"onceDelay": "2",
"topic": "2a6e,2a6f,2a6d,422302f1234223422342234223422342",
"payload": "{\"notify\":true,\"period\":0}",
"payloadType": "json",
"x": 170,
"y": 220,
"wires": [
[
"7b89673.36ec498"
]
]
},
{
"id": "81f4444e.789ba",
"type": "influxdb out",
"z": "80bdd197.628e3",
"influxdb": "713e33d1.0ab5f4",
"name": "",
"measurement": "air",
"precision": "",
"retentionPolicy": "",
"database": "database",
"precisionV18FluxV20": "ms",
"retentionPolicyV18Flux": "",
"org": "organisation",
"bucket": "bucket",
"x": 920,
"y": 360,
"wires": []
},
{
"id": "7f392681.7d2c4",
"type": "function",
"z": "80bdd197.628e3",
"name": "",
"func": "d = new DataView(new ArrayBuffer(5));\ncharacteristics = msg.payload.characteristics;\n\ntemperature_uuid = \"2a6e\";\nhumidity_uuid = \"2a6f\";\npressure_uuid = \"2a6d\";\niaq_uuid = \"422302f1234223422342234223422342\"\n\n\npayload = {};\n\nif (temperature_uuid in characteristics) {\n data_raw = characteristics[temperature_uuid];\n d.setUint8(0, data_raw[0]);\n d.setUint8(1, data_raw[1]);\n payload[\"temperature\"] = d.getInt16(0, true) / 100;\n}\n\nif (humidity_uuid in characteristics) {\n data_raw = characteristics[humidity_uuid];\n d.setUint8(0, data_raw[0]);\n d.setUint8(1, data_raw[1]);\n payload[\"humidity\"] = d.getUint16(0, true) / 100;\n}\n\nif (pressure_uuid in characteristics) {\n data_raw = characteristics[pressure_uuid];\n d.setUint8(0, data_raw[0]);\n d.setUint8(1, data_raw[1]);\n d.setUint8(2, data_raw[2]);\n d.setUint8(3, data_raw[3]);\n \n payload[\"pressure\"] = d.getInt32(0, true) / 1000;\n}\n\nif (iaq_uuid in characteristics) {\n data_raw = characteristics[iaq_uuid];\n d.setUint8(0, data_raw[0]);\n d.setUint8(1, data_raw[1]);\n d.setUint8(2, data_raw[2]);\n d.setUint8(3, data_raw[3]);\n d.setUint8(4, data_raw[4]);\n \n payload[\"iaq_accuracy\"] = d.getUint8(0);\n payload[\"iaq\"] = d.getUint16(1, true);\n payload[\"co2\"] = d.getUint16(3, true);\n}\n\n\n//node.warn(payload)\n\nreturn {payload: payload};",
"outputs": 1,
"noerr": 0,
"initialize": "// Code added here will be run once\n// whenever the node is deployed.\n\nlast_humidity = 0\nlast_temperature = 0",
"finalize": "",
"x": 560,
"y": 380,
"wires": [
[
"60082717.b120b",
"81f4444e.789ba"
]
]
},
{
"id": "65f9ae64.9e6a5",
"type": "debug",
"z": "80bdd197.628e3",
"name": "",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload.characteristics",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 850,
"y": 140,
"wires": []
},
{
"id": "d9d9d6ec.5d3038",
"type": "inject",
"z": "80bdd197.628e3",
"d": true,
"name": "Start Temperature Notify Events",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": "2",
"topic": "2a6e",
"payload": "{\"notify\":true,\"period\":0}",
"payloadType": "json",
"x": 190,
"y": 380,
"wires": [
[
"7b89673.36ec498"
]
]
},
{
"id": "4747b82.2030c48",
"type": "Generic BLE",
"localName": "card10",
"address": "ca:4d:10:01:ff:64",
"uuid": "ca4d1001ff64",
"characteristics": []
},
{
"id": "713e33d1.0ab5f4",
"type": "influxdb",
"hostname": "influxdb",
"port": "8086",
"protocol": "http",
"database": "card10",
"name": "",
"usetls": false,
"tls": "",
"influxdbVersion": "1.x",
"url": "http://localhost:8086",
"rejectUnauthorized": true
}
]
\ No newline at end of file
tutorials/grafana/grafana-1.png

34.8 KiB

tutorials/grafana/grafana-2.png

22.3 KiB

tutorials/grafana/grafana-3.png

51.8 KiB

tutorials/grafana/grafana-4.png

15.4 KiB

tutorials/grafana/grafana-5.png

12.5 KiB

tutorials/grafana/grafana-6.png

19.4 KiB

tutorials/grafana/grafana-7.png

19.7 KiB

tutorials/grafana/grafana-8.png

18.3 KiB

tutorials/grafana/grafana-9.png

40 KiB

tutorials/grafana/grafana.png

102 KiB