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 json
import logging
import argparse
from pathlib import Path
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")
for i, sensor in enumerate(sensors, 1):
# Mark as reviewed when shown
manager.mark_reviewed(sensor.mac)
display_sensor(sensor, i, len(sensors))
choice = get_user_choice()
@@ -209,6 +213,31 @@ def process_sensors(sensors: List[DiscoveredSensor], manager: DiscoveryManager):
def main():
"""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
logging.basicConfig(
level=logging.WARNING,
@@ -223,27 +252,38 @@ def main():
# Load discovery manager
manager = DiscoveryManager()
# Get pending and ignored sensors
pending = manager.get_pending()
ignored = manager.get_ignored()
# Get sensors based on flags
if args.all:
pending = manager.get_pending()
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:
print("\n✅ No pending or ignored sensors found")
print("\nDiscovered sensors will appear here when detected.")
if args.all or args.ignored:
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
# Process pending sensors first
# Process pending sensors
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)
# Ask about ignored sensors
# Process ignored sensors if requested
if ignored:
print(f"\n\nThere are {len(ignored)} ignored sensor(s).")
review = input("Review ignored sensors? [y/N]: ").strip().lower()
if review == 'y':
process_sensors(ignored, manager)
if pending:
print("\n" + "=" * 70)
print(f"\n📋 Processing {len(ignored)} ignored sensor(s)...")
process_sensors(ignored, manager)
print("\n" + "=" * 70)
print("Done!")

View File

@@ -27,6 +27,7 @@ class DiscoveredSensor:
last_seen: str
sample_reading: Dict[str, float]
status: str = "pending" # pending, approved, ignored
reviewed: bool = False # Has been shown in approval CLI
ignored_at: Optional[str] = None
ignore_reason: Optional[str] = None
@@ -195,10 +196,26 @@ class DiscoveryManager:
"""Get list of sensors with 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]:
"""Get list of sensors with 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):
"""
Send ntfy notification for a newly discovered sensor.