fix: Light up only the specific pad where tag is placed

- Changed apply_tag_color() to accept pad parameter
- LED effects now apply to tag.pad instead of Pad.ALL
- Tag removal only turns off the specific pad, not all pads
- Added active_pads tracking dictionary
- Added speed parameter support from tag_colors.json
This commit is contained in:
2026-04-06 16:15:09 +10:00
parent 8a9faac09c
commit 3606afd1f8
+41 -20
View File
@@ -52,6 +52,7 @@ def load_tag_colors(filepath: str = TAG_COLORS_FILE) -> tuple:
default_config = { default_config = {
'color': COLORS['CYAN'], 'color': COLORS['CYAN'],
'effect': 'solid', 'effect': 'solid',
'speed': 1.0,
'name': 'Default' 'name': 'Default'
} }
@@ -83,6 +84,7 @@ def load_tag_colors(filepath: str = TAG_COLORS_FILE) -> tuple:
default_config = { default_config = {
'color': data['default'].get('color', COLORS['CYAN']), 'color': data['default'].get('color', COLORS['CYAN']),
'effect': data['default'].get('effect', 'solid'), 'effect': data['default'].get('effect', 'solid'),
'speed': data['default'].get('speed', 1.0),
'name': data['default'].get('name', 'Default') 'name': data['default'].get('name', 'Default')
} }
@@ -94,6 +96,7 @@ def load_tag_colors(filepath: str = TAG_COLORS_FILE) -> tuple:
tag_colors[legacy_key] = { tag_colors[legacy_key] = {
'color': config.get('color', COLORS['CYAN']), 'color': config.get('color', COLORS['CYAN']),
'effect': config.get('effect', 'solid'), 'effect': config.get('effect', 'solid'),
'speed': config.get('speed', 1.0),
'name': config.get('name', '') 'name': config.get('name', '')
} }
except ValueError: except ValueError:
@@ -114,6 +117,7 @@ TAG_COLORS = {}
DEFAULT_TAG_COLOR = { DEFAULT_TAG_COLOR = {
'color': COLORS['CYAN'], 'color': COLORS['CYAN'],
'effect': 'solid', 'effect': 'solid',
'speed': 1.0,
'name': 'Default' 'name': 'Default'
} }
@@ -235,11 +239,14 @@ def portal_mode(server_ip, port):
last_sent_time = 0 last_sent_time = 0
DEBOUNCE_TIME = 2.0 # Seconds before allowing same tag again DEBOUNCE_TIME = 2.0 # Seconds before allowing same tag again
# Track which pads have active tags
active_pads = {} # pad_num -> legacy_key
# Will be set after reader is created # Will be set after reader is created
reader = None reader = None
def apply_tag_color(legacy_key: int): def apply_tag_color(pad: Pad, legacy_key: int):
"""Apply color effect to ALL pads based on tag mapping""" """Apply color effect to SPECIFIC pad based on tag mapping"""
if reader is None: if reader is None:
return return
@@ -247,21 +254,27 @@ def portal_mode(server_ip, port):
config = TAG_COLORS.get(legacy_key, DEFAULT_TAG_COLOR) config = TAG_COLORS.get(legacy_key, DEFAULT_TAG_COLOR)
color = config.get('color', COLORS['CYAN']) color = config.get('color', COLORS['CYAN'])
effect = config.get('effect', 'solid') effect = config.get('effect', 'solid')
speed = config.get('speed', 1.0)
name = config.get('name', '') name = config.get('name', '')
if name: if name:
print(f" Theme: {name}") print(f" Theme: {name}")
# Apply effect to ALL pads # Calculate timing based on speed
base_time = 10 # Base ticks (~50ms each)
on_time = int(base_time * speed)
off_time = int(base_time * speed)
# Apply effect to ONLY the specific pad where tag is placed
if effect == 'pulse': if effect == 'pulse':
# Slow pulsing fade on all pads (count=255 for continuous) # Slow pulsing fade on specific pad (count=255 for continuous)
reader.fade_pad(Pad.ALL, color, speed=15, count=255) reader.fade_pad(pad, color, speed=int(15 * speed), count=255)
elif effect == 'flash': elif effect == 'flash':
# Quick flashing on all pads # Quick flashing on specific pad
reader.flash_pad(Pad.ALL, color, on_time=8, off_time=8, count=255) reader.flash_pad(pad, color, on_time=on_time, off_time=off_time, count=255)
else: else:
# Solid color on all pads # Solid color on specific pad
reader.set_pad_color(Pad.ALL, color) reader.set_pad_color(pad, color)
def on_tag_insert(tag: TagInfo): def on_tag_insert(tag: TagInfo):
nonlocal last_sent_key, last_sent_time nonlocal last_sent_key, last_sent_time
@@ -274,15 +287,18 @@ def portal_mode(server_ip, port):
print(f" UID: {tag.uid_hex}") print(f" UID: {tag.uid_hex}")
print(f" Legacy Key: {legacy_key}") print(f" Legacy Key: {legacy_key}")
# Step 1: ALL LEDs OFF # Track this pad as active
active_pads[tag.pad.value] = legacy_key
# Turn off ONLY this pad first (clean slate for new effect)
if reader: if reader:
reader.set_pad_color(Pad.ALL, COLORS['OFF']) reader.set_pad_color(tag.pad, COLORS['OFF'])
# Debounce - don't resend same tag too quickly # Debounce - don't resend same tag too quickly
if legacy_key == last_sent_key and (current_time - last_sent_time) < DEBOUNCE_TIME: if legacy_key == last_sent_key and (current_time - last_sent_time) < DEBOUNCE_TIME:
print(f" (Skipping server - same tag sent {current_time - last_sent_time:.1f}s ago)") print(f" (Skipping server - same tag sent {current_time - last_sent_time:.1f}s ago)")
# Still apply the theme effect even if skipping server # Still apply the theme effect even if skipping server
apply_tag_color(legacy_key) apply_tag_color(tag.pad, legacy_key)
return return
# Send to server # Send to server
@@ -292,23 +308,28 @@ def portal_mode(server_ip, port):
last_sent_time = current_time last_sent_time = current_time
if reader: if reader:
# Step 2: Blue blink CENTER to confirm scan # Quick blue blink on THIS pad to confirm scan
reader.set_pad_color(Pad.CENTER, COLORS['BLUE']) reader.set_pad_color(tag.pad, COLORS['BLUE'])
time.sleep(0.15) time.sleep(0.15)
# Step 3: ALL OFF # Turn off THIS pad
reader.set_pad_color(Pad.ALL, COLORS['OFF']) reader.set_pad_color(tag.pad, COLORS['OFF'])
time.sleep(0.1) time.sleep(0.1)
# Step 4: Apply theme effect to ALL pads # Apply theme effect to THIS pad only
apply_tag_color(legacy_key) apply_tag_color(tag.pad, legacy_key)
print() print()
def on_tag_remove(tag: TagInfo): def on_tag_remove(tag: TagInfo):
print(f"[-] TAG REMOVED from {tag.pad.name} pad") print(f"[-] TAG REMOVED from {tag.pad.name} pad")
# Turn off ALL pad LEDs
# Remove from active tracking
if tag.pad.value in active_pads:
del active_pads[tag.pad.value]
# Turn off ONLY this pad's LED (not all pads!)
if reader: if reader:
reader.set_pad_color(Pad.ALL, COLORS['OFF']) reader.set_pad_color(tag.pad, COLORS['OFF'])
def on_connect(): def on_connect():
print("✓ Portal connected and initialized") print("✓ Portal connected and initialized")