├── src ├── __init__.py └── retrieve.py ├── tests ├── __init__.py └── unit_test.py ├── .gitignore ├── requirements.txt ├── .github └── main.workflow └── CompuTEach.spec /src/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea/ 2 | /venv/ 3 | /data.txt 4 | /dist/ 5 | /build/ 6 | __pycache__ 7 | *.pyc 8 | .vscode 9 | .noseids 10 | nosetests.xml 11 | .venv/ 12 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | certifi==2019.3.9 2 | chardet==3.0.4 3 | idna==2.8 4 | py-cpuinfo==5.0.0 5 | pywin32==224 6 | requests==2.21.0 7 | urllib3==1.24.2 8 | WMI==1.4.9 9 | -------------------------------------------------------------------------------- /.github/main.workflow: -------------------------------------------------------------------------------- 1 | workflow "Python test" { 2 | resolves = ["python-nose-test"] 3 | on = "pull_request" 4 | } 5 | 6 | action "python-nose-test" { 7 | uses = "CyberZHG/github-action-python-test@0.0.1" 8 | } 9 | -------------------------------------------------------------------------------- /tests/unit_test.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | from src import retrieve 4 | 5 | 6 | class TestRetrieve(unittest.TestCase): 7 | def test_data(self): 8 | data = retrieve.hardware_json() 9 | response = retrieve.post_data(data) 10 | self.assertEqual(response.status_code, 201) 11 | test_compare_request_response(data, response.json()["computer"]) 12 | 13 | 14 | def test_compare_request_response(expected, actual): 15 | if type(expected) is dict: 16 | for key in expected.keys(): 17 | test_compare_request_response(expected[key], actual[key]) 18 | elif type(expected) is list: 19 | for i in range(len(expected)): 20 | test_compare_request_response(expected[i], actual[i]) 21 | else: 22 | assert expected == actual, f"expected: {expected} -- actual: {actual}" 23 | 24 | 25 | if __name__ == '__main__': 26 | unittest.main() 27 | -------------------------------------------------------------------------------- /CompuTEach.spec: -------------------------------------------------------------------------------- 1 | # -*- mode: python -*- 2 | 3 | block_cipher = None 4 | 5 | 6 | a = Analysis(['src\\retrieve.py'], 7 | pathex=['C:\\Users\\BaruchR\\source\\repos\\HWRecommendation-local'], 8 | binaries=[], 9 | datas=[], 10 | hiddenimports=[], 11 | hookspath=[], 12 | runtime_hooks=[], 13 | excludes=[], 14 | win_no_prefer_redirects=False, 15 | win_private_assemblies=False, 16 | cipher=block_cipher, 17 | noarchive=False) 18 | pyz = PYZ(a.pure, a.zipped_data, 19 | cipher=block_cipher) 20 | exe = EXE(pyz, 21 | a.scripts, 22 | a.binaries, 23 | a.zipfiles, 24 | a.datas, 25 | [], 26 | name='CompuTEach', 27 | debug=False, 28 | bootloader_ignore_signals=False, 29 | strip=False, 30 | upx=True, 31 | runtime_tmpdir=None, 32 | console=True ) 33 | -------------------------------------------------------------------------------- /src/retrieve.py: -------------------------------------------------------------------------------- 1 | import cpuinfo 2 | import requests 3 | import multiprocessing 4 | import webbrowser 5 | from wmi import WMI 6 | import sys 7 | 8 | 9 | def log(text): 10 | if debug: 11 | print(text) 12 | 13 | 14 | def get_ram_maxcapacity(wmi2): 15 | return wmi2.Win32_PhysicalMemoryArray()[0].MaxCapacity 16 | 17 | 18 | def get_num_of_ram_slots(wmi2): 19 | memory = wmi2.query( 20 | "select MemoryDevices from win32_PhysicalMemoryArray") 21 | return int(memory[0].MemoryDevices) 22 | 23 | 24 | def get_memories(wmi2): 25 | memory_types = { 26 | 1: "Other", 27 | 2: "Unknown", 28 | 3: "DRAM", 29 | 4: "EDRAM", 30 | 5: "VRAM", 31 | 6: "SRAM", 32 | 7: "RAM", 33 | 8: "ROM", 34 | 9: "FLASH", 35 | 10: "EEPROM", 36 | 11: "FEPROM ", 37 | 12: "EPROM", 38 | 13: "CDRAM", 39 | 14: "3DRAM", 40 | 15: "SDRAM", 41 | 16: "SGRAM", 42 | 17: "RDRAM", 43 | 18: "DDR", 44 | 19: "DDR2", 45 | 20: "DDR2 FB-DIMM", 46 | 21: "Reserved", 47 | 22: "Reserved", 48 | 23: "Reserved", 49 | 24: "DDR3", 50 | 25: "FBD2", 51 | 26: "DDR4", 52 | 27: "LPDDR", 53 | 28: "LPDDR2", 54 | 29: "LPDDR3", 55 | 30: "LPDDR4", 56 | } 57 | # 01h Other 58 | # 02h Unknown 59 | # 03h DRAM 60 | # 04h EDRAM 61 | # 05h VRAM 62 | # 06h SRAM 63 | # 07h RAM 64 | # 08h ROM 65 | # 09h FLASH 66 | # 0Ah EEPROM 67 | # 0Bh FEPROM 68 | # 0Ch EPROM 69 | # 0Dh CDRAM 70 | # 0Eh 3DRAM 71 | # 0Fh SDRAM 72 | # 10h SGRAM 73 | # 11h RDRAM 74 | # 12h DDR 75 | # 13h DDR2 76 | # 14h DDR2 FB-DIMM 77 | # 15h-17h Reserved 78 | # 18h DDR3 79 | # 19h FBD2 80 | # 1Ah DDR4 81 | # 1Bh LPDDR 82 | # 1Ch LPDDR2 83 | # 1Dh LPDDR3 84 | # 1Eh LPDDR4 85 | result = [] 86 | memories = wmi2.query("select * from Win32_PhysicalMemory") 87 | for memory in memories: 88 | obj = { 89 | "capacity": int(memory.Capacity), 90 | "ghz": int(memory.Speed), 91 | "bankLabel": memory.bankLabel, 92 | "deviceLocator": memory.DeviceLocator 93 | } 94 | if hasattr(memory, "SMBIOSMemoryType"): 95 | obj["type"] = memory_types[int(memory.SMBIOSMemoryType)] 96 | else: 97 | obj["type"] = memory_types[int(memory.MemoryType)] 98 | result.append(obj) 99 | return result 100 | 101 | 102 | def get_motherboard(wmi2): 103 | return wmi2.Win32_baseboard()[0] 104 | 105 | 106 | def get_gpus(wmi2): 107 | res1 = [] 108 | gpu = wmi2.query("select * from Win32_VideoController") 109 | for gpus in gpu: 110 | if gpus.VideoProcessor is not None: 111 | res1.append( 112 | { 113 | "name": gpus.Name, 114 | "processor": gpus.VideoProcessor 115 | } 116 | ) 117 | return res1 118 | 119 | 120 | def get_hardDisk(wmi2): 121 | res2 = [] 122 | hd = wmi2.query("select * from Win32_DiskDrive") 123 | for hds in hd: 124 | res2.append( 125 | { 126 | "model": hds.model, 127 | "capacity": int(hds.Size) 128 | } 129 | ) 130 | return res2 131 | 132 | 133 | def hardware_json(): 134 | cpu = cpuinfo.cpuinfo.get_cpu_info() 135 | 136 | wmi = WMI() 137 | 138 | # Same thing about mediaType HardDisk, and GPU details. 139 | 140 | mobo = get_motherboard(wmi) 141 | 142 | data = { 143 | "processor": { 144 | "name": cpu['brand'], 145 | "gHz": cpu['hz_advertised_raw'][0], 146 | "numOfCores": cpu['count'], 147 | "architecture": f"x{cpu['bits']}" 148 | }, 149 | "memories": get_memories(wmi), 150 | "disks": get_hardDisk(wmi), 151 | "motherBoard": { 152 | "ddrSockets": get_num_of_ram_slots(wmi), 153 | "maxRam": get_ram_maxcapacity(wmi), 154 | "manufacturer": mobo.Manufacturer, 155 | "product": mobo.Product 156 | }, 157 | "gpus": get_gpus(wmi) 158 | } 159 | return data 160 | 161 | 162 | def post_data(data_post): 163 | headers = {'Content-Type': 'application/json'} 164 | return requests.post( 165 | 'https://hwwebapi.azurewebsites.net/api/Scans', json=data_post, headers=headers) 166 | 167 | 168 | if __name__ == "__main__": 169 | debug = "debug" in sys.argv 170 | 171 | multiprocessing.freeze_support() 172 | 173 | data = hardware_json() 174 | log(data) 175 | 176 | r = post_data(data) 177 | 178 | log(r.status_code) 179 | log(r.text) 180 | idS = str(r.json()['id']) 181 | webbrowser.open( 182 | 'https://baruchiro.github.io/HWRecommendation-WebAPI/?id=' + idS) 183 | --------------------------------------------------------------------------------