目录
项目概述
系统设计
硬件设计
软件设计
系统架构图
代码实现
1. 开发环境
2. STM32 微控制器代码示例
3. ROS 节点代码示例
4. 后端服务器代码示例(Flask)
数据库部分
3.4 删除药物记录
随着老龄化社会的加剧,患者按时服药的重要性日益凸显。智能药盒通过使用STM32微控制器和多种传感器,能够实时监测药盒状态,提醒患者按时服药。此外,通过MQTT与ROS系统的通信,智能药盒可以记录患者的用药情况,并将数据发送给医生,实现远程监控。本文将详细介绍该项目的系统设计、代码实现和总结。
STM32微控制器
STM32系列微控制器是本项目的核心,负责处理传感器数据和控制逻辑。
传感器
通信接口
Wi-Fi模块
采用ESP8266或ESP32模块,负责将数据上传至云端。
MQTT协议
ROS系统
后端服务器
前端与移动应用

在开始编码之前,确保您已经设置好以下开发环境:
在 Python 环境中,安装所需的库:
pip install flask flask-sqlalchemy paho-mqtt 下面是 STM32 微控制器代码的详细实现,包括传感器的初始化、数据读取和 MQTT 消息发布功能。
#include "stm32f4xx_hal.h" #include "mqtt.h" #include "sensor.h" // 定义 MQTT 相关参数 #define MQTT_BROKER "tcp://broker.hivemq.com:1883" #define CLIENT_ID "DrugBoxClient" #define TOPIC "drugbox/status" // 函数声明 void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_USART2_UART_Init(void); void MQTT_Publish(const char *topic, const char *message); void Sensor_Init(void); int Sensor_Read(void); int main(void) { HAL_Init(); // 初始化 HAL 库 SystemClock_Config(); // 配置系统时钟 MX_GPIO_Init(); // 初始化 GPIO MX_USART2_UART_Init(); // 初始化 UART MQTT_Init(); // 初始化 MQTT 客户端 Sensor_Init(); // 初始化传感器 while (1) { if (Sensor_Read() == 1) { // 检测到药盒打开 MQTT_Publish(TOPIC, "药盒已打开"); // 发送消息 HAL_Delay(1000); // 避免重复发送 } HAL_Delay(500); // 主循环延时 } } // MQTT 发布函数 void MQTT_Publish(const char *topic, const char *message) { MQTTClient client; MQTTClient_create(&client, MQTT_BROKER, CLIENT_ID); MQTTClient_connect(client); MQTTClient_publish(client, topic, message, strlen(message), QOS, 0); MQTTClient_disconnect(client); } // 传感器初始化 void Sensor_Init(void) { // 配置 GPIO 引脚,用于传感器输入 __HAL_RCC_GPIOC_CLK_ENABLE(); GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = GPIO_PIN_0; // 假设传感器连接在 PC0 GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); } // 读取传感器状态 int Sensor_Read(void) { return HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_0); // 返回传感器状态 } 以下是完整的 ROS 节点的实现代码,包括 MQTT 客户端的配置和消息处理。
import rospy from std_msgs.msg import String import paho.mqtt.client as mqtt # 定义 MQTT Broker 地址和主题 MQTT_BROKER = "broker.hivemq.com" MQTT_TOPIC = "drugbox/status" # 处理收到的 MQTT 消息 def on_message(client, userdata, message): msg = message.payload.decode("utf-8") rospy.loginfo(f"Received message: {msg}") # 将消息发布到 ROS 主题 pub.publish(msg) # 初始化 ROS 节点和发布者 rospy.init_node('drugbox_listener', anonymous=True) pub = rospy.Publisher('drugbox/status', String, queue_size=10) # 设置 MQTT 客户端 client = mqtt.Client() client.on_message = on_message client.connect(MQTT_BROKER) # 连接到 MQTT Broker client.subscribe(MQTT_TOPIC) # 订阅主题 # 启动 MQTT 循环 client.loop_start() # ROS 主循环 try: rospy.spin() # 保持节点运行 except KeyboardInterrupt: pass finally: client.loop_stop() # 停止 MQTT 循环 client.disconnect() # 断开 MQTT 连接 drugbox/status 用于接收药盒状态消息。rospy.init_node 初始化 ROS 节点,并创建一个发布者 pub,用于将消息发布到 drugbox/status 主题。client.loop_start() 启动 MQTT 循环,保持客户端运行并接收消息。rospy.spin() 保持节点运行,直到用户中断。最后,确保在退出时停止 MQTT 循环并断开连接。接下来是后端服务器代码示例,使用 Flask 框架实现一个简单的 API 来存储和检索患者的服药数据。
from flask import Flask, request, jsonify from flask_sqlalchemy import SQLAlchemy app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///medications.db' db = SQLAlchemy(app) # 定义数据库模型 class Medication(db.Model): id = db.Column(db.Integer, primary_key=True) patient_id = db.Column(db.String(80), nullable=False) medication_name = db.Column(db.String(120), nullable=False) timestamp = db.Column(db.DateTime, nullable=False) # 初始化数据库 @app.before_first_request def create_tables(): db.create_all() # 添加药物记录的 API @app.route('/medication', methods=['POST']) def add_medication(): data = request.get_json() new_medication = Medication( patient_id=data['patient_id'], medication_name=data['medication_name'], timestamp=datetime.utcnow() ) db.session.add(new_medication) db.session.commit() return jsonify({"message": "Medication added successfully."}), 201 # 获取药物记录的 API @app.route('/medications/', methods=['GET']) def get_medications(patient_id): medications = Medication.query.filter_by(patient_id=patient_id).all() return jsonify([{ "id": med.id, "patient_id": med.patient_id, "medication_name": med.medication_name, "timestamp": med.timestamp.strftime("%Y-%m-%d %H:%M:%S") } for med in medications]) if __name__ == '__main__': app.run(debug=True) id:药物记录的唯一标识符,主键,自动递增。patient_id:与患者相关的唯一标识符,表示该记录属于哪个患者。medication_name:记录的药物名称,表示患者服用的药物。timestamp:记录被添加的时间戳,使用 UTC 时间,以便追踪服药时间。初始化数据库:
@app.before_first_request 装饰器在应用的第一次请求之前创建数据库表(如果尚不存在)。添加药物记录的 API:
/medication,方法:POST。{ "patient_id": "12345", "medication_name": "Aspirin" } Medication 实例,将其添加到数据库中,并返回成功消息。@app.route('/medication', methods=['POST']) def add_medication(): data = request.get_json() new_medication = Medication( patient_id=data['patient_id'], medication_name=data['medication_name'], timestamp=datetime.utcnow() ) db.session.add(new_medication) db.session.commit() return jsonify({"message": "Medication added successfully."}), 201 获取药物记录的 API:
/medications/,方法:GET。@app.route('/medications/', methods=['GET']) def get_medications(patient_id): medications = Medication.query.filter_by(patient_id=patient_id).all() return jsonify([{ "id": med.id, "patient_id": med.patient_id, "medication_name": med.medication_name, "timestamp": med.timestamp.strftime("%Y-%m-%d %H:%M:%S") } for med in medications]) 启动 Flask 应用:
app.run(debug=True) 启动 Flask 应用,开启调试模式,方便开发时查看错误信息。在本项目中,我们使用 SQLite 数据库来存储患者的服药记录。SQLite 是一个轻量级的数据库,适合于小型应用和开发阶段的原型设计。通过 Flask-SQLAlchemy 来处理数据库的操作。
数据库主要包含一个表,用于存储药物记录。我们将定义一个名为 medications 的表,表结构如下:
| 列名 | 数据类型 | 描述 |
|---|---|---|
| id | INTEGER | 主键,自增 |
| patient_id | VARCHAR(80) | 患者的唯一标识符 |
| medication_name | VARCHAR(120) | 药物名称 |
| timestamp | DATETIME | 记录的时间戳 |
通过这个表,我们可以记录每个患者的服药情况,包括他们服用的药物和时间。
以下是后端 Flask 应用中数据库操作的具体实现,包括模型定义和 CRUD 操作。
在 Flask 应用中,我们使用 SQLAlchemy 定义数据库模型。以下是 Medication 模型的定义,它对应于 medications 表。
from flask_sqlalchemy import SQLAlchemy from datetime import datetime db = SQLAlchemy() class Medication(db.Model): __tablename__ = 'medications' # 指定表名 id = db.Column(db.Integer, primary_key=True) # 主键 patient_id = db.Column(db.String(80), nullable=False) # 患者 ID medication_name = db.Column(db.String(120), nullable=False) # 药物名称 timestamp = db.Column(db.DateTime, nullable=False, default=datetime.utcnow) # 时间戳 def __repr__(self): return f"" 在后端的 API 中,使用 POST 请求来添加新的药物记录。以下是完整的 API 实现:
from flask import Flask, request, jsonify from flask_sqlalchemy import SQLAlchemy from datetime import datetime app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///medications.db' db = SQLAlchemy(app) class Medication(db.Model): __tablename__ = 'medications' id = db.Column(db.Integer, primary_key=True) patient_id = db.Column(db.String(80), nullable=False) medication_name = db.Column(db.String(120), nullable=False) timestamp = db.Column(db.DateTime, nullable=False, default=datetime.utcnow) # 初始化数据库 @app.before_first_request def create_tables(): db.create_all() # 添加药物记录的 API @app.route('/medication', methods=['POST']) def add_medication(): data = request.get_json() new_medication = Medication( patient_id=data['patient_id'], medication_name=data['medication_name'] ) db.session.add(new_medication) db.session.commit() return jsonify({"message": "Medication added successfully."}), 201 使用 GET 请求可以根据患者 ID 查询所有药物记录。以下是实现代码:
# 获取药物记录的 API @app.route('/medications/', methods=['GET']) def get_medications(patient_id): medications = Medication.query.filter_by(patient_id=patient_id).all() return jsonify([{ "id": med.id, "patient_id": med.patient_id, "medication_name": med.medication_name, "timestamp": med.timestamp.strftime("%Y-%m-%d %H:%M:%S") } for med in medications]) 如果需要更新某条药物记录,可以实现一个 PUT 请求的 API。例如,更新药物名称:
# 更新药物记录的 API @app.route('/medication/', methods=['PUT']) def update_medication(id): data = request.get_json() medication = Medication.query.get(id) if medication: medication.medication_name = data['medication_name'] db.session.commit() return jsonify({"message": "Medication updated successfully."}), 200 else: return jsonify({"message": "Medication not found."}), 404 我们可以通过 DELETE 请求来实现删除药物记录的功能。用户可以根据药物记录的 ID 来删除特定的记录。
以下是删除药物记录 API 的完整实现:
# 删除药物记录的 API @app.route('/medication/', methods=['DELETE']) def delete_medication(id): medication = Medication.query.get(id) # 根据 ID 查询药物记录 if medication: db.session.delete(medication) # 删除记录 db.session.commit() # 提交更改 return jsonify({"message": "Medication deleted successfully."}), 200 else: return jsonify({"message": "Medication not found."}), 404 @app.route('/medication/', methods=['DELETE']) 来定义路由, 是 URL 中的参数,表示药物记录的 ID。Medication.query.get(id) 根据传入的 ID 查询药物记录。db.session.delete(medication) 删除该记录,并通过 db.session.commit() 提交更改。以下是包含所有 CRUD 操作的完整 Flask 后端代码示例,包括添加、获取、更新和删除药物记录的 API。
from flask import Flask, request, jsonify from flask_sqlalchemy import SQLAlchemy from datetime import datetime app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///medications.db' db = SQLAlchemy(app) # 定义数据库模型 class Medication(db.Model): __tablename__ = 'medications' id = db.Column(db.Integer, primary_key=True) patient_id = db.Column(db.String(80), nullable=False) medication_name = db.Column(db.String(120), nullable=False) timestamp = db.Column(db.DateTime, nullable=False, default=datetime.utcnow) # 初始化数据库 @app.before_first_request def create_tables(): db.create_all() # 添加药物记录的 API @app.route('/medication', methods=['POST']) def add_medication(): data = request.get_json() new_medication = Medication( patient_id=data['patient_id'], medication_name=data['medication_name'] ) db.session.add(new_medication) db.session.commit() return jsonify({"message": "Medication added successfully."}), 201 # 获取药物记录的 API @app.route('/medications/', methods=['GET']) def get_medications(patient_id): medications = Medication.query.filter_by(patient_id=patient_id).all() return jsonify([{ "id": med.id, "patient_id": med.patient_id, "medication_name": med.medication_name, "timestamp": med.timestamp.strftime("%Y-%m-%d %H:%M:%S") } for med in medications]) # 更新药物记录的 API @app.route('/medication/', methods=['PUT']) def update_medication(id): data = request.get_json() medication = Medication.query.get(id) if medication: medication.medication_name = data['medication_name'] db.session.commit() return jsonify({"message": "Medication updated successfully."}), 200 else: return jsonify({"message": "Medication not found."}), 404 # 删除药物记录的 API @app.route('/medication/', methods=['DELETE']) def delete_medication(id): medication = Medication.query.get(id) if medication: db.session.delete(medication) db.session.commit() return jsonify({"message": "Medication deleted successfully."}), 200 else: return jsonify({"message": "Medication not found."}), 404 if __name__ == '__main__': app.run(debug=True) 本项目致力于开发一个智能药盒系统,旨在通过先进的嵌入式技术和物联网(IoT)解决方案,提高患者的用药依从性,确保患者能够按时服药。该系统结合了 STM32 微控制器、传感器、MQTT 协议和 ROS 系统,形成了一个高效的药物监测与提醒机制。
实时药物监测:
数据传输与处理:
远程监控:
数据库管理: