completed basic recording functionality
This commit is contained in:
@@ -1,21 +1,20 @@
|
||||
from typing import List
|
||||
from tools.cfg_util.record.manager import RecordingManager
|
||||
from tools.cfg_util.record.layout import record_window
|
||||
import PySimpleGUI as sg
|
||||
|
||||
|
||||
async def start_recording(ips: List[str], file: str, interval: int = 10):
|
||||
async def start_recording(
|
||||
ips: List[str], file: str, record_window: sg.Window, interval: int = 10
|
||||
):
|
||||
record_window["start_recording"].update(visible=False)
|
||||
record_window["stop_recording"].update(visible=True)
|
||||
record_window["pause_recording"].update(visible=True)
|
||||
record_window["resume_recording"].update(visible=False)
|
||||
record_window["_placeholder"].update(visible=False)
|
||||
await RecordingManager().record(
|
||||
ips,
|
||||
file,
|
||||
)
|
||||
await RecordingManager().record(ips, file, record_window, interval=interval)
|
||||
|
||||
|
||||
async def pause_recording():
|
||||
async def pause_recording(record_window):
|
||||
await RecordingManager().pause()
|
||||
record_window["resume_recording"].update(visible=True)
|
||||
record_window["start_recording"].update(visible=False)
|
||||
@@ -23,7 +22,7 @@ async def pause_recording():
|
||||
record_window["pause_recording"].update(visible=False)
|
||||
|
||||
|
||||
async def stop_recording():
|
||||
async def stop_recording(record_window):
|
||||
await RecordingManager().stop()
|
||||
record_window["start_recording"].update(visible=True)
|
||||
record_window["stop_recording"].update(visible=False)
|
||||
@@ -32,7 +31,7 @@ async def stop_recording():
|
||||
record_window["_placeholder"].update(visible=True)
|
||||
|
||||
|
||||
async def resume_recording():
|
||||
async def resume_recording(record_window):
|
||||
await RecordingManager().resume()
|
||||
record_window["start_recording"].update(visible=False)
|
||||
record_window["stop_recording"].update(visible=True)
|
||||
|
||||
@@ -104,4 +104,5 @@ def record_layout():
|
||||
return record_layout
|
||||
|
||||
|
||||
record_window = sg.Window("Record Miner Data", record_layout(), modal=True)
|
||||
def get_record_window():
|
||||
return sg.Window("Record Miner Data", record_layout(), modal=True)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import asyncio
|
||||
|
||||
from tools.cfg_util.record.layout import record_window
|
||||
from tools.cfg_util.record.pdf import generate_pdf
|
||||
|
||||
from miners.miner_factory import MinerFactory
|
||||
|
||||
@@ -27,14 +27,15 @@ class RecordingManager(metaclass=Singleton):
|
||||
self.miners = []
|
||||
self.output_file = None
|
||||
self.interval = 10
|
||||
self.record_window = None
|
||||
|
||||
async def _check_pause(self):
|
||||
if self.state == PAUSING:
|
||||
self.state = PAUSED
|
||||
record_window["record_status"].update("Paused.")
|
||||
self.record_window["record_status"].update("Paused.")
|
||||
while not self.state == RESUMING and not self.state == STOPPING:
|
||||
await asyncio.sleep(0.1)
|
||||
record_window["record_status"].update("Recording...")
|
||||
self.record_window["record_status"].update("Recording...")
|
||||
|
||||
async def _record_loop(self):
|
||||
while True:
|
||||
@@ -58,36 +59,39 @@ class RecordingManager(metaclass=Singleton):
|
||||
await asyncio.sleep(0.1)
|
||||
|
||||
self.state = DONE
|
||||
record_window["record_status"].update("Writing to file...")
|
||||
await self.write_output()
|
||||
record_window["record_status"].update("")
|
||||
self.record_window["record_status"].update(
|
||||
"Writing to file (this could take a minute)..."
|
||||
)
|
||||
await asyncio.sleep(0.5)
|
||||
await asyncio.create_task(self.write_output())
|
||||
self.record_window["record_status"].update("")
|
||||
|
||||
async def write_output(self):
|
||||
from pprint import pprint
|
||||
await generate_pdf(self.data, self.output_file)
|
||||
|
||||
pprint(self.data)
|
||||
|
||||
async def record(self, ips: List[str], output_file: str, interval: int = 10):
|
||||
async def record(
|
||||
self, ips: List[str], output_file: str, record_window, interval: int = 10
|
||||
):
|
||||
self.record_window = record_window
|
||||
for ip in ips:
|
||||
self.data[ip] = []
|
||||
self.output_file = output_file
|
||||
self.interval = interval
|
||||
self.state = RECORDING
|
||||
record_window["record_status"].update("Recording...")
|
||||
self.record_window["record_status"].update("Recording...")
|
||||
async for miner in MinerFactory().get_miner_generator(ips):
|
||||
self.miners.append(miner)
|
||||
print(miner)
|
||||
|
||||
asyncio.create_task(self._record_loop())
|
||||
|
||||
async def pause(self):
|
||||
self.state = PAUSING
|
||||
record_window["record_status"].update("Pausing...")
|
||||
self.record_window["record_status"].update("Pausing...")
|
||||
|
||||
async def resume(self):
|
||||
self.state = RESUMING
|
||||
record_window["record_status"].update("Resuming...")
|
||||
self.record_window["record_status"].update("Resuming...")
|
||||
|
||||
async def stop(self):
|
||||
self.state = STOPPING
|
||||
record_window["record_status"].update("Stopping...")
|
||||
self.record_window["record_status"].update("Stopping...")
|
||||
|
||||
177
tools/cfg_util/record/pdf.py
Normal file
177
tools/cfg_util/record/pdf.py
Normal file
@@ -0,0 +1,177 @@
|
||||
from datetime import datetime, timedelta
|
||||
from typing import List, Dict
|
||||
from data import MinerData
|
||||
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
from matplotlib.ticker import MultipleLocator
|
||||
from matplotlib.dates import DateFormatter
|
||||
import numpy as np
|
||||
from reportlab.lib import colors
|
||||
from reportlab.lib.pagesizes import letter, inch
|
||||
from reportlab.lib.styles import (
|
||||
ParagraphStyle,
|
||||
TA_CENTER, # noqa - not declared in __all__
|
||||
)
|
||||
from reportlab.lib.utils import ImageReader
|
||||
from reportlab.platypus import (
|
||||
SimpleDocTemplate,
|
||||
KeepInFrame,
|
||||
Table,
|
||||
Image,
|
||||
Paragraph,
|
||||
TableStyle,
|
||||
PageBreak,
|
||||
Spacer,
|
||||
)
|
||||
from io import BytesIO
|
||||
from svglib.svglib import svg2rlg
|
||||
|
||||
|
||||
async def generate_pdf(data: Dict[str, List[MinerData]], file_loc):
|
||||
doc = SimpleDocTemplate(
|
||||
file_loc,
|
||||
pagesize=letter,
|
||||
topMargin=0.25 * inch,
|
||||
leftMargin=1 * inch,
|
||||
rightMargin=1 * inch,
|
||||
bottomMargin=1 * inch,
|
||||
title=f"Recorded Data",
|
||||
)
|
||||
|
||||
elements = []
|
||||
i = 0
|
||||
for item in data.keys():
|
||||
i += 1
|
||||
if not i == 1:
|
||||
elements.append(PageBreak())
|
||||
page_elem = await generate_page(data[item])
|
||||
for elem in page_elem:
|
||||
elements.append(elem)
|
||||
|
||||
doc.build(
|
||||
elements,
|
||||
)
|
||||
|
||||
|
||||
async def generate_page(data):
|
||||
title_style = ParagraphStyle(
|
||||
"Title",
|
||||
alignment=TA_CENTER,
|
||||
fontSize=25,
|
||||
spaceAfter=40,
|
||||
spaceBefore=150,
|
||||
fontName="Helvetica-Bold",
|
||||
)
|
||||
|
||||
hr_graph = create_hr_graph(data)
|
||||
fan_graph = create_fans_graph(data)
|
||||
temp_graph = create_temp_graph(data)
|
||||
title = Paragraph(data[0].ip, style=title_style)
|
||||
|
||||
elements = [
|
||||
title,
|
||||
await hr_graph,
|
||||
Spacer(0, 40),
|
||||
await temp_graph,
|
||||
Spacer(0, 40),
|
||||
await fan_graph,
|
||||
]
|
||||
return elements
|
||||
|
||||
|
||||
async def create_hr_graph(data):
|
||||
fig, ax = plt.subplots(figsize=(6, 2))
|
||||
xpoints = []
|
||||
ypoints = []
|
||||
for item in data:
|
||||
xpoints.append(item.datetime)
|
||||
ypoints.append(item.hashrate)
|
||||
for label in ax.get_xticklabels() + ax.get_yticklabels():
|
||||
label.set_fontsize(6)
|
||||
ax.plot(xpoints, ypoints)
|
||||
ax.set_ylim(0, max(ypoints) * 1.4)
|
||||
date_form = DateFormatter("%H:%M:%S")
|
||||
ax.xaxis.set_major_formatter(date_form)
|
||||
ax.yaxis.set_major_formatter("{x:1.1f} TH/s")
|
||||
ax.set_title("Hashrate", fontsize=15)
|
||||
ax.yaxis.set_major_locator(MultipleLocator(5))
|
||||
ax.yaxis.set_minor_locator(MultipleLocator(1))
|
||||
|
||||
imgdata = BytesIO()
|
||||
fig.savefig(imgdata, format="svg")
|
||||
imgdata.seek(0) # rewind the data
|
||||
drawing = svg2rlg(imgdata)
|
||||
imgdata.close()
|
||||
plt.close("all")
|
||||
|
||||
hr_graph = KeepInFrame(375, 375, [Image(drawing)], hAlign="CENTER")
|
||||
|
||||
return hr_graph
|
||||
|
||||
|
||||
async def create_fans_graph(data):
|
||||
fig, ax = plt.subplots(figsize=(6, 2))
|
||||
xpoints = []
|
||||
ypoints_f1 = []
|
||||
ypoints_f2 = []
|
||||
ypoints_f3 = []
|
||||
ypoints_f4 = []
|
||||
for item in data:
|
||||
xpoints.append(item.datetime)
|
||||
ypoints_f1.append(item.fan_1)
|
||||
ypoints_f2.append(item.fan_2)
|
||||
ypoints_f3.append(item.fan_3)
|
||||
ypoints_f4.append(item.fan_4)
|
||||
for label in ax.get_xticklabels() + ax.get_yticklabels():
|
||||
label.set_fontsize(6)
|
||||
for ypoints in [ypoints_f1, ypoints_f2, ypoints_f3, ypoints_f4]:
|
||||
if not ypoints == [-1 for x in range(len(ypoints))]:
|
||||
ax.plot(xpoints, ypoints)
|
||||
ax.set_ylim(0, 10000)
|
||||
date_form = DateFormatter("%H:%M:%S")
|
||||
ax.xaxis.set_major_formatter(date_form)
|
||||
ax.yaxis.set_major_formatter("{x:1.0f} RPM")
|
||||
ax.set_title("Fans", fontsize=15)
|
||||
|
||||
imgdata = BytesIO()
|
||||
fig.savefig(imgdata, format="svg")
|
||||
imgdata.seek(0) # rewind the data
|
||||
drawing = svg2rlg(imgdata)
|
||||
imgdata.close()
|
||||
plt.close("all")
|
||||
|
||||
fans_graph = KeepInFrame(375, 375, [Image(drawing)], hAlign="CENTER")
|
||||
|
||||
return fans_graph
|
||||
|
||||
|
||||
async def create_temp_graph(data):
|
||||
fig, ax = plt.subplots(figsize=(6, 2))
|
||||
# plt.figure()
|
||||
xpoints = []
|
||||
ypoints = []
|
||||
for item in data:
|
||||
xpoints.append(item.datetime)
|
||||
ypoints.append(item.temperature_avg)
|
||||
for label in ax.get_xticklabels() + ax.get_yticklabels():
|
||||
label.set_fontsize(6)
|
||||
ax.plot(xpoints, ypoints)
|
||||
ax.set_ylim(0, 130)
|
||||
ax.yaxis.set_major_locator(MultipleLocator(20))
|
||||
ax.yaxis.set_minor_locator(MultipleLocator(5))
|
||||
date_form = DateFormatter("%H:%M:%S")
|
||||
ax.xaxis.set_major_formatter(date_form)
|
||||
ax.yaxis.set_major_formatter("{x:1.1f} C")
|
||||
ax.set_title("Temperature", fontsize=15)
|
||||
|
||||
imgdata = BytesIO()
|
||||
fig.savefig(imgdata, format="svg")
|
||||
imgdata.seek(0) # rewind the data
|
||||
drawing = svg2rlg(imgdata)
|
||||
imgdata.close()
|
||||
plt.close("all")
|
||||
|
||||
temp_graph = KeepInFrame(375, 375, [Image(drawing)], hAlign="CENTER")
|
||||
|
||||
return temp_graph
|
||||
@@ -1,7 +1,7 @@
|
||||
import asyncio
|
||||
|
||||
import PySimpleGUI as sg
|
||||
from tools.cfg_util.record.layout import record_window
|
||||
from tools.cfg_util.record.layout import get_record_window
|
||||
from tools.cfg_util.record.func import (
|
||||
start_recording,
|
||||
stop_recording,
|
||||
@@ -11,8 +11,9 @@ from tools.cfg_util.record.func import (
|
||||
|
||||
|
||||
async def record_ui(ips: list):
|
||||
# if not len(ips) > 0:
|
||||
# return
|
||||
if not len(ips) > 0:
|
||||
return
|
||||
record_window = get_record_window()
|
||||
while True:
|
||||
event, values = record_window.read(0.001)
|
||||
if event in (None, "Close", sg.WIN_CLOSED):
|
||||
@@ -20,13 +21,15 @@ async def record_ui(ips: list):
|
||||
|
||||
if event == "start_recording":
|
||||
if values["record_file"]:
|
||||
asyncio.create_task(start_recording(ips, values["record_file"]))
|
||||
asyncio.create_task(
|
||||
start_recording(ips, values["record_file"], record_window)
|
||||
)
|
||||
if event == "stop_recording":
|
||||
asyncio.create_task(stop_recording())
|
||||
asyncio.create_task(stop_recording(record_window))
|
||||
if event == "resume_recording":
|
||||
asyncio.create_task(resume_recording())
|
||||
asyncio.create_task(resume_recording(record_window))
|
||||
if event == "pause_recording":
|
||||
asyncio.create_task(pause_recording())
|
||||
asyncio.create_task(pause_recording(record_window))
|
||||
|
||||
if event == "__TIMEOUT__":
|
||||
await asyncio.sleep(0.001)
|
||||
|
||||
Reference in New Issue
Block a user