| | import asyncio |
| | import json |
| | import time |
| | import threading |
| | from typing import Dict |
| | from datetime import datetime |
| |
|
| | from src.application import Application |
| | from src.constants.constants import DeviceState |
| | from src.iot.thing import Thing, Parameter, ValueType |
| | from src.network.mqtt_client import MqttClient |
| |
|
| |
|
| |
|
| | class TemperatureSensor(Thing): |
| | def __init__(self): |
| | super().__init__("TemperatureSensor", "温度传感器设备") |
| | self.temperature = 0.0 |
| | self.humidity = 0.0 |
| | self.last_update_time = 0 |
| | self.is_running = False |
| | self.mqtt_client = None |
| | self.app = None |
| |
|
| | print("[IoT设备] 温度传感器接收端初始化完成") |
| |
|
| | |
| | self.add_property("temperature", "当前温度(摄氏度)", |
| | lambda: self.temperature) |
| | self.add_property("humidity", "当前湿度(%)", |
| | lambda: self.humidity) |
| | self.add_property("last_update_time", "最后更新时间", |
| | lambda: self.last_update_time) |
| |
|
| | |
| | |
| | |
| |
|
| | |
| | self._init_mqtt() |
| |
|
| | def _init_mqtt(self): |
| | """初始化MQTT客户端""" |
| | from src.utils.config_manager import ConfigManager |
| | config = ConfigManager.get_instance() |
| | try: |
| | self.mqtt_client = MqttClient( |
| | server=config.get_config("TEMPERATURE_SENSOR_MQTT_INFO.endpoint"), |
| | port=config.get_config("TEMPERATURE_SENSOR_MQTT_INFO.port"), |
| | username=config.get_config("TEMPERATURE_SENSOR_MQTT_INFO.username"), |
| | password=config.get_config("TEMPERATURE_SENSOR_MQTT_INFO.password"), |
| | |
| | subscribe_topic=config.get_config("TEMPERATURE_SENSOR_MQTT_INFO.subscribe_topic"), |
| | ) |
| | |
| | |
| | self.mqtt_client.client.on_message = self._on_mqtt_message |
| | |
| | |
| | self.mqtt_client.connect() |
| | self.mqtt_client.start() |
| | print("[温度传感器] MQTT客户端已连接") |
| | except Exception as e: |
| | print(f"[温度传感器] MQTT连接失败: {e}") |
| |
|
| | def _on_mqtt_message(self, client, userdata, msg): |
| | """处理MQTT消息""" |
| | try: |
| | topic = msg.topic |
| | payload = msg.payload.decode('utf-8') |
| | print(f"[温度传感器] 收到数据 - 主题: {topic}, 内容: {payload}") |
| | |
| | |
| | try: |
| | data = json.loads(payload) |
| | |
| | |
| | if 'temperature' in data and 'humidity' in data: |
| | |
| | self.temperature = data.get('temperature') |
| | self.humidity = data.get('humidity') |
| | |
| | |
| | timestamp = data.get('timestamp') |
| | if timestamp is not None: |
| | |
| | if isinstance(timestamp, str): |
| | try: |
| | |
| | dt = datetime.fromisoformat(timestamp.replace('Z', '+00:00')) |
| | self.last_update_time = int(dt.timestamp()) |
| | except ValueError: |
| | |
| | self.last_update_time = int(time.time()) |
| | else: |
| | |
| | self.last_update_time = int(timestamp) |
| | else: |
| | |
| | self.last_update_time = int(time.time()) |
| | |
| | |
| | update_time = time.strftime( |
| | '%Y-%m-%d %H:%M:%S', |
| | time.localtime(self.last_update_time) |
| | ) |
| |
|
| |
|
| | print(f"[温度传感器] 更新数据: 温度={self.temperature}°C, " |
| | f"湿度={self.humidity}%, 时间={update_time}") |
| | |
| | self.handle_temperature_update() |
| | except json.JSONDecodeError: |
| | print(f"[温度传感器] 无法解析JSON消息: {payload}") |
| | |
| | except Exception as e: |
| | print(f"[温度传感器] 处理MQTT消息时出错: {e}") |
| |
|
| | def handle_temperature_update(self): |
| | """处理温度更新后的操作""" |
| | try: |
| | if self.app is None: |
| | self.app = Application.get_instance() |
| | |
| | |
| | self.app.set_device_state(DeviceState.IDLE) |
| | |
| | |
| | threading.Thread( |
| | target=self._delayed_send_wake_word, |
| | daemon=True |
| | ).start() |
| | |
| | except Exception as e: |
| | print(f"[温度传感器] 处理温度更新时出错: {e}") |
| | |
| | def _delayed_send_wake_word(self): |
| | """延迟发送唤醒词消息,确保连接稳定""" |
| | try: |
| | |
| | channel_opened = False |
| | if not self.app.protocol.is_audio_channel_opened(): |
| | |
| | future = asyncio.run_coroutine_threadsafe( |
| | self.app.protocol.open_audio_channel(), |
| | self.app.loop |
| | ) |
| | |
| | try: |
| | channel_opened = future.result(timeout=5.0) |
| | except Exception as e: |
| | print(f"[温度传感器] 打开音频通道失败: {e}") |
| | return |
| | |
| | if channel_opened: |
| | |
| | print("[温度传感器] 音频通道已打开,等待3秒后发送唤醒词...") |
| | time.sleep(3) |
| | else: |
| | print("[温度传感器] 打开音频通道失败") |
| | return |
| | |
| | self.app._update_iot_states(delta=True) |
| | |
| | |
| | asyncio.run_coroutine_threadsafe( |
| | self.app.protocol.send_wake_word_detected("播报温湿度传感器数据(无需调用任何方法)"), |
| | self.app.loop |
| | ) |
| | print("[温度传感器] 已发送唤醒词消息") |
| | |
| | except Exception as e: |
| | print(f"[温度传感器] 延迟发送唤醒词时出错: {e}") |
| |
|
| | def _request_sensor_data(self): |
| | """请求所有传感器报告当前状态""" |
| | if self.mqtt_client: |
| | |
| | command = { |
| | "command": "get_data", |
| | "action": "get_data", |
| | "timestamp": int(time.time()) |
| | } |
| | self.mqtt_client.publish(json.dumps(command)) |
| | print("[温度传感器] 已发送数据请求命令") |
| | |
| | def send_command(self, action_name, **kwargs): |
| | """发送命令到传感器""" |
| | if self.mqtt_client: |
| | command = { |
| | "command": action_name, |
| | "action": action_name, |
| | "timestamp": int(time.time()) |
| | } |
| | |
| | command.update(kwargs) |
| | |
| | self.mqtt_client.publish(json.dumps(command)) |
| | print(f"[温度传感器] 已发送命令: {action_name}") |
| | return True |
| | return False |
| |
|
| | def get_temperature(self): |
| | return {"success": True, "message": f"[温度传感器] 更新数据: 温度={self.temperature}°C, " |
| | f"湿度={self.humidity}%, 时间={self.last_update_time}"} |
| |
|
| | def __del__(self): |
| | """析构函数,确保资源被正确释放""" |
| | if self.mqtt_client: |
| | try: |
| | self.mqtt_client.stop() |
| | except Exception: |
| | pass |
| |
|
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |