---
tags: Python系統設計
---
# Python,Django,DHT22,Raspberry Pi 4,树莓派搭派DHT22架设温湿度侦测,Django架站接收资料,Python编程,与AP设定,HTML5前端图形显示分享
## AP设定:
PS:示范AP型号RT-AC58U
1.你需要有个固定IP。
2.ASUS AP 提供固定域名功能:

3.外部网路(WAN)-虚拟伺服器IP PORT 转发设定:

## Raspberry Pi 4 DHT22 安装与设定

1.更新系统
```
sudo apt update
sudo apt full-upgrade
```
2.安装 Python 3(如果未安装)
```
sudo apt install python3
```
3.安装 pip(Python 包管理工具)
```
sudo apt install python3-pip
```
4.安装常用的 Python 库
```
pip3 install numpy
pip3 install pandas
pip3 install matplotlib
```
5-1.安装 Adafruit_DHT 库
Adafruit 提供了一个用于读取 DHT22 传感器的库。你可以通过以下命令安装该库:
```
sudo pip3 install Adafruit_DHT
```
5-2.(我使用的是)安装 Adafruit Blinka
Adafruit Blinka 是让 CircuitPython 库能够在 Raspberry Pi 上运行的库。首先,你需要安装这个库:
```
sudo pip3 install --upgrade adafruit-blinka
```
5-2-1.启用 I2C 和 SPI(如果需要)
有些项目可能需要启用 I2C 或 SPI,可以通过 Raspberry Pi 配置工具来启用:
```
sudo raspi-config
```
选择以下选项:
Interface Options
启用 I2C 和 SPI(如果项目使用这些接口)
5-2-2.安装 Adafruit CircuitPython DHT 库
接下来,安装处理 DHT22 传感器的库 adafruit_dht:
```
sudo pip3 install adafruit-circuitpython-dht
```
5-2-3.安装 libgpiod
adafruit_dht 库依赖 libgpiod 来控制 GPIO,因此你还需要安装 libgpiod:
```
sudo apt install libgpiod2
```
5-2-4.Python代码
1.在根目录建立一个Python资料夹
2.将左右Python指令都放入此资料夹
3.DHT22所运行的Python程式码:
```
import board
import adafruit_dht
import requests
import time
from datetime import datetime
# 设置 DHT22 传感器
dht_device = adafruit_dht.DHT22(board.D4) # GPIO 4 引脚
# 获取温度和湿度数据的函数
def get_sensor_data():
try:
# 尝试读取温度和湿度数据
temperature_c = dht_device.temperature
humidity = dht_device.humidity
if temperature_c is None or humidity is None:
raise ValueError("Temperature or humidity data is None")
print(f"Temp: {temperature_c:.1f} C Humidity: {humidity:.1f}%")
return temperature_c, humidity
except Exception as e:
# 如果读取数据失败,打印错误并返回 None
print(f"Failed to retrieve data from sensor: {e}")
return None, None
# 设置服务器 URL(确保这是你的 Django 服务器的 URL)
server_url = 'http://genesisofdestiny.asuscomm.com/upload/'
while True:
# 获取温度和湿度数据
temperature, humidity = get_sensor_data()
# 如果数据有效,发送到服务器
if temperature is not None and humidity is not None:
timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
payload = {
'timestamp': timestamp,
'temperature': temperature,
'humidity': humidity
}
# 发送数据到服务器
try:
response = requests.post(server_url, json=payload)
#print(response.text) # 打印服务器响应
except requests.RequestException as e:
print(f"Request failed: {e}")
else:
print("Skipping data transmission due to invalid sensor data.")
# 每秒获取一次数据
time.sleep(1)
```
4.存成DHT22.py檔
## Raspberry Pi 4 与 DHT22 硬体连接


