-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathVoyagerModule.cpp
More file actions
306 lines (230 loc) · 11.5 KB
/
Copy pathVoyagerModule.cpp
File metadata and controls
306 lines (230 loc) · 11.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
#include <iostream>
#include <string>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "SystemAudit.h"
// Load third party dependencies
#include "ThirdParty/httplib.h"
#include "ThirdParty/json.hpp"
#include "ThirdParty/qrcodegen.hpp"
namespace CONFIG {
constexpr const char* SERVER_ADDRES = "127.0.0.1";
constexpr unsigned int SERVER_PORT = 3001;
constexpr unsigned int FRONTEND_PORT = 3000;
constexpr const char* TMP_API_KEY = "api_key"; //TEMP: hardcoded key, replace later with .env
}
using json = nlohmann::json;
json createPayload(AuditResults sysResults, ManualInputData manualResults)
{
json payload;
// Item Identifiers
payload["identifiers"]["product_category"] = sysResults.isLaptop ? "Laptop" : "Computer";
payload["identifiers"]["product_model"] = sysResults.model;
payload["identifiers"]["manufacturer"] = sysResults.manufacturer;
payload["identifiers"]["serial_number"] = sysResults.serialNumber;
payload["identifiers"]["uuid"] = sysResults.uuid;
payload["identifiers"]["internal_grade"] = manualResults.conditionGrade;
// BIOS
payload["hardware"]["motherboard"]["bios_version"] = sysResults.biosVersion;
// CPU
payload["hardware"]["cpu"]["cpu_model"] = sysResults.cpuName;
payload["hardware"]["cpu"]["cpu_cores"] = sysResults.cpuCores;
payload["hardware"]["cpu"]["cpu_threads"] = sysResults.cpuThreads;
payload["hardware"]["cpu"]["cpu_base_clock_mhz"] = sysResults.cpuBaseClockMHz;
payload["hardware"]["cpu"]["cpu_l3_cache"] = sysResults.cpuL3CacheMB;
// RAM Memory
payload["hardware"]["memory"]["ram_total_gb"] = sysResults.ramTotalGB;
payload["hardware"]["memory"]["ram_type"] = sysResults.ramType;
payload["hardware"]["memory"]["ram_speed_mhz"] = sysResults.ramSpeedMHz;
payload["hardware"]["memory"]["ram_slots_total"] = sysResults.ramSlotsTotal;
payload["hardware"]["memory"]["ram_slots_used"] = sysResults.ramSlotsUsed;
payload["hardware"]["memory"]["has_soldered_ram"] = sysResults.hasSolderedRam;
// Hard Drives
payload["hardware"]["storage"] = json::array();
for (const auto& disk : sysResults.disksInfo) {
json diskObj;
diskObj["name"] = disk.diskName;
diskObj["type"] = disk.diskType;
diskObj["interface"] = disk.diskInterface;
diskObj["capacity_gb"] = disk.diskCapacityGB;
payload["hardware"]["storage"].push_back(diskObj);
}
// Screen
if (sysResults.isLaptop)
{
payload["hardware"]["screen"]["display_resolution"] = sysResults.resolution;
payload["hardware"]["screen"]["display_type"] = manualResults.screenCoating;
payload["hardware"]["screen"]["display_refresh_rate_hz"] = sysResults.refreshRateHz;
payload["hardware"]["screen"]["is_touchscreen"] = sysResults.isTouchscreen;
}
// GPU
payload["hardware"]["gpu"] = json::array();
for (const auto& gpu : sysResults.gpusInfo) {
json gpuObj;
gpuObj["name"] = gpu.GraphicsProcessorName;
gpuObj["memory_gb"] = gpu.GraphicsProcessorMemoryGB;
payload["hardware"]["gpu"].push_back(gpuObj);
}
// Battery
if (sysResults.isLaptop)
{
payload["hardware"]["battery"]["has_battery"] = sysResults.hasBattery;
if (sysResults.hasBattery)
{
payload["hardware"]["battery"]["battery_health_percent"] = sysResults.batteryHealthPercent;
payload["hardware"]["battery"]["battery_capacity"] = sysResults.batteryCapacityWh;
}
}
// Keyboard
if (sysResults.isLaptop)
{
payload["hardware"]["keyboard"]["keyboard_layout"] = manualResults.keyboardLayout;
payload["hardware"]["keyboard"]["has_numpad"] = manualResults.hasNumpad;
payload["hardware"]["keyboard"]["has_trackpoint"] = manualResults.hasTrackpoint;
payload["hardware"]["keyboard"]["is_backlit"] = manualResults.isBacklit;
}
// Comms
payload["hardware"]["communication"]["has_wifi"] = sysResults.hasWifi;
payload["hardware"]["communication"]["has_bluetooth"] = sysResults.hasBluetooth;
payload["hardware"]["communication"]["lan_gbps"] = sysResults.lanSpeed;
// Misc
payload["hardware"]["misc"]["has_optical_drive"] = sysResults.hasOpticalDrive;
payload["hardware"]["misc"]["has_camera"] = sysResults.hasCamera;
// System
payload["software"]["windows"]["windows_version"] = sysResults.windowsEdition;
payload["software"]["windows"]["is_autopilot_locked"] = sysResults.isAutopilotLocked;
return payload;
}
// Function to conduct a quick physical survey with the employee
ManualInputData RunManualSurvey( AuditResults sysResults) {
ManualInputData data;
std::string input;
std::cout << "\n========================================\n";
std::cout << " PHYSICAL CONDITION SURVEY \n";
std::cout << "========================================\n";
std::cout << "Packaging condition (1 - None, 2 - Original, 3 - Replacement):";
std::getline(std::cin, input);
if (input == "1") data.packagingState = "None";
else if (input == "2") data.packagingState = "Original";
else if (input == "3") data.packagingState = "Replacement";
else data.packagingState = "Unknown";
if (sysResults.isLaptop)
{
std::cout << "Screen coating (1 - Matte, 2 - Glossy, 3 - Anti-glare): ";
std::getline(std::cin, input);
if (input == "1") data.screenCoating = "Matte";
else if (input == "2") data.screenCoating = "Glossyy";
else if (input == "3") data.screenCoating = "Anti-glare";
else data.screenCoating = "Unknown";
std::cout << "Does the keyboard have a numeric keypad? (Y/N): ";
std::getline(std::cin, input);
data.hasNumpad = (input == "T" || input == "t");
std::cout << "Is the keyboard backlit? (Y/N): ";
std::getline(std::cin, input);
data.isBacklit = (input == "T" || input == "t");
std::cout << "Does the keyboard have a trackpoint? (Y/N): ";
std::getline(std::cin, input);
data.hasTrackpoint = (input == "T" || input == "t");
std::cout << "What is your keyboard layout? (1 - US 2 - UK 3 - Nordic 4 - DE 5 - Other): ";
std::getline(std::cin, input);
if (input == "1") data.keyboardLayout = "us";
else if (input == "2") data.keyboardLayout = "uk";
else if (input == "3") data.keyboardLayout = "nordic";
else if (input == "4") data.keyboardLayout = "de";
else data.keyboardLayout = "Unknown";
}
std::cout << "Select condition grade (0 - New, 1 - A, 2 - A-, 3 - B, 4 - C): ";
std::getline(std::cin, input);
if (input == "0") data.conditionGrade = "New";
else if (input == "1") data.conditionGrade = "A";
else if (input == "2") data.conditionGrade = "A-";
else if (input == "3") data.conditionGrade = "B";
else if (input == "4") data.conditionGrade = "C";
else data.conditionGrade = "Unknown";
return data;
}
int main() {
SetConsoleOutputCP(CP_UTF8);
SetConsoleCP(CP_UTF8);
std::cout << "Running WMI scan...\n";
// 1. Collecting data from API and WMI (takes about 1-2 seconds)
AuditResults sysResults = RunSystemAudit();
if (!sysResults.wmiSuccess) {
std::cerr << "Critical WMI error: " << sysResults.errorMessage << "\n";
return 1;
}
// 2. Survey for the technician
ManualInputData manualResults = RunManualSurvey(sysResults);
json payloadToSend = createPayload(sysResults, manualResults);
std::string json_str = payloadToSend.dump();
std::cout << "[INFO] Data collected. Size: " << json_str.length() << " bytes." << std::endl;
// Sending
httplib::Client cli(CONFIG::SERVER_ADDRES, CONFIG::SERVER_PORT);
std::string api_key = std::string(CONFIG::TMP_API_KEY);
httplib::Headers headers = {
{"Authorization", "Bearer " + api_key},
{"Content-Type", "application/json"}
};
std::cout << "[INFO] Sending data to the server" << std::endl;
auto res = cli.Post("/api/computers/ingest", headers, json_str, "application/json");
// 4. Response handling
if (res) {
// Status 200 (OK) or 201 (Created) is a standard sign of success
if (res->status == 200 || res->status == 201) {
std::cout << "[SUCCESS] Data ingested by the server!" << std::endl;
// 1. Pharse backend response
auto responseJson = json::parse(res->body);
std::string computerId = responseJson["computer_id"];
// 2. Create targer URL representing device page
std::string url = std::string("http://") + CONFIG::SERVER_ADDRES + ":" + std::to_string(CONFIG::FRONTEND_PORT) + "/panel/computer/" + computerId;
std::cout << "\n==========================================" << std::endl;
std::cout << " SCAN WITH YOUR PHONE TO OPEN THE DEVICE CARD AND ADD PHOTOS:" << std::endl;
std::cout << " URL: " << url << std::endl;
std::cout << "==========================================\n" << std::endl;
// 3. Generate QR code
using qrcodegen::QrCode;
QrCode qr = QrCode::encodeText(url.c_str(), QrCode::Ecc::LOW);
// 4. Draw QR code
int border = 2; // Margin / Quiet zone around the QR code
// Note: Console characters are roughly twice as tall as they are wide.
// We iterate 'y' by 2 because we will draw two vertical pixels of the QR code
// using a single console character (Upper Half Block).
for (int y = -border; y < qr.getSize() + border; y += 2) {
for (int x = -border; x < qr.getSize() + border; x++) {
// Check the color of the top pixel in the current column
bool topBlack = qr.getModule(x, y);
// Boundary check to ensure the bottom row doesn't exceed the QR code matrix
bool bottomBlack = false;
if (y + 1 < qr.getSize() + border) {
bottomBlack = qr.getModule(x, y + 1);
}
// Set FOREGROUND color for the top pixel (controls the top half of the block)
if (topBlack) std::cout << "\033[30m"; // 30 - Black text
else std::cout << "\033[37m"; // 37 - White text
// Set BACKGROUND color for the bottom pixel (controls the bottom half of the block)
if (bottomBlack) std::cout << "\033[40m"; // 40 - Black background
else std::cout << "\033[47m"; // 47 - White background
// Print the "Upper Half Block" character (UTF-8: \xE2\x96\x80)
// This renders the top color on the top half, and lets the background show on the bottom half
std::cout << "\xE2\x96\x80";
}
// Reset console colors to default and move to the next line
std::cout << "\033[0m" << std::endl;
}
std::cout << "\n==========================================\n" << std::endl;
}
else {
std::cout << "[Error] Server rejected request. Error code: " << res->status << std::endl;
std::cout << "Error content: " << res->body << std::endl;
}
}
else {
// This will execute if the server is completely down (Connection Refused)
auto err = res.error();
std::cout << "[FATAL] No connection to server. Are you sure it's working? Network error code: "
<< httplib::to_string(err) << std::endl;
}
std::cout << "\Press ENTER to exit program...";
std::cin.get();
return 0;
}