EMQX+INFLUXDB+GRAFANA物联网可视化平台搭建

EMQX+INFLUXDB+GRAFANA物联网可视化平台搭建

    • 前言
    • 一、DOCKER配置
      • 1.Docker介绍:
      • 2.Docker镜像准备
      • 3.Docker常用指令及解释
    • 二、服务器上配置EMQX
    • 三、服务器上配置INFLUXDB
    • 四、服务器上配置GRAFANA
    • 五、EMQX-INFUXDB规则引擎配置与测试
      • 1.规则引擎配置
      • 2.脚本测试
    • 六、INFLUXDB-GRAFANA配置
    • 七、GRAFANA图表配置
      • 1.Stat数据
      • 2.Bar gauge数据
      • 3.Graph线性图
    • 八、GRAFANA大地图配置
    • 九、最终面板展示
    • 十、Grafana用户管理系统
      • 1.创建用户
      • 2.单独设置权限
    • 十一、附件:Influxdb常用语句

前言

总项目目的是实现基于Lora通信的物联网可视化系统的实现,其中工作流程为单片机连接传感器获取数值通过Lora协议实现无线长距离传输到网关,网关通过4G模块基于MQTT连接到网络服务器进行转发到应用服务器,最后由应用服务器进行数据解析、存储与展示。而物联网可视化部分即包括网络服务器到应用服务器的搭建,因此我们使用到三个主要应用平台。

(1)EMQX:EMQX是基于高并发的 Erlang/OTP 语言平台开发,支持百万级连接和分布式集群架构,发布订阅模式的开源 MQTT 消息服务器。EMQ X 内置了大量开箱即用的功能,其开源版 EMQ X Broker 及企业版 EMQ X Enterprise 均支持通过规则引擎将设备消息存储到 TDengine。
(2)INFLUXDB:InfluxDB是一个由InfluxData开发的开源时序型数据库。它由Go写成,着力于高性能地查询与存储时序型数据。InfluxDB被广泛应用于存储系统的监控数据,IoT行业的实时数据等场景。
(3)Grafana:Grafana 是一个跨平台、开源的度量分析和可视化工具,可以查询处理各类数据源中的数据,进行可视化的展示。它可以快速灵活创建的客户端图表,面板插件有许多不同方式的可视化指标和日志,官方库中具有丰富的仪表盘插件,比如热图、折线图、图表等多种展示方式;支持 Graphite,TDengine、InfluxDB,OpenTSDB,Prometheus,Elasticsearch,CloudWatch和 KairosDB 等数据源,支持数据项独立/混合查询展示;可以创建自定义告警规则并通知到其他消息处理服务或组件中。
以下使用平台为Linux Ubuntu 20.04 与 Docker。

MQTT-JSON内容如下:

{
  "host": "test0",
  "latitude": 123.123456,
  "longitude": 22.564234,
  "temperature": 16.22,
  "battery": 4.3
}

一、DOCKER配置

1.Docker介绍:

Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化,这里不一定要使用Docker。

2.Docker镜像准备

使用指令

apt-get install docker docker.io

然后使用docker指令准备两个镜像 分别是emqx influxdb

EMQX:
    docker pull emqx/emqx-ee:latest
    INFLUXDB:
	docker pull influxdb:1.8

此时使用指令

docker images

可以发现有两个镜像emqx influxdb
在这里插入图片描述

文件准备完成,开始配置安装EMQX。

3.Docker常用指令及解释

这里简单列出使用到的指令

docker pull [images] //拉取镜像指令
docker run -d --name [镜像名称] -p [容器端口:服务器端口] [镜像文件] //运行镜像以指定名称 指定映射端口 运行的镜像名称
docker restart/stop/start/rm [镜像名称] //重启、停止、开始、移除容器但是不会吧镜像移除
docker ps //展示镜像
docker exec -it [镜像名称] bash(/bin/sh) //进入容器 使用bash/sh控制台
//进入容器之后可以输入exit退出容器
docker cp [本地文件/容器文件] [本地文件/容器文件]
//例如 docker cp influxdb.conf influxDb:/etc/influxdb/ 则是拷贝当前文件夹中的influxdb.conf到influxdb容器中的/etc/influxdb/文件夹下
//docker cp influxDb:/etc/influxdb/influxdb.conf . 则表示拷贝influxdb容器中/etc/influxdb/influxdb.conf到当前文件夹	