1.将DHT22 VCC脚连接至Raspberry Pi 4的3.3V GPIO 接脚
2.将DHT22 GND脚连接至Raspberry Pi 4 的GND GPIO 接脚
3.将DHT22 out脚连接至Raspberry Pi 4的GPIO 4 接脚
## Python Django安装、设定、程式码
1.[安装Python](https://www.python.org/downloads/)
2-1.安装 virtualenv(可选但推荐)
```
pip install virtualenv
```
2-2.创建和激活虚拟环境
在C:\中
```
CD C:\
```
在你希望存放 Django 项目的目录下,创建一个新的虚拟环境:
```
virtualenv Django
```
Windows: 激活虚拟环境:
```
CD C:\Django
Scripts\activate
```
2-3.安装 Django 和其他依赖
在激活的虚拟环境中,安装 Django 和 Django REST framework:
```
pip install django djangorestframework
```
2-4.创建 Django 项目
使用 Django 的 django-admin 工具创建一个新的项目:
```
django-admin startproject DHT22
```
这将创建一个名为 DHT22 的目录,其中包含 Django 项目的基本结构。
2-5.启动开发服务器
进入项目目录:
```
cd DHT22
```
2-6.创建 Django 应用
在 Django 项目中,你可以创建多个应用(app)来实现不同的功能。创建一个新应用:
```
python manage.py startapp myapp
```
这将创建一个名为 myapp 的目录,其中包含了应用的基本结构。
2-7.配置 Django 项目
在项目的 Django\DHT22\DHT22\settings.py 文件中,你可以进行各种配置,如数据库设置、安装的应用、静态文件配置等。你还需要在 INSTALLED_APPS 列表中添加你的应用:
```
INSTALLED_APPS = [
...
'myapp',
...
]
```
2-8.在手动建立资料夹data,static,templates

1.在C:\Django\DHT22\中手动建立三个资料夹:data,static,templates
2-9.测试启动DHT22伺服器
1.C:\Django\DHT22\DHT22\settings.py
```
ALLOWED_HOSTS = ['*']
```
2.
```
CD C:\Django
Scripts\activate
CD DHT22
python manage.py runserver 0.0.0.0:80
```
3.开启浏览器测试是否能连上网页
```
127.0.0.1
```
2-10.Python安装所需库
1.
```
CD C:\Django
Scripts\activate
CD DHT22
pip install matplotlib # 用来绘图
pip install pandas # 用来处理数据
```
2.URL 设置
编辑 C:\Django\DHT22\DHT22\urls.py,配置主页和次页的 URL:
```
"""
URL configuration for DHT22 project.
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/5.1/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
# from django.urls import path
# urlpatterns = [
# path('admin/', admin.site.urls),
# ]
from django.urls import path
from myapp import views
urlpatterns = [
path('', views.home, name='home'),
path('upload/', views.upload_data, name='upload_data'),
]
```
2-11.接下来在 C:\Django\DHT22\myapp/views.py 中编写两个视图函数,一个用于显示主页的曲线图,另一个用于接收并保存数据。
```
from django.shortcuts import render
# Create your views here.
import os
import pandas as pd
import matplotlib.pyplot as plt
# from django.shortcuts import render
from datetime import datetime
def home(request):
# 获取今天的日期字符串
today_str = datetime.now().strftime("%Y%m%d")
filename = f"DHT22_{today_str}.txt"
filepath = os.path.join("data", filename)
if not os.path.exists(filepath):
return render(request, 'home.html', {'error': 'No data available'})
# 读取数据
data = pd.read_csv(filepath, sep='\t', header=None, names=['Time', 'Temperature', 'Humidity'])
# 将数据传递给模板
return render(request, 'home.html', {'data': data.to_dict(orient='list')})
#################################################################
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
import json
# from datetime import datetime
# import os
@csrf_exempt
def upload_data(request):
if request.method == 'POST':
try:
data = json.loads(request.body) # 解析 JSON 数据
timestamp = data.get('timestamp')
temperature = data.get('temperature')
humidity = data.get('humidity')
if not all([timestamp, temperature, humidity]):
return JsonResponse({"error": "Missing data"}, status=400)
today_str = datetime.now().strftime("%Y%m%d")
filename = f"DHT22_{today_str}.txt"
filepath = os.path.join("data", filename)
if not os.path.exists('data'):
os.makedirs('data')
with open(filepath, 'a') as f:
f.write(f"{timestamp}\t{temperature}\t{humidity}\n")
return JsonResponse({"message": "Data saved successfully"})
except Exception as e:
return JsonResponse({"error": f"Error processing request: {e}"}, status=500)
else:
return JsonResponse({"error": "Invalid request method"}, status=405)
```
2-12.创建模板
1.创建一个home.html在下面路径:
C:\Django\DHT22\templates\home.html
```
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Home</title>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
</head>
<body>
<h1>Data Charts</h1>
{% if error %}
<p>{{ error }}</p>
{% else %}
<canvas id="temperatureChart"></canvas>
<canvas id="humidityChart"></canvas>
<script>
const temperatureCtx = document.getElementById('temperatureChart').getContext('2d');
const humidityCtx = document.getElementById('humidityChart').getContext('2d');
const data = {{ data|safe }};
new Chart(temperatureCtx, {
type: 'line',
data: {
labels: data['Time'],
datasets: [{
label: 'Temperature',
data: data['Temperature'],
borderColor: 'rgba(255, 99, 132, 0.2)',
borderWidth: 1
}]
}
});
new Chart(humidityCtx, {
type: 'line',
data: {
labels: data['Time'],
datasets: [{
label: 'Humidity',
data: data['Humidity'],
borderColor: 'rgba(54, 162, 235, 0.2)',
borderWidth: 1
}]
}
});
</script>
{% endif %}
</body>
</html>
```
2-13.静态文件设置
确保 Django 能够找到生成的图表图片。添加如下配置到 settings.py 中:
C:\Django\DHT22\DHT22\settings.py
```
STATIC_URL = '/static/'
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]
```
2-14.告诉 Django 模板的路径
在 settings.py 中,你需要告诉 Django 在哪里寻找模板文件。编辑 settings.py 并修改 TEMPLATES 设置:
C:\Django\DHT22\DHT22\settings.py
```
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')], # 告诉 Django 去哪里查找模板
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
```
## 相关Python与HTML程式码
1.Raspberry Pi 4 DTH22.py
Python\DTH22.py
```
import board
import adafruit_dht
import requests
import time
from datetime import datetime
# 设置 DHT22 传感器
dht_device = adafruit_dht.DHT22(board.D4) # GPIO 4 引脚
# 获取温度和湿度数据的函数
def get_sensor_data():
try:
# 尝试读取温度和湿度数据
temperature_c = dht_device.temperature
humidity = dht_device.humidity
if temperature_c is None or humidity is None:
raise ValueError("Temperature or humidity data is None")
print(f"Temp: {temperature_c:.1f} C Humidity: {humidity:.1f}%")
return temperature_c, humidity
except Exception as e:
# 如果读取数据失败,打印错误并返回 None
print(f"Failed to retrieve data from sensor: {e}")
return None, None
# 设置服务器 URL(确保这是你的 Django 服务器的 URL)
server_url = 'http://genesisofdestiny.asuscomm.com/upload/'
while True:
# 获取温度和湿度数据
temperature, humidity = get_sensor_data()
# 如果数据有效,发送到服务器
if temperature is not None and humidity is not None:
timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
payload = {
'timestamp': timestamp,
'temperature': temperature,
'humidity': humidity
}
# 发送数据到服务器
try:
response = requests.post(server_url, json=payload)
print(response.text) # 打印服务器响应
except requests.RequestException as e:
print(f"Request failed: {e}")
else:
print("Skipping data transmission due to invalid sensor data.")
# 每秒获取一次数据
time.sleep(1)
```
2-1.Django settings.py
C:\Django\DHT22\DHT22\settings.py
```
"""
Django settings for DHT22 project.
Generated by 'django-admin startproject' using Django 5.1.1.
For more information on this file, see
https://docs.djangoproject.com/en/5.1/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/5.1/ref/settings/
"""
from pathlib import Path
import os
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
# BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/5.1/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-2tz%upjb8kc81i)=9ix!ce&i$l1%b609ba5w6*-339xve#z&v5'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = ['*']
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'myapp',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'DHT22.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'DHT22.wsgi.application'
# Database
# https://docs.djangoproject.com/en/5.1/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
# 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
'NAME': BASE_DIR / 'db.sqlite3',
}
}
# Password validation
# https://docs.djangoproject.com/en/5.1/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/5.1/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/5.1/howto/static-files/
STATIC_URL = 'static/'
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]
# Default primary key field type
# https://docs.djangoproject.com/en/5.1/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
```
2-2.Django urls.py
C:\Django\DHT22\DHT22\urls.py
```
"""
URL configuration for DHT22 project.
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/5.1/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
# from django.urls import path
# urlpatterns = [
# path('admin/', admin.site.urls),
# ]
from django.urls import path
from myapp import views
urlpatterns = [
path('', views.home, name='home'),
path('upload/', views.upload_data, name='upload_data'),
]
```
2-3.Django views.py
C:\Django\DHT22\myapp\views.py
```
from django.shortcuts import render
# Create your views here.
import os
import pandas as pd
import matplotlib.pyplot as plt
# from django.shortcuts import render
from datetime import datetime
def home(request):
# 获取今天的日期字符串
today_str = datetime.now().strftime("%Y%m%d")
filename = f"DHT22_{today_str}.txt"
filepath = os.path.join("data", filename)
if not os.path.exists(filepath):
return render(request, 'home.html', {'error': 'No data available'})
# 读取数据
data = pd.read_csv(filepath, sep='\t', header=None, names=['Time', 'Temperature', 'Humidity'])
# 将数据传递给模板
return render(request, 'home.html', {'data': data.to_dict(orient='list')})
#################################################################
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
import json
# from datetime import datetime
# import os
@csrf_exempt
def upload_data(request):
if request.method == 'POST':
try:
data = json.loads(request.body) # 解析 JSON 数据
timestamp = data.get('timestamp')
temperature = data.get('temperature')
humidity = data.get('humidity')
if not all([timestamp, temperature, humidity]):
return JsonResponse({"error": "Missing data"}, status=400)
today_str = datetime.now().strftime("%Y%m%d")
filename = f"DHT22_{today_str}.txt"
filepath = os.path.join("data", filename)
if not os.path.exists('data'):
os.makedirs('data')
with open(filepath, 'a') as f:
f.write(f"{timestamp}\t{temperature}\t{humidity}\n")
return JsonResponse({"message": "Data saved successfully"})
except Exception as e:
return JsonResponse({"error": f"Error processing request: {e}"}, status=500)
else:
return JsonResponse({"error": "Invalid request method"}, status=405)
```
3.Django home.html
C:\Django\DHT22\templates\home.html
```
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Home</title>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
</head>
<body>
<h1>Data Charts</h1>
{% if error %}
<p>{{ error }}</p>
{% else %}
<canvas id="temperatureChart"></canvas>
<canvas id="humidityChart"></canvas>
<script>
const temperatureCtx = document.getElementById('temperatureChart').getContext('2d');
const humidityCtx = document.getElementById('humidityChart').getContext('2d');
const data = {{ data|safe }};
new Chart(temperatureCtx, {
type: 'line',
data: {
labels: data['Time'],
datasets: [{
label: 'Temperature',
data: data['Temperature'],
borderColor: 'rgba(255, 99, 132, 0.2)',
borderWidth: 1
}]
}
});
new Chart(humidityCtx, {
type: 'line',
data: {
labels: data['Time'],
datasets: [{
label: 'Humidity',
data: data['Humidity'],
borderColor: 'rgba(54, 162, 235, 0.2)',
borderWidth: 1
}]
}
});
</script>
{% endif %}
</body>
</html>
```