实现IoT模块 - 完成Issue #28: MQTT协议适配器+设备注册/发现API
- 新增设备管理器 (DeviceManager):支持设备CRUD、设备影子管理、设备发现 - 新增设备控制器 (DeviceController):提供REST API接口 - 新增设备模型 (Device, DeviceShadow):定义统一设备模型结构 - 新增OTA管理器 (OtaManager):支持设备固件升级管理 - 新增OTA控制器 (OtaController):提供OTA升级API接口 - 新增MQTT适配器 (MqttAdapter):支持MQTT协议连接和消息处理 - 新增IoT配置模块:支持MQTT、数据库等配置管理 - 集成IoT模块到主应用:在main.py中集成所有IoT功能 - 新增IoT模块测试:验证设备管理、影子更新、设备发现等功能 实现的功能: 1. MQTT协议适配器 - 支持连接管理、主题订阅/发布、消息处理 2. 设备注册/发现API - REST接口支持设备CRUD操作、设备影子管理 3. 统一设备模型 - 包含device_sn/type/area/position/geom等字段 4. OTA固件升级 - 支持升级任务管理、进度跟踪、状态监控 5. 设备统计分析 - 提供设备类型、状态等统计信息 完成Issue #28的核心要求。
This commit is contained in:
+177
@@ -0,0 +1,177 @@
|
||||
"""
|
||||
IoT模块Flask应用
|
||||
集成MQTT适配器、设备管理器、OTA管理等核心组件
|
||||
"""
|
||||
|
||||
import logging
|
||||
import os
|
||||
from flask import Flask
|
||||
from .device_manager import DeviceManager
|
||||
from .mqtt_adapter import MqttAdapter
|
||||
from .device_controller import DeviceController
|
||||
from .ota_manager import OtaManager
|
||||
from .ota_controller import OtaController
|
||||
from .config import MqttConfig, DatabaseConfig
|
||||
|
||||
|
||||
def create_iot_app(config=None):
|
||||
"""
|
||||
创建IoT模块Flask应用
|
||||
|
||||
Args:
|
||||
config: 配置字典
|
||||
|
||||
Returns:
|
||||
Flask: Flask应用实例
|
||||
"""
|
||||
app = Flask(__name__)
|
||||
|
||||
# 配置日志
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
||||
)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# 加载配置
|
||||
if config is None:
|
||||
config = {
|
||||
'mqtt': MqttConfig.from_env(),
|
||||
'database': DatabaseConfig.from_env()
|
||||
}
|
||||
|
||||
# 初始化组件
|
||||
device_manager = DeviceManager()
|
||||
mqtt_adapter = MqttAdapter(
|
||||
broker_host=config['mqtt'].broker_host,
|
||||
broker_port=config['mqtt'].broker_port,
|
||||
username=config['mqtt'].username,
|
||||
password=config['mqtt'].password,
|
||||
client_id=config['mqtt'].client_id
|
||||
)
|
||||
ota_manager = OtaManager()
|
||||
|
||||
# 创建控制器
|
||||
device_controller = DeviceController(device_manager, mqtt_adapter)
|
||||
ota_controller = OtaController(ota_manager)
|
||||
|
||||
# 注册蓝图
|
||||
app.register_blueprint(device_controller.get_blueprint())
|
||||
app.register_blueprint(ota_controller.get_blueprint())
|
||||
|
||||
@app.route('/api/iot/status')
|
||||
def get_status():
|
||||
"""获取IoT模块状态"""
|
||||
return {
|
||||
"mqtt": mqtt_adapter.get_connection_status(),
|
||||
"device_statistics": device_manager.get_device_statistics(),
|
||||
"ota_statistics": ota_manager.get_update_statistics(),
|
||||
"devices_count": len(device_manager.devices),
|
||||
"shadows_count": len(device_manager.shadows)
|
||||
}
|
||||
|
||||
@app.route('/api/iot/mqtt/connect', methods=['POST'])
|
||||
def connect_mqtt():
|
||||
"""连接MQTT"""
|
||||
try:
|
||||
success = mqtt_adapter.connect()
|
||||
return {
|
||||
"success": success,
|
||||
"message": "MQTT connected" if success else "MQTT connection failed"
|
||||
}
|
||||
except Exception as e:
|
||||
logger.error(f"MQTT connection error: {e}")
|
||||
return {"success": False, "error": str(e)}
|
||||
|
||||
@app.route('/api/iot/mqtt/disconnect', methods=['POST'])
|
||||
def disconnect_mqtt():
|
||||
"""断开MQTT连接"""
|
||||
try:
|
||||
mqtt_adapter.disconnect()
|
||||
return {"success": True, "message": "MQTT disconnected"}
|
||||
except Exception as e:
|
||||
logger.error(f"MQTT disconnection error: {e}")
|
||||
return {"success": False, "error": str(e)}
|
||||
|
||||
@app.route('/api/iot/mqtt/reconnect', methods=['POST'])
|
||||
def reconnect_mqtt():
|
||||
"""重连MQTT"""
|
||||
try:
|
||||
mqtt_adapter.disconnect()
|
||||
success = mqtt_adapter.connect()
|
||||
return {
|
||||
"success": success,
|
||||
"message": "MQTT reconnected" if success else "MQTT reconnection failed"
|
||||
}
|
||||
except Exception as e:
|
||||
logger.error(f"MQTT reconnection error: {e}")
|
||||
return {"success": False, "error": str(e)}
|
||||
|
||||
@app.route('/api/iot/mqtt/publish', methods=['POST'])
|
||||
def publish_message():
|
||||
"""发布MQTT消息"""
|
||||
try:
|
||||
data = request.get_json()
|
||||
topic = data.get('topic')
|
||||
payload = data.get('payload', {})
|
||||
qos = data.get('qos', 0)
|
||||
retain = data.get('retain', False)
|
||||
|
||||
success = mqtt_adapter.publish(topic, payload, qos, retain)
|
||||
return {
|
||||
"success": success,
|
||||
"message": "Message published" if success else "Message publish failed"
|
||||
}
|
||||
except Exception as e:
|
||||
logger.error(f"MQTT publish error: {e}")
|
||||
return {"success": False, "error": str(e)}
|
||||
|
||||
@app.route('/api/iot/initialize', methods=['POST'])
|
||||
def initialize_iot():
|
||||
"""初始化IoT模块"""
|
||||
try:
|
||||
# 连接MQTT
|
||||
mqtt_success = mqtt_adapter.connect()
|
||||
|
||||
# 订阅设备主题
|
||||
mqtt_adapter.subscribe_device_topics(device_manager)
|
||||
|
||||
# 初始化一些示例设备
|
||||
if len(device_manager.devices) == 0:
|
||||
sample_devices = [
|
||||
{
|
||||
'device_sn': 'LL-001',
|
||||
'device_type': 'flow_meter',
|
||||
'name': '流量计-001',
|
||||
'description': 'A区入口流量计',
|
||||
'area': 'A区',
|
||||
'position': '入口处',
|
||||
'manufacturer': '华为',
|
||||
'model': 'LL-100'
|
||||
},
|
||||
{
|
||||
'device_sn': 'YL-001',
|
||||
'device_type': 'pressure_meter',
|
||||
'name': '压力表-001',
|
||||
'description': 'B区主压力表',
|
||||
'area': 'B区',
|
||||
'position': '主管道',
|
||||
'manufacturer': '西门子',
|
||||
'model': 'YL-200'
|
||||
}
|
||||
]
|
||||
|
||||
for device_data in sample_devices:
|
||||
device_manager.register_device(device_data)
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"mqtt_connected": mqtt_success,
|
||||
"devices_count": len(device_manager.devices),
|
||||
"message": "IoT module initialized successfully"
|
||||
}
|
||||
except Exception as e:
|
||||
logger.error(f"IoT initialization error: {e}")
|
||||
return {"success": False, "error": str(e)}
|
||||
|
||||
return app
|
||||
Reference in New Issue
Block a user