105浏览
查看: 105|回复: 1

基于行空板的智慧农业网页系统

[复制链接]
本帖最后由 IvanDMido 于 2022-5-8 23:49 编辑

智慧农业网页系统
前言
这个项目被砍了,emmmm,那就简化后悄悄发在这儿吧,留个纪念。

项目背景
课堂教学场景下的智慧农业项目最先是这样的:利用一块单片机(microbit/掌控板?)结合几个传感器(土壤湿度、光线等)来采集数据,之后将数据显示出来(GUI界面或IDE终端)并对它进行判别,当数值不佳时自动改善环境(浇水、补光等)。这里主要通过它的自动化来体现所谓的“智慧”。

之后,随着物联网技术的发展,借助以MQTT为底层技术的物联网平台(SIoT/EasyIoT等),我们可以将传感器检测到的数据存放到平台上,随后在服务器的网页端远程直观地查看数据记录,将数据以图表形式(折线图)呈现出来,将数据导出进行数据分析,甚至在平台网页端远程发送消息通过手动控制来实现浇水、补光等功能。这里,数据呈现形式的清晰化及功能的全面性(远程查看并控制)极大得丰富了项目的课堂效果,也提升了真实性。

然而,用多了我们会发现,它还是有些许不足之处的,比如,服务器网页端页面结构的固定化、数据呈现方式的固定化、图表样式的的单一化,等等。

那么,有没有什么工具能在保留物联网系统的优点的同时,还能让页面呈现的方式更加多样化,或者能让我们自己设计页面数据的呈现方式呢?
1652004940(1).jpg

项目目标
这个项目中,我们将借助Python的PyWebIO库来自主设计并开启一个网页服务,在页面上呈现通过传感器检测到的土壤湿度值和光线值,并在数值不佳时以弹窗的形式进行提醒,同时,可通过页面上的按钮来控制浇水等功能。
1652005083(1).jpg
材料清单
硬件清单:
理论上需要:行空板、USB数据线、土壤湿度传感器、两头PH2.0-3P白色硅胶绞线、12V/1000mA 电源适配器简易继电器模块带水管潜水泵
1652005124(1).jpg


实际上:没有传感器、执行器硬件怎么办?那就不用了吧,有行空板即可,不影响实验效果的模拟。

软件使用:Mind+编程软件x1

其他:  
1、带植物的花盆 x1
2、盛有水的烧杯 x1
3、十字/一字两用螺丝刀 x1

知识储备
1、行空板
简介:这个不介绍了。
还是说两句吧。
行空板是一块有趣的板子,它是单片机系统和单板机系统的集合体。单片机系统类似一块Arduino/micro:bit,各种常见传感器、执行器(加速度计、蜂鸣器、按键等等)都接在了单片机上;单板机类似一台小电脑,上面有触摸显示屏、USB口、麦克风等等。
这个项目中我们会用到行空板上面内置的WiFi蓝牙天线(连接网络)、光线传感器(检测光线值)、扩展接口(外接土壤湿度传感器检测数值)。
Tips:要是对板子感兴趣,可以看看相关的Wiki和详细教程介绍。
行空板官方WiKi文档:wiki.unihiker.com

2、Pinpong库
简介:这个真不介绍了,它是一套用来控制开源硬件的Python库。

3、PyWebIO库
介绍:传统的网站开发需要通过前端和后端的交互配合来实现。前端负责网页页面的版式布局等,后端负责提供服务数据接口、逻辑功能等。因此,要想实现网站页面的设计,我们需要学习多方面的知识。比如前端中涉及到的html和css外加一些js等一些样式的布局,后端中涉及的数据库、服务器技术等等。

听起来很复杂,那有没......肯定有的。

与传统相对,PyWebIO是一个用于在浏览器上获取输入和进行输出的工具库。能够将原有的通过终端交互的脚本快速服务化,供其他人在网络上通过浏览器访问使用; PyWebIO还可以方便地整合进现有的Web服务,让你不需要编写Html和JS代码,就可以构建出具有良好可用性的Web程序。
特点:
l 使用同步而不是基于回调的方式获取输入,无需在各个步骤之间保存状态,使用更方便
l 代码侵入性小,对于旧脚本代码仅需修改输入输出逻辑
l 支持多用户与并发请求
l 支持结合第三方库实现数据可视化
l 支持整合到现有的Web服务,目前支持与Flask、Django、Tornado、aiohttp框架集成
l 同时支持基于线程的执行模型和基于协程的执行模型

