mirror of
https://github.com/outbackdingo/OpCore-Simplify.git
synced 2026-01-27 10:19:49 +00:00
607 lines
29 KiB
Python
Executable File
607 lines
29 KiB
Python
Executable File
from Scripts.datasets import pci_data
|
|
from Scripts import utils
|
|
from bs4 import BeautifulSoup
|
|
|
|
class AIDA64:
|
|
def __init__(self):
|
|
self.aida64_download_url = "https://www.aida64.com/downloads"
|
|
self.headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"}
|
|
self.encodings = ['utf-8', 'latin-1', 'ISO-8859-1']
|
|
self.utils = utils.Utils()
|
|
|
|
def try_open(self, file_path):
|
|
for encoding in self.encodings:
|
|
try:
|
|
with open(file_path, 'r', encoding=encoding) as file:
|
|
return file.read()
|
|
except UnicodeDecodeError:
|
|
continue
|
|
raise UnicodeDecodeError(f"Unable to decode file {file_path} with given encodings")
|
|
|
|
def hardware_id(self, hardware_id):
|
|
if "VEN" in hardware_id:
|
|
return {
|
|
"Bus Type": hardware_id.split("\\")[0],
|
|
"Device ID": "{}-{}".format(hardware_id.split("VEN_")[-1].split("&")[0], hardware_id.split("DEV_")[-1].split("&")[0])
|
|
}
|
|
|
|
if "VID" in hardware_id:
|
|
return {
|
|
"Bus Type": hardware_id.split("\\")[0],
|
|
"Device ID": "{}-{}".format(hardware_id.split("VID_")[-1].split("&")[0], hardware_id.split("PID_")[-1].split("&")[0]),
|
|
"Revision": hardware_id.split("REV_")[-1].split("&")[0]
|
|
}
|
|
|
|
return {
|
|
"Bus Type": hardware_id.split("\\")[0],
|
|
"Device": hardware_id.split("\\")[-1]
|
|
}
|
|
|
|
def motherboard(self, motherboard_props, dmi):
|
|
motherboard_info = {}
|
|
|
|
# Extract motherboard name and chipset from provided properties
|
|
motherboard_info["Motherboard Name"] = motherboard_props.get("Motherboard Name", "Unknown").split("(")[0].strip()
|
|
motherboard_info["Motherboard Chipset"] = motherboard_props.get("Motherboard Chipset", "Unknown").split(", ")[0]
|
|
|
|
# If motherboard name is still unknown, attempt to derive it from DMI information
|
|
if "Unknown" in motherboard_info.get("Motherboard Name"):
|
|
motherboard_info["Motherboard Name"] = "Unknown"
|
|
merged_report = dmi.get("System", {}).copy()
|
|
merged_report.update(dmi.get("Motherboard", {}))
|
|
for device_key, device_value in merged_report.items():
|
|
motherboard_name = "{} {}".format(device_value.get("Manufacturer", "O.E.M."), device_value.get("Product", "O.E.M."))
|
|
if "O.E.M." not in motherboard_name and "System Product Name" not in motherboard_name and len(motherboard_name) > len(motherboard_info.get("Motherboard Name")):
|
|
motherboard_info["Motherboard Name"] = motherboard_name
|
|
|
|
# Extract platform type from chassis information
|
|
motherboard_info["Platform"] = dmi.get("Chassis", {}).get("Chassis Properties", {}).get("Chassis Type", "Unknown")
|
|
if any(word in motherboard_info["Platform"].lower() for word in ["convertible", "notebook", "laptop", "docking station"]):
|
|
motherboard_info["Platform"] = "Laptop"
|
|
elif any(word in motherboard_info["Platform"].lower() for word in ["desktop", "mini pc"]):
|
|
motherboard_info["Platform"] = "Desktop"
|
|
elif "NUC" in motherboard_info["Motherboard Name"]:
|
|
motherboard_info["Platform"] = "NUC"
|
|
|
|
# Count and format CPU configuration
|
|
motherboard_info["CPU Configuration"] = str(len(dmi.get("Processors", {}))).zfill(2)
|
|
|
|
return motherboard_info
|
|
|
|
def cpu(self, cpu_table):
|
|
cpu_info = {}
|
|
|
|
# Extract CPU Manufacturer
|
|
cpu_info["CPU Manufacturer"] = cpu_table.get("CPU Manufacturer", {}).get("Company Name", "Unknown")
|
|
|
|
# Extract Processor Name
|
|
cpu_props = cpu_table.get("CPU Properties", {})
|
|
cpu_info["Processor Name"] = cpu_props.get("CPU Type", "Unknown").split(",")[0]
|
|
|
|
# Determine CPU Manufacturer if still unknown
|
|
if "Intel" in cpu_info["CPU Manufacturer"]:
|
|
cpu_info["CPU Manufacturer"] = "Intel"
|
|
elif "Advanced Micro Devices" in cpu_info["CPU Manufacturer"]:
|
|
cpu_info["CPU Manufacturer"] = "AMD"
|
|
elif cpu_info["CPU Manufacturer"] == "Unknown":
|
|
processor_name = cpu_table.get("Multi CPU", {}).get("CPU #1", "Unknown").split("with")[0].split(",")[0]
|
|
if "Intel" in processor_name:
|
|
cpu_info["CPU Manufacturer"] = "Intel"
|
|
elif "AMD" in processor_name:
|
|
cpu_info["CPU Manufacturer"] = "AMD"
|
|
cpu_info["Processor Name"] += cpu_info["CPU Manufacturer"] + processor_name.split(cpu_info["CPU Manufacturer"])[-1]
|
|
|
|
# Extract CPU Codename
|
|
cpu_info["CPU Codename"] = cpu_props.get("CPU Alias", "Unknown")
|
|
|
|
# Extract CPU Cores count
|
|
core_indices = []
|
|
for key in list(cpu_table.get("CPU Utilization", {}).keys()):
|
|
core_index = key.split("#")[2].split(" ")[0]
|
|
if "CPU #1" in key and core_index not in core_indices:
|
|
core_indices.append(core_index)
|
|
cpu_info["CPU Cores"] = str(len(core_indices)).zfill(2)
|
|
|
|
# Extract Instruction Set
|
|
cpu_info["Instruction Set"] = cpu_props.get("Instruction Set", "Unknown")
|
|
|
|
return cpu_info
|
|
|
|
def memory(self, memory_arrays, memory_devices):
|
|
return {
|
|
"Memory Arrays": [
|
|
memory_array.get("Memory Array Properties", {})
|
|
for function, memory_array in memory_arrays.items()
|
|
],
|
|
"Memory Devices": [
|
|
memory_device.get("Memory Device Properties", {})
|
|
for device_locator, memory_device in memory_devices.items()
|
|
]
|
|
}
|
|
|
|
def storage(self, ata_controllers, storage_controllers, ata_devices):
|
|
storage_info = {
|
|
"Storage Controllers": {},
|
|
"Disk Drives": {}
|
|
}
|
|
|
|
storage_controllers.update(ata_controllers)
|
|
for controller_name, controller_props in storage_controllers.items():
|
|
bus_type = controller_props.get("Bus Type", "Unknown")
|
|
if "PCI" in bus_type or "VID" in bus_type:
|
|
pci_device = controller_props.get("PCI Device")
|
|
if " SD " in pci_device or "MMC" in pci_device:
|
|
continue
|
|
|
|
storage_info["Storage Controllers"][controller_name] = {
|
|
"Bus Type": controller_props.get("Bus Type", "Unknown"),
|
|
"Device ID": controller_props.get("Device ID", "Unknown"),
|
|
"Device Description": controller_props.get("PCI Device", "Unknown")
|
|
}
|
|
|
|
device_categories = ["NVMe Device Properties", "SSD Physical Info", "ATA Device Properties", "Disk Device Physical Info", "Device Properties"]
|
|
|
|
for device_name, device_props in ata_devices.items():
|
|
disk_props = {}
|
|
relevant_categories = [key for key in list(device_props.keys()) if key in device_categories]
|
|
for category in relevant_categories:
|
|
category_props = device_props[category]
|
|
|
|
disk_props["Controller"] = category_props.get("Controller Type", "Unknown")
|
|
disk_props["Interface"] = category_props.get("Interface", "Unknown")
|
|
if category_props.get("Device Type", None):
|
|
disk_props["Interface"] = category_props.get("Device Type")
|
|
|
|
storage_info["Disk Drives"][device_name] = disk_props
|
|
|
|
return storage_info
|
|
|
|
def monitor(self, monitor):
|
|
return {
|
|
monitor_data["Monitor Properties"].get("Monitor Name", monitor_name): {
|
|
"Monitor Type": monitor_data["Monitor Properties"].get("Monitor Type", "Unknown"),
|
|
"Maximum Resolution": monitor_data["Monitor Properties"].get("Maximum Resolution", list(monitor_data.get("Supported Video Modes", {}).keys())[-1].split("_")[0] if "Supported Video Modes" in monitor_data else "Unknown")
|
|
}
|
|
for monitor_name, monitor_data in monitor.items()
|
|
if "Monitor Properties" in monitor_data
|
|
}
|
|
|
|
def acpi(self, acpi_tables):
|
|
return [
|
|
{
|
|
"ACPI Signature": acpi_table["ACPI Table Properties"].get("ACPI Signature", "Unknown"),
|
|
"Table Description": acpi_table["ACPI Table Properties"].get("Table Description", "Unknown"),
|
|
"Table Length": acpi_table["ACPI Table Properties"].get("Table Length", "Unknown"),
|
|
"OEM Table ID": acpi_table["ACPI Table Properties"].get("OEM Table ID", "Unknown")
|
|
}
|
|
for table_key, acpi_table in acpi_tables.items()
|
|
if "ACPI Table Properties" in acpi_table
|
|
]
|
|
|
|
def audio(self, windows_devices):
|
|
audio_devices_info = {}
|
|
audio_device_ids = []
|
|
|
|
for device_name, device_props in windows_devices.get("Audio inputs and outputs", {}).items():
|
|
driver_description = device_props.get("Driver Description", "Unknown")
|
|
|
|
if " (" not in driver_description:
|
|
continue
|
|
|
|
audio_endpoint = driver_description.split(" (")[0]
|
|
audio_controller_name = driver_description.split(" (")[-1].strip(" )").split("- ")[-1]
|
|
|
|
audio_controller_props = self.utils.search_dict_iter(windows_devices, audio_controller_name)
|
|
bus_type = audio_controller_props.get("Bus Type", "")
|
|
|
|
if audio_controller_name not in audio_devices_info and (bus_type.endswith("AUDIO") or bus_type.endswith("USB") or bus_type.endswith("ACP")):
|
|
audio_devices_info[audio_controller_name] = {
|
|
"Bus Type": bus_type,
|
|
"{} ID".format("USB" if bus_type.endswith("USB") else "Codec"): audio_controller_props.get("Device ID", "Unknown"),
|
|
"Audio Endpoints": [audio_endpoint]
|
|
}
|
|
audio_device_ids.append(audio_controller_props.get("Device ID", "Unknown"))
|
|
elif audio_controller_name in audio_devices_info:
|
|
audio_devices_info[audio_controller_name]["Audio Endpoints"].append(audio_endpoint)
|
|
|
|
detected_audio_devices = self.utils.search_dict_iter(windows_devices, "AUDIO", equal=False)
|
|
windows_audio_devices = self.utils.search_dict_iter(windows_devices, detected_audio_devices)
|
|
|
|
for device_name, device_props in windows_audio_devices.items():
|
|
bus_type = device_props.get("Bus Type", "")
|
|
if bus_type.endswith("AUDIO") or bus_type.endswith("USB"):
|
|
if device_props.get("Device ID", "Unknown") not in audio_device_ids:
|
|
occurrences = self.count_keys(audio_devices_info, device_name)
|
|
unique_device_name = f"{device_name}_#{occurrences}" if occurrences > 0 else device_name
|
|
audio_devices_info[unique_device_name] = {
|
|
"Bus Type": bus_type,
|
|
"{} ID".format("USB" if bus_type.endswith("USB") else "Codec"): device_props.get("Device ID", "Unknown")
|
|
}
|
|
|
|
return audio_devices_info
|
|
|
|
def gpu(self, gpu_data, vulkan_data, windows_devices):
|
|
gpu_info_dict = {}
|
|
|
|
for adapter_name, adapter_props in windows_devices.get("Display adapters", windows_devices.get("Display adaptors", {})).items():
|
|
device_id = adapter_props.get("Device ID")
|
|
if not device_id:
|
|
continue
|
|
manufacturer = "Intel" if device_id.startswith("8086") else "AMD" if device_id.startswith("1002") else "NVIDIA" if device_id.startswith("10DE") else "Unknown"
|
|
props_in_vulkan = self.utils.search_dict_iter(vulkan_data, device_id, equal=False)
|
|
gpu_props = self.utils.search_dict_iter(gpu_data, device_id, equal=False)
|
|
bus_type = gpu_props.get("Bus Type", "Unknown")
|
|
device_type = props_in_vulkan.get("Device Type", "Discrete GPU" if "PCI Express" in bus_type else "Integrated GPU" if "Integrated" in bus_type else "Unknown")
|
|
gpu_codename = gpu_props.get("GPU Code Name", props_in_vulkan.get("Device Code Name", "Unknown"))
|
|
|
|
gpu_info_dict[gpu_props.get("Video Adapter", adapter_name)] = {
|
|
"Manufacturer": manufacturer,
|
|
"GPU Codename": gpu_codename,
|
|
"Device ID": device_id,
|
|
"Device Type": device_type,
|
|
"Memory Size": gpu_props.get("Memory Size", "Unknown")
|
|
}
|
|
|
|
if not gpu_info_dict:
|
|
if gpu_data:
|
|
for gpu_name, gpu_props in gpu_data.items():
|
|
gpu_props = gpu_props.get("Graphics Processor Properties", {})
|
|
device_id = gpu_props.get("PCI Device", "Unknown").split(" / ")[0]
|
|
manufacturer = "Intel" if device_id.startswith("8086") else "AMD" if device_id.startswith("1002") else "NVIDIA" if device_id.startswith("10DE") else "Unknown"
|
|
bus_type = gpu_props.get("Bus Type", "Unknown")
|
|
device_type = "Discrete GPU" if "PCI Express" in bus_type else "Integrated GPU" if "Integrated" in bus_type else "Unknown"
|
|
gpu_codename = gpu_props.get("GPU Code Name", "Unknown")
|
|
|
|
gpu_info_dict[gpu_props.get("Video Adapter", gpu_name.split(": ")[-1])] = {
|
|
"Manufacturer": manufacturer,
|
|
"GPU Codename": gpu_codename,
|
|
"Device ID": device_id,
|
|
"Device Type": device_type,
|
|
"Memory Size": gpu_props.get("Memory Size", "Unknown")
|
|
}
|
|
|
|
return self.utils.sort_dict_by_key(gpu_info_dict, "Device Type")
|
|
|
|
def input(self, human_interface_devices, keyboards, pointing_devices, usb_devices):
|
|
input_devices_info = {}
|
|
|
|
combined_devices = human_interface_devices.copy()
|
|
combined_devices.update(keyboards)
|
|
combined_devices.update(pointing_devices)
|
|
|
|
for device_name, device_props in combined_devices.items():
|
|
bus_type = device_props.get("Bus Type", "Unknown")
|
|
device_id = device_props.get("Device ID", "Unknown")
|
|
|
|
if "ACPI" in bus_type or "ROOT" in bus_type or "USB" in bus_type:
|
|
if "USB" in bus_type:
|
|
device_name = self.utils.search_dict_iter(usb_devices, device_props["Device ID"]).get("Device Description", device_name)
|
|
|
|
input_devices_info[device_name] = {
|
|
"Bus Type": bus_type,
|
|
"Device ID": device_id
|
|
}
|
|
|
|
return input_devices_info
|
|
|
|
def usb(self, usb_controllers, usb_devices, windows_devices):
|
|
usb_info = {
|
|
"USB Controllers": {
|
|
controller_name: {
|
|
"Bus Type": controller_props.get("Bus Type", "Unknown"),
|
|
"Device ID": controller_props.get("Device ID", "Unknown")
|
|
}
|
|
for controller_name, controller_props in usb_controllers.items()
|
|
if controller_props.get("Bus Type", "Unknown").startswith("PCI")
|
|
},
|
|
"USB Devices": {}
|
|
}
|
|
|
|
for device_name, device_data in usb_devices.items():
|
|
device_props = device_data.get("Device Properties", {})
|
|
manufacturer = device_props.get("Manufacturer", None)
|
|
product = device_props.get("Product", None)
|
|
device_description = f"{manufacturer} {product}" if manufacturer and product else product if product else None
|
|
|
|
if not device_description:
|
|
device_id = device_props.get("Device ID", None)
|
|
revision = device_props.get("Revision", None)[:-1] if device_props.get("Revision") else None
|
|
hardware_id = f'USB\\VID_{device_id[:4]}&PID_{device_id[5:]}&REV_{revision}' if device_id and revision else None
|
|
|
|
if hardware_id:
|
|
device_description = self.utils.search_dict_iter(windows_devices, hardware_id + "&MI_00").get("Driver Description", None)
|
|
if not device_description:
|
|
device_description = self.utils.search_dict_iter(windows_devices, hardware_id).get("Driver Description", device_name)
|
|
|
|
occurrences = self.count_keys(usb_info["USB Devices"], device_description)
|
|
device_description = f"{device_description}_#{occurrences}" if occurrences > 0 else device_description
|
|
|
|
if "Hub" not in device_description and "Billboard" not in device_description and not "0000-0000" in device_props.get("Device ID"):
|
|
usb_info["USB Devices"][device_description] = {
|
|
"Device Description": device_description.split("_#")[0],
|
|
"Device Class": device_props.get("Device Class"),
|
|
"Device ID": device_props.get("Device ID"),
|
|
"Revision": device_props.get("Revision")
|
|
}
|
|
|
|
return usb_info
|
|
|
|
def network(self, windows_devices, pci_devices):
|
|
network_info = {}
|
|
|
|
for device_name, device_props in pci_devices.items():
|
|
device_class = device_props.get("Device Properties", {}).get("Device Class", "Unknown")[6:-1]
|
|
|
|
if self.utils.contains_any(["Network", "Ethernet", "WiFi", "Wi-Fi", "Wireless"], device_class + device_name):
|
|
device_id = device_props.get("Device Properties").get("Device ID")
|
|
|
|
network_adapter = self.utils.search_dict_iter(windows_devices, device_id)
|
|
network_adapters = self.utils.search_dict_iter(windows_devices, network_adapter)
|
|
|
|
for adapter_name, adapter_props in network_adapters.items():
|
|
device_description = adapter_name + adapter_props.get("PCI Device", "Unknown")
|
|
connection_name = "WiFi" if "WiFi" in device_description or "Wi-Fi" in device_description or "Wireless" in device_description else \
|
|
"Ethernet" if "Network" in device_description or "Ethernet" in device_description else None
|
|
bus_type = adapter_props.get("Bus Type", "Unknown")
|
|
if (bus_type.startswith("PCI") or bus_type.startswith("USB")) and connection_name:
|
|
device_key = adapter_props.get("PCI Device") if not " - " in adapter_props.get("PCI Device", " - ") else adapter_name
|
|
network_info[device_key.split(" [")[0]] = {
|
|
"Connection Name": connection_name,
|
|
"Bus Type": bus_type,
|
|
"Device ID": adapter_props.get("Device ID", "Unknown")
|
|
}
|
|
|
|
return self.utils.sort_dict_by_key(network_info, "Connection Name")
|
|
|
|
def sd_controller(self, pci_devices, usb_devices, hardware):
|
|
combined_devices = pci_devices.copy()
|
|
combined_devices.update(usb_devices)
|
|
|
|
for device_name, device_data in combined_devices.items():
|
|
device_props = device_data.get("Device Properties", device_data)
|
|
device_class = device_props.get("Device Class", "Unknown")
|
|
|
|
if self.utils.contains_any(["SD Host Controller", "Card Reader", "SDHC", "SDXC", "SDUC", " SD ", "MMC"], f"{device_name} {device_class}"):
|
|
hardware["SD Controller"] = {
|
|
"Device Description": device_name,
|
|
"Bus Type": "PCI" if device_props.get("Bus Type", "Unknown").startswith("PCI") else "USB",
|
|
"Device ID": device_props.get("Device ID", "Unknown")
|
|
}
|
|
|
|
return hardware
|
|
|
|
def intel_mei(self, cpu_codename, pci_devices, hardware):
|
|
if "Sandy Bridge" in cpu_codename or "Ivy Bridge" in cpu_codename:
|
|
intel_mei_data = self.utils.search_dict_iter(pci_devices, "HECI", equal=False)
|
|
|
|
if not intel_mei_data:
|
|
intel_mei_data = self.utils.search_dict_iter(pci_devices, "Management Engine Interface", equal=False)
|
|
|
|
if intel_mei_data:
|
|
intel_mei_props = intel_mei_data.get("Device Properties", {})
|
|
hardware["Intel MEI"] = {
|
|
"Bus Type": intel_mei_props.get("Bus Type", "Unknown"),
|
|
"Device ID": intel_mei_props.get("Device ID", "Unknown")
|
|
}
|
|
|
|
return hardware
|
|
|
|
def bluetooth(self, bluetooth, usb_devices, hardware):
|
|
bluetooth_info = {}
|
|
|
|
for device_name, device_props in bluetooth.items():
|
|
bus_type = device_props.get("Bus Type", "Unknown")
|
|
|
|
if bus_type.startswith("USB"):
|
|
bluetooth_info[device_name] = {
|
|
"Device ID": device_props.get("Device ID"),
|
|
"Revision": device_props.get("Revision")
|
|
}
|
|
|
|
if not bluetooth_info:
|
|
for usb_device_name, usb_device_props in usb_devices.items():
|
|
device_class = usb_device_props.get("Device Class", {})
|
|
device_id = usb_device_props.get("Device ID", {})
|
|
|
|
if "bluetooth" in (usb_device_name + device_class).lower() or device_id in pci_data.BluetoothIDs:
|
|
bluetooth_info[usb_device_name] = usb_device_props
|
|
|
|
if bluetooth_info:
|
|
hardware["Bluetooth"] = bluetooth_info
|
|
|
|
return hardware
|
|
|
|
def biometric(self, biometric_devices, usb_devices, hardware):
|
|
biometric_info = {
|
|
device_name: {
|
|
"Bus Type": device_props.get("Bus Type", "Unknown"),
|
|
"Device ID": device_props.get("Device ID", "Unknown")
|
|
}
|
|
for device_name, device_props in biometric_devices.items()
|
|
}
|
|
|
|
if not biometric_info:
|
|
for device_name, device_data in usb_devices.items():
|
|
if "fingerprint" in device_name.lower():
|
|
device_props = device_data.get("Device Properties", {})
|
|
|
|
biometric_info[device_name] = {
|
|
"Bus Type": device_props.get("Bus Type", "Unknown"),
|
|
"Device ID": device_props.get("Device ID", "Unknown")
|
|
}
|
|
|
|
if biometric_info:
|
|
hardware["Biometric"] = biometric_info
|
|
|
|
return hardware
|
|
|
|
def parse_dmi(self, dmi_data):
|
|
parsed_dmi = {}
|
|
|
|
for full_key, item_value in dmi_data.items():
|
|
occurrence_suffix = ''
|
|
category_name = None
|
|
|
|
if '_#' in full_key:
|
|
suffix_idx = full_key.index('_#')
|
|
occurrence_suffix = full_key[suffix_idx:]
|
|
full_key = full_key[:suffix_idx]
|
|
|
|
if ' / ' in full_key:
|
|
category_idx = full_key.index(' / ')
|
|
category_name = full_key[:category_idx]
|
|
device_name = full_key[category_idx + 3:]
|
|
|
|
if not category_name:
|
|
parsed_dmi[f"{full_key}{occurrence_suffix}"] = item_value
|
|
else:
|
|
if category_name not in parsed_dmi:
|
|
parsed_dmi[category_name] = {}
|
|
parsed_dmi[category_name][f"{device_name}{occurrence_suffix}"] = item_value
|
|
|
|
return parsed_dmi
|
|
|
|
def parse_windows_devices(self, windows_devices):
|
|
parsed_windows_devices = {}
|
|
|
|
for full_key, item_value in windows_devices.items():
|
|
device_props = item_value.get("Device Properties", {})
|
|
|
|
# Update device properties with hardware ID if available
|
|
if "Hardware ID" in device_props:
|
|
device_props.update(self.hardware_id(device_props.get("Hardware ID")))
|
|
|
|
# Extract category name from the full key
|
|
category_name = full_key.split(" / ")[0]
|
|
|
|
# Initialize category dictionary if not already present
|
|
if category_name not in parsed_windows_devices:
|
|
parsed_windows_devices[category_name] = {}
|
|
|
|
# Extract device name from device properties
|
|
device_name = device_props.get("Driver Description")
|
|
|
|
# Count occurrences of device name within category
|
|
occurrences = self.count_keys(parsed_windows_devices[category_name], device_name)
|
|
device_name = f"{device_name}_#{occurrences}" if occurrences > 0 else device_name
|
|
|
|
# Add device to category dictionary
|
|
parsed_windows_devices[category_name][device_name] = device_props
|
|
|
|
return parsed_windows_devices
|
|
|
|
def count_keys(self, dictionary, target_key):
|
|
return sum(1 for key in dictionary if target_key in key)
|
|
|
|
def html_to_dict(self, html_content):
|
|
soup = BeautifulSoup(html_content, "html.parser")
|
|
tables = soup.find_all('table')
|
|
|
|
if not tables:
|
|
return {}
|
|
|
|
root = {}
|
|
table_names = [
|
|
"Summary",
|
|
"DMI",
|
|
"CPU",
|
|
"GPU",
|
|
"Vulkan",
|
|
"ATA",
|
|
"Windows Devices",
|
|
"PCI Devices",
|
|
"USB Devices"
|
|
]
|
|
table = None
|
|
|
|
for table_content in tables:
|
|
# Find the table header to identify the table
|
|
pt_element = table_content.find("td", class_="pt")
|
|
if pt_element:
|
|
table = pt_element.text.strip()
|
|
elif table in table_names:
|
|
root[table] = {}
|
|
stack = [(root[table], -1)] # Stack holds (current_dict, current_level)
|
|
|
|
lines = str(table_content).strip().splitlines()
|
|
|
|
for line in lines:
|
|
if line.startswith('<tr>'):
|
|
# Remove <tr> tag
|
|
line = line.replace('<tr>', '')
|
|
|
|
# Calculate the current level based on the number of <td> tags
|
|
level = (len(line) - len(line.lstrip('<td>'))) // 3 - 1
|
|
if level < 1:
|
|
continue
|
|
|
|
# Remove all <td> tags from the left
|
|
while line.startswith("<td>"):
|
|
line = line[line.find(">") + 1:]
|
|
|
|
if not line.startswith('<td') and '<td' in line:
|
|
idx = line.index('<td')
|
|
line = '{}{}{}{}'.format('<td>', line[:idx], '</td>', line[idx:])
|
|
else:
|
|
continue
|
|
|
|
soup_line = BeautifulSoup(line, "html.parser")
|
|
td_elements = soup_line.find_all('td')
|
|
key = td_elements[0].text.strip()
|
|
value = None if len(td_elements) < 2 else td_elements[-1].text.strip()
|
|
|
|
# Clean the key
|
|
key = key.rstrip(":").strip("[]").strip()
|
|
|
|
# Pop from stack to find the correct parent dictionary
|
|
while stack and stack[-1][1] >= level:
|
|
stack.pop()
|
|
|
|
# Add the new key-value pair
|
|
current_dict = stack[-1][0]
|
|
occurrences = self.count_keys(current_dict, key)
|
|
key = f"{key}_#{occurrences}" if occurrences > 0 else key
|
|
|
|
if value is None:
|
|
new_dict = {}
|
|
current_dict[key] = new_dict
|
|
stack.append((new_dict, level))
|
|
else:
|
|
if '<td class="cc">' not in line:
|
|
current_dict[key] = value
|
|
else:
|
|
if not current_dict.items():
|
|
current_dict[key] = []
|
|
current_dict[value] = []
|
|
else:
|
|
current_dict[list(current_dict.keys())[0]].append(key)
|
|
current_dict[list(current_dict.keys())[1]].append(value)
|
|
|
|
if len(table_names) - len(root) > 1:
|
|
raise Exception("Your AIDA64 report is missing some information. Please revise it according to the provided guidelines")
|
|
return root
|
|
|
|
def dump(self, report_path):
|
|
html_content = self.try_open(report_path)
|
|
report_dict = self.html_to_dict(html_content)
|
|
|
|
dmi = self.parse_dmi(report_dict.get("DMI", {}))
|
|
windows_devices = self.parse_windows_devices(report_dict.get("Windows Devices", {}))
|
|
|
|
hardware = {}
|
|
hardware["Motherboard"] = self.motherboard(report_dict.get("Summary", {}).get("Motherboard", {}), dmi)
|
|
hardware["CPU"] = self.cpu(report_dict.get("CPU", {}))
|
|
hardware["GPU"] = self.gpu(report_dict.get("GPU", {}), report_dict.get("Vulkan", {}), windows_devices)
|
|
hardware["Network"] = self.network(windows_devices, report_dict.get("PCI Devices", {}))
|
|
hardware["Storage"] = self.storage(windows_devices.get("IDE ATA/ATAPI controllers", {}), windows_devices.get("Storage controllers", {}), report_dict.get("ATA", {}))
|
|
hardware["Audio"] = self.audio(windows_devices)
|
|
hardware["USB"] = self.usb(windows_devices.get("Universal Serial Bus controllers", {}), report_dict.get("USB Devices", {}), windows_devices)
|
|
hardware["Input"] = self.input(windows_devices.get("Human Interface Devices", {}), windows_devices.get("Keyboards", {}), windows_devices.get("Mice and other pointing devices", {}), hardware["USB"].get("USB Devices", {}))
|
|
|
|
hardware = self.biometric(windows_devices.get("Biometric devices", {}), hardware["USB"].get("USB Devices", {}), hardware)
|
|
hardware = self.bluetooth(windows_devices.get("Bluetooth", {}), hardware["USB"].get("USB Devices", {}), hardware)
|
|
hardware = self.sd_controller(report_dict.get("PCI Devices", {}), hardware["USB"].get("USB Devices", {}), hardware)
|
|
hardware = self.intel_mei(hardware["CPU"].get("CPU Codename"), report_dict.get("PCI Devices", {}), hardware)
|
|
|
|
return hardware
|