from flask import Flask, request, jsonify, render_template, redirect, url_for from flask_sqlalchemy import SQLAlchemy from datetime import datetime, timedelta import os 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) message = db.Column(db.String(500), nullable=False) timestamp = db.Column(db.DateTime, default=datetime.utcnow) relay1_status = db.Column(db.String(10), default='off') relay2_status = db.Column(db.String(10), default='off') relay3_status = db.Column(db.String(10), default='off') relay4_status = db.Column(db.String(10), default='off') input1_status = db.Column(db.String(10), default='off') input2_status = db.Column(db.String(10), default='off') input3_status = db.Column(db.String(10), default='off') input4_status = db.Column(db.String(10), default='off') # 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') message = data.get('message') if hostname and message: # Get the latest log for the hostname to determine the current status latest_log = Log.query.filter_by(hostname=hostname).order_by(Log.timestamp.desc()).first() relay1_status = latest_log.relay1_status if latest_log else 'off' relay2_status = latest_log.relay2_status if latest_log else 'off' relay3_status = latest_log.relay3_status if latest_log else 'off' relay4_status = latest_log.relay4_status if latest_log else 'off' input1_status = latest_log.input1_status if latest_log else 'off' input2_status = latest_log.input2_status if latest_log else 'off' input3_status = latest_log.input3_status if latest_log else 'off' input4_status = latest_log.input4_status if latest_log else 'off' # Update the status based on the log message if "Relay 1 turned ON" in message: relay1_status = 'on' elif "Relay 1 turned OFF" in message: relay1_status = 'off' if "Relay 2 turned ON" in message: relay2_status = 'on' elif "Relay 2 turned OFF" in message: relay2_status = 'off' if "Relay 3 turned ON" in message: relay3_status = 'on' elif "Relay 3 turned OFF" in message: relay3_status = 'off' if "Relay 4 turned ON" in message: relay4_status = 'on' elif "Relay 4 turned OFF" in message: relay4_status = 'off' if "Input 1 pressed" in message: input1_status = 'on' elif "Input 1 released" in message: input1_status = 'off' if "Input 2 pressed" in message: input2_status = 'on' elif "Input 2 released" in message: input2_status = 'off' if "Input 3 pressed" in message: input3_status = 'on' elif "Input 3 released" in message: input3_status = 'off' if "Input 4 pressed" in message: input4_status = 'on' elif "Input 4 released" in message: input4_status = 'off' new_log = Log( hostname=hostname, message=message, relay1_status=relay1_status, relay2_status=relay2_status, relay3_status=relay3_status, relay4_status=relay4_status, input1_status=input1_status, input2_status=input2_status, input3_status=input3_status, input4_status=input4_status ) 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(days=10) 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.asc()).all() # Order by ascending timestamp relay_status = ['off', 'off', 'off', 'off'] input_status = ['off', 'off', 'off', 'off'] relay_messages = ['', '', '', ''] input_messages = ['', '', '', ''] # 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 elif f"Input {i + 1} released" in log.message: input_status[i] = 'off' input_messages[i] = log.message return render_template('board.html', hostname=hostname, logs=logs, relay_status=relay_status, input_status=input_status, relay_messages=relay_messages, input_messages=input_messages) @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() latest_log = logs[0] if logs else None return jsonify({ 'logs': [{'timestamp': log.timestamp, 'message': log.message} for log in logs], 'relay_status': { 'relay1': latest_log.relay1_status if latest_log else 'off', 'relay2': latest_log.relay2_status if latest_log else 'off', 'relay3': latest_log.relay3_status if latest_log else 'off', 'relay4': latest_log.relay4_status if latest_log else 'off' }, 'input_status': { 'input1': latest_log.input1_status if latest_log else 'off', 'input2': latest_log.input2_status if latest_log else 'off', 'input3': latest_log.input3_status if latest_log else 'off', 'input4': latest_log.input4_status if latest_log else 'off' } }) if __name__ == '__main__': app.run(host='0.0.0.0', port=5000)