对应文章:进一步完善前端框架搭建及vue-konva依赖的使用(Vscode)-CSDN博客
目录
2.4.1步骤1:Django 视图中添加获取模拟传感器数据的接口
2.4.3步骤3:前端 Vue3 使用 Axios 获取数据
一、后端开发
功能模块 | 子功能 | 描述 | 技术建议 |
---|---|---|---|
🧪 模拟传感器程序 | 数据模拟 | 模拟温度、湿度、火情等传感器数据 | Python 脚本 / Node.js |
网络发送 | 将数据定时打包并发送至本机某个端口(TCP/UDP) | Socket 编程 | |
配置可调 | 支持调整模拟频率、数值范围等 | JSON 配置或命令行参数 | |
🌐 后端服务 | 端口监听 | 后端监听指定端口,接收来自模拟程序的数据 | Spring Boot / Node.js / django |
数据解析 | 将接收到的字符串(如 JSON)解析为结构化数据 | JSON解析器 | |
数据推送 | 使用 WebSocket 将实时数据推送给前端 | Spring Boot WebSocket / Socket.IO | |
REST 查询接口 | 提供历史数据查询接口(可选) | RESTful API | |
日志与错误处理 | 数据记录、连接失败、格式异常处理 | 日志组件如 Logback |
1.模拟传感器数据
由于硬件还未到位所以手动模拟传感器数据:
-
在原本的工程中创建脚本文件夹:scripts
然后再创建🧪 模拟传感器程序:
# sensor_simulator.py import socket import json import random import time # 模拟数据生成函数 def generate_sensor_data(): return { "temperature": round(random.uniform(20, 40), 2), # 摄氏度 "humidity": round(random.uniform(30, 90), 2), # 百分比 "light": random.randint(100, 1000), # lux "pressure": random.randint(80, 120), # kPa } # 启动 TCP 服务器 def start_sensor_server(host='127.0.0.1', port=9000): server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_socket.bind((host, port)) server_socket.listen(1) print(f"传感器模拟器已启动,监听 {host}:{port}") client_socket, addr = server_socket.accept() print(f"客户端已连接:{addr}") try: while True: data = generate_sensor_data() json_data = json.dumps(data) client_socket.sendall((json_data + '\n').encode('utf-8')) print(f"发送数据: {json_data}") time.sleep(2) # 每2秒发送一次数据 except (ConnectionResetError, BrokenPipeError): print("客户端断开连接") finally: client_socket.close() server_socket.close() if __name__ == '__main__': start_sensor_server()
同时呢,可以写一个模拟前端的测试程序,看模拟传感器数据程序是否正常运行:
# test_client.py import socket with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.connect(('127.0.0.1', 9000)) while True: data = s.recv(1024) print("接收到数据:", data.decode('utf-8'))
然后,我们就在Vscode中创建两个终端分别运行这两个脚本文件:
PS E:\py_project\Security_System\Security_System_workplace\Security_System_project\scripts> python .\sensor_simulator_v2.py PS E:\py_project\Security_System\Security_System_workplace\Security_System_project\scripts> python .\test_client.py
如图所示:
2.前端页面呈现数据+后端互通
2.1更新模拟传感器数据程序(多次请求)
# sensor_simulator.py import socket import json import random import time # 生成模拟传感器数据 def generate_sensor_data(): return { "temperature": round(random.uniform(20, 40), 2), # 摄氏度 "humidity": round(random.uniform(30, 90), 2), # 百分比 "light": random.randint(100, 1000), # lux "pressure": random.randint(80, 120), # kPa "timestamp": time.strftime('%Y-%m-%d %H:%M:%S') } def start_sensor_server(host='127.0.0.1', port=9000): server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_socket.bind((host, port)) server_socket.listen() print(f"传感器模拟器已启动,监听 {host}:{port}") try: while True: # 等待客户端连接 client_socket, addr = server_socket.accept() print(f"新连接:{addr}") # 生成并发送一次数据 data = generate_sensor_data() json_data = json.dumps(data) client_socket.sendall(json_data.encode('utf-8')) client_socket.close() # 关闭当前连接 except KeyboardInterrupt: print("模拟器已停止") finally: server_socket.close() if __name__ == '__main__': start_sensor_server()
2.2🧩 功能目标
通过 Django 后端连接本地 socket 模拟器程序,将接收到的数据通过接口返回给 Vue 前端页面进行展示。
2.3🧱 系统结构简述
Vue3 (前端页面) ⇅ Axios 请求 Django 后端接口 ⇅ socket 通信 传感器模拟器(本地监听端口)
2.4✅ 实现步骤(附代码)
2.4.1步骤1:Django 视图中添加获取模拟传感器数据的接口
def get_sensor_data(request): try: # 创建 socket 客户端连接本地监听端口 with socket.create_connection(("127.0.0.1", 9000), timeout=5) as client: # 接收数据(1024字节) received_data = client.recv(1024).decode('utf-8') parsed_data = json.loads(received_data) # ✅ 转为 dict return JsonResponse({"status": "success", "data": parsed_data}) except Exception as e: return JsonResponse({"status": "error", "message": str(e)})
2.4.2步骤2:配置 Django URL 路由
path('api/sensor-data/', views.get_sensor_data, name='get_sensor_data')
2.4.3步骤3:前端 Vue3 使用 Axios 获取数据
<template> <div class="sensor-view"> <h2>实时传感器数据</h2> <div v-if="error" class="error">{{ error }}</div> <div v-else-if="!sensorData || Object.keys(sensorData).length === 0" class="loading">加载中...</div> <div v-else class="sensor-data"> <p><strong>温度:</strong>{{ sensorData.temperature }} ℃</p> <p><strong>湿度:</strong>{{ sensorData.humidity }} %</p> <p><strong>光照强度:</strong>{{ sensorData.light }}</p> <p><strong>气压:</strong>{{ sensorData.pressure }}</p> <p><strong>时间戳:</strong>{{ sensorData.timestamp }}</p> </div> <button @click="fetchData">刷新</button> </div> </template> <script setup> import { ref, onMounted } from 'vue' import { getSensorData } from '@/api/sensor_data' const sensorData = ref(null) const error = ref(null) const fetchData = async () => { try { const res = await getSensorData() console.log('传感器数据:', res.data) if (res.data.status === 'success') { sensorData.value = res.data.data error.value = null } else { error.value = res.data.message || '数据异常' } } catch (err) { error.value = '请求失败:' + err.message console.error(err) } } onMounted(() => { fetchData() setInterval(fetchData, 2000) }) </script> <style scoped> .sensor-view { max-width: 400px; margin: auto; padding: 20px; font-family: Arial, sans-serif; } .sensor-data p { margin: 6px 0; } .error { color: red; } .loading { color: gray; } button { margin-top: 12px; padding: 6px 12px; } </style>
2.4.4完善2.4.3
想要让2.4.3中的组件在浏览器中能够正常显示,应该再做以下几个操作:
-
Vue 前端通过 Axios 请求 Django 后端 API 接口。比如:
axios.get('http://127.0.0.1:8000/api/sensor-data/')
这样前端才能访问后端接口
-
因为前后端分别运行在不同端口,所以需要进行跨域配置:
前端:
-
首先:需要配置axios
操作步骤:
-
在src目录下创建api文件夹放置有关后端的接口函数:
-
创建axios.js文件:
import axios from 'axios' const instance = axios.create({ baseURL: 'http://127.0.0.1:8000/api', // Django 后端地址 timeout: 5000, }) export default instance
-
就在全局中进行注册axios:main.js文件中
// 全局挂载 axios 到 $axios app.config.globalProperties.$axios = axios
-
为了和后端接口对应上:path('api/sensor-data/', views.get_sensor_data, name='get_sensor_data'),
所以需要创建sensor_data.js文件中的接口函数:
// 获取模拟传感器数据 export const getSensorData = () => { return request.get('sensor-data/') // 实际访问的是 http://127.0.0.1:8000/api/sensor-data/ }
-
接下来写我们的传感器数据组件即可:
<template> <div class="sensor-view"> <h2>实时传感器数据</h2> <div v-if="error" class="error">{{ error }}</div> <div v-else-if="!sensorData || Object.keys(sensorData).length === 0" class="loading">加载中...</div> <div v-else class="sensor-data"> <p><strong>温度:</strong>{{ sensorData.temperature }} ℃</p> <p><strong>湿度:</strong>{{ sensorData.humidity }} %</p> <p><strong>光照强度:</strong>{{ sensorData.light }}</p> <p><strong>气压:</strong>{{ sensorData.pressure }}</p> <p><strong>时间戳:</strong>{{ sensorData.timestamp }}</p> </div> <button @click="fetchData">刷新</button> </div> </template> <script setup> import { ref, onMounted } from 'vue' import { getSensorData } from '@/api/sensor_data' const sensorData = ref(null) const error = ref(null) const fetchData = async () => { try { const res = await getSensorData() console.log('传感器数据:', res.data) if (res.data.status === 'success') { sensorData.value = res.data.data error.value = null } else { error.value = res.data.message || '数据异常' } } catch (err) { error.value = '请求失败:' + err.message console.error(err) } } onMounted(() => { fetchData() setInterval(fetchData, 2000) }) </script> <style scoped> .sensor-view { max-width: 400px; margin: auto; padding: 20px; font-family: Arial, sans-serif; } .sensor-data p { margin: 6px 0; } .error { color: red; } .loading { color: gray; } button { margin-top: 12px; padding: 6px 12px; } </style>
-
运行后我们可以发现并没有正确界面显示
-
所以这就是我接下来要说的:
端口转发问题:
配置 Vite 的开发代理
打开或创建
vite.config.js
文件,然后添加如下配置:// vite.config.js server: { proxy: { '/api': { target: 'http://127.0.0.1:8000', changeOrigin: true, // rewrite: (path) => path.replace(/^\/api/, '') } } }
-
同时我接下来要说的:
我们每次需要跳转一个界面时都需要使用router(路由),所以我们需要再router下的index.js文件里面的内容完善以下:
import SensorViewer from '../components/SensorViewer.vue' { path: '/sensor-view',name: 'SensorView',component: SensorViewer}
-
后端:
-
首先:需要再settings.py文件中的INSTALLED_APPS中添加:
"corsheaders"
然后在MIDDLEWARE 中添加:
"corsheaders.middleware.CorsMiddleware",
注意:上面这行代码必须在:
"django.middleware.common.CommonMiddleware",
之前。
-
接着:
配置允许的前端地址:
CORS_ALLOWED_ORIGINS = [ "http://localhost:5173", # 允许 Vue 的端口 ]
-
获取传感器数据的视图函数中:
parsed_data = json.loads(received_data) # ✅ 转为 dict
将原本的字符串格式转换成为JSON格式。
以JSON格式的数据传递给前端部分,然后前端获取标准数据格式后进行数据解析最终
在页面中呈现数据
-
实现效果图: