Add card_presence support: app.py (load/sync/log/RFID+LED gating), config.py GUI dropdown
This commit is contained in:
79
app.py
79
app.py
@@ -153,6 +153,7 @@ def load_config():
|
|||||||
"device_ip": "127.0.0.1",
|
"device_ip": "127.0.0.1",
|
||||||
"device_location": "",
|
"device_location": "",
|
||||||
"device_info_reviewed_at": "1970-01-01T00:00:00",
|
"device_info_reviewed_at": "1970-01-01T00:00:00",
|
||||||
|
"card_presence": "enable",
|
||||||
"last_synced": "1970-01-01T00:00:00",
|
"last_synced": "1970-01-01T00:00:00",
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,6 +199,8 @@ def load_config():
|
|||||||
cfg["device_info_reviewed_at"] = parser.get("device", "info_reviewed_at")
|
cfg["device_info_reviewed_at"] = parser.get("device", "info_reviewed_at")
|
||||||
if parser.has_option("device", "location"):
|
if parser.has_option("device", "location"):
|
||||||
cfg["device_location"] = parser.get("device", "location")
|
cfg["device_location"] = parser.get("device", "location")
|
||||||
|
if parser.has_option("device", "card_presence"):
|
||||||
|
cfg["card_presence"] = parser.get("device", "card_presence")
|
||||||
|
|
||||||
if parser.has_section("meta"):
|
if parser.has_section("meta"):
|
||||||
if parser.has_option("meta", "last_synced"):
|
if parser.has_option("meta", "last_synced"):
|
||||||
@@ -269,6 +272,7 @@ def _write_config_from_server(new_cfg):
|
|||||||
p.set("device", "ip", new_cfg.get("device_ip", ""))
|
p.set("device", "ip", new_cfg.get("device_ip", ""))
|
||||||
p.set("device", "location", new_cfg.get("location") or new_cfg.get("device_location", ""))
|
p.set("device", "location", new_cfg.get("location") or new_cfg.get("device_location", ""))
|
||||||
p.set("device", "info_reviewed_at", new_cfg.get("info_reviewed_at") or "1970-01-01T00:00:00")
|
p.set("device", "info_reviewed_at", new_cfg.get("info_reviewed_at") or "1970-01-01T00:00:00")
|
||||||
|
p.set("device", "card_presence", new_cfg.get("card_presence", "enable"))
|
||||||
|
|
||||||
p.add_section("meta")
|
p.add_section("meta")
|
||||||
sync_ts = new_cfg.get("config_updated_at") or datetime.now().isoformat()
|
sync_ts = new_cfg.get("config_updated_at") or datetime.now().isoformat()
|
||||||
@@ -364,6 +368,7 @@ def sync_config_with_server():
|
|||||||
"device_ip": _ip,
|
"device_ip": _ip,
|
||||||
"client_config_mtime": last_synced_str,
|
"client_config_mtime": last_synced_str,
|
||||||
"client_info_reviewed_at": local_info_reviewed_str,
|
"client_info_reviewed_at": local_info_reviewed_str,
|
||||||
|
"card_presence": APP_CONFIG.get("card_presence", "enable"),
|
||||||
},
|
},
|
||||||
timeout=5,
|
timeout=5,
|
||||||
)
|
)
|
||||||
@@ -381,6 +386,12 @@ APP_CONFIG = load_config()
|
|||||||
# Attempt to sync with server at startup (non-blocking – failures are logged and ignored)
|
# Attempt to sync with server at startup (non-blocking – failures are logged and ignored)
|
||||||
sync_config_with_server()
|
sync_config_with_server()
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Card presence flag – controls whether RFID functions are started
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
CARD_PRESENCE_ENABLED = APP_CONFIG.get("card_presence", "enable").strip().lower() == "enable"
|
||||||
|
print(f"Card presence: {'ENABLED' if CARD_PRESENCE_ENABLED else 'DISABLED'}")
|
||||||
|
|
||||||
# Early configuration mode detection (before heavy initialization)
|
# Early configuration mode detection (before heavy initialization)
|
||||||
def early_launch_configuration_mode():
|
def early_launch_configuration_mode():
|
||||||
"""
|
"""
|
||||||
@@ -986,6 +997,7 @@ def send_log_to_server(log_message, n_masa, hostname, device_ip):
|
|||||||
"os_version": _get_os_version(),
|
"os_version": _get_os_version(),
|
||||||
"location": APP_CONFIG.get("device_location", ""),
|
"location": APP_CONFIG.get("device_location", ""),
|
||||||
"mac_address": _get_mac_address(),
|
"mac_address": _get_mac_address(),
|
||||||
|
"card_presence": APP_CONFIG.get("card_presence", "enable"),
|
||||||
}
|
}
|
||||||
server_url = APP_CONFIG.get("server_log_url", "http://rpi-ansible:80/logs")
|
server_url = APP_CONFIG.get("server_log_url", "http://rpi-ansible:80/logs")
|
||||||
print(log_data) # Debugging: Print log_data to verify its contents
|
print(log_data) # Debugging: Print log_data to verify its contents
|
||||||
@@ -1607,28 +1619,32 @@ def post_info_thread(info):
|
|||||||
print(f"Async posting failed, using sync fallback: {e}")
|
print(f"Async posting failed, using sync fallback: {e}")
|
||||||
post_info(info)
|
post_info(info)
|
||||||
|
|
||||||
# Initialize LEDs with error handling
|
# Initialize LEDs – only when card reader is active
|
||||||
try:
|
class DummyLED:
|
||||||
print("Initializing LED controls...")
|
def __init__(self, pin):
|
||||||
led1 = OutputDevice(23)
|
self.pin = pin
|
||||||
led2 = OutputDevice(24)
|
def on(self):
|
||||||
print("✓ LED controls initialized successfully")
|
pass
|
||||||
log_info_with_server("LED controls initialized")
|
def off(self):
|
||||||
except Exception as e:
|
pass
|
||||||
print(f"Warning: Could not initialize LED controls: {e}")
|
|
||||||
print("Creating dummy LED objects - visual feedback will be disabled")
|
|
||||||
# Create dummy LED objects that don't crash the app
|
|
||||||
class DummyLED:
|
|
||||||
def __init__(self, pin):
|
|
||||||
self.pin = pin
|
|
||||||
def on(self):
|
|
||||||
print(f"LED {self.pin} would turn ON")
|
|
||||||
def off(self):
|
|
||||||
print(f"LED {self.pin} would turn OFF")
|
|
||||||
|
|
||||||
|
if CARD_PRESENCE_ENABLED:
|
||||||
|
try:
|
||||||
|
print("Initializing LED controls...")
|
||||||
|
led1 = OutputDevice(23)
|
||||||
|
led2 = OutputDevice(24)
|
||||||
|
print("✓ LED controls initialized successfully")
|
||||||
|
log_info_with_server("LED controls initialized")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Warning: Could not initialize LED controls: {e}")
|
||||||
|
print("Creating dummy LED objects - visual feedback will be disabled")
|
||||||
|
led1 = DummyLED(23)
|
||||||
|
led2 = DummyLED(24)
|
||||||
|
log_info_with_server("LED controls using dummy mode")
|
||||||
|
else:
|
||||||
|
print("🚫 Card presence disabled – LED controls skipped")
|
||||||
led1 = DummyLED(23)
|
led1 = DummyLED(23)
|
||||||
led2 = DummyLED(24)
|
led2 = DummyLED(24)
|
||||||
log_info_with_server("LED controls using dummy mode")
|
|
||||||
|
|
||||||
# Initialize table name/ID
|
# Initialize table name/ID
|
||||||
print("Initializing device configuration...")
|
print("Initializing device configuration...")
|
||||||
@@ -1726,13 +1742,18 @@ def initialize_rfid_reader():
|
|||||||
log_info_with_server("ERROR: RFID reader initialization failed")
|
log_info_with_server("ERROR: RFID reader initialization failed")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# Start RFID reader
|
# Start RFID reader only if card_presence is enabled
|
||||||
try:
|
if CARD_PRESENCE_ENABLED:
|
||||||
rfid_reader = initialize_rfid_reader()
|
try:
|
||||||
if rfid_reader is None:
|
rfid_reader = initialize_rfid_reader()
|
||||||
print("WARNING: Application starting without RFID functionality")
|
if rfid_reader is None:
|
||||||
print("Card reading will not work until RFID reader is properly configured")
|
print("WARNING: Application starting without RFID functionality")
|
||||||
except Exception as e:
|
print("Card reading will not work until RFID reader is properly configured")
|
||||||
print(f"Critical error initializing RFID reader: {e}")
|
except Exception as e:
|
||||||
log_info_with_server(f"Critical RFID error: {str(e)}")
|
print(f"Critical error initializing RFID reader: {e}")
|
||||||
print("Application will start but RFID functionality will be disabled")
|
log_info_with_server(f"Critical RFID error: {str(e)}")
|
||||||
|
print("Application will start but RFID functionality will be disabled")
|
||||||
|
else:
|
||||||
|
rfid_reader = None
|
||||||
|
print("🚫 Card presence disabled – RFID reader NOT started")
|
||||||
|
log_info_with_server("Card presence is disabled – RFID reader skipped, running without card reader")
|
||||||
|
|||||||
24
config.py
24
config.py
@@ -47,6 +47,7 @@ def _read_config():
|
|||||||
"hostname": p.get("device", "hostname", fallback=socket.gethostname()),
|
"hostname": p.get("device", "hostname", fallback=socket.gethostname()),
|
||||||
"device_ip": p.get("device", "ip", fallback=_get_local_ip()),
|
"device_ip": p.get("device", "ip", fallback=_get_local_ip()),
|
||||||
"location": p.get("device", "location", fallback=""),
|
"location": p.get("device", "location", fallback=""),
|
||||||
|
"card_presence": p.get("device", "card_presence", fallback="enable"),
|
||||||
"info_reviewed_at":p.get("device", "info_reviewed_at", fallback="1970-01-01T00:00:00"),
|
"info_reviewed_at":p.get("device", "info_reviewed_at", fallback="1970-01-01T00:00:00"),
|
||||||
# preserve other sections verbatim
|
# preserve other sections verbatim
|
||||||
"chrome_url": p.get("chrome", "chrome_url", fallback=""),
|
"chrome_url": p.get("chrome", "chrome_url", fallback=""),
|
||||||
@@ -84,6 +85,7 @@ def _write_config(cfg):
|
|||||||
p.set("device", "hostname", cfg["hostname"])
|
p.set("device", "hostname", cfg["hostname"])
|
||||||
p.set("device", "ip", cfg["device_ip"])
|
p.set("device", "ip", cfg["device_ip"])
|
||||||
p.set("device", "location", cfg.get("location", ""))
|
p.set("device", "location", cfg.get("location", ""))
|
||||||
|
p.set("device", "card_presence", cfg.get("card_presence", "enable"))
|
||||||
p.set("device", "info_reviewed_at", cfg.get("info_reviewed_at", "1970-01-01T00:00:00"))
|
p.set("device", "info_reviewed_at", cfg.get("info_reviewed_at", "1970-01-01T00:00:00"))
|
||||||
|
|
||||||
# Bump last_synced → tells app.py local config is newer → push update request
|
# Bump last_synced → tells app.py local config is newer → push update request
|
||||||
@@ -176,6 +178,12 @@ def main():
|
|||||||
size=(INPUT_W, 1),
|
size=(INPUT_W, 1),
|
||||||
tooltip="Physical location, e.g. Floor 2, Line A, Masa-01")],
|
tooltip="Physical location, e.g. Floor 2, Line A, Masa-01")],
|
||||||
|
|
||||||
|
[sg.Text("Card Presence", size=(LABEL_W, 1)),
|
||||||
|
sg.Combo(["enable", "disable"],
|
||||||
|
default_value=cfg.get("card_presence", "enable"),
|
||||||
|
key="-CARD_PRESENCE-", size=(INPUT_W - 2, 1), readonly=True,
|
||||||
|
tooltip="enable = card reader active; disable = no card reader")],
|
||||||
|
|
||||||
# ── Read-only system info ─────────────────────────────────
|
# ── Read-only system info ─────────────────────────────────
|
||||||
[sg.HorizontalSeparator()],
|
[sg.HorizontalSeparator()],
|
||||||
[sg.Text("── System Info (read-only) ──", font=("Arial Bold", 13),
|
[sg.Text("── System Info (read-only) ──", font=("Arial Bold", 13),
|
||||||
@@ -218,9 +226,10 @@ def main():
|
|||||||
break
|
break
|
||||||
|
|
||||||
if event == "-SAVE-":
|
if event == "-SAVE-":
|
||||||
new_hostname = values["-HOSTNAME-"].strip()
|
new_hostname = values["-HOSTNAME-"].strip()
|
||||||
new_masa = values["-MASA-"].strip()
|
new_masa = values["-MASA-"].strip()
|
||||||
new_location = values["-LOCATION-"].strip()
|
new_location = values["-LOCATION-"].strip()
|
||||||
|
new_card_presence = values["-CARD_PRESENCE-"]
|
||||||
|
|
||||||
if not new_hostname or not new_masa:
|
if not new_hostname or not new_masa:
|
||||||
_show_result("Validation Error",
|
_show_result("Validation Error",
|
||||||
@@ -228,10 +237,11 @@ def main():
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
# Update cfg dict with edited values
|
# Update cfg dict with edited values
|
||||||
cfg["hostname"] = new_hostname
|
cfg["hostname"] = new_hostname
|
||||||
cfg["device_name"] = new_masa
|
cfg["device_name"] = new_masa
|
||||||
cfg["location"] = new_location
|
cfg["location"] = new_location
|
||||||
cfg["device_ip"] = local_ip
|
cfg["card_presence"] = new_card_presence
|
||||||
|
cfg["device_ip"] = local_ip
|
||||||
|
|
||||||
# 1. Save config.txt (bumps last_synced → triggers server update request)
|
# 1. Save config.txt (bumps last_synced → triggers server update request)
|
||||||
try:
|
try:
|
||||||
|
|||||||
Reference in New Issue
Block a user