diff --git a/layouter.py b/layouter.py new file mode 100644 index 0000000..2d481e2 --- /dev/null +++ b/layouter.py @@ -0,0 +1,134 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +""" Author: Hendrik Schutter, localhorst@mosad.xyz + Date of creation: 2022/11/16 + Date of last modification: 2022/11/16 +""" + +import re +import os +import sys +import time +import subprocess +import shlex +import shutil +from dataclasses import dataclass +import glob +import PIL +from PIL import Image +from PIL import ImageFont +from PIL import ImageDraw +import datetime + + +rehddversion="bV0.2.2" # read this from rehdd process + +@dataclass +class DriveData: + drive_index: int + drive_state: str #none, deleted, shredded + modelfamiliy: str + modelname: str + capacity: int #in bytes + serialnumber: str + power_on_hours: int #in hours + power_cycle: int + smart_error_count: int + shred_timestamp: int #unix timestamp + shred_duration: int #in seconds + +@dataclass +class DriveDataPrintable: + modelfamiliy: str #max lenght 25 + modelname: str #max lenght 25 + capacity: str #max lenght 25, in human-readable format with unit (GB/TB) + serialnumber: str #max lenght 25 + power_on_hours: str #max lenght 25, in hours and days and years + power_cycle: str #max lenght 25 + smart_error_count: str #max lenght 25 + shred_timestamp: str #max lenght 25, human-readable + shred_duration: str #max lenght 25, human-readable + + +temp_drive = DriveData(drive_index=0, drive_state="shredded", modelfamiliy="Toshiba 2.5\\ HDD MK..65GSSX",\ + modelname="TOSHIBA MK3265GSDX", capacity=343597383680, serialnumber="70fFr-_/ tefrtg", power_on_hours=7074,\ + power_cycle=4792, smart_error_count=1, shred_timestamp=1647937421, shred_duration=81718) + + +def get_font_path(): + path = "/usr/share/fonts" + files = glob.glob(path + "/**/DejaVuSans-Bold.ttf", recursive = True) + return files[0] + +def human_readable_capacity(size, decimal_places=0): + for unit in ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB']: + if size < 1024.0 or unit == 'PiB': + break + size /= 1024.0 + return f"{size:.{decimal_places}f} {unit}" + +def human_readable_power_on_hours(hours, decimal_places=2): + return str(hours) + "h or " + str(int(hours/24)) + "d or " + str("{:.2f}".format(float(hours/24/365))) + "y" + +def cut_string(max_lenght, data): + if (len(data) > max_lenght): + return data[0:(max_lenght-4)] + " ..." + else: + return data + +def format_to_printable(drive): + + #print(cut_string(20, re.sub(r"[^a-zA-Z0-9. ]", "", drive.modelfamiliy))) + #print(cut_string(20, re.sub(r"[^a-zA-Z0-9. ]", "", drive.modelname))) + #print(cut_string(20, human_readable_capacity(drive.capacity))) + #print(cut_string(20, re.sub(r"[^a-zA-Z0-9.-_]", "", drive.serialnumber))) + #print(cut_string(30, human_readable_power_on_hours(drive.power_on_hours))) + #print(cut_string(10, str(drive.power_cycle))) + #print(cut_string(10, str(drive.smart_error_count))) + #print(cut_string(30, datetime.datetime.utcfromtimestamp(drive.shred_timestamp).strftime('%Y-%m-%d %H:%M:%S'))) + #print(cut_string(30, str(datetime.timedelta(seconds = drive.shred_duration)))) + + return DriveDataPrintable(cut_string(20, re.sub(r"[^a-zA-Z0-9. ]", "", drive.modelfamiliy)),\ + cut_string(20, re.sub(r"[^a-zA-Z0-9. ]", "", drive.modelname)),\ + cut_string(20, human_readable_capacity(drive.capacity)),\ + cut_string(20, re.sub(r"[^a-zA-Z0-9.-_]", "", drive.serialnumber)),\ + cut_string(30, human_readable_power_on_hours(drive.power_on_hours)),\ + cut_string(10, str(drive.power_cycle)),\ + cut_string(10, str(drive.smart_error_count)),\ + cut_string(30, datetime.datetime.utcfromtimestamp(drive.shred_timestamp).strftime('%Y-%m-%d %H:%M:%S')),\ + cut_string(30, str(datetime.timedelta(seconds = drive.shred_duration)))) + + +def main(): + + output_width = 696 + output_height = 348 + + printable_data = format_to_printable(temp_drive) + + print(printable_data) + + text_y_offset= int(output_width / 3) + + output_image = Image.new('1', (output_width, output_height), "white") + font_file = get_font_path() + + draw = ImageDraw.Draw(output_image) + + + draw.text((text_y_offset, 5), "modelfamiliy: " + printable_data.modelfamiliy,(0),font=ImageFont.truetype(font_file, 15)) + draw.text((text_y_offset, 20), "modelname: " + printable_data.modelname,(0),font=ImageFont.truetype(font_file, 15)) + draw.text((text_y_offset, 35), "serial: " + printable_data.serialnumber,(0),font=ImageFont.truetype(font_file, 15)) + draw.text((text_y_offset, 50), "poweronhours: " + printable_data.power_on_hours,(0),font=ImageFont.truetype(font_file, 15)) + draw.text((text_y_offset, 65), "powercycle: " + printable_data.power_cycle,(0),font=ImageFont.truetype(font_file, 15)) + draw.text((text_y_offset, 80), "errorcount: " + printable_data.smart_error_count,(0),font=ImageFont.truetype(font_file, 15)) + draw.text((text_y_offset, 95), "shredtimestamp: " + printable_data.shred_timestamp,(0),font=ImageFont.truetype(font_file, 15)) + draw.text((text_y_offset, 110), "shredduration: " + printable_data.shred_duration,(0),font=ImageFont.truetype(font_file, 15)) + + + output_image.save("output.png") + + +if __name__ == "__main__": + main() \ No newline at end of file