from flask import Flask, request, jsonify, render_template, redirect, url_for from flask_sqlalchemy import SQLAlchemy from datetime import datetime, timedelta import os import threading import requests app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///logs.db' app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False db = SQLAlchemy(app) class Log(db.Model): id = db.Column(db.Integer, primary_key=True) hostname = db.Column(db.String(100), nullable=False) ip_address = db.Column(db.String(100), nullable=False) message = db.Column(db.String(500), nullable=False) timestamp = db.Column(db.DateTime, default=datetime.utcnow) # Create the database if it does not exist if not os.path.exists('instance/logs.db'): with app.app_context(): db.create_all() # Flag to check if tables are created tables_created = False @app.before_request def create_tables(): global tables_created if not tables_created: db.create_all() tables_created = True @app.route('/log', methods=['POST']) def log_message(): data = request.get_json() hostname = data.get('hostname') ip_address = data.get('ip_address') message = data.get('message') if hostname and ip_address and message: new_log = Log(hostname=hostname, ip_address=ip_address, message=message) db.session.add(new_log) db.session.commit() return jsonify({'status': 'success', 'message': 'Log saved'}), 201 return jsonify({'status': 'error', 'message': 'Invalid data'}), 400 @app.route('/logs', methods=['GET']) def get_logs(): logs = Log.query.all() return jsonify([{'id': log.id, 'hostname': log.hostname, 'message': log.message, 'timestamp': log.timestamp} for log in logs]) @app.route('/cleanup', methods=['DELETE']) def cleanup_logs(): cutoff_date = datetime.utcnow() - timedelta(hours=24) Log.query.filter(Log.timestamp < cutoff_date).delete() db.session.commit() return jsonify({'status': 'success', 'message': 'Old logs deleted'}) @app.route('/') def index(): # Get the latest log entry for each board latest_logs = db.session.query(Log).order_by(Log.timestamp.desc()).all() boards = {} for log in latest_logs: if log.hostname not in boards: boards[log.hostname] = log # Determine the status of each board board_status = [] for hostname, log in boards.items(): time_diff = datetime.utcnow() - log.timestamp status = 'Online' if time_diff.total_seconds() <= 20 else 'Possible Offline' board_status.append({'hostname': hostname, 'status': status, 'last_seen': log.timestamp}) return render_template('index.html', boards=board_status) @app.route('/board/') def view_board(hostname): logs = Log.query.filter_by(hostname=hostname).order_by(Log.timestamp.desc()).limit(50).all() relay_status = ['off', 'off', 'off', 'off'] input_status = ['off', 'off', 'off', 'off'] relay_messages = ['', '', '', ''] input_messages = ['', '', '', ''] ip_address = logs[0].ip_address if logs else '' # Get the IP address from the logs last_update = logs[0].timestamp if logs else None # Get the last update time # Determine the status of each relay and input based on the latest log messages for log in logs: for i in range(4): if f"Relay {i + 1} turned ON" in log.message: relay_status[i] = 'on' relay_messages[i] = log.message elif f"Relay {i + 1} turned OFF" in log.message: relay_status[i] = 'off' relay_messages[i] = log.message if f"Input {i + 1} pressed" in log.message: input_status[i] = 'on' input_messages[i] = log.message post_action_to_server(hostname, f"Input {i + 1} pressed") elif f"Input {i + 1} released" in log.message: input_status[i] = 'off' input_messages[i] = log.message post_action_to_server(hostname, f"Input {i + 1} released") return render_template('board.html', hostname=hostname, ip_address=ip_address, logs=logs, relay_status=relay_status, input_status=input_status, relay_messages=relay_messages, input_messages=input_messages, last_update=last_update) @app.route('/delete_board/', methods=['POST']) def delete_board(hostname): Log.query.filter_by(hostname=hostname).delete() db.session.commit() return redirect(url_for('index')) @app.route('/board//logs', methods=['GET']) def get_board_logs(hostname): logs = Log.query.filter_by(hostname=hostname).order_by(Log.timestamp.desc()).all() return jsonify({'logs': [{'timestamp': log.timestamp, 'message': log.message} for log in logs]}) @app.route('/board//relay//', methods=['POST']) def control_relay(hostname, relay, action): log = Log.query.filter_by(hostname=hostname).order_by(Log.timestamp.desc()).first() if log: ip_address = log.ip_address url = f"http://{ip_address}/relay" payload = { "relay": relay, "action": action } try: response = requests.post(url, data=payload) if response.status_code == 200: return redirect(url_for('view_board', hostname=hostname)) else: return f"Failed to control relay: {response.text}", 500 except Exception as e: return f"Error controlling relay: {e}", 500 else: return f"No logs found for hostname: {hostname}", 404 def post_action_to_server(hostname, action): url = "http://your-server-url.com/action" payload = { "hostname": hostname, "action": action } try: response = requests.post(url, json=payload) if response.status_code == 200: print(f"Action posted successfully: {action}") else: print(f"Failed to post action: {action}") except Exception as e: print(f"Error posting action: {e}") def schedule_cleanup(): with app.app_context(): cutoff_date = datetime.utcnow() - timedelta(hours=24) Log.query.filter(Log.timestamp < cutoff_date).delete() db.session.commit() threading.Timer(3600, schedule_cleanup).start() if __name__ == '__main__': schedule_cleanup() # Start the cleanup scheduler app.run(host='0.0.0.0', port=5000)