由于docker容器环境中没有提供vi编辑器所以需要先拷贝文件夹下来更改再复制进入容器后再重启容器才能够生效

二、服务器上配置EMQX

使用以下指令

docker run -d --name emqx-ee -p 1883:1883 -p 8083:8083 -p 8883:8883 -p 8084:8084 -p 18083:18083 emqx/emqx-ee:latest
docker ps 

得到如图 则运行成功 我们使用浏览器输入服务器IP:18083 如xxx.xxx.xxx.xxx:18083进入网页在这里插入图片描述
网页如图所示 默认用户名admin 密码public
EMQX+INFLUXDB+GRAFANA物联网可视化平台搭建_第1张图片
如图所示安装成功
EMQX+INFLUXDB+GRAFANA物联网可视化平台搭建_第2张图片
但是由于websocket工具占用了8083端口 会导致influxdb无法正常安装
解决方法1:在EMQX主界面左侧栏目->设置->启用->监听器->8083端口的ws->关闭
这样做会导致websocket工具无法使用 但是可以使用MQTT.fx测试工具代替
EMQX+INFLUXDB+GRAFANA物联网可视化平台搭建_第3张图片
解决方法2: 在配置Influxdb更改8083的映射端口号,可能会有其他影响。

三、服务器上配置INFLUXDB

强调一下这里本文使用的是influx1.8版本,influx2.0版本之后各方面大改,想学习可以自行学习。
先在本地创建一个文件,名称为influxdb.conf
内容如下:配置文件详解

reporting-disabled = false
bind-address = "127.0.0.1:8088"

[meta]
  dir = "/var/lib/influxdb/meta"
  retention-autocreate = true
  logging-enabled = true

[data]
  dir = "/var/lib/influxdb/data"
  index-version = "inmem"
  wal-dir = "/var/lib/influxdb/wal"
  wal-fsync-delay = "0s"
  validate-keys = false
  query-log-enabled = true
  cache-max-memory-size = 1073741824
  cache-snapshot-memory-size = 26214400
  cache-snapshot-write-cold-duration = "10m0s"
  compact-full-write-cold-duration = "4h0m0s"
  compact-throughput = 50331648
  compact-throughput-burst = 50331648
  max-series-per-database = 1000000
  max-values-per-tag = 100000
  max-concurrent-compactions = 0
  max-index-log-file-size = 1048576
  trace-logging-enabled = false
  tsm-use-madv-willneed = false

[coordinator]
  write-timeout = "10s"
  max-concurrent-queries = 0
  query-timeout = "0s"
  log-queries-after = "0s"
  max-select-point = 0
  max-select-series = 0
  max-select-buckets = 0

[retention]
  enabled = true
  check-interval = "30m0s"

[shard-precreation]
  enabled = true
  check-interval = "10m0s"
  advance-period = "30m0s"

[monitor]
  store-enabled = true
  store-database = "_internal"
  store-interval = "10s"

[subscriber]
  enabled = true
  http-timeout = "30s"
  insecure-skip-verify = false
  ca-certs = ""
  write-concurrency = 40
  write-buffer-size = 1000

[http]
  enabled = true
  bind-address = ":8086"
  auth-enabled = false
  log-enabled = true
  suppress-write-log = false
  write-tracing = false
  flux-enabled = false
  pprof-enabled = true
  debug-pprof-enabled = false
  https-enabled = false
  https-certificate = "/etc/ssl/influxdb.pem"
  https-private-key = ""
  max-row-limit = 0
  max-connection-limit = 0
  shared-secret = ""
  realm = "InfluxDB"
  unix-socket-enabled = false
  unix-socket-permissions = "0777"
  bind-socket = "/var/run/influxdb.sock"
  max-body-size = 25000000
  access-log-path = ""
  max-concurrent-write-limit = 0
  max-enqueued-write-limit = 0
  enqueued-write-timeout = 30000000000

[logging]
  format = "auto"
  level = "info"
  suppress-logo = false

[[graphite]]
  enabled = false
  bind-address = ":2003"
  database = "graphite"
  retention-policy = ""
  protocol = "tcp"
  batch-size = 5000
  batch-pending = 10
  batch-timeout = "1s"
  consistency-level = "one"
  separator = "."
  udp-read-buffer = 0

[[collectd]]
  enabled = false
  bind-address = ":25826"
  database = "collectd"
  retention-policy = ""
  batch-size = 5000
  batch-pending = 10
  batch-timeout = "10s"
  read-buffer = 0
  typesdb = "/usr/share/collectd/types.db"
  security-level = "none"
  auth-file = "/etc/collectd/auth_file"
  parse-multivalue-plugin = "split"

[[opentsdb]]
  enabled = false
  bind-address = ":4242"
  database = "opentsdb"
  retention-policy = ""
  consistency-level = "one"
  tls-enabled = false
  certificate = "/etc/ssl/influxdb.pem"
  batch-size = 1000
  batch-pending = 5
  batch-timeout = "1s"
  log-point-errors = true

[[udp]]
  enabled = true
  bind-address = ":8089"
  database = "db"
  retention-policy = ""
  batch-size = 1
  batch-pending = 1
  read-buffer = 0
  batch-timeout = "1s"
  precision = ""

[continuous_queries]
  log-enabled = true
  enabled = true
  query-stats-enabled = false
  run-interval = "1s"

[tls]
  min-version = ""
  max-version = ""

生成文件在当前文件夹后使用命令

docker run --name=influxdb --rm -d -p 8086:8086 -p 8089:8089/udp -v influxdb.conf:/etc/influxdb/influxdb.conf:ro -e INFLUXDB_DB=db influxdb:1.8

参数介绍:

	-e INFLUXDB_DB=db:创建一个名为db的数据库
	-v:   需要配置的文件
	-d:deamon,后台启动
	-p:port, 端口映射,宿主机端口:容器内端口;8083是influxdb的web管理工具端口,8086是influxdb的HTTP API端口
	--expose:允许容器接受外部传入的数据
	--name:容器名称,此处为influxDb
	influxdb:镜像名

使用指令

docker ps 

得到如下图两个docker运行中的容器
在这里插入图片描述
我们进入容器 使用如下指令 发现最后展示两个数据库 一个是db 一个是自带的_internal

docker exec -it influxdb bash
influxdb
show databses
quit //退出数据库

EMQX+INFLUXDB+GRAFANA物联网可视化平台搭建_第4张图片
influxdb安装成功。

四、服务器上配置GRAFANA

输入指令获取grafana镜像并安装运行

docker run -d --name=grafana -p 3000:3000 grafana/grafana

自行下载grafana 完成后打开浏览器输入ip:3000 即可进入界面 账号密码admin
EMQX+INFLUXDB+GRAFANA物联网可视化平台搭建_第5张图片
成功后界面如图所示
EMQX+INFLUXDB+GRAFANA物联网可视化平台搭建_第6张图片

五、EMQX-INFUXDB规则引擎配置与测试

1.规则引擎配置

参考链接
这一部分目的是EMQX接收到MQTT信息之后能够解析并储存起来。
1.打开EMQX服务器登入选择左侧菜单栏->规则引擎->创建
2.SQL输入

SELECT
  payload.host as host,
  payload.temperature as temperature,
  payload.battery as battery,
  payload.latitude as latitude,
  payload.longitude as longitude
FROM
  "sensor/influxdb"

EMQX+INFLUXDB+GRAFANA物联网可视化平台搭建_第7张图片
3.打开SQL测试 输入主题 sensor/influxdb 输入json数据

{
  "host": "test0",
  "latitude": 123.123456,
  "longitude": 22.564234,
  "temperature": 16.22,
  "battery": 4.3
}

4.SQL测试初入正常
EMQX+INFLUXDB+GRAFANA物联网可视化平台搭建_第8张图片
5.添加响应动作->动作类型:数据持久化->保存数据到InfluxDB
EMQX+INFLUXDB+GRAFANA物联网可视化平台搭建_第9张图片
6.使用资源->新建 如果数据库写入失败这里的influxDB主机填写公网 IP试试
EMQX+INFLUXDB+GRAFANA物联网可视化平台搭建_第10张图片
确定后返回填写Measurement Fields Tags等信息
7.根据传入Json内容填写内容如下
EMQX+INFLUXDB+GRAFANA物联网可视化平台搭建_第11张图片
确定生成新规则。

2.脚本测试

1.这里提供一个随机数生成脚本测试,这里我使用了vscode terminal 安装了node.js
并安装了mock、mqtt库

npm install mqtt mockjs --save --registry=https://registry.npm.taobao.org
node mock.js

// mock.js
const mqtt = require('mqtt')
const Mock = require('mockjs')

const EMQX_SERVER = 'mqtt://xxx.xxx.xxx.xxx:1883' //根据ip进行修改
const CLIENT_NUM = 5 //连接设备 由于EMQX非认证版本有10个设备限制 建议最大不超过10
const STEP = 5000 // 模拟采集时间间隔 ms
const AWAIT = 5000 // 每次发送完后休眠时间,防止消息速率过快 ms
const CLIENT_POOL = []
const LONGITUDE_POOL = [113.584557, 113.624811, 113.596916, 113.590908, 113.587132, 113.587132, 113.592796, 113.621464, 113.611593, 113.627815]
const LATITUDE_POOL = [22.345233, 22.347377, 22.341899, 22.337374, 22.349282, 22.328561, 22.359046, 22.347774, 22.361983, 22.357696]
const HOST_POOL = ["test0", "test1", "test2", "test3", "test4", "test5", "test6", "test7", "test8", "test9"]

startMock()


function sleep(timer = 100) {
    return new Promise(resolve => {
        setTimeout(resolve, timer)
    })
}

async function startMock() {
    const now = Date.now()
    for (let i = 0; i < CLIENT_NUM; i++) {
        const client = await createClient(`mock_client_${i}`)
        CLIENT_POOL.push(client)
    }
    // last 24h every 5s
    const last = 24 * 3600 * 1000
    for (let ts = now - last; ts <= now; ts += STEP) {
        for (const client of CLIENT_POOL) {
            const mockData = generateMockData()
            const data = {
                ...mockData,
                id: client.clientId,
                area: 0,
                ts,
            }
            client.publish('sensor/influxdb', JSON.stringify(data))
        }
        const dateStr = new Date(ts).toLocaleTimeString()
        console.log(`${dateStr} send success.`)
        await sleep(AWAIT)
    }
    console.log(`Done, use ${(Date.now() - now) / 1000}s`)
}

/**
 * Init a virtual mqtt client
 * @param {string} clientId ClientID
 */
function createClient(clientId) {
    return new Promise((resolve, reject) => {
        const client = mqtt.connect(EMQX_SERVER, {
            clientId,
        })
        client.on('connect', () => {
            console.log(`client ${clientId} connected`)
            resolve(client)
        })
        client.on('reconnect', () => {
            console.log('reconnect')
        })
        client.on('error', (e) => {
            console.error(e)
            reject(e)
        })
    })
}

/**
 * Generate mock data
 */
function generateMockData() {
    let i = Mock.Random.integer(0, 9);
    return {
        "host": HOST_POOL[i],
        "latitude": LATITUDE_POOL[i],
        "longitude": LONGITUDE_POOL[i],
        //"geohash": GEOHASH_POOL[i],
        "temperature": parseFloat(Mock.Random.float(10, 40).toFixed(2)),
        "battery": parseFloat(Mock.Random.float(3, 4).toFixed(2))
    }
}

使用vscode呼出控制台 node mock.js 运行
EMQX+INFLUXDB+GRAFANA物联网可视化平台搭建_第12张图片
2.运行之后可以发现emqx上有5个设备连接EMQX+INFLUXDB+GRAFANA物联网可视化平台搭建_第13张图片
3.规则引擎->监控也有成功动作统计
EMQX+INFLUXDB+GRAFANA物联网可视化平台搭建_第14张图片
4.然后我们docker 运行influxdb

docker exec -it influxdb bash //使用bash 进入influxdb容器
influx //influxdb数据库指令
use db //使用db数据库
show measurements //展示db下的measurement类似数据库的tables
select * from influx_location //查看所有influx_location里面的信息

5.发现有数据输入
EMQX+INFLUXDB+GRAFANA物联网可视化平台搭建_第15张图片
6.表明EMQX收到数据->INFLUXDB转发写入数据成功!

六、INFLUXDB-GRAFANA配置

1.进入grafana->datasource->influxdb界面如图
EMQX+INFLUXDB+GRAFANA物联网可视化平台搭建_第16张图片
2.填写IP地址与database
EMQX+INFLUXDB+GRAFANA物联网可视化平台搭建_第17张图片
user与password没设置就填写admin(可能空着也行没试过)
填写完之后点击save&test 如果返回如图则成功
EMQX+INFLUXDB+GRAFANA物联网可视化平台搭建_第18张图片
3.图表测试
左侧选择explor 根据图选择最后展示出曲线图则证明Influxdb->Grafana成功!
EMQX+INFLUXDB+GRAFANA物联网可视化平台搭建_第19张图片
测试成功!

七、GRAFANA图表配置

(最好打开上面说的node脚本不断上传随机数来验证可视化)
先Create->Dashbord->Add new panel
这里只距离三类图标的引用。

1.Stat数据

1.在右侧panel->Visualization->stat
EMQX+INFLUXDB+GRAFANA物联网可视化平台搭建_第20张图片
2.选择
form:influx_location
WHERE:host = test0
select:field(value)->temperature mean()->remove
GROUP BY:time()->remove
FORMAT AS:Table
EMQX+INFLUXDB+GRAFANA物联网可视化平台搭建_第21张图片
实现数据展示
3.复制多一个 把host = test0 改为 host = test1
可以得到
EMQX+INFLUXDB+GRAFANA物联网可视化平台搭建_第22张图片
以此类推可以得到更多数据源
4.初次之外还有Field->unit->temperature->Celsius(℃)符号展示
min max为最大最小值 decimals 小数多少位等等可以自行尝试
最后根据需求美化出结果如图所示
EMQX+INFLUXDB+GRAFANA物联网可视化平台搭建_第23张图片

2.Bar gauge数据

同理我们在Visualzation选择Bar gauge选择内容如下
EMQX+INFLUXDB+GRAFANA物联网可视化平台搭建_第24张图片
根据需求美化后展示结果
EMQX+INFLUXDB+GRAFANA物联网可视化平台搭建_第25张图片

3.Graph线性图

Graph最大的去别是需要一个方位的时间,这里time(1m)和mean()分别代表以一分钟为一段做平均值。
EMQX+INFLUXDB+GRAFANA物联网可视化平台搭建_第26张图片
单图表展示
EMQX+INFLUXDB+GRAFANA物联网可视化平台搭建_第27张图片
美化后最终效果
EMQX+INFLUXDB+GRAFANA物联网可视化平台搭建_第28张图片

八、GRAFANA大地图配置

Grafana地图大屏不是Grafana默认搭配的插件,需要自己去下载:网址点我
回到SSH工具 使用linux指令

