Compare commits

..

5 Commits
1.4.6 ... 1.4.7

Author SHA1 Message Date
pdxlocations
56637f806b bump version 2025-12-26 23:32:06 -08:00
pdxlocations
c6abedec75 Merge pull request #237 from pdxlocations:close-interface
close the interface on quit
2025-12-27 02:26:28 -05:00
pdxlocations
6b18809215 close the interface on quit 2025-12-26 23:26:14 -08:00
pdxlocations
b048fe2480 Merge pull request #236 from pdxlocations:notification-sound-delay
wait for all messages to play notif sound
2025-12-27 02:21:45 -05:00
pdxlocations
600fc61ed7 wait for all messages to play notif sound 2025-12-26 23:21:25 -08:00
3 changed files with 43 additions and 2 deletions

View File

@@ -129,8 +129,10 @@ def start() -> None:
try:
curses.wrapper(main)
interface_state.interface.close()
except KeyboardInterrupt:
logging.info("User exited with Ctrl+C")
interface_state.interface.close()
sys.exit(0)
except Exception as e:
logging.critical("Fatal error", exc_info=True)

View File

@@ -2,7 +2,46 @@ import logging
import os
import platform
import shutil
import time
import subprocess
import threading
# Debounce notification sounds so a burst of queued messages only plays once.
_SOUND_DEBOUNCE_SECONDS = 0.8
_sound_timer: threading.Timer | None = None
_sound_timer_lock = threading.Lock()
_last_sound_request = 0.0
def schedule_notification_sound(delay: float = _SOUND_DEBOUNCE_SECONDS) -> None:
"""Schedule a notification sound after a short quiet period.
If more messages arrive before the delay elapses, the timer is reset.
This prevents playing a sound for each message when a backlog flushes.
"""
global _sound_timer, _last_sound_request
now = time.monotonic()
with _sound_timer_lock:
_last_sound_request = now
# Cancel any previously scheduled sound.
if _sound_timer is not None:
try:
_sound_timer.cancel()
except Exception:
pass
_sound_timer = None
def _fire(expected_request_time: float) -> None:
# Only play if nothing newer has been scheduled.
with _sound_timer_lock:
if expected_request_time != _last_sound_request:
return
play_sound()
_sound_timer = threading.Timer(delay, _fire, args=(now,))
_sound_timer.daemon = True
_sound_timer.start()
from typing import Any, Dict
from contact.utilities.utils import (
@@ -108,7 +147,7 @@ def on_receive(packet: Dict[str, Any], interface: Any) -> None:
if config.notification_sound == "True":
play_sound()
schedule_notification_sound()
message_bytes = packet["decoded"]["payload"]
message_string = message_bytes.decode("utf-8")

View File

@@ -1,6 +1,6 @@
[project]
name = "contact"
version = "1.4.6"
version = "1.4.7"
description = "This Python curses client for Meshtastic is a terminal-based client designed to manage device settings, enable mesh chat communication, and handle configuration backups and restores."
authors = [
{name = "Ben Lipsey",email = "ben@pdxlocations.com"}