fix: Don't kill cycle effect when removing non-cycle tags

Previously stop_cycle_effect() was called on every tag removal,
which froze the cycle when a non-cycle tag was removed. Now the
removal logic has three distinct paths:

1. Cycle tag removed → stop cycle, restore other pads
2. Non-cycle tag removed while cycle still active → do nothing,
   let the cycle thread keep controlling all pads
3. Normal removal (no cycle) → just turn off the pad
This commit is contained in:
2026-04-06 17:00:30 +10:00
parent 2b4ca6423d
commit ac190d49c1
+30 -8
View File
@@ -122,6 +122,12 @@ DEFAULT_TAG_COLOR = {
}
def _get_tag_effect(legacy_key: int) -> str:
"""Get the effect type for a tag's legacy key."""
config = TAG_COLORS.get(legacy_key, DEFAULT_TAG_COLOR)
return config.get('effect', 'solid')
def uid_to_legacy_key(uid: bytes) -> int:
"""
Convert 7-byte UID to legacy integer key format.
@@ -311,26 +317,31 @@ def portal_mode(server_ip, port):
def on_tag_remove(tag: TagInfo):
print(f"[-] TAG REMOVED from {tag.pad.name} pad")
# Check if removed tag had a cycle effect (affects all pads)
# Check if the removed tag had a cycle effect
removed_key = active_pads.get(tag.pad.value)
was_cycle = False
removed_is_cycle = False
if removed_key is not None:
config = TAG_COLORS.get(removed_key, DEFAULT_TAG_COLOR)
was_cycle = config.get('effect', 'solid') == 'cycle'
removed_is_cycle = _get_tag_effect(removed_key) == 'cycle'
# Remove from active tracking
if tag.pad.value in active_pads:
del active_pads[tag.pad.value]
# Check if any REMAINING active tag has a cycle effect
remaining_cycle = False
for pad_val, key in active_pads.items():
if _get_tag_effect(key) == 'cycle':
remaining_cycle = True
break
if reader:
# Stop cycle effect if running (it uses all pads)
if removed_is_cycle:
# The cycle tag itself was removed - stop cycle and restore pads
reader.stop_cycle_effect()
# Stop individual pad effect and turn off the removed pad
reader.stop_effect(tag.pad)
reader.set_pad_color(tag.pad, COLORS['OFF'])
# If a cycle effect was running, restore all other pads
if was_cycle:
# Restore all other pads to their proper state
for pad_enum in [Pad.CENTER, Pad.LEFT, Pad.RIGHT]:
if pad_enum == tag.pad:
continue # Already handled above
@@ -342,6 +353,17 @@ def portal_mode(server_ip, port):
reader.stop_effect(pad_enum)
reader.set_pad_color(pad_enum, COLORS['OFF'])
elif remaining_cycle:
# A cycle effect from another tag is still running
# Don't stop anything - the cycle thread controls all pads
# Just update tracking (already done above)
pass
else:
# Normal removal (no cycle involved at all)
reader.stop_effect(tag.pad)
reader.set_pad_color(tag.pad, COLORS['OFF'])
def on_connect():
print("✓ Portal connected and initialized")
print()