docker exec -it grafana /bin/sh //这里不适用bash是该容器不支持bash
grafana-cli plugins install grafana-worldmap-panel //安装地图插件
exit //退出grafana容器
docker restart grafana //重启grafana容器

重启完刷新界面可以发现Visualzation下多出了Worlmap panel
EMQX+INFLUXDB+GRAFANA物联网可视化平台搭建_第29张图片
但是此时由于网络原因地图加载十分缓慢 我们需要配置地图源文件


worldmap解决地图背景不显示的问题
其实主要的问题就是网络的问题,worldmap-panel的访问地址需要进行修改。

1.1 grafana-worldmap-panel\src\worldmap.ts
1.2 grafana-worldmap-panel\dist\module.js
1.3 grafana-worldmap-panel\dist\module.js.map
将文件中的url进行修改.
2.1 https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_all/{z}/{x}/{y}.png 修改为 http://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png
2.2 https://cartodb-basemaps-{s}.global.ssl.fastly.net/dark_all/{z}/{x}/{y}.png 修改为 http://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png


以上为引用 以下为操作步骤

docker cp grafana:/var/lib/grafana/plugins/grafana-worldmap-panel/src/worldmap.ts .
docker cp grafana:/var/lib/grafana/plugins/grafana-worldmap-panel/dist/module.js .
docker cp grafana:/var/lib/grafana/plugins/grafana-worldmap-panel/dist/module.js.map .
vi worldmap.ts
vi module.js
vi moduel.js.map

按照上述修改url

docker cp worldmap.ts grafana:/var/lib/grafana/plugins/grafana-worldmap-panel/src/
docker cp module.js grafana:/var/lib/grafana/plugins/grafana-worldmap-panel/dist/
docker cp module.js.map grafana:/var/lib/grafana/plugins/grafana-worldmap-panel/dist/
docker restart grafana

因为修改了文件所以在plugins下的worldmap panel出现modified signature是正常现象
在这里插入图片描述
现在我们就可以很快的刷新地图啦
配置图和展示图如下EMQX+INFLUXDB+GRAFANA物联网可视化平台搭建_第30张图片
其中alias表示重命名与右侧coordinates中的metric、latitude、longitude链接起来
query->data也能看到传入的数据
EMQX+INFLUXDB+GRAFANA物联网可视化平台搭建_第31张图片

九、最终面板展示

把一切部署完成后展示页面如图所示

十、Grafana用户管理系统

1.创建用户

Configuration->Users->Invite创建一个用户
EMQX+INFLUXDB+GRAFANA物联网可视化平台搭建_第32张图片
根据需要起名字和邮箱 选择Viewer 关闭Send invite email Submit生成用户
EMQX+INFLUXDB+GRAFANA物联网可视化平台搭建_第33张图片
按图选择 这里复制出来的链接是 localhost.com/… localhost需要改为服务器的公网IP
EMQX+INFLUXDB+GRAFANA物联网可视化平台搭建_第34张图片
然后就进入用户登陆界面
EMQX+INFLUXDB+GRAFANA物联网可视化平台搭建_第35张图片
第一次登陆输入密码就可以以游客身份登陆啦

可以看到游客仅有查看的权限没有编辑权限

2.单独设置权限

此时我们先回到管理员权限进入dashboard->setting->permissions
如图所示
EMQX+INFLUXDB+GRAFANA物联网可视化平台搭建_第36张图片
最终实现了只有单一游客用户查看此图功能!

十一、附件:Influxdb常用语句

修改时间查看方式
precision rfc3339
创建超级账户
create user "sitech" with password 'sitech' with all privileges
创建普通账户
create user "123" with password '123'
展示用户
show users
展示数据库
show databases
展示图表
show measurement
搜索语法
Select [avg(temperature)] from [measurement] [where/order/group]
登录有用户的数据库
influx -username sitech -password sitech

influxdb docker环境中:
重置系统时间
rm -rf /etc/localtime
ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

你可能感兴趣的:(linux,物联网,docker,数据库)