Add .gitignore, update app.py and config.py, remove stale docs

This commit is contained in:
2026-04-23 16:04:35 +03:00
parent c6dcdc068d
commit 35fb6b93ad
6 changed files with 677 additions and 531 deletions

442
config.py
View File

@@ -1,203 +1,273 @@
# config py este gandit pentru a verifica configurarile raspberiului
# verifica hostname-ul si il afiseaza
# verifica ce nume are masa si o afiseaza
# verifica daca masa este configurata cu sistem de prezenta operator
# verifica daca imprimanta este instalata corespunzator
# WMT Device Configuration Tool
# Reads/writes data/config.txt (INI format).
# On save, bumps [meta] last_synced to NOW so app.py will push an
# update-request to Server_Monitorizare_v2 on next startup.
import os
import time
import socket
import subprocess
import configparser
from datetime import datetime
import os, time, socket, cups, subprocess
import FreeSimpleGUI as psg
import FreeSimpleGUI as sg
from multiprocessing import Process
CONFIG_PATH = "./data/config.txt"
# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------
# import socket
host = socket.gethostname() # luam numele de host
def set_printer(): # importam codul python pentru printer
print("Cheking printer")
# acest segment acceseaza fisierul local idmas.txt si verifica ce informatii sunt acolo
# in mod normal acolo salvam numele mesei care trebuie sa corespunda cu numele imprimantei
f = open("./data/idmasa.txt","r") # deschid fisierul in care am salvat numele printerului
test = f.readlines() # citesc toate liniile
f.close()
# in cazul in care avem fisier corupt il resetam la original
def _get_os_version():
try:
idmasa = test[0]
except IndexError:
idmasa = "0"
print(idmasa)
# citim lista de printere disponibila
conn = cups.Connection ()
printers = conn.getPrinters ()
printer_stat=0
for printer in printers:
print (printer, printers[printer]["device-uri"])
if printer == idmasa:
printer_stat = 1
with open("/etc/os-release") as f:
for line in f:
if line.startswith("PRETTY_NAME="):
return line.split("=", 1)[1].strip().strip('"')
except Exception:
pass
return "unknown"
if printer_stat == 1:
print("Printer is Ok")
else:
print("Printer is not ok")
p_Name = idmasa
print("Installing the new printer")
time.sleep(2)
cmd = "sudo /usr/sbin/lpadmin -p "+idmasa+" -E -v usb://CITIZEN/CT-S310II?serial=00000000 -m CTS310II.ppd"
os.popen(cmd)
time.sleep(2)
print("Printer Was Installed")
def _get_local_ip():
try:
h = socket.gethostname()
return socket.gethostbyname(h)
except Exception:
return "127.0.0.1"
def _read_config():
"""Return a dict with all device-relevant fields from config.txt."""
p = configparser.ConfigParser()
p.read(CONFIG_PATH)
return {
"device_name": p.get("device", "name", fallback="notconfig"),
"hostname": p.get("device", "hostname", fallback=socket.gethostname()),
"device_ip": p.get("device", "ip", fallback=_get_local_ip()),
"location": p.get("device", "location", fallback=""),
"info_reviewed_at":p.get("device", "info_reviewed_at", fallback="1970-01-01T00:00:00"),
# preserve other sections verbatim
"chrome_url": p.get("chrome", "chrome_url", fallback=""),
"chrome_local_url": p.get("chrome", "chrome_local_url", fallback=""),
"chrome_insecure_origin":p.get("chrome", "chrome_insecure_origin",fallback=""),
"card_api_base_url": p.get("card_api", "base_url", fallback=""),
"server_log_url": p.get("server", "log_url", fallback=""),
"update_host": p.get("server", "update_host", fallback=""),
"update_user": p.get("server", "update_user", fallback=""),
"internet_check_host": p.get("server", "internet_check_host", fallback=""),
"last_synced": p.get("meta", "last_synced", fallback="1970-01-01T00:00:00"),
}
def _write_config(cfg):
"""Write all fields back to config.txt and bump last_synced to NOW."""
p = configparser.ConfigParser()
p.add_section("chrome")
p.set("chrome", "chrome_url", cfg.get("chrome_url", ""))
p.set("chrome", "chrome_local_url", cfg.get("chrome_local_url", ""))
p.set("chrome", "chrome_insecure_origin",cfg.get("chrome_insecure_origin", ""))
p.add_section("card_api")
p.set("card_api", "base_url", cfg.get("card_api_base_url", ""))
p.add_section("server")
p.set("server", "log_url", cfg.get("server_log_url", ""))
p.set("server", "update_host", cfg.get("update_host", ""))
p.set("server", "update_user", cfg.get("update_user", ""))
p.set("server", "internet_check_host", cfg.get("internet_check_host", ""))
p.add_section("device")
p.set("device", "name", cfg["device_name"])
p.set("device", "hostname", cfg["hostname"])
p.set("device", "ip", cfg["device_ip"])
p.set("device", "location", cfg.get("location", ""))
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
now_ts = datetime.now().isoformat(timespec="seconds")
p.add_section("meta")
p.set("meta", "last_synced", now_ts)
os.makedirs("./data", exist_ok=True)
with open(CONFIG_PATH, "w") as f:
f.write("# WMT Application Configuration\n")
f.write(f"# Last updated by config.py: {now_ts}\n\n")
p.write(f)
# Keep legacy idmasa.txt in sync for older code paths
with open("./data/idmasa.txt", "w") as f:
f.write(cfg["device_name"])
print(f"✓ config.txt saved (last_synced={now_ts})")
def _set_printer(device_name):
"""Configure CUPS printer to match the device/masa name."""
try:
import cups
conn = cups.Connection()
printers = conn.getPrinters()
for printer in printers:
print(printer, printers[printer]["device-uri"])
time.sleep(1)
print("Printerwas seted to "+idmasa+"")
print("Test printer App Closed")
# partea acesata se ocupa de verificarea existentei celor doua fisiere pentru a nu avea erori
# verificam daca exista fisierul care identifica masa
path = './data/idmasa.txt'
isFile = os.path.isfile(path) #verifica existenta fisierului prin bolean Tru/false
if not isFile:
# print(path)# nu se face nimic pentru ca exista fisierul
fp = open("./data/idmasa.txt", 'w') # cream fisier
fp.write('noconfig') # scriem in fisier prima line pentru a avea un punct de pornire
fp.close() # inchidem fisierul
# verificam fisierul de prezenta pe baza acestuia stim daca locul de munca este configurat cu card de prezenta sau nu
path1 = './data/idmasa.txt' #verificare existenta al doilea fisier
isFile = os.path.isfile(path1)# verifica existenta fisierului
#urmeaza sa citim fisierele pentru a crea cateva variabile
# prima variabila este idmasa
f = open("./data/idmasa.txt","r") # deschid fisierul
name = f.readlines() # citesc toate liniile
f.close() # inchid fisierul
try:
idmasa = name[0]# se verifica daca exista informatie in text
except IndexError:
idmasa = "noconfig"# daca nu exista informatie in text setam variabila
n_config = 0
#incepem sa definim primele functii din configurare
def notokfunction(): # este functie pentru butonul cancel din formular
global n_config
msg1 = "Id masa a fost actualizat la: "+ idmasa +"" ## pregatim mesajul pentru fereastra pop up
n_config = 1
msg2 = "Slotul Pentru cartela este configurat by default" # pregatim mesajul pentru fereastra pop up
layout = [[sg.Text(msg1)], [sg.Text(msg2)], [sg.Button("Ok")]]
window = sg.Window("Configurari", layout)
while True:
event, values = window.read()
if event == "Ok" or event == sg.WIN_CLOSED:
break
window.close()
#am inchis functia notok
#functia pentru butonul ok din formular
def okfunction():
global n_config
if idmasa == config1: # variabila config 1 este preluata din formular
msg1 = "Masa este setat corect: "+ idmasa +"" # se printeaza mesaj ca nu se actualizeaza id de masa
# print(msg1)
else:
f = open("./data/idmasa.txt","w") # deschidem fisierul config in mod scriere
L = config1
f.write(L) # actualizam linia cu noua valuare din config
f.close() # inchidem fisierul
msg1 = "Id masa a fost actualizat la: "+ config1 +"" # pregatim mesajul pentru fereastra pop up
n_config = 0
#
# definim fereastra pentru ok asemena cu functia notok
layout = [[sg.Text(msg1)], [sg.Output(size=(40, 15))], [sg.Button("Ok")]]
window = sg.Window("Configurari", layout)
while True:
event, values = window.read()
# End program if user closes window or
# presses the OK button
if event == "Ok" or event == sg.WIN_CLOSED:
break
if nook == 1:
notokfunction()
n_config = 1
time.sleep(2)
#asteptam 10 secunde si pornim functia de setare printer
set_printer()
#verificam daca hostul corespunde cu ce este in formular
time.sleep(2)
if host == host_conf:
print("Host name ok")
else:
print("Host name not ok")
time.sleep(2)
print("Update Hostname" )
cmd = "sudo hostnamectl set-hostname "+host_conf+"" # comanda sa schimbam hostnameul
if device_name in printers:
print(f"Printer '{device_name}' is already configured.")
return
print(f"Installing printer '{device_name}' ...")
cmd = (f"sudo /usr/sbin/lpadmin -p {device_name} -E "
f"-v usb://CITIZEN/CT-S310II?serial=00000000 -m CTS310II.ppd")
os.popen(cmd)
print("Os hostname updated")
time.sleep(2)
print("System will reboot in 5 seconds")
time.sleep(1)
print("System will reboot in 4 seconds")
time.sleep(1)
print("System will reboot in 3 seconds")
time.sleep(1)
print("System will reboot in 2 seconds")
time.sleep(1)
print("System will reboot in 1 seconds")
time.sleep(3)
print(f"Printer '{device_name}' installed.")
except Exception as e:
print(f"Printer setup skipped: {e}")
def _update_hostname(new_hostname):
"""Change system hostname if it differs from the current one."""
current = socket.gethostname()
if current == new_hostname:
print(f"Hostname unchanged: {new_hostname}")
return
print(f"Updating hostname: {current}{new_hostname}")
subprocess.run(["sudo", "hostnamectl", "set-hostname", new_hostname], check=False)
print("Hostname updated. A reboot is recommended.")
def _show_result(title, lines):
"""Simple modal popup."""
layout = [[sg.Text(line)] for line in lines] + [[sg.Button("OK")]]
w = sg.Window(title, layout, modal=True)
while True:
ev, _ = w.read()
if ev in (sg.WIN_CLOSED, "OK"):
break
w.close()
# ---------------------------------------------------------------------------
# Main GUI
# ---------------------------------------------------------------------------
def main():
cfg = _read_config()
os_ver = _get_os_version()
local_ip = _get_local_ip()
sg.theme("Dark Grey 9")
sg.set_options(font=("Arial Bold", 15))
LABEL_W = 22
INPUT_W = 38
layout = [
[sg.Text("WMT Device Configuration", font=("Arial Bold", 18),
justification="center", expand_x=True, pad=(0, 12))],
# ── Editable fields ──────────────────────────────────────
[sg.HorizontalSeparator()],
[sg.Text("── Device Identity ──", font=("Arial Bold", 13),
text_color="#aaaaaa", pad=(0, 6))],
[sg.Text("Hostname", size=(LABEL_W, 1)),
sg.InputText(cfg["hostname"], key="-HOSTNAME-", size=(INPUT_W, 1))],
[sg.Text("Loc de Munca / Masa", size=(LABEL_W, 1)),
sg.InputText(cfg["device_name"], key="-MASA-", size=(INPUT_W, 1))],
[sg.Text("Location", size=(LABEL_W, 1)),
sg.InputText(cfg.get("location", ""), key="-LOCATION-",
size=(INPUT_W, 1),
tooltip="Physical location, e.g. Floor 2, Line A, Masa-01")],
# ── Read-only system info ─────────────────────────────────
[sg.HorizontalSeparator()],
[sg.Text("── System Info (read-only) ──", font=("Arial Bold", 13),
text_color="#aaaaaa", pad=(0, 6))],
[sg.Text("OS Version", size=(LABEL_W, 1)),
sg.InputText(os_ver, key="-OS-", size=(INPUT_W, 1),
disabled=True, text_color="#888888")],
[sg.Text("IP Address", size=(LABEL_W, 1)),
sg.InputText(local_ip, key="-IP-", size=(INPUT_W, 1),
disabled=True, text_color="#888888")],
[sg.Text("Last Synced", size=(LABEL_W, 1)),
sg.InputText(cfg["last_synced"], key="-SYNC-", size=(INPUT_W, 1),
disabled=True, text_color="#888888")],
# ── Status output ─────────────────────────────────────────
[sg.HorizontalSeparator()],
[sg.Multiline("", key="-OUT-", size=(62, 5), disabled=True,
autoscroll=True, background_color="#1a1a1a",
text_color="#cccccc", font=("Courier", 12))],
# ── Buttons ───────────────────────────────────────────────
[sg.Button("Save & Apply", key="-SAVE-", button_color=("white", "#2980b9"), size=(18, 1)),
sg.Button("Cancel", key="-CANCEL-", size=(12, 1))],
]
window = sg.Window("WMT Configuration", layout, size=(720, 540), finalize=True)
def log(msg):
window["-OUT-"].update(disabled=False)
window["-OUT-"].print(msg)
window["-OUT-"].update(disabled=True)
while True:
event, values = window.read()
if event in (sg.WIN_CLOSED, "-CANCEL-"):
break
if event == "-SAVE-":
new_hostname = values["-HOSTNAME-"].strip()
new_masa = values["-MASA-"].strip()
new_location = values["-LOCATION-"].strip()
if not new_hostname or not new_masa:
_show_result("Validation Error",
["Hostname and Loc de Munca / Masa are required."])
continue
# Update cfg dict with edited values
cfg["hostname"] = new_hostname
cfg["device_name"] = new_masa
cfg["location"] = new_location
cfg["device_ip"] = local_ip
# 1. Save config.txt (bumps last_synced → triggers server update request)
try:
_write_config(cfg)
log("✓ config.txt saved. last_synced updated to NOW.")
log(" → app.py will push update request to server on next start.")
except Exception as e:
log(f"✗ Failed to save config.txt: {e}")
# 2. Update hostname if changed
try:
_update_hostname(new_hostname)
log(f"✓ Hostname: {new_hostname}")
except Exception as e:
log(f"✗ Hostname update error: {e}")
# 3. Configure printer
try:
_set_printer(new_masa)
log(f"✓ Printer check done for '{new_masa}'.")
except Exception as e:
log(f" Printer: {e}")
log("")
log("Done. Reboot recommended if hostname changed.")
window.close()
# incepem initializarea feresteri ptrincipale gui
sg.theme('dark grey 9') #alegem tema dark grey
psg.set_options(font=('Arial Bold', 16)) # setam fontul
#setarile de layout
layout = [
[sg.Text('Host_Name', size=(20,1)),sg.InputText(default_text= ""+host+"" , enable_events=False)],
[sg.Text('Loc De Munca', size=(20,1)),sg.InputText(default_text=""+idmasa+"", enable_events=False)],
[sg.Button('Ok'), sg.Button('Cancel')]
]
# setam window
window = psg.Window('Form', layout, size=(800,190),finalize=True)
# citim si configuram widgetul pentru butoanele 1 si 0 din randul
while True:
nook = 0 # cream o variabila care sa ne spuna daca a fost setao butonul ok sau nu
event, values = window.read() # citim valorile intr-o lista numita values
host_conf= values[0] # atribuim primul item din lista variabilei Host config
# aceasta variabila o vom folosi pentru a scrie sa nu noul hostname
print(host_conf)
if event == sg.WIN_CLOSED or event == 'Cancel':
nook = 1 # daca se da cancel setam variabila nook la 1
n_config = 1 # setam variabila n_config la 1
break
config1 = values[1] # atribuim lui config 1 valuarea din campul Loc de munca care a fost scris cu Id masa
# pornim functi care scrie valorile config in fisiere ok function
okfunction()
# si inchidem formularul
# semnalam ca s-a terminat afisarea formularului
break
#inchidem formularul
if __name__ == "__main__":
main()
window.close()
# daca variabila nook este 1
time.sleep(2)