Add .gitignore, update app.py and config.py, remove stale docs
This commit is contained in:
442
config.py
442
config.py
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user