212 lines
7.3 KiB
Python
212 lines
7.3 KiB
Python
import subprocess
|
|
import threading
|
|
import time
|
|
import requests
|
|
import os
|
|
import pymysql
|
|
import logging
|
|
import bcrypt
|
|
import configparser
|
|
from functools import partial
|
|
|
|
CONFIG_PATH = "/app/config.ini"
|
|
#CONFIG_PATH = "../config.ini"
|
|
config = configparser.ConfigParser()
|
|
config.read(CONFIG_PATH)
|
|
loglevel_str = config["log"]["level"].upper()
|
|
loglevel = getattr(logging, loglevel_str, logging.INFO)
|
|
logging.basicConfig(level=loglevel)
|
|
|
|
DB_CONFIG = {
|
|
'host': config["database"]["host"],
|
|
'user': config["database"]["user"],
|
|
'password': config["database"]["password"],
|
|
'database': config["database"]["database"]
|
|
}
|
|
|
|
LICENSE_SERVER = "https://sikkerdata.com/validate_license.php"
|
|
LICENSE_KEY = config["license"]["license_key"]
|
|
with open("/etc/machine-id", "r") as f:
|
|
get_HWID = f.read().strip()
|
|
|
|
def validate_license():
|
|
try:
|
|
hwid = get_HWID
|
|
response = requests.post(LICENSE_SERVER, json={
|
|
"license_key": LICENSE_KEY,
|
|
"hwid": hwid
|
|
}, timeout=5)
|
|
logging.info(f"[MAIN] License server response: {response.text}")
|
|
if response.status_code == 200:
|
|
result = response.json()
|
|
if result.get("status") == "valid":
|
|
logging.info("[MAIN] License validated")
|
|
return True
|
|
else:
|
|
logging.info(f"[MAIN] License check failed: {result.get('message')}")
|
|
return False
|
|
else:
|
|
logging.info(f"[MAIN] License server error: {response.status_code}")
|
|
return False
|
|
except Exception as e:
|
|
logging.info(f"[MAIN] License check exception: {e}")
|
|
return False
|
|
|
|
def setup_database(db_config):
|
|
conn = pymysql.connect(**db_config)
|
|
cursor = conn.cursor()
|
|
|
|
def table_exists(name):
|
|
cursor.execute("SHOW TABLES LIKE %s", (name,))
|
|
return cursor.fetchone() is not None
|
|
|
|
# Create `users` table if missing
|
|
if not table_exists('users'):
|
|
print("[DB] Creating 'users' table...")
|
|
cursor.execute("""
|
|
CREATE TABLE users (
|
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
username VARCHAR(50) NOT NULL UNIQUE,
|
|
full_name VARCHAR(100) NOT NULL,
|
|
email VARCHAR(255) NOT NULL UNIQUE,
|
|
phone VARCHAR(20),
|
|
password_hash VARCHAR(255) NOT NULL,
|
|
totp_secret VARCHAR(64),
|
|
user_role ENUM('Admin','Operator','Installer','Client') DEFAULT 'Client',
|
|
access_group VARCHAR(100),
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
""")
|
|
|
|
# Create `signals` table if missing
|
|
if not table_exists('signals'):
|
|
print("[DB] Creating 'signals' table...")
|
|
cursor.execute("""
|
|
CREATE TABLE signals (
|
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
protocol VARCHAR(10) NOT NULL,
|
|
raw_message TEXT NOT NULL,
|
|
account VARCHAR(20),
|
|
sequence VARCHAR(10),
|
|
line_number VARCHAR(10),
|
|
event_code VARCHAR(10),
|
|
partition VARCHAR(10),
|
|
zone VARCHAR(20),
|
|
signal_time DATETIME,
|
|
source_ip VARCHAR(45),
|
|
signal_text VARCHAR(255),
|
|
v TEXT,
|
|
x TEXT,
|
|
y TEXT
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
""")
|
|
if not table_exists('receivers'):
|
|
print("[DB] Creating 'receivers' table...")
|
|
cursor.execute("""
|
|
CREATE TABLE receivers (
|
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
name VARCHAR(50) NOT NULL,
|
|
type ENUM('SIA-DC09') NOT NULL DEFAULT 'SIA-DC09',
|
|
tcpport INT NOT NULL,
|
|
enabled BOOLEAN DEFAULT 1
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
""")
|
|
cursor.execute("""INSERT INTO receivers (name, type, tcpport, enabled) VALUES ('Main Receiver', 'SIA-DC09', 9000, 1);""")
|
|
|
|
# If no users exist, create default admin
|
|
cursor.execute("SELECT COUNT(*) FROM users")
|
|
(user_count,) = cursor.fetchone()
|
|
if user_count == 0:
|
|
print("[DB] Inserting default admin user...")
|
|
default_password = bcrypt.hashpw("admin123".encode(), bcrypt.gensalt()).decode('utf-8')
|
|
cursor.execute("""
|
|
INSERT INTO users (username, full_name, email, password_hash, user_role)
|
|
VALUES (%s, %s, %s, %s, %s)
|
|
""", ("admin", "Admin", "admin@example.com", default_password, "Admin"))
|
|
print("[DB] Admin created with username 'admin' and password 'admin123'")
|
|
|
|
conn.commit()
|
|
cursor.close()
|
|
conn.close()
|
|
|
|
running_services = {}
|
|
|
|
def watchdog():
|
|
bin_path = "/app/watchdog.bin"
|
|
def run_watchdog():
|
|
while True:
|
|
cmd = [bin_path]
|
|
logging.debug(f"[MAIN] Starting Watchdog...")
|
|
process = subprocess.Popen(cmd)
|
|
running_services["Watchdog"] = process
|
|
process.wait()
|
|
logging.debug(f"[MAIN] Watchdog finished. Restarting in 5s...")
|
|
time.sleep(5)
|
|
|
|
thread = threading.Thread(target=run_watchdog, name="Watchdog", daemon=True)
|
|
thread.start()
|
|
|
|
def is_watchdog_running():
|
|
return any(thread.name == "Watchdog" and thread.is_alive() for thread in threading.enumerate())
|
|
|
|
def main():
|
|
logging.info("[MAIN] Starting main function")
|
|
try:
|
|
if not validate_license():
|
|
logging.info("[MAIN] Shutting down due to invalid license.")
|
|
return
|
|
setup_thread = threading.Thread(target=partial(setup_database, DB_CONFIG), daemon=True)
|
|
setup_thread.start()
|
|
setup_thread.join() # Wait for DB setup before continuing
|
|
|
|
while True:
|
|
try:
|
|
logging.debug(f"[MAIN] Main is running")
|
|
|
|
if is_watchdog_running():
|
|
logging.debug("[MAIN] Watchdog thread is already running")
|
|
else:
|
|
watchdog()
|
|
|
|
time.sleep(10)
|
|
except Exception as e:
|
|
logging.exception(f"[MAIN] Exception while logging thread status: {e}")
|
|
|
|
except KeyboardInterrupt:
|
|
logging.info("Graceful shutdown requested")
|
|
|
|
def wait_for_mariadb(host, port, user, password, database, timeout=5):
|
|
logging.info(f"[WAIT] Waiting for MariaDB at {host}:{port} to become ready...")
|
|
while True:
|
|
try:
|
|
conn = pymysql.connect(
|
|
host=host,
|
|
port=port,
|
|
user=user,
|
|
password=password,
|
|
database=database,
|
|
connect_timeout=timeout
|
|
)
|
|
with conn.cursor() as cursor:
|
|
cursor.execute("SELECT 1;")
|
|
result = cursor.fetchone()
|
|
if result:
|
|
logging.info("[WAIT] MariaDB is ready.")
|
|
conn.close()
|
|
break
|
|
except pymysql.MySQLError as e:
|
|
logging.warning(f"[WAIT] MariaDB not ready yet: {e}")
|
|
time.sleep(timeout)
|
|
|
|
if __name__ == "__main__":
|
|
wait_for_mariadb(
|
|
host=config["database"]["host"],
|
|
port=3306,
|
|
user=config["database"]["user"],
|
|
password=config["database"]["password"],
|
|
database=config["database"]["database"]
|
|
)
|
|
main()
|
|
|