Track reviewed status for discovered sensors

Changes:
- Added 'reviewed' field to DiscoveredSensor dataclass
- By default, only show new (unreviewed) pending sensors
- Mark sensors as reviewed when shown in approval CLI
- Add --all flag to show all pending sensors (including reviewed)
- Add --ignored flag to show ignored sensors
- Prevent repeatedly asking for approval of same sensor

Usage:
  approve-sensors              # Only new sensors
  approve-sensors --all        # All pending sensors
  approve-sensors --ignored    # Ignored sensors
  approve-sensors --all --ignored  # Everything
This commit is contained in:
2025-12-27 20:33:14 +01:00
parent c8e8afff67
commit 5850089de9
2 changed files with 70 additions and 13 deletions

View File

@@ -8,6 +8,7 @@ Interactive tool to manage pending and ignored sensors.
import sys import sys
import json import json
import logging import logging
import argparse
from pathlib import Path from pathlib import Path
from typing import List from typing import List
@@ -191,6 +192,9 @@ def process_sensors(sensors: List[DiscoveredSensor], manager: DiscoveryManager):
print(f"\nFound {len(sensors)} sensor(s) to review") print(f"\nFound {len(sensors)} sensor(s) to review")
for i, sensor in enumerate(sensors, 1): for i, sensor in enumerate(sensors, 1):
# Mark as reviewed when shown
manager.mark_reviewed(sensor.mac)
display_sensor(sensor, i, len(sensors)) display_sensor(sensor, i, len(sensors))
choice = get_user_choice() choice = get_user_choice()
@@ -209,6 +213,31 @@ def process_sensors(sensors: List[DiscoveredSensor], manager: DiscoveryManager):
def main(): def main():
"""Main entry point for approve-sensors CLI.""" """Main entry point for approve-sensors CLI."""
# Parse command line arguments
parser = argparse.ArgumentParser(
description="Approve or ignore discovered Bluetooth sensors",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
Examples:
%(prog)s # Show only new pending sensors
%(prog)s --all # Show all pending sensors (including reviewed)
%(prog)s --ignored # Show only ignored sensors
%(prog)s --all --ignored # Show all sensors
"""
)
parser.add_argument(
'--all', '-a',
action='store_true',
help='Show all pending sensors, including previously reviewed ones'
)
parser.add_argument(
'--ignored', '-i',
action='store_true',
help='Show ignored sensors'
)
args = parser.parse_args()
# Setup logging # Setup logging
logging.basicConfig( logging.basicConfig(
level=logging.WARNING, level=logging.WARNING,
@@ -223,26 +252,37 @@ def main():
# Load discovery manager # Load discovery manager
manager = DiscoveryManager() manager = DiscoveryManager()
# Get pending and ignored sensors # Get sensors based on flags
if args.all:
pending = manager.get_pending() pending = manager.get_pending()
ignored = manager.get_ignored() pending_label = "all pending"
else:
pending = manager.get_new_pending()
pending_label = "new pending"
ignored = manager.get_ignored() if args.ignored else []
if not pending and not ignored: if not pending and not ignored:
print("\n✅ No pending or ignored sensors found") if args.all or args.ignored:
print("\nDiscovered sensors will appear here when detected.") print(f"\n✅ No {pending_label if pending else 'ignored'} sensors found")
else:
print("\n✅ No new sensors to review")
all_pending = manager.get_pending()
if all_pending:
print(f"\nThere are {len(all_pending)} previously reviewed pending sensor(s).")
print("Run with --all to review them again.")
return 0 return 0
# Process pending sensors first # Process pending sensors
if pending: if pending:
print(f"\n📋 Processing {len(pending)} pending sensor(s)...") print(f"\n📋 Processing {len(pending)} {pending_label} sensor(s)...")
process_sensors(pending, manager) process_sensors(pending, manager)
# Ask about ignored sensors # Process ignored sensors if requested
if ignored: if ignored:
print(f"\n\nThere are {len(ignored)} ignored sensor(s).") if pending:
review = input("Review ignored sensors? [y/N]: ").strip().lower() print("\n" + "=" * 70)
print(f"\n📋 Processing {len(ignored)} ignored sensor(s)...")
if review == 'y':
process_sensors(ignored, manager) process_sensors(ignored, manager)
print("\n" + "=" * 70) print("\n" + "=" * 70)

View File

@@ -27,6 +27,7 @@ class DiscoveredSensor:
last_seen: str last_seen: str
sample_reading: Dict[str, float] sample_reading: Dict[str, float]
status: str = "pending" # pending, approved, ignored status: str = "pending" # pending, approved, ignored
reviewed: bool = False # Has been shown in approval CLI
ignored_at: Optional[str] = None ignored_at: Optional[str] = None
ignore_reason: Optional[str] = None ignore_reason: Optional[str] = None
@@ -195,10 +196,26 @@ class DiscoveryManager:
"""Get list of sensors with status 'pending'.""" """Get list of sensors with status 'pending'."""
return [s for s in self.sensors.values() if s.status == "pending"] return [s for s in self.sensors.values() if s.status == "pending"]
def get_new_pending(self) -> List[DiscoveredSensor]:
"""Get list of pending sensors that haven't been reviewed yet."""
return [s for s in self.sensors.values() if s.status == "pending" and not s.reviewed]
def get_ignored(self) -> List[DiscoveredSensor]: def get_ignored(self) -> List[DiscoveredSensor]:
"""Get list of sensors with status 'ignored'.""" """Get list of sensors with status 'ignored'."""
return [s for s in self.sensors.values() if s.status == "ignored"] return [s for s in self.sensors.values() if s.status == "ignored"]
def mark_reviewed(self, mac: str):
"""
Mark a sensor as reviewed (shown in approval CLI).
Args:
mac: MAC address
"""
mac = mac.upper()
if mac in self.sensors:
self.sensors[mac].reviewed = True
self.save()
def send_ntfy_notification(self, sensor: DiscoveredSensor): def send_ntfy_notification(self, sensor: DiscoveredSensor):
""" """
Send ntfy notification for a newly discovered sensor. Send ntfy notification for a newly discovered sensor.