创建项目及AI生成基本代码
This commit is contained in:
2
internal/protocol/__init__.py
Normal file
2
internal/protocol/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
# 协议处理模块
|
||||
# 处理与各种通信协议相关的功能
|
||||
57
internal/protocol/base.py
Normal file
57
internal/protocol/base.py
Normal file
@@ -0,0 +1,57 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
协议处理基类模块
|
||||
"""
|
||||
|
||||
import logging
|
||||
from abc import ABC, abstractmethod
|
||||
|
||||
# 配置日志
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ProtocolHandler(ABC):
|
||||
"""协议处理基类"""
|
||||
|
||||
def __init__(self, config):
|
||||
"""
|
||||
初始化协议处理器
|
||||
|
||||
Args:
|
||||
config: 配置对象
|
||||
"""
|
||||
self.config = config
|
||||
self.device_manager = None
|
||||
logger.info(f"初始化 {self.__class__.__name__}")
|
||||
|
||||
@abstractmethod
|
||||
def initialize(self):
|
||||
"""初始化协议处理器"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def send_command(self, command, data):
|
||||
"""
|
||||
发送命令到设备
|
||||
|
||||
Args:
|
||||
command (str): 命令类型
|
||||
data (dict): 命令数据
|
||||
|
||||
Returns:
|
||||
dict: 命令执行结果
|
||||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def receive_response(self):
|
||||
"""
|
||||
接收设备响应
|
||||
|
||||
Returns:
|
||||
dict: 设备响应数据
|
||||
"""
|
||||
pass
|
||||
2
internal/protocol/coap/__init__.py
Normal file
2
internal/protocol/coap/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
# CoAP协议处理模块
|
||||
# 处理受限应用协议,轻量级的RESTful协议,适用于资源受限设备
|
||||
6
internal/protocol/lora/__init__.py
Normal file
6
internal/protocol/lora/__init__.py
Normal file
@@ -0,0 +1,6 @@
|
||||
# LoRa协议处理模块
|
||||
# 处理LoRa物理层通信相关功能
|
||||
|
||||
from .handler import LoRaHandler
|
||||
|
||||
__all__ = ['LoRaHandler']
|
||||
192
internal/protocol/lora/handler.py
Normal file
192
internal/protocol/lora/handler.py
Normal file
@@ -0,0 +1,192 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
LoRa协议处理模块
|
||||
处理LoRa物理层通信相关功能
|
||||
支持四级结构:平台->中继->区域主控->普通设备
|
||||
"""
|
||||
|
||||
import logging
|
||||
import time
|
||||
import random
|
||||
from ..base import ProtocolHandler
|
||||
|
||||
# 配置日志
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class LoRaHandler(ProtocolHandler):
|
||||
"""LoRa协议处理器"""
|
||||
|
||||
def __init__(self, config):
|
||||
"""
|
||||
初始化LoRa协议处理器
|
||||
|
||||
Args:
|
||||
config: 配置对象
|
||||
"""
|
||||
super().__init__(config)
|
||||
self.initialized = False
|
||||
logger.info("初始化LoRa协议处理器")
|
||||
|
||||
def initialize(self):
|
||||
"""初始化LoRa协议处理器"""
|
||||
logger.info("开始初始化LoRa通信")
|
||||
|
||||
# 模拟LoRa硬件初始化
|
||||
time.sleep(0.5)
|
||||
self.initialized = True
|
||||
|
||||
# 如果启用模拟模式,初始化设备管理器
|
||||
if self.config.simulation_enabled:
|
||||
from internal.simulation import DeviceManager, AreaController, NormalDevice
|
||||
self.device_manager = DeviceManager()
|
||||
|
||||
# 根据配置创建模拟区域主控设备
|
||||
controllers = {}
|
||||
for controller_config in self.config.simulation_controllers:
|
||||
controller = AreaController(
|
||||
device_id=controller_config['id'],
|
||||
lora_address=controller_config['lora_address'],
|
||||
status=controller_config.get('status', 'stopped')
|
||||
)
|
||||
self.device_manager.add_controller(controller)
|
||||
controllers[controller.device_id] = controller
|
||||
|
||||
# 根据配置创建模拟普通设备,并关联到区域主控
|
||||
for device_config in self.config.simulation_devices:
|
||||
device = NormalDevice(
|
||||
device_id=device_config['id'],
|
||||
device_type=device_config['type'],
|
||||
rs485_bus=device_config['rs485_bus'],
|
||||
rs485_address=device_config['rs485_address'],
|
||||
controller_id=device_config['controller_id'],
|
||||
status=device_config.get('status', 'stopped')
|
||||
)
|
||||
self.device_manager.add_device(device)
|
||||
|
||||
# 将设备添加到对应的区域主控中
|
||||
controller_id = device_config['controller_id']
|
||||
if controller_id in controllers:
|
||||
controllers[controller_id].add_device(device)
|
||||
|
||||
logger.info(f"模拟模式已启用,创建了 {len(controllers)} 个区域主控和 {len(self.config.simulation_devices)} 个普通设备")
|
||||
else:
|
||||
logger.info("真实模式,需要连接LoRa硬件")
|
||||
|
||||
logger.info("LoRa协议处理器初始化完成")
|
||||
|
||||
def send_command(self, command, data):
|
||||
"""
|
||||
通过LoRa发送命令到设备
|
||||
|
||||
Args:
|
||||
command (str): 命令类型
|
||||
data (dict): 命令数据
|
||||
|
||||
Returns:
|
||||
dict: 命令执行结果
|
||||
"""
|
||||
if not self.initialized:
|
||||
logger.error("LoRa协议处理器未初始化")
|
||||
return {
|
||||
"status": "failed",
|
||||
"message": "LoRa协议处理器未初始化"
|
||||
}
|
||||
|
||||
logger.info(f"通过LoRa发送命令: {command}, 数据: {data}")
|
||||
|
||||
# 如果启用模拟模式,直接处理命令
|
||||
if self.config.simulation_enabled and self.device_manager:
|
||||
result = self._handle_simulated_command(command, data)
|
||||
logger.info(f"模拟命令处理结果: {result}")
|
||||
return result
|
||||
|
||||
# 真实模式下需要实际发送命令到LoRa设备
|
||||
logger.info("真实模式下发送命令到LoRa设备")
|
||||
# 这里应该是实际的LoRa通信代码
|
||||
# 暂时返回模拟响应
|
||||
time.sleep(0.1) # 模拟通信延迟
|
||||
return {
|
||||
"status": "success" if random.choice([True, False]) else "failed",
|
||||
"message": "命令发送成功" if random.choice([True, False]) else "命令发送失败",
|
||||
"data": {
|
||||
"device_id": data.get("device_id", "unknown"),
|
||||
"timestamp": time.time()
|
||||
}
|
||||
}
|
||||
|
||||
def receive_response(self):
|
||||
"""
|
||||
从LoRa接收设备响应
|
||||
|
||||
Returns:
|
||||
dict: 设备响应数据
|
||||
"""
|
||||
if not self.initialized:
|
||||
logger.error("LoRa协议处理器未初始化")
|
||||
return {
|
||||
"status": "failed",
|
||||
"message": "LoRa协议处理器未初始化"
|
||||
}
|
||||
|
||||
logger.info("从LoRa接收设备响应")
|
||||
|
||||
# 如果启用模拟模式,返回模拟响应
|
||||
if self.config.simulation_enabled and self.device_manager:
|
||||
# 在模拟模式下,我们假设命令已经直接处理完成,不需要单独接收响应
|
||||
logger.info("模拟模式下命令已直接处理完成")
|
||||
return {
|
||||
"status": "success",
|
||||
"message": "模拟响应",
|
||||
"data": {}
|
||||
}
|
||||
|
||||
# 真实模式下需要实际从LoRa设备接收响应
|
||||
logger.info("真实模式下从LoRa设备接收响应")
|
||||
# 这里应该是实际的LoRa通信代码
|
||||
# 暂时返回模拟响应
|
||||
time.sleep(0.1) # 模拟通信延迟
|
||||
return {
|
||||
"status": "success",
|
||||
"message": "接收响应成功",
|
||||
"data": {
|
||||
"response_data": "sample_data",
|
||||
"timestamp": time.time()
|
||||
}
|
||||
}
|
||||
|
||||
def _handle_simulated_command(self, command, data):
|
||||
"""
|
||||
处理模拟命令
|
||||
|
||||
Args:
|
||||
command (str): 命令类型
|
||||
data (dict): 命令数据
|
||||
|
||||
Returns:
|
||||
dict: 命令执行结果
|
||||
"""
|
||||
logger.info(f"处理模拟命令: {command}")
|
||||
|
||||
if command == "control_device":
|
||||
device_id = data.get("device_id")
|
||||
action = data.get("action")
|
||||
return self.device_manager.control_device(device_id, action)
|
||||
elif command == "query_device_status":
|
||||
device_id = data.get("device_id")
|
||||
return self.device_manager.query_device_status(device_id)
|
||||
elif command == "query_all_device_status":
|
||||
statuses = self.device_manager.query_all_device_status()
|
||||
return {
|
||||
"status": "success",
|
||||
"message": "查询所有设备状态成功",
|
||||
"data": statuses
|
||||
}
|
||||
else:
|
||||
return {
|
||||
"status": "failed",
|
||||
"message": f"不支持的命令: {command}"
|
||||
}
|
||||
2
internal/protocol/lorawan/__init__.py
Normal file
2
internal/protocol/lorawan/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
# LoRaWAN协议处理模块
|
||||
# 处理基于LoRa物理层的广域网协议功能,包括设备认证、加密和网络管理
|
||||
2
internal/protocol/lwm2m/__init__.py
Normal file
2
internal/protocol/lwm2m/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
# LwM2M协议处理模块
|
||||
# 处理轻量级机器到机器协议,提供设备管理、固件更新等功能
|
||||
2
internal/protocol/senml/__init__.py
Normal file
2
internal/protocol/senml/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
# SenML数据格式处理模块
|
||||
# 处理传感器标记语言,标准化的传感器数据表示格式
|
||||
6
internal/protocol/websocket/__init__.py
Normal file
6
internal/protocol/websocket/__init__.py
Normal file
@@ -0,0 +1,6 @@
|
||||
# WebSocket通信处理模块
|
||||
# 处理与猪场主控的WebSocket通信
|
||||
|
||||
from .client import WebSocketClient
|
||||
|
||||
__all__ = ['WebSocketClient']
|
||||
143
internal/protocol/websocket/client.py
Normal file
143
internal/protocol/websocket/client.py
Normal file
@@ -0,0 +1,143 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
WebSocket客户端模块
|
||||
用于与平台建立WebSocket连接并处理通信
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import json
|
||||
import logging
|
||||
import websockets
|
||||
from datetime import datetime
|
||||
from urllib.parse import urlencode
|
||||
|
||||
from config import config
|
||||
|
||||
# 配置日志
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class WebSocketClient:
|
||||
"""WebSocket客户端类"""
|
||||
|
||||
def __init__(self, relay_service):
|
||||
"""
|
||||
初始化WebSocket客户端
|
||||
|
||||
Args:
|
||||
relay_service: 中继器服务实例
|
||||
"""
|
||||
self.relay_service = relay_service
|
||||
self.device_id = config._config.get('relay', {}).get('device_id', '1')
|
||||
self.host = config._config.get('websocket', {}).get('host', 'localhost')
|
||||
self.port = config._config.get('websocket', {}).get('port', 8086)
|
||||
self.timeout = config._config.get('websocket', {}).get('timeout', 5)
|
||||
self.websocket = None
|
||||
self.connected = False
|
||||
self.running = False
|
||||
|
||||
logger.info(f"初始化WebSocket客户端: device_id={self.device_id}, host={self.host}, port={self.port}")
|
||||
|
||||
async def connect(self):
|
||||
"""建立WebSocket连接"""
|
||||
try:
|
||||
# 构建连接URL
|
||||
params = urlencode({'device_id': self.device_id})
|
||||
uri = f"ws://{self.host}:{self.port}/ws/device?{params}"
|
||||
|
||||
logger.info(f"正在连接到平台: {uri}")
|
||||
|
||||
# 建立WebSocket连接(移除了timeout参数以兼容新版本websockets库)
|
||||
self.websocket = await websockets.connect(uri)
|
||||
self.connected = True
|
||||
self.running = True
|
||||
|
||||
logger.info("成功连接到平台")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"连接平台失败: {e}")
|
||||
self.connected = False
|
||||
return False
|
||||
|
||||
async def disconnect(self):
|
||||
"""断开WebSocket连接"""
|
||||
logger.info("断开WebSocket连接")
|
||||
self.running = False
|
||||
|
||||
if self.websocket:
|
||||
await self.websocket.close()
|
||||
self.websocket = None
|
||||
|
||||
self.connected = False
|
||||
logger.info("WebSocket连接已断开")
|
||||
|
||||
async def send_message(self, message):
|
||||
"""
|
||||
发送消息到平台
|
||||
|
||||
Args:
|
||||
message (dict): 要发送的消息
|
||||
"""
|
||||
if not self.connected or not self.websocket:
|
||||
logger.warning("WebSocket未连接,无法发送消息")
|
||||
return False
|
||||
|
||||
try:
|
||||
message_str = json.dumps(message, ensure_ascii=False)
|
||||
await self.websocket.send(message_str)
|
||||
logger.debug(f"发送消息到平台: {message_str}")
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.error(f"发送消息失败: {e}")
|
||||
return False
|
||||
|
||||
async def listen(self):
|
||||
"""监听平台消息"""
|
||||
if not self.connected or not self.websocket:
|
||||
logger.error("WebSocket未连接,无法监听消息")
|
||||
return
|
||||
|
||||
logger.info("开始监听平台消息")
|
||||
|
||||
try:
|
||||
async for message in self.websocket:
|
||||
try:
|
||||
# 解析收到的消息
|
||||
message_data = json.loads(message)
|
||||
logger.info(f"收到平台消息: {message_data}")
|
||||
|
||||
# 将消息传递给中继器服务处理
|
||||
self.relay_service.handle_platform_command(message)
|
||||
|
||||
except json.JSONDecodeError as e:
|
||||
logger.error(f"解析平台消息失败: {e}")
|
||||
except Exception as e:
|
||||
logger.error(f"处理平台消息时发生错误: {e}")
|
||||
|
||||
except websockets.exceptions.ConnectionClosed:
|
||||
logger.warning("WebSocket连接已关闭")
|
||||
self.connected = False
|
||||
except Exception as e:
|
||||
logger.error(f"监听平台消息时发生错误: {e}")
|
||||
self.connected = False
|
||||
|
||||
async def send_heartbeat(self):
|
||||
"""发送心跳消息"""
|
||||
if not self.connected:
|
||||
return False
|
||||
|
||||
heartbeat_msg = {
|
||||
"type": "heartbeat",
|
||||
"device_id": self.device_id,
|
||||
"timestamp": datetime.utcnow().isoformat() + 'Z'
|
||||
}
|
||||
|
||||
return await self.send_message(heartbeat_msg)
|
||||
|
||||
def is_connected(self):
|
||||
"""检查是否已连接"""
|
||||
return self.connected
|
||||
Reference in New Issue
Block a user