From 5ef67d71f606308558e7e2496ce189f0c418bfae Mon Sep 17 00:00:00 2001 From: stu2not Date: Mon, 15 Jun 2026 10:07:58 +0800 Subject: [PATCH] =?UTF-8?q?=E9=80=82=E9=85=8D=E5=91=8A=E8=AD=A6=E4=BA=8B?= =?UTF-8?q?=E4=BB=B6=E6=8F=90=E7=A4=BA=E9=9F=B3=E5=9B=9E=E5=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- talkingq-url/handlers/mqtt_handler.py | 12 +- .../tests/test_alarm_event_response_audio.py | 38 ++++ .../tests/test_alarm_gps_location_refresh.py | 200 ++++++++++++++++++ 3 files changed, 249 insertions(+), 1 deletion(-) create mode 100644 talkingq-url/tests/test_alarm_event_response_audio.py create mode 100644 talkingq-url/tests/test_alarm_gps_location_refresh.py diff --git a/talkingq-url/handlers/mqtt_handler.py b/talkingq-url/handlers/mqtt_handler.py index b0aa940..3e0c4f8 100644 --- a/talkingq-url/handlers/mqtt_handler.py +++ b/talkingq-url/handlers/mqtt_handler.py @@ -455,7 +455,17 @@ class TalkingQMQTTService: sms_notification_service.schedule_alarm_notification(device_id=device_id, alarm_id=alarm_id) await self._schedule_persistence(device_id, "alarm_event", _record_alarm_and_notify()) - await self._publish(f"device/{device_id}/event_resp", {"msg_id": "010", "status": "success"}) + await self._publish( + f"device/{device_id}/event_resp", + { + "msg_id": "010", + "status": "success", + "type": 0, + "params": { + "url": f"http://{settings.server_host}:{settings.server_port}/assets/audio/message_ok.mp3" + }, + }, + ) async def _handle_short_press_message(self, device_id: str, payload: dict): params = payload.get("params", {}) diff --git a/talkingq-url/tests/test_alarm_event_response_audio.py b/talkingq-url/tests/test_alarm_event_response_audio.py new file mode 100644 index 0000000..e05178e --- /dev/null +++ b/talkingq-url/tests/test_alarm_event_response_audio.py @@ -0,0 +1,38 @@ +import pytest + +from handlers.mqtt_handler import TalkingQMQTTService + + +@pytest.mark.asyncio +async def test_alarm_event_response_includes_v2_audio_url(monkeypatch): + service = TalkingQMQTTService({"broker": "127.0.0.1"}) + published = [] + + async def fake_publish(topic, payload): + published.append((topic, payload)) + return True + + async def fake_schedule_persistence(device_id, label, coro): + del device_id, label + coro.close() + + monkeypatch.setattr(service, "_publish", fake_publish) + monkeypatch.setattr(service, "_schedule_persistence", fake_schedule_persistence) + monkeypatch.setattr("handlers.mqtt_handler.settings.server_host", "101.35.224.118") + monkeypatch.setattr("handlers.mqtt_handler.settings.server_port", 8080) + + await service._handle_alarm_report("TalkingQ_XQSN00001005", {"msg_id": "010"}) + + assert published == [ + ( + "device/TalkingQ_XQSN00001005/event_resp", + { + "msg_id": "010", + "status": "success", + "type": 0, + "params": { + "url": "http://101.35.224.118:8080/assets/audio/message_ok.mp3", + }, + }, + ) + ] diff --git a/talkingq-url/tests/test_alarm_gps_location_refresh.py b/talkingq-url/tests/test_alarm_gps_location_refresh.py new file mode 100644 index 0000000..2bbf5c2 --- /dev/null +++ b/talkingq-url/tests/test_alarm_gps_location_refresh.py @@ -0,0 +1,200 @@ +import pytest + +from handlers.mqtt_handler import TalkingQMQTTService + + +@pytest.mark.asyncio +async def test_alarm_requests_fresh_gps_before_sms(monkeypatch): + service = TalkingQMQTTService({"broker": "127.0.0.1"}) + published = [] + calls = [] + + async def fake_publish(topic, payload): + published.append((topic, payload)) + return True + + async def fake_schedule_persistence(device_id, label, coro): + calls.append(("schedule", label)) + await coro + + async def fake_record_alarm_event(**kwargs): + calls.append(("record_alarm", kwargs)) + return 123 + + async def fake_query_gps_and_wait_for_location(device_id, *, timeout_seconds): + calls.append(("query_gps", device_id, timeout_seconds)) + return { + "child_id": 9, + "device_id": device_id, + "coord_type": "gcj02", + "lat": 30.245, + "lng": 120.215, + "updated_at": "2026-06-08 12:00:00", + "address": "浙江省杭州市萧山区扬帆路附近", + } + + async def fake_apply_alarm_location(**kwargs): + calls.append(("apply_alarm_location", kwargs)) + return True + + def fake_schedule_alarm_notification(**kwargs): + calls.append(("sms", kwargs)) + + monkeypatch.setattr(service, "_publish", fake_publish) + monkeypatch.setattr(service, "_schedule_persistence", fake_schedule_persistence) + monkeypatch.setattr(service, "query_gps_and_wait_for_location", fake_query_gps_and_wait_for_location) + monkeypatch.setattr("handlers.mqtt_handler.settings.alarm_gps_query_timeout_seconds", 2.5) + monkeypatch.setattr("handlers.mqtt_handler.device_alarm_service.record_alarm_event", fake_record_alarm_event) + monkeypatch.setattr("handlers.mqtt_handler.device_alarm_service.apply_alarm_location", fake_apply_alarm_location) + monkeypatch.setattr("handlers.mqtt_handler.sms_notification_service.schedule_alarm_notification", fake_schedule_alarm_notification) + + await service._handle_alarm_report("TalkingQ_device001", {"msg_id": "010"}) + + assert published == [ + ( + "device/TalkingQ_device001/event_resp", + { + "msg_id": "010", + "status": "success", + "type": 0, + "params": { + "url": "http://192.168.101.78:8080/assets/audio/message_ok.mp3", + }, + }, + ), + ] + assert calls == [ + ("schedule", "alarm_event"), + ( + "record_alarm", + { + "device_id": "TalkingQ_device001", + "source_msg_id": "010", + "resolve_address": False, + }, + ), + ("query_gps", "TalkingQ_device001", 2.5), + ( + "apply_alarm_location", + { + "alarm_id": 123, + "device_id": "TalkingQ_device001", + "location": { + "child_id": 9, + "device_id": "TalkingQ_device001", + "coord_type": "gcj02", + "lat": 30.245, + "lng": 120.215, + "updated_at": "2026-06-08 12:00:00", + "address": "浙江省杭州市萧山区扬帆路附近", + }, + }, + ), + ("sms", {"device_id": "TalkingQ_device001", "alarm_id": 123}), + ] + + +@pytest.mark.asyncio +async def test_alarm_falls_back_to_existing_alarm_location_when_gps_times_out(monkeypatch): + service = TalkingQMQTTService({"broker": "127.0.0.1"}) + calls = [] + + async def fake_publish(topic, payload): + del topic, payload + return True + + async def fake_schedule_persistence(device_id, label, coro): + calls.append(("schedule", label)) + await coro + + async def fake_record_alarm_event(**kwargs): + calls.append(("record_alarm", kwargs)) + return 456 + + async def fake_query_gps_and_wait_for_location(device_id, *, timeout_seconds): + calls.append(("query_gps", device_id, timeout_seconds)) + return None + + async def fake_resolve_alarm_current_location(**kwargs): + calls.append(("resolve_existing", kwargs)) + return True + + def fake_schedule_alarm_notification(**kwargs): + calls.append(("sms", kwargs)) + + monkeypatch.setattr(service, "_publish", fake_publish) + monkeypatch.setattr(service, "_schedule_persistence", fake_schedule_persistence) + monkeypatch.setattr(service, "query_gps_and_wait_for_location", fake_query_gps_and_wait_for_location) + monkeypatch.setattr("handlers.mqtt_handler.settings.alarm_gps_query_timeout_seconds", 1.0) + monkeypatch.setattr("handlers.mqtt_handler.device_alarm_service.record_alarm_event", fake_record_alarm_event) + monkeypatch.setattr("handlers.mqtt_handler.device_alarm_service.resolve_alarm_current_location", fake_resolve_alarm_current_location) + monkeypatch.setattr("handlers.mqtt_handler.sms_notification_service.schedule_alarm_notification", fake_schedule_alarm_notification) + + await service._handle_alarm_report("TalkingQ_device001", {"msg_id": "010"}) + + assert calls == [ + ("schedule", "alarm_event"), + ( + "record_alarm", + { + "device_id": "TalkingQ_device001", + "source_msg_id": "010", + "resolve_address": False, + }, + ), + ("query_gps", "TalkingQ_device001", 1.0), + ("resolve_existing", {"alarm_id": 456, "device_id": "TalkingQ_device001"}), + ("sms", {"device_id": "TalkingQ_device001", "alarm_id": 456}), + ] + + +@pytest.mark.asyncio +async def test_gps_waiter_returns_persisted_location(monkeypatch): + service = TalkingQMQTTService({"broker": "127.0.0.1"}) + published = [] + + async def fake_publish(topic, payload): + published.append((topic, payload)) + return True + + async def fake_schedule_persistence(device_id, label, coro): + del device_id, label + await coro + + async def fake_report_mqtt_device_location(**kwargs): + return { + "child_id": 9, + "device_id": kwargs["device_id"], + "lat": kwargs["latitude"], + "lng": kwargs["longitude"], + "updated_at": "2026-06-08 12:00:00", + } + + monkeypatch.setattr(service, "_publish", fake_publish) + monkeypatch.setattr(service, "_schedule_persistence", fake_schedule_persistence) + monkeypatch.setattr("handlers.mqtt_handler.location_service.report_mqtt_device_location", fake_report_mqtt_device_location) + + wait_task = __import__("asyncio").create_task( + service.query_gps_and_wait_for_location("TalkingQ_device001", timeout_seconds=1.0) + ) + await __import__("asyncio").sleep(0) + + await service._handle_gps_response( + "TalkingQ_device001", + { + "msg_id": "001", + "status": "success", + "data": { + "latitude": 30.245, + "longitude": 120.215, + }, + }, + ) + + location = await wait_task + + assert published == [ + ("device/TalkingQ_device001/command", {"msg_id": "001"}), + ] + assert location["lat"] == 30.245 + assert location["lng"] == 120.215