如何将本地Arduino采集的温度同步至Azure数据库并完成植物适配检测?
问题描述
我通过串口连接Arduino采集室内温度,同时在Azure上存储了记录植物适宜生长温度范围的数据库。现在需要验证当前室温是否符合数据库中植物的生长温度要求,但不清楚如何将本地采集的温度值同步至Azure并查询数据库中的温度列。目前我构想分为本地与云端两个脚本实现,但尚未掌握云端脚本上传至Azure的方法,以下是我编写的两段代码:
本地采集脚本
import datetime import time import serial arduino = serial.Serial(port='COM3', baudrate=115200, timeout=.1) def update_T(): """ 更新显示时间和温度的标签内容 """ return arduino_read_T(arduino, -1) def arduino_read_T(arduino, unit): """ 从Arduino读取当前温度 :param arduino: 用于读取温度的硬件对象 :param unit: 温度单位偏好(0=摄氏度,1=华氏度,其他值返回空文本) :return: f, c: 当前温度的华氏度和摄氏度数值 txt_currentT: 用于GUI显示的温度文本 """ global fbefore global cbefore x = datetime.datetime.now() arduino.write(bytes("readT", 'utf-8')) time.sleep(0.05) value = arduino.readline() try: value = str(value).lstrip("b'") value = str(value).rstrip("'") f, c = str(value).split(",") except: try: f = fbefore c = cbefore except: f=65.3 c=18.5 fbefore=f cbefore=c if unit == 1: txt_currentT = f"今日 {x.day}/{x.month}/{x.year} {x.hour}:{x.minute}:{x.second} 温度:{f}ºF" elif unit == 0: txt_currentT = f"今日 {x.day}/{x.month}/{x.year} {x.hour}:{x.minute}:{x.second} 温度:{c}ºC" else: txt_currentT = "" return float(f), float(c), txt_currentT def arduino_write_cold(arduino): arduino.write(bytes("cold", 'utf-8')) def arduino_write_hot(arduino): arduino.write(bytes("hot", 'utf-8'))
云端验证脚本
import pyodbc import time server = '...' database = '...' username = '...' password = '...' driver= '{ODBC Driver 17 for SQL Server}' conn = pyodbc.connect('DRIVER='+driver+';SERVER=tcp:'+server+';PORT=1433;DATABASE='+database+';UID='+username+';PWD='+ password) cursor = conn.cursor() def db_check_temperature_cold(farenh): # 注意:原代码存在*SQL注入风险*,建议改用参数化查询 cursor.execute("SELECT * FROM my_plants WHERE minTinF >= ?;", farenh) row = cursor.fetchone() list_of_names = [] while row: list_of_names.append(row) row = cursor.fetchone() return list_of_names def db_check_temperature_hot(farenh): # 注意:原代码存在*SQL注入风险*,建议改用参数化查询 cursor.execute("SELECT * FROM my_plants WHERE maxTinF <= ?;", farenh) row = cursor.fetchone() list_of_names = [] while row: list_of_names.append(row) row = cursor.fetchone() return list_of_names currentTinF =0 currentTinC=0 text_currentT=0 while True: # 原代码中update_T()依赖本地Arduino,云端无法直接调用,需调整为接收本地传来的温度数据 # currentTinF, currentTinC, text_currentT = update_T() # 示例:假设通过HTTP请求或MQTT接收本地温度 # currentTinF = 从本地获取的华氏温度值 too_cold = db_check_temperature_cold(currentTinF) too_hot = db_check_temperature_hot(currentTinF) # 云端无法直接控制本地Arduino,需将结果返回给本地脚本,由本地执行指令 # if (too_cold): arduino_write_cold(arduino) # if (too_hot): arduino_write_hot(arduino) time.sleep(600) # 改为每10分钟执行一次
解决方案
1. 修正本地与云端的交互逻辑
当前两段脚本互相导入对方模块,在分布式场景下无法运行,需调整为:
- 本地脚本:负责采集温度,将温度数据发送到云端服务,同时接收云端返回的验证结果,控制Arduino输出提示(cold/hot)。
- 云端脚本:负责接收本地传来的温度数据,查询Azure数据库进行验证,将结果返回给本地。
常用交互方式:
- HTTP请求:本地用
requests库发送POST请求到云端服务,云端用Flask/FastAPI或Azure Function提供接口。 - MQTT协议:借助Azure IoT Hub作为中间件,本地脚本作为设备发送温度数据,云端服务从Hub接收数据并处理。
2. 云端脚本的Azure部署方法
方法一:Azure Function(推荐,无服务器架构)
- 在Azure Portal创建HTTP触发的Function App(选择Python运行时)。
- 将云端脚本的核心逻辑(数据库查询)改写为Function的请求处理函数,接收本地传来的温度参数,执行查询后返回结果。
- 部署时将依赖的
pyodbc包添加到requirements.txt中,Azure会自动安装。
方法二:Azure Virtual Machine
- 创建一台Azure VM(选择支持Python的镜像,如Ubuntu或Windows Server)。
- 通过SSH/RDP连接VM,安装Python和
pyodbc依赖,上传云端脚本。 - 配置防火墙规则,允许本地脚本与VM的通信端口(如HTTP的80/443)。
方法三:Azure App Service
- 创建Web App(Python运行时),将云端脚本封装为Flask/FastAPI应用。
- 部署应用到App Service,配置环境变量存储数据库连接信息(避免硬编码)。
3. 数据库查询的安全性优化
原代码使用f-string拼接SQL语句,存在SQL注入风险,必须改为参数化查询:
# 错误写法(存在注入风险) cursor.execute(f"SELECT * FROM my_plants WHERE minTinF >= {farenh};") # 正确写法(参数化查询) cursor.execute("SELECT * FROM my_plants WHERE minTinF >= ?;", farenh)
内容的提问来源于stack exchange,提问作者fermarx
相关产品推荐
相关产品推荐