简单来说,最大的特点便是,这个库可以将让你通过简单的函数指令一边设计页面布局,一边将数据呈现出来。


4、HTTP超文本传输协议与MQTT消息队列遥测传输协议
简介:略

动手实践
任务描述:在网页上显示传感器实时采集到的数据以及通过页面按钮控制输出
1、硬件搭建
STEP1:通过USB连接线将行空板连接到计算机
1652005210(1).jpg

STEP2:手机开个热点,行空板联网
打开浏览器,输入“10.1.2.3”,进入行空板网页菜单,这里可以设置板子的网络连接。
1652005228(1).jpg

Tips:下面几个步骤没有硬件的可以忽略。
STEP3:将土壤湿度传感器接入行空板的P21引脚,将继电器接入行空板的P23引脚
STEP4:将土壤湿度传感器插入花盆中
STEP5:利用螺丝刀将水泵正负线与转接头连接起来。
STEP6:利用继电器将12V电源开关与水泵的转接头连接起来
STEP7:将继电器开关拨至NO端
STEP8:将水泵固定在满水的烧杯中
STEP9:将水管插入花盆中

2、程序编写
STEP1:创建与保存项目文件
启动Mind+,另存项目并命名为“010、智慧农业网页系统”。

STEP2:创建与保存Python文件
创建一个Python程序文件“main.py”,双击打开。

STEP3:导入图片文件夹
在项目文件夹中导入背景图文件夹。(图片文件夹与程序文件同在项目文件夹中,附录有all)

STEP4:程序编写
(1) 导入所需功能库
Pinpong库用来控制硬件,pywebio库start_server模块用来开启网页服务,pywebio库output模块用来在页面输出呈现内容,datetime模块用来获取时间。

  1. from pinpong.board import Board, Pin, ADC # 从pinpong.board包中导入Board, Pin, ADC模块
  2. from pinpong.extension.unihiker import * # 导入pinpong.extension.unihiker包中所有模块
  3. from pywebio import start_server # pywebio to provide the PyWebIO application as a web service
  4. from pywebio import output  # to obtain user input content
  5. import time  # python's time module
  6. import datetime  # python's datetime module
复制代码
(2) 初始化板子和引脚
  1. Board().begin()  # 初始化行空板
  2. adc0 = ADC(Pin(Pin.P21, Pin.IN))  # 初始化21引脚为模拟输入模式
  3. relay = Pin(Pin.P23, Pin.OUT)  # 初始化23引脚为数字输出模式
复制代码
(3) 定义页面上两个按钮的功能
当按钮A被点击后,继电器输出高电平,进行浇水,页面显示一个提示“浇水”的小弹窗,一秒后弹窗关闭。按钮B同理,继电器输出低电平,用来停止浇水。
  1. <font face="微软雅黑" size="2">'''定义按钮A、B的功能'''
  2. def button_A():
  3.     """浇水 button and  popoup message 浇水 when clicked"""
  4.     relay.value(1) # 继电器输出高电平,浇水
  5.     output.popup('提示', '浇水', size=output.PopupSize.SMALL) # 输出显示一个提示弹窗
  6.     time.sleep(1) # delay 1 second
  7.     output.close_popup() # close弹窗

  8. def button_B():
  9.     """关水 button and  popoup message 关水 when clicked"""
  10.     relay.value(0) # 继电器输出低电平,关水
  11.     output.popup('提示', '关水', size=output.PopupSize.SMALL) # 输出显示一个提示弹窗
  12.     time.sleep(1) # delay 1 sec
  13.     output.close_popup() # close弹窗</font>
复制代码

(4) 定义在网页上显示数值的函数
这里,我们在网页上画一个表格,然后将“检测对象”、“数值”、“监测时间”、“数值占比”分别呈现在表格中,其中数值占比以进度条的形式体现,之后在表格下方放两个按钮,用来控制继电器浇水和关水,同时在这里,我们对监测到的数据进行判别,当土壤湿度值过低时在网页上显示一秒弹窗警报。
  1. <font face="微软雅黑" size="2">'''定义一个显示数值的函数'''
  2. def display_value():
  3.     """display value of the sensors on the browser"""
  4.     while True:
  5.         # open or enter a new output scope, or enter an existing output scope
  6.         with output.use_scope(name='time', clear=True):
  7.             now1 = datetime.datetime.now()  # get the current local date.
  8.             now2 = now1.strftime("%Y-%m-%d %H:%M:%S")
  9.             Soil_moisture_value = adc0.read() # read土壤湿度传感器的模拟值并用变量Soil_moisture_value存储
  10.             # check soil moisture value
  11.             if Soil_moisture_value < 50: # 土壤湿度值<50时自动显示弹窗提示
  12.                 # pop up message
  13.                 output.popup('提示', '请浇水', size=output.PopupSize.SMALL) # 输出显示一个提示弹窗
  14.                 time.sleep(1)  # pop up for 1 sec and disappear
  15.                 output.close_popup()  # close the pop up after 1 sec

  16.             # 输出显示一个表格
  17.             output.put_table([  # progress bar of the sensors\
  18.                 # headers of the table, scoep and position
  19.                 ['监测对象', '数值', '监测时间', '数值占比'],
  20.                 # read soil moisture sensor
  21.                 ['土壤湿度:', output.put_text(adc0.read()), now2, output.put_processbar('土壤湿度')],
  22.                 # read light
  23.                 ['光线强度:', output.put_text(light.read()), now2, output.put_processbar('光线强度')],
  24.             ])
  25.             # process bar for soil sensor
  26.             output.set_processbar('土壤湿度', (adc0.read())/4095)
  27.             # process bar for light sensor
  28.             output.set_processbar('光线强度', (light.read())/4095)
  29.             # buttons for 浇水 and 关水
  30.             output.put_buttons(['浇水', '关水'], onclick=[button_A, button_B])
  31.             time.sleep(5)  # refreshes the sensor value every 5 seconds</font>
复制代码
(5) 定义一个app函数
之后,我们定义一个app函数显示主页的内容。这里,我们首先设置一个标题,之后输出显示一张图片,最后调用之前的数值显示函数,将它放在主页面上。
  1. <font face="微软雅黑" size="2"># 定义一个函数显示主页
  2. def app():
  3.     """pywebio application"""
  4.     output.put_markdown('## 环境数据监控系统')  # title of the application # 输出显示markdown格式标题
  5.     img = open('img/tree.png', 'rb').read()  # image path used for the app # 打开图片
  6.     # settings of the image
  7.     output.put_image(img, height='100px', width='90px') # 输出显示图片
  8.     display_value() # 调用数值显示函数</font>
复制代码
(6) 启动网页服务
最后,我们设置函数app为要启动的主页即可,并设置端口号8078。
  1. <font face="微软雅黑" size="2">#  Start a server to provide the PyWebIO application as a web service.
  2. start_server(app, port=8078, debug=True) # 启动网页服务</font>
复制代码

