【Mind+Python】基于Pyecharts+Flask+Pinpong智能家居数字大屏系统 您所在的位置:网站首页 python硬件编程智能家居 【Mind+Python】基于Pyecharts+Flask+Pinpong智能家居数字大屏系统

【Mind+Python】基于Pyecharts+Flask+Pinpong智能家居数字大屏系统

2024-06-29 04:29| 来源: 网络整理| 查看: 265

【Mind+Python】基于Pyecharts+Flask+Pinpong智能家居数字大屏系统

pyecharts

前言

之前在做项目的时候,遇到了一个问题:就是我想将单片机板子的传感器数据,实时上传到物联网平台,然后进行数字大屏显示。一开始使用的是onenet平台→多协议接入→应用管理来进行设置,奈何里面的一个组件少的可怜!

又看到它家的‘数据可视化View’功能!被他酷炫的数字大屏模板深深吸引了。

心想这不就我要找的模板吗?于是信誓旦旦的准备大概一场的时候:在我们选择一个2D项目模板,准备创建项目的时候,它跳出来一个对话框“提示氪金”(ps:新用户有7天的专业版试用资格,我当时要做项目的时候,已经过了!)

眼看着比赛的时间节点就快到了,于是咬咬牙,就买了两个月!

买了一个企业版的会员,买完回来发现:“里面的有些功能不能用!需要升级专业版会员!(腾讯svip直呼:“内行”)”没有办法了,只能展示用这个了。勉强将项目如期完成!

数字项目大屏项目做完后,我再想能不能自己来写一个数字大屏demo呢?恰好DF的‘’Mind+Python编程与智能设计大赛’正在进行中,于是就开始着手去实现这个想法!本教程将会带领你从零开始搭建一个:基于Pyecharts + Flask + Pinpong 智能家居数字大屏系统的项目!

准备阶段 1、安装pyecharts

概况

Echarts 是一个由百度开源的数据可视化,凭借着良好的交互性,精巧的图表设计,得到了众多开发者的认可。而 Python 是一门富有表达力的语言,很适合用于数据处理。当数据分析遇上数据可视化时,pyecharts 诞生了。

特性

简洁的 API 设计,使用如丝滑般流畅,支持链式调用囊括了 30+ 种常见图表,应有尽有支持主流 Notebook 环境,Jupyter Notebook 和 JupyterLab可轻松集成至 Flask,Django 等主流 Web 框架高度灵活的配置项,可轻松搭配出精美的图表详细的文档和示例,帮助开发者更快的上手项目多达 400+ 地图文件以及原生的百度地图,为地理数据可视化提供强有力的支持 具体开发文档详见pyecharts开发文档

如何安装?

方法一:

在mind+的python模式下:点击“库管理”→"图表"→"pyecharts"点击安装即可!

方法二:pip安裝

在mind+的python模式下:点击“库管理”→"pip模式"下:

输入:pip install pyecharts

(ps:因为我这里已经安装了,界面中提示了欢迎已经存在)

7

2、安装Flask

简介:

Flask是一个轻量级的可定制框架,使用Python语言编写,较其他同类型框架更为灵活、轻便、安全且容易上手。它可以很好地结合MVC模式进行开发,开发人员分工合作,小型团队在短时间内就可以完成功能丰富的中小型网站或Web服务的实现。另外,Flask还有很强的定制性,用户可以根据自己的需求来添加相应的功能,在保持核心功能简单的同时实现功能的丰富与扩展,其强大的插件库可以让用户实现个性化的网站定制,开发出功能强大的网站。

基本模式:

Flask的基本模式为在程序里将一个视图函数分配给一个URL,每当用户访问这个URL时,系统就会执行给该URL分配好的视图函数,获取函数的返回值并将其显示到浏览器上,其工作过程见图。

12

特点:

1、简单,Flask的路由以及路由函数由修饰器设定,开发人员不需要借助其他文件匹配;2、配置灵活,有多种方法配置,不同环境的配置也非常方便;环境部署简单,Flask运行不需要借助其他任何软件,只需要安装了Python的IDE,在命令行运行即可。只需要在Python中导入相应包即可满足所有需求;3、入门简单,通过官方指南便可以清楚的了解Flask的运行流程;4、低耦合,Flask可以兼容多种数据库、模板。

