Files
NecroHash/app.py

134 lines
4.4 KiB
Python

from flask import Flask, render_template, jsonify, request, redirect, url_for, flash
from cgminer_api import CgminerAPI
from config_manager import ConfigManager
import os
import subprocess
import json
app = Flask(__name__)
app.secret_key = 'necrohash_miner_control_secret'
miner_api = CgminerAPI()
config_mgr = ConfigManager()
@app.route('/')
def index():
return render_template('dashboard.html', active_page='dashboard')
@app.route('/settings')
def settings():
config = config_mgr.load_config()
# Load mode
mode = 'sha256'
if os.path.exists('mining_mode.conf'):
with open('mining_mode.conf', 'r') as f:
mode = f.read().strip()
return render_template('settings.html', config=config, active_page='settings', mode=mode)
@app.route('/api/data')
def api_data():
try:
summary = miner_api.summary()
devs = miner_api.devs()
pools = miner_api.pools()
stats = miner_api.stats()
# Debug prints to console (visible in journalctl)
if not summary: print("API Error: Summary is None")
if not devs: print("API Error: Devs is None")
# Process data for easier frontend consumption
data = {
'summary': summary['SUMMARY'][0] if summary and 'SUMMARY' in summary else {},
'devs': devs['DEVS'] if devs and 'DEVS' in devs else [],
'pools': pools['POOLS'] if pools and 'POOLS' in pools else [],
'stats': stats if stats else {}
}
return jsonify(data)
except Exception as e:
print(f"API Data Error: {e}")
return jsonify({'error': str(e)})
@app.route('/api/log')
def api_log():
log_path = 'cgminer.log'
if not os.path.exists(log_path):
return jsonify({'log': 'Kein Log gefunden.'})
try:
# Read last 50 lines
with open(log_path, 'r') as f:
lines = f.readlines()
return jsonify({'log': ''.join(lines[-50:])})
except Exception as e:
return jsonify({'log': f'Fehler beim Lesen des Logs: {str(e)}'})
@app.route('/save_settings', methods=['POST'])
def save_settings():
# Construct config object from form
# Note: cgminer config structure handling
new_config = config_mgr.load_config() # Start with existing
# Save mode
mode = request.form.get('mining_mode', 'sha256')
try:
with open('mining_mode.conf', 'w') as f:
f.write(mode)
except Exception as e:
print(f"Error saving mode: {e}")
# Update simple fields
new_config['gridseed-options'] = f"freq={request.form.get('freq', '850')}"
# Update pool (handling single pool for simplicity in this MVP, extended later)
pool_url = request.form.get('pool_url')
pool_user = request.form.get('pool_user')
pool_pass = request.form.get('pool_pass')
if pool_url:
# Replace first pool or add if empty
pool_data = {"url": pool_url, "user": pool_user, "pass": pool_pass}
if new_config.get('pools'):
new_config['pools'][0] = pool_data
else:
new_config['pools'] = [pool_data]
if config_mgr.save_config(new_config):
flash('Einstellungen gespeichert. Bitte Miner neu starten.', 'success')
else:
flash('Fehler beim Speichern.', 'danger')
return redirect(url_for('settings'))
@app.route('/save_raw_config', methods=['POST'])
def save_raw_config():
try:
raw_data = request.form.get('raw_config')
config_data = json.loads(raw_data)
if config_mgr.save_config(config_data):
flash('Konfiguration gespeichert. Miner Neustart erforderlich.', 'success')
else:
flash('Fehler beim Speichern der Datei.', 'danger')
except json.JSONDecodeError:
flash('Ungültiges JSON Format.', 'danger')
except Exception as e:
flash(f'Fehler: {str(e)}', 'danger')
return redirect(url_for('settings'))
@app.route('/control/restart')
def restart_miner():
# Attempt to restart via API first, if fails, might need system command
result = miner_api.restart()
if result:
return jsonify({'status': 'success', 'message': 'Restart command sent'})
return jsonify({'status': 'error', 'message': 'Could not contact miner'})
if __name__ == '__main__':
# Run on all interfaces
# Port 80 requires authbind or root
app.run(host='0.0.0.0', port=80, debug=True)