Tips:完整示例程序如下:
  1. <font face="微软雅黑" size="2">#!/usr/bin/python
  2. # -*- coding: UTF-8 -*-

  3. # import libraries
  4. from pinpong.board import Board, Pin, ADC # 从pinpong.board包中导入Board, Pin, ADC模块
  5. from pinpong.extension.unihiker import * # 导入pinpong.extension.unihiker包中所有模块
  6. from pywebio import start_server # pywebio to provide the PyWebIO application as a web service
  7. from pywebio import output  # to obtain user input content
  8. import time  # python's time module
  9. import datetime  # python's datetime module
  10. # import threading  # python's threading module
  11. # import os
  12. # cwd = os.getcwd() # get the current working directory

  13. Board().begin()  # 初始化行空板
  14. adc0 = ADC(Pin(Pin.P21, Pin.IN))  # 初始化21引脚为模拟输入模式
  15. relay = Pin(Pin.P23, Pin.OUT)  # 初始化23引脚为数字输出模式


  16. '''定义按钮A、B的功能'''
  17. def button_A():
  18.     """浇水 button and  popoup message 浇水 when clicked"""
  19.     relay.value(1) # 继电器输出高电平,浇水
  20.     output.popup('提示', '浇水', size=output.PopupSize.SMALL) # 输出显示一个提示弹窗
  21.     time.sleep(1) # delay 1 second
  22.     output.close_popup() # close弹窗


  23. def button_B():
  24.     """关水 button and  popoup message 关水 when clicked"""
  25.     relay.value(0) # 继电器输出低电平,关水
  26.     output.popup('提示', '关水', size=output.PopupSize.SMALL) # 输出显示一个提示弹窗
  27.     time.sleep(1) # delay 1 sec
  28.     output.close_popup() # close弹窗


  29. '''定义一个显示数值的函数'''
  30. def display_value():
  31.     """display value of the sensors on the browser"""
  32.     while True:
  33.         # open or enter a new output scope, or enter an existing output scope
  34.         with output.use_scope(name='time', clear=True):
  35.             now1 = datetime.datetime.now()  # get the current local date.
  36.             now2 = now1.strftime("%Y-%m-%d %H:%M:%S")
  37.             Soil_moisture_value = adc0.read() # read土壤湿度传感器的模拟值并用变量Soil_moisture_value存储
  38.             # check soil moisture value
  39.             if Soil_moisture_value < 50: # 土壤湿度值<50时自动显示弹窗提示
  40.                 # pop up message
  41.                 output.popup('提示', '请浇水', size=output.PopupSize.SMALL) # 输出显示一个提示弹窗
  42.                 time.sleep(1)  # pop up for 1 sec and disappear
  43.                 output.close_popup()  # close the pop up after 1 sec

  44.             # 输出显示一个表格
  45.             output.put_table([  # progress bar of the sensors\
  46.                 # headers of the table, scoep and position
  47.                 ['监测对象', '数值', '监测时间', '数值占比'],
  48.                 # read soil moisture sensor
  49.                 ['土壤湿度:', output.put_text(adc0.read()), now2, output.put_processbar('土壤湿度')],
  50.                 # read light
  51.                 ['光线强度:', output.put_text(light.read()), now2, output.put_processbar('光线强度')],
  52.             ])
  53.             # process bar for soil sensor
  54.             output.set_processbar('土壤湿度', (adc0.read())/4095)
  55.             # process bar for light sensor
  56.             output.set_processbar('光线强度', (light.read())/4095)
  57.             # buttons for 浇水 and 关水
  58.             output.put_buttons(['浇水', '关水'], onclick=[button_A, button_B])
  59.             time.sleep(5)  # refreshes the sensor value every 5 seconds


  60. # 定义一个函数显示主页
  61. def app():
  62.     """pywebio application"""
  63.     output.put_markdown('## 环境数据监控系统')  # title of the application # 输出显示markdown格式标题
  64.     img = open('img/tree.png', 'rb').read()  # image path used for the app # 打开图片
  65.     # settings of the image
  66.     output.put_image(img, height='100px', width='90px') # 输出显示图片
  67.     display_value() # 调用数值显示函数
  68.     # t = session.threading.Thread(target=screen_value)
  69.     # session.register_thread(t)
  70.     # t.start()


  71. #  Start a server to provide the PyWebIO application as a web service.
  72. start_server(app, port=8078, debug=True) # 启动网页服务
  73. </font>
复制代码
3、程序运行

STEP1:将12V电源开关插上220V电源插座(没有硬件忽略)

STEP2:远程连接行空板,运行程序
1652005648(1).jpg

STEP3:观察终端
出现下列界面说明网页服务已成功启动。
1652005667(1).jpg

STEP4:打开网页查看效果
打开手机浏览器,输入上面终端内提示的地址“192.168.43.201:8078”,可以看到我们设计的数据监控系统的页面呈现在眼前,并且每隔五秒刷新一次页面更新数据。而当我们点击“浇水”和“按钮”后,页面内也有相应的弹窗提示,如果成功外接了继电器,还会看到水泵开始抽水工作。
Tip1:“192.168.43.201”为我的热点手机的IP,每个手机不一样,视实际情况而定。
Tip2:由于手头只有裸板,因此土壤湿度读到的数值巨大(假值),远超过我们设定的阈值“50”,此时无法呈现警报弹窗的效果。
1652006893(1).jpg
同样地,我们也可以在电脑的浏览器中输入网址打开网页,不过须将电脑网络也连接在热点手机下。
1652005704(1).jpg
1652005714(1).jpg

小结
1、项目小结
这个项目中,我们模拟设计了一个智慧农业网页系统,通过传感器来检测植物生长环境中土壤湿度值和光线值,并将数据呈现在自主设计的网站主页上,从而能够方便得在家中通过网页远程监测农作物的生长,并且通过网页按钮远程对植物进行补水。