更多详情:flask开发文档

如何安装Flask?

在mind+的python模式下:点击“库管理”→"pip模式"下:

输入:pip install Flask

3、安装pinpong

简介:

pinpong库是一套控制开源硬件主控板的Python库,基于Firmata协议并兼容MicroPython语法,5分钟即可让你上手使用Python控制开源硬件。

借助于pinpong库,直接用Python代码就能给各种常见的开源硬件编程。其原理是给开源硬件烧录一个特定的固件,使开源硬件可以通过串口与电脑通讯,执行各种命令。

pinpong库的名称由“Pin”和“Pong”组成,“Pin”指引脚,“PinPong”为“乒乓球”的谐音,指信号的往复。

特点:

pinpong库的设计,是为了让开发者在开发过程中不用被繁杂的硬件型号束缚,而将重点转移到软件的实现。哪怕程序编写初期用Arduino开发,部署时改成了掌控板,只要修改一下硬件的参数就能正常运行,实现了“一次编写处处运行”。

当前PinPong库正在快速更新中,已支持Arduino系列uno、leonardo、mega2560,ESP32系列掌控板(handpy)以及micro:bit板,传感器支持50+,其他主控板及更多扩展库将逐步支持。

更多详情:pinpong开发手册

如何安装pinpong?

方法一:

在mind+的python模式下:点击“库管理”→"推荐库"→"硬件控制"→"pinpong"点击安装即可

9

4、硬件清单 序列硬件1Romeo 三合一Arduino兼容控制器2Gravity: I2C BME280环境传感器 (温度,湿度,气压) 程序设计 step1:新建一个flask项目

在mind+的右侧项目文件:

1、新建一个文件 pyecharts-flask-demo

2、在pyecharts-flask-demo文件夹下 创建 templates文件夹

app

Step 2: 拷贝 pyecharts 模板

将 pyecharts 模板,位于 “C:\Users\83731\Documents\mindplus-py\environment\Python3.6.5-64\Lib\site-packages\pyecharts\render\templates”拷贝至刚新建的 templates 文件夹

(ps:这里的index.html文件是我自己新建的,后面会讲到)

tempates

Flask 前后端分离

Step 3: 新建一个 HTML 文件

新建 HTML 文件保存位于项目根目录的 templates 文件夹,这里以如下 index.html 为例. 主要用到了 jquery 和 pyecharts 管理的 echarts.min.js 依赖!后面用到水球图和词云需要用到echarts-liquidfill.min.js,echarts-wordcloud.min.js

这里你可能需要一点HTML,CSS,javascript等前端的知识,有兴趣的老师可以去w3school了解一下!(PS:本人也是小白一个,所设计的界面很low,希望大神勿喷!)

前端主动向后端进行数据刷新

定时刷新的核心在于 HTML 的 setInterval 方法。

智能家居 h1{font-family:"隶书";color:#9AB3F5;font-size:50px;margin-align:center;line-height:80px;} div{box-shadow:0 10px 20px rgba(191, 216, 184,0.19), 0 6px 6px rgba(191, 216, 184,0.23);border-radius:5px;background:#E8F6EF;position:relative; } #liquid{width:800px; height:400px;margin-left:50px; margin-top:20px;float: left;} #pressure{width:500px; height:400px;margin-left:40px; margin-top:20px; float: left;} #altitude{width:500px; height:400px;margin-left:40px; margin-top:20px;float: left;} #line{width:800px; height:400px;margin-top:20px;margin-left:50px;float: left;} #bar{width:500px; height:400px;margin-left:40px;margin-top:20px;float: left;} #wordcloud{width:500px; height:400px;margin-left:40px;margin-top:20px;float: left;} .ttop{width:100%;height:90px;text-align:center; margin-top:-20px;background:#6F69AC;} 基于Pyecharts + Flask + Pingpong 智能家居数字大屏系统 var liquid = echarts.init(document.getElementById('liquid'), 'white', {renderer: 'canvas'}); $( function () { fetchliquidData(liquid); setInterval(fetchliquidData, 2000); } ); function fetchliquidData() { $.ajax({ type: "GET", url: "http://127.0.0.1:5000/liquidChart", dataType:'json', success: function (result) { var jsonResult = JSON.stringify(result); var jsonResult = JSON.parse(jsonResult,function(key,value){ if(key === "formatter"){ console.log(value); return eval('('+value+')'); }else{ return value; } }); console.log(jsonResult); liquid.setOption(jsonResult); }, }); } var pressure = echarts.init(document.getElementById('pressure'), 'white', {renderer: 'canvas'}); $( function () { fetchpressureData(pressure); setInterval(fetchpressureData, 2000); } ); function fetchpressureData() { $.ajax({ type: "GET", url: "http://127.0.0.1:5000/pressureChart", dataType:'json', success: function (result) { pressure.setOption(result); }, }); } var altitude = echarts.init(document.getElementById('altitude'), 'white', {renderer: 'canvas'}); $( function () { fetchaltitudeData(altitude); setInterval(fetchaltitudeData, 2000); } ); function fetchaltitudeData() { $.ajax({ type: "GET", url: "http://127.0.0.1:5000/altitudeChart", dataType:'json', success: function (result) { altitude.setOption(result); }, }); } var line = echarts.init(document.getElementById('line'), 'white', {renderer: 'canvas'}); var old_data = []; $( function () { fetchlineData(line); setInterval(getDynamicData, 2000); } ); function fetchlineData() { $.ajax({ type: "GET", url: "http://127.0.0.1:5000/lineChart", dataType: "json", success: function (result) { line.setOption(result); old_data = line.getOption().series[0].data; } }); } function getDynamicData() { $.ajax({ type: "GET", url: "http://127.0.0.1:5000/lineDynamicData", dataType: "json", success: function (result) { old_data.push([result.name, result.value]); line.setOption({ series: [{data: old_data}] }); } }); } var bar = echarts.init(document.getElementById('bar'), 'white', {renderer: 'canvas'}); $( function () { fetchbarData(bar); setInterval(fetchbarData, 2000); } ); function fetchbarData() { $.ajax({ type: "GET", url: "http://127.0.0.1:5000/barChart", dataType:'json', success: function (result) { bar.setOption(result); }, }); } var wordcloud = echarts.init(document.getElementById('wordcloud'), 'white', {renderer: 'canvas'}); $( function () { fetchwordcloudData(wordcloud); setInterval(fetchwordcloudData, 2000); } ); function fetchwordcloudData() { $.ajax({ type: "GET", url: "http://127.0.0.1:5000/wordcloudChart", dataType:'json', success: function (result) { wordcloud.setOption(result); }, }); } Step 4: 新建app.py文件

请将下面的代码保存为 app.py 文件并移至项目的根目录下。

该程序主要用pingpong来获取传感器的数据,然后将数据放到pyecharts的chart中。然后通过falsk web框架每个两秒将数据发送到前端!浏览器输入:http://127.0.0.1:5000/。进行页面显示。主要用到了get请求来获取数据。

from random import randrange # 导入Flask 相关库文件 from flask import Flask, render_template from flask.json import jsonify # 导入pyecharts 相关库文件 from pyecharts import options as opts from pyecharts.charts import Grid, Liquid,Gauge,Line,Pie,Bar,WordCloud from pyecharts.faker import Faker from pyecharts.commons.utils import JsCode from pyecharts.globals import ThemeType # 导入pinpong库相关文件 from pinpong.board import Board,Pin from pinpong.libs.dfrobot_bme280 import BME280 import time Board("uno").begin() # BME280 初始化 bme = BME280() app = Flask(__name__, static_folder="templates") date=[0,0,0,0] # 创建水球图 def create_liquid_charts(temp,humi) ->Liquid: l1 = ( Liquid() .add("湿度", # 系列名称 [humi], # 系列数值 center=["48%", "50%"], # 设置x,y坐标值 label_opts=opts.LabelOpts( # 标签配置项 font_size=35, # 标签大小 position="inside", ) ) .set_global_opts(title_opts=opts.TitleOpts(title="温湿度电量水球图")) # 提示框组件配置项 ) l2 = ( Liquid() .add( "温度", [temp], center=["18%", "50%"], color=["#FFA500"], label_opts=opts.LabelOpts( font_size=35, formatter=JsCode( """function (param) { return (Math.floor(param.value * 10000) / 100) + '℃'; }""" ), position="inside", ), ) ) l3=( Liquid() .add("电量", [0.8], center=["78%", "50%"], color=["#00FA9A"], # 水球图波浪颜色 label_opts=opts.LabelOpts( font_size=35, position="inside", ) ) ) # 通过grid 并行多图将三个水球合并在一张图上 grid = Grid().add(l1, grid_opts=opts.GridOpts()).add(l2, grid_opts=opts.GridOpts()).add(l3, grid_opts=opts.GridOpts()) return grid # 创建仪表盘 def creat_pressure_chart(press) -> Gauge: c = ( Gauge() .add("", [("压强", press)], min_=['0'], # 最小值 max_=['2000'], # 最大值 split_number=5, axisline_opts=opts.AxisLineOpts( # 设置仪表盘颜色及宽度 linestyle_opts=opts.LineStyleOpts( color=[(0.3, "#67e0e3"), (0.7, "#37a2da"), (1, "#fd666d")], width=30 ) ), detail_label_opts=opts.LabelOpts(formatter="{value} Pa"),) # 格式 .set_global_opts(title_opts=opts.TitleOpts(title="压强仪表盘")) ) return c # 创建海拔仪表盘 def creat_altitude_chart(alti) -> Gauge: c1 =( Gauge() .add("", [("海拔", alti)], min_=['0'], # 最小值 max_=['1000'], # 最大值 split_number=5, axisline_opts=opts.AxisLineOpts( # 设置仪表盘颜色及宽度 linestyle_opts=opts.LineStyleOpts( color=[(0.3, "#F3EAC2"), (0.7, "#F5B461"), (1, "#EC524B")], width=30 ) ), detail_label_opts=opts.LabelOpts(formatter="{value} M"),) # 格式 .set_global_opts(title_opts=opts.TitleOpts(title="海拔仪表盘")) ) return c1 # 创建折现图 def line_base() -> Line: line = ( Line() .add_xaxis(["{}".format(i) for i in range(10)]) .add_yaxis( series_name="", y_axis=[randrange(20, 35) for _ in range(10)], is_smooth=True, label_opts=opts.LabelOpts(is_show=False), ) .set_global_opts( title_opts=opts.TitleOpts(title="温度动态数据显示"), xaxis_opts=opts.AxisOpts(type_="value"), yaxis_opts=opts.AxisOpts(type_="value"), ) ) return line # 创建主创图 def creat_bar_chart(temp,humi,press,alti) -> Bar: c = ( Bar(init_opts=opts.InitOpts(theme=ThemeType.LIGHT)) .add_xaxis(["温度","湿度","压强","海拔"]) .add_yaxis("小明家", [temp,humi,press,alti]) .set_global_opts(title_opts=opts.TitleOpts(title="BME280数据显示")) ) return c # 词条 data = [ ("hockel", "2004"), ("智能家居", "1500"), ("少儿编程", "777"), ("人工智能", "666"), ("python", "200"), ("mind+", "555"), ("Erised", "1204"), ("温度", "50"), ("湿度", "40"), ("压强", "21"), ("海拔", "30"), ("BME280", "21"), ("pyecharts", "99"), ("arduino", "50"), ("flask", "80"), ("html", "60"), ("css", "20"), ("js", "70"), ("pinpong", "120"), ] # 创建词云 def creat_wordcloud_chart() -> WordCloud: c = ( WordCloud() .add(series_name="所用技术", data_pair=data, word_size_range=[6, 66]) .set_global_opts( title_opts=opts.TitleOpts( title="所用技术", title_textstyle_opts=opts.TextStyleOpts(font_size=23) ), tooltip_opts=opts.TooltipOpts(is_show=True), ) ) return c @app.route("/") def index(): return render_template("index.html") @app.route("/liquidChart") def get_liquid_chart(): date[0] = bme.temp_c() date[1] = bme.humidity() date[2] = bme.press_pa() date[3] = bme.cal_altitudu() temp = date[0] / 100 humi = date[1] / 100 c = create_liquid_charts(temp,humi) return c.dump_options_with_quotes() # 压强仪表盘 @app.route("/pressureChart") def get_pressure_chart(): press = date[2] / 100 c = creat_pressure_chart(press) return c.dump_options_with_quotes() # 海拔仪表盘 @app.route("/altitudeChart") def get_altitude_chart(): alti = date[3] c = creat_altitude_chart(alti) return c.dump_options_with_quotes() # 动态图 @app.route("/lineChart") def get_line_chart(): c = line_base() return c.dump_options_with_quotes() idx = 9 @app.route("/lineDynamicData") def update_line_data(): global idx idx = idx + 1 return jsonify({"name": idx, "value": date[0]}) # 柱状图 @app.route("/barChart") def get_bar_chart(): c = creat_bar_chart(date[0],date[1],date[2]/100,date[3]) return c.dump_options_with_quotes() # 词云 @app.route("/wordcloudChart") def get_wordcloud_chart(): c = creat_wordcloud_chart() return c.dump_options_with_quotes() if __name__ == "__main__": app.run() 演示效果

基于Pyecharts + Flask + Pinpong 智能家居数字大屏系统

FAQ: 1、Gauge 仪表板显示图例与数据重叠!

gauge图例与数据重叠

这个是pyecharts V1.9.0的BUG!在V2.0.0将被修复!

解决方法:

找到pyecharts的安装目录(右击右侧项目:打开文件所在位置即可找到):

C:\Users\83731\Documents\mindplus-py\environment\Python3.6.5-64\Lib\site-packages\

然后修改pyecharts\charts\basic_charts\chart.py文件

gauge1

2、pyecharts中的水球图不显示问题:

在遇到这个问题之后,了解一下echarts,才知道echarts-liquidfill是第三方插件,需要单独导入

需要在index.html文件中标签内加入:

3、水球图在进行数据精度显示是时:单位不能显示!

在看了pyecharts文档时有一处写到:

注: 目前由于 json 数据类型的问题,无法将 pyecharts 中的 JSCode 类型的数据转换成 json 数据格式返回到前端页面中使用。因此在使用前后端分离的情况下尽量避免使用 JSCode 进行画图。

l2 = ( Liquid() .add( "温度", [0.3254], center=["18%", "50%"], color=["#FFA500"], label_opts=opts.LabelOpts( font_size=35, formatter=JsCode( """function (param) { return (Math.floor(param.value * 10000) / 100) + '℃'; }""" ), position="inside", ), ) )

err1

我这这里jscode返回的对象是str:str! 然而我们需要调用jscode的函数!我们需要在html的文档中进行数据处理:将str:str 转换成 str:function().找到我们调用的liquid的script标签进行如下更改!

function fetchliquidData() { $.ajax({ type: "GET", url: "http://127.0.0.1:5000/liquidChart", dataType:'json', success: function (result) { var jsonResult = JSON.stringify(result); jsonResult = JSON.parse(jsonResult,function(key,value){ if(key === "formatter"){ console.log(value); return eval('('+value+')'); }else{ return value; } }); console.log(jsonResult); liquid.setOption(jsonResult); }, } 4.用grid组件无法将liquid和gauge并列合并在同一图上!

使用grid时,一般情况下,永远不要先给grid加入一个没有x y轴的图,比如饼图、仪表盘、地图等等。

如果你想加的,可以参考这篇文章:pyecharts丨页面布局工具——grid注意事项和overlap的使用

总结

整个项目做下来!被Flask的前后端分离数据显示问题搞得崩溃!主要还是因为自己的前端知识有点薄弱。为此自己恶补了一晚的前端的html,css,js等知识!对falsk web框架和pyecharts有了进一步的了解!屏幕前的你,有没有学吐了呢?反正我是秃了!

更多教程欢迎关注个人博客:www.hockel.club

项目源码请关注微信公众号:跟着hockel玩科创

​ 回复:“pyecharts”即可获得

2d7483a0cfabe7931818c378c25a9f91



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有