88 lines
3.3 KiB
Python
88 lines
3.3 KiB
Python
import os
|
|
import warnings
|
|
|
|
os.environ['EVENTLET_NO_GREENDNS'] = 'yes'
|
|
import eventlet
|
|
eventlet.monkey_patch(all=True)
|
|
|
|
from flask import Flask, render_template, jsonify, request
|
|
from flask_socketio import SocketIO
|
|
from influxdb import InfluxDBClient
|
|
import config
|
|
|
|
warnings.filterwarnings("ignore", category=DeprecationWarning, module="eventlet")
|
|
|
|
app = Flask(__name__)
|
|
app.config['SECRET_KEY'] = config.FLASK_CONFIG['secret_key']
|
|
socketio = SocketIO(app, cors_allowed_origins="*", async_mode='eventlet')
|
|
|
|
def get_influx_client():
|
|
client = InfluxDBClient(
|
|
host=config.INFLUXDB_CONFIG['host'],
|
|
port=config.INFLUXDB_CONFIG['port'],
|
|
database=config.INFLUXDB_CONFIG['database']
|
|
)
|
|
if config.INFLUXDB_CONFIG['username']:
|
|
client.switch_user(config.INFLUXDB_CONFIG['username'], config.INFLUXDB_CONFIG['password'])
|
|
return client
|
|
|
|
def get_current_voltage(phase_id):
|
|
client = get_influx_client()
|
|
entity_id = config.PHASES[phase_id]['entity_id']
|
|
query = f'SELECT "value" FROM "{config.MEASUREMENT}" WHERE "entity_id" = \'{entity_id}\' ORDER BY time DESC LIMIT 1'
|
|
try:
|
|
result = client.query(query)
|
|
points = list(result.get_points())
|
|
if points and points[0].get('value') is not None:
|
|
return {'voltage': round(float(points[0]['value']), 2), 'timestamp': points[0]['time']}
|
|
except Exception as e:
|
|
print(f"Current Error: {e}")
|
|
finally:
|
|
client.close()
|
|
return {'voltage': 0, 'timestamp': None}
|
|
|
|
@app.route('/')
|
|
def index():
|
|
return render_template('index.html', phases=config.PHASES, time_ranges=config.TIME_RANGES,
|
|
default_range=config.DEFAULT_TIME_RANGE, footer=config.FOOTER)
|
|
|
|
@app.route('/api/timeseries/<int:phase_id>')
|
|
def api_timeseries(phase_id):
|
|
if phase_id not in config.PHASES: return jsonify({'error': 'Invalid phase'}), 400
|
|
client = get_influx_client()
|
|
t_range = request.args.get('range', config.DEFAULT_TIME_RANGE)
|
|
cfg = config.TIME_RANGES.get(t_range, config.TIME_RANGES['24h'])
|
|
query = config.PHASES[phase_id]['query'].replace('$timeFilter', cfg['filter']).replace('$__interval', cfg['interval'])
|
|
try:
|
|
result = client.query(query)
|
|
data = []
|
|
for p in result.get_points():
|
|
val = p.get('voltage') or p.get('min') or p.get('mean') or p.get('value')
|
|
if val is not None:
|
|
data.append({'time': p['time'], 'voltage': round(float(val), 2)})
|
|
else:
|
|
data.append({'time': p['time'], 'voltage': 0})
|
|
return jsonify(data)
|
|
except Exception as e:
|
|
print(f"History Error: {e}")
|
|
return jsonify([])
|
|
finally:
|
|
client.close()
|
|
|
|
def background_voltage_update():
|
|
while True:
|
|
try:
|
|
voltages = {'timestamp': None}
|
|
for pid in config.PHASES.keys():
|
|
res = get_current_voltage(pid)
|
|
voltages[f'phase{pid}'] = res['voltage']
|
|
if res['timestamp']: voltages['timestamp'] = res['timestamp']
|
|
socketio.emit('voltage_update', voltages)
|
|
except Exception as e:
|
|
print(f"Worker Error: {e}")
|
|
eventlet.sleep(config.CHART_CONFIG['update_interval'] / 1000)
|
|
|
|
if __name__ == '__main__':
|
|
eventlet.spawn(background_voltage_update)
|
|
socketio.run(app, host='0.0.0.0', port=config.FLASK_CONFIG['port'])
|