物联网(IoT)是由相互连接的计算机,电话,平板电脑和诸如恒温器,车库门开启器,灯泡,门铃摄像头,气象站之类的物理设备组成的网络。 当我们谈论Internet时,通常是指与网页,程序和应用程序通信的计算机,平板电脑,电话和服务器。 物联网通过包含除计算机,电话,平板电脑和服务器以外的设备在Internet上的构建。
我有两个基于ESP8266的WiFi气象站。 这些小设备是物联网的一部分。 气象站由ESP8266微控制器和通过跨接线和面包板连接的温度传感器组成。 基于ESP8266的WiFi气象站将温度测量结果传输到云中的服务器。 这些WiFi气象站是物联网设备。
与物联网设备交互的服务器(如基于ESP8266的WiFi气象站)称为物联网服务器或IoT服务器。 物联网服务器与物联网设备通信。 在该项目开始时,基于ESP8266的WiFi气象站与ThingSpeak.com物联网服务器进行通信。 WiFi气象站将温度测量结果发送到保存数据的ThingSpeak.com IoT服务器。
IoT服务器需要实现两个主要功能:
使用flask和Python构建IoT服务器是一个多部分的问题。我们可以将问题分解为以下步骤:
在本文中,我们将描述项目中使用的服务器设置和微控制器硬件。
以下是用于构建基于ESP8266的WiFi气象站的硬件列表。
请注意,作为该项目的一部分,我使用了两个ESP8266微控制器。 一个ESP8266连接到BMP280温度传感器,另一个ESP8266连接到MCP9808温度传感器。 这两个温度传感器是以前项目中遗留下来的(我本来应该使用两个相同的传感器,但是我所用的是一个BMP280和一个MCP9808)。
一个ESP8266-温度传感器组合用于测量外部温度,另一个ESP8266-温度传感器组合用于测量内部温度。
我构建的flask应用程序是相对基本的,主要包含2个文件:flaskapp.py和index.html。 Digital Ocean服务器上的文件结构如下所示:
~/
└── flaskapp
├── flaskapp.ini
├── flaskapp.py
├── flaskapp.sock
├── flaskappenv
├── templates
│ ├── index.html
└── wsgi.py
运行flask应用程序的主要文件是flaskapp.py
>
flask应用程序用于构建网页的唯一jinja模板位于/ templates目录中,名为index.html:
>
创建了flask应用程序并配置了域名,nginx,uWSGI,systemd和SSL后,该应用程序将在服务器上启动,并具有以下功能:
>
生成的网页如下所示:
我们已经在Digital Ocean上托管了一个工作Flask应用程序。现在,我们需要将Web API添加到flask应用程序的功能中。
Web API是基于Web的应用程序编程接口。这是一种幻想的说法,即服务器根据服务器从Web浏览器接收的URL保存输入或生成输出。
Web API的一个示例是ThingSpeak.com Web API。当网络浏览器(例如chrome)定向到以下URL时:
https://api.thingspeak.com/channels/266256/fields/2/last.txt
响应是存储在ThingSpeak.com上的数据条目,其对应于:
如果粘贴到Web浏览器中的URL不同,则ThingSpeak.com的响应也将不同。
https://api.thingspeak.com/channels/9/fields/1/last.json
对上述URL的响应是存储在ThingSpeak.com上的数据条目,其对应于:
大多数Web API允许您从其服务器中提取数据,但是许多Web API也使您能够在其服务器上放置数据。
如果粘贴到Web浏览器中的URL的格式如下,ThingSpeak.com将存储一个新的数据点。
https://api.thingspeak.com/update?api_key=THECLASSAPIKEY&field1=87
ThingSpeak.com收到GET请求时存储的数据点为:
我们将使用flask构建的Web API需要完全满足ThingSpeak.com Web API实现的两个基本功能:
我们将在Flask IoT服务器Web API中模仿ThingSpeak.com Web API的一部分。 为了基于服务器接收的URL存储数据点,我们需要指定URL的结构。 我们基于ESP8266的WiFi气象站需要知道URL格式,才能将数据点发布到Flask IoT服务器上。
数据将基于服务器从基于ESP8266的WiFi气象站接收的URL存储在我们的Flask IoT服务器上。
每个基于ESP8266的WiFi气象站都有几个独特的方面:
如果我们将这4个标识符作为Web API URL的一部分,我们的IoT服务器将提供WiFi气象站所需的功能。
我们的Web API URL的一般形式如下:
https://mydomain.com/update/API_key=ASCIISTR/mac=6c:rf:7f:2b:0e:g8/field=1/data=72.3
在上面的网址中,我们提供了:
现在,当出现类似于我们上面指定的URL时,我们需要使Flask IoT服务器保存数据点。
由于flask可以选择在路由中包含变量,因此在flask中构建Web API非常容易。通用语法如下:
@app.route("/update/key=", methods=['GET'])
def update(route_var):
# code to run
return render_template("index.html")
在上面的代码中,路由"/update/key=
在Flask Web API的@ pp.route()URL中分配了四个变量:
parameter | purpose | route variable |
API key | 每个用户的唯一标识符 | |
mac address | 每个ESP8266设备的唯一标识符 | |
field | 表示温度或湿度 | |
data | 数据点保存在服务器上 |
我们的Web API的完整@ pp.route()URL如下所示:
"/update/API_key=/mac=/field=/data="
现在,我们可以为此URL构建一个新的@ app.route()函数对。请注意,我们返回了一个名为update.html的新模板,并将数据点数据传递给该模板。
@app.route("/update/API_key=/mac=/field=/data=", methods=['GET'])
def update(api_key, mac, field, data):
return render_template("update.html", data=data)
由于我们正在调用新模板,因此我们需要构造一个新模板。模板update.html可以具有与index.html相同的形式。让我们创建一个新文件,并将其复制到以下html代码和jinja字段中。
$ cd ~
$ cd flaskapp
$ cd templates
$ nano update.html
新的update.html模板的代码如下:
>
现在,在我们的服务器上,我们可以重新启动flask应用程序,并查看我们的Web API是否有效。
>
如果浏览到服务器的网址,我们仍然应该看到相同的索引模板。
但是现在,如果我们转到网址:
https://yourdomain.com//update/API_key=APGLMD/mac=a3:45:b5:c9/field=1/data=98.6
您会看到显示的温度为98.6时更新的温度。
现在我们有了Web API,我们可以使用Web浏览器发出GET请求,并参阅Flask返回的网页中的输出。添加到由我们的Web API指定的URL中的任何字符串都可以通过。 我们不希望任何WiFi气象站都上传数据。 我们需要的是一些数据验证。
Web API是基于Web的应用程序编程接口。这是说服务器保存输入或根据某人在Web浏览器中键入的URL生成输出的一种奇特的方式。我们的Flask IoT Web服务器接受的示例URL是:
https://mydomain.com/update/API_key=ASCIISTR/mac=6c:rf:7f:2b:0e:g8/field=1/data=72.3
在上面的网址中,我们提供了:
现在,可以将API_key =和mac =之后的任何字符串插入URL。 这允许具有Internet连接的任何人将数据上传到服务器,并可能将恶意代码上传到服务器。 由于可以将任意字符串作为API_key或mac插入,因此我们的flask IoT服务器将读取该任意字符串。
为了在我们的服务器中增加一点安全性,我们将使用一种数据验证形式。这意味着我们的Flask IoT服务器将仅接受某些API_key =和mac =字符串作为Web API URL的一部分。
进入我们的物联网服务器的数据仅来自基于ESP8266的WiFi气象站的两个特定数据。每个基于ESP8266的WiFi气象站都有几个独特的方面。
如果我们将这4个标识符作为URL的一部分,我们的IoT服务器将提供WiFi气象站所需的功能。
以下是有效的Web API网址的一般形式:
https://mydomain.com/update/API_key=GTW89NF3/mac=6c:rf:7f:2b:0e:g8/field=1/data=72.3
在上面的网址中,我们提供了:
现在,我们需要对Flask IoT服务器进行编程,使其仅接受URL,例如上述URL,并具有一组唯一的API_key,mac地址以及URL的字段和数据部分的限制。
在服务器上,创建一个名为config.py的新文件。 该文件将包含可接受的API_key和mac地址。 将这些类型的私钥保存在单独的文件中并且不受版本控制是一个好习惯。 如果使用git,请确保将config.py添加到.gitignore文件。
#config.py
API_key = GTW89NF3
mac = mac=6c:rf:7f:2b:0e:g8
现在,在服务器上,我们将修改flaskapp.py文件的imports部分,以从config.py中导入API密钥和mac地址字符串。我们可以从单独的.py文件中导入变量以及函数和类。
>
现在,我们将修改flaskapp.py的@ app.route部分:
>
需要在模板目录中创建一个显示错误消息的新模板403.html。
>
我们的Web API接受数据点,但是很高兴看到温度测量的时间戳。通过将时间戳记连接到每个数据点,我们可以显示带有温度和测量时间的网页。
用Python处理时间可能会有些混乱。 这似乎是一个简单的概念,但时间和日期实际上却非常复杂。 哪个时区? 保存秒或分钟? 时间将是哪种格式? 在构建用于记录时间戳的代码之前,我们需要回答这些问题。 我希望时间和日期显示在我们的Flask IoT服务器生成的网站上的方式是:
05:18:48 PM Aug 17, 2018
其中05:18:48是太平洋时区的小时:分钟:秒,AM或PM(12小时格式),日期2018年8月17日采用月日,年格式。
>
showrecent.html模板如下:
详情参阅http://viadean.com/flask_iot_server.html