2、编程知识小结
主要还是库中各函数方法的使用,具体的用法,可查看官方文档(多数函数都有Demo)。
1、output模块popup()方法输出显示一个弹窗
2、output模块close_popup()方法关闭弹窗
3、output模块put_table()方法输出显示表格
4、output模块put_text()方法输出显示文字
5、output模块put_processbar()方法输出显示进度条
6、output模块set_processbar()方法设置进度条
7、output模块put_buttons()方法输出显示多个按钮
8、output模块put_markdown()方法输出markdown格式标题
9、output模块use_scope()方法控制内容输出的位置
10、output模块put_image()方法输出显示图片
11、start_server()函数启动网页服务


挑战自我
这里,我们只是用了PyWebIO库的冰山一角,随便设计并开启了一个网页服务,在页面上显示了一下标题、文字、图片、进度条、表格、按钮、弹窗等。如果你坚持看到了这里,不妨来一起思考一下:
-1)如果既没有硬件,又没有行空板,这个项目还能做吗?
Tips:在这个项目中,我们借助行空板的单片机系统来采集了数据,又借助了它内置的网卡来连接网络,然后通过编程开启了网页服务。因此本质上,你只要有一台能联网的电脑就能设计网页并在其上显示一些内容了,而如果你手上有micro:bit或者其他单片机,可以用它来采集数据,然后呈现在页面上。不过对于相关的库,需要手动pip install来安装(行空板的固件中已内置了PyWebIO库故无需手动安装)。

0)有什么办法能仅刷新显示数值而非刷新整个网页呢?
Tips:略,自己来试一试吧!

(1)在网页上如何将数据绘制成各种图表显示出来了呢,就像SIoT服务器网页端的折线图?
Tips:可以试试PyWebIO中第三方库的数据可视化功能。

(2)行空板本身的2.8寸彩屏是一大特色,我们是否可以将数据发送到网页的同时在板子的屏幕上也显示出来呢?
Tip1:这里或许需要采用多线程的方式。
Tip2:Python的threading模块、PyWebIO库中的session模块下register_thread方法以及行空板Unihiker库(屏幕控制)下皆有实现多线程的方式。

(3)在使用行空板上内置的SIoT服务搭建物联网系统时(板子本身作为服务器),我们将通过传感器检测到的数据发送到物联网平台后,是否可以再从平台获取,然后应用到我们自己设计的网页上呢?SIoT与PyWebIO间数据的联系该如何打通?
Tips:当数据繁琐不便时,或许可以考虑借助数据库(如轻量式的sqlite)。当然首先需要订阅接收Topic下的数据然后调整好它的字符格式。

(4)在使用3块行空板搭建物联网系统时(板1开启SIoT服务和热点作为服务器,板2和板3作为客户端连在它的热点下,通过传感器检测数据并发送给板1服务器),此时,要想在板3上再起一个PyWebIO网页服务,显示板1和板2发来的数据,又该如何实现呢,原理和上述(3)是否相通呢?
接着,如果再想给板3添加一个警报发邮件功能(SMTP),该如何实现呢?

(5)内网穿透技术在这样的衍生项目中会有什么使用空间吗,场景可能是怎样的呢?

(6)就先这样吧......


最后
如果你又坚持看完了上述碎碎念,那么恭喜,此文终于要结束了,希望它能给你引来一些独立思考。如果你对其中涉及的任何技术感兴趣,欢迎自己作进一步研究,并将你的成果开源出来。最后,特别感谢一下PyWebIO库的开发者成员,以及在原版“智慧农业网页系统”项目中一起研讨和提供help的小伙伴们。

题外话
想起了几年前在外滩听罗胖子的跨年演讲,有句话令人印象深刻,他说,“我其实知道,你们哪里是来听什么演讲的,你们无非是想在时间的长河当中给自己找一个时间的标识,这是你们独特的跨年方式。”        
那么,就让此文来纪念一下这段一天三捅(两次抗原一次核酸)的“难忘”日子吧,愿各地疫情早日结束,生活回归正常!   
2022年5月8日  上海宝山
智慧农业网页系统.zip (110.13 KB, 下载次数: 4)

hnyzcj  版主

发表于 2022-5-8 19:51:06

上海加油
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
关于楼主
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2022 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail