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 = {
'color': COLORS['CYAN'],
'effect': 'solid',
'speed': 1.0,
'name': 'Default'
}
@@ -83,6 +84,7 @@ def load_tag_colors(filepath: str = TAG_COLORS_FILE) -> tuple:
default_config = {
'color': data['default'].get('color', COLORS['CYAN']),
'effect': data['default'].get('effect', 'solid'),
'speed': data['default'].get('speed', 1.0),
'name': data['default'].get('name', 'Default')
}
@@ -94,6 +96,7 @@ def load_tag_colors(filepath: str = TAG_COLORS_FILE) -> tuple:
tag_colors[legacy_key] = {
'color': config.get('color', COLORS['CYAN']),
'effect': config.get('effect', 'solid'),
'speed': config.get('speed', 1.0),
'name': config.get('name', '')
}
except ValueError:
@@ -114,6 +117,7 @@ TAG_COLORS = {}
DEFAULT_TAG_COLOR = {
'color': COLORS['CYAN'],
'effect': 'solid',
'speed': 1.0,
'name': 'Default'
}
@@ -235,11 +239,14 @@ def portal_mode(server_ip, port):
last_sent_time = 0
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
reader = None
def apply_tag_color(legacy_key: int):
"""Apply color effect to ALL pads based on tag mapping"""
def apply_tag_color(pad: Pad, legacy_key: int):
"""Apply color effect to SPECIFIC pad based on tag mapping"""
if reader is None:
return
@@ -247,21 +254,27 @@ def portal_mode(server_ip, port):
config = TAG_COLORS.get(legacy_key, DEFAULT_TAG_COLOR)
color = config.get('color', COLORS['CYAN'])
effect = config.get('effect', 'solid')
speed = config.get('speed', 1.0)
name = config.get('name', '')
if 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':
# Slow pulsing fade on all pads (count=255 for continuous)
reader.fade_pad(Pad.ALL, color, speed=15, count=255)
# Slow pulsing fade on specific pad (count=255 for continuous)
reader.fade_pad(pad, color, speed=int(15 * speed), count=255)
elif effect == 'flash':
# Quick flashing on all pads
reader.flash_pad(Pad.ALL, color, on_time=8, off_time=8, count=255)
# Quick flashing on specific pad
reader.flash_pad(pad, color, on_time=on_time, off_time=off_time, count=255)
else:
# Solid color on all pads
reader.set_pad_color(Pad.ALL, color)
# Solid color on specific pad
reader.set_pad_color(pad, color)
def on_tag_insert(tag: TagInfo):
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" 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:
reader.set_pad_color(Pad.ALL, COLORS['OFF'])
reader.set_pad_color(tag.pad, COLORS['OFF'])
# Debounce - don't resend same tag too quickly
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)")
# Still apply the theme effect even if skipping server
apply_tag_color(legacy_key)
apply_tag_color(tag.pad, legacy_key)
return
# Send to server
@@ -292,23 +308,28 @@ def portal_mode(server_ip, port):
last_sent_time = current_time
if reader:
# Step 2: Blue blink CENTER to confirm scan
reader.set_pad_color(Pad.CENTER, COLORS['BLUE'])
# Quick blue blink on THIS pad to confirm scan
reader.set_pad_color(tag.pad, COLORS['BLUE'])
time.sleep(0.15)
# Step 3: ALL OFF
reader.set_pad_color(Pad.ALL, COLORS['OFF'])
# Turn off THIS pad
reader.set_pad_color(tag.pad, COLORS['OFF'])
time.sleep(0.1)
# Step 4: Apply theme effect to ALL pads
apply_tag_color(legacy_key)
# Apply theme effect to THIS pad only
apply_tag_color(tag.pad, legacy_key)
print()
def on_tag_remove(tag: TagInfo):
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:
reader.set_pad_color(Pad.ALL, COLORS['OFF'])
reader.set_pad_color(tag.pad, COLORS['OFF'])
def on_connect():
print("✓ Portal connected and initialized")