massive refactor

main
xad1 3 years ago
parent 97179e7860
commit 9c40400d26

@ -0,0 +1,9 @@
#include <Arduino.h>
#ifndef GLOBAL_H_
#define GLOBAL_H_
extern String selectedNode;
extern int selectedItem;
#endif

@ -0,0 +1,9 @@
#ifndef JSON_RETRIEVE_H
#define JSON_RETRIEVE_H
#include <ArduinoJson.h>
JsonArray getNodeInfo();
JsonArray getContainerInfo(String node);
JsonArray getVMInfo(String node);
#endif /* JSON_RETRIEVE_H */

@ -0,0 +1,8 @@
#ifndef JSON_UTILS_H
#define JSON_UTILS_H
#include <ArduinoJson.h>
JsonObject getNode(String name, JsonArray nodes);
JsonObject getContainer(int id, JsonArray containers);
#endif /* JSON_UTILS_H */

@ -0,0 +1,17 @@
#ifndef MENU_H_
#define MENU_H_
#include <ArduinoJson.h>
#include <Arduino.h>
// Struct for static menu items such as on the main menu. Has the name of the menu item and a function to run when it is selected.
typedef struct {
String name;
void (*function)();
} MenuItem;
void listNodes(JsonArray nodes);
int listContainers(JsonArray containers);
void mainMenu();
extern int selectedItem;
#endif

@ -1,12 +1,14 @@
#include <Arduino.h>
#ifndef SERVER_H_
#define SERVER_H_
/**
* Enter WiFi network and Proxmox information
*/
const char* WIFI_SSID = "";
const char* WIFI_PASS = "";
const String PROXMOX_ADDRESS = "";
const String PROXMOX_TOKEN_USER = "";
const String PROXMOX_TOKEN_NAME = "";
const String PROXMOX_TOKEN_SECRET = "";
const String PROXMOX_TOKEN_SECRET = "";
#endif

@ -0,0 +1,7 @@
#ifndef STATISTICS_H
#define STATISTICS_H
void nodeInfo();
void containerInfo();
void vmInfo();
#endif /* STATISTICS_H */

@ -0,0 +1,8 @@
#ifndef UTILS_H
#define UTILS_H
#include <Arduino.h>
void displayError(String message);
void connectWiFi();
#endif /* UTILS_H */

@ -0,0 +1,11 @@
#ifndef WIFI_H_
#define WIFI_H_
/**
* Enter WiFi network and Proxmox information
*/
const char* WIFI_SSID = "";
const char* WIFI_PASS = "";
#endif

@ -15,3 +15,4 @@ framework = arduino
lib_deps =
leeseungcheol/ODROID-GO@^1.0.0
bblanchon/ArduinoJson@^6.20.1
monitor_speed = 115200

@ -0,0 +1,76 @@
#include <ArduinoJson.h>
#include <HTTPClient.h>
#include <server.h>
#include <utils.h>
// todo make the bottom part of these into one function
// ######################################
// ######################################
// ######################################
// ######################################
// ######################################
JsonArray getNodeInfo() {
HTTPClient http;
String apiAddress = PROXMOX_ADDRESS + "/api2/json/nodes/";
String auth = "PVEAPIToken=" + PROXMOX_TOKEN_USER + "!" + PROXMOX_TOKEN_NAME + "=" + PROXMOX_TOKEN_SECRET;
char authc[auth.length() + 1];
auth.toCharArray(authc, auth.length() + 1);
http.begin(apiAddress);
http.setAuthorization(authc);
int httpCode = http.GET();
if (httpCode > 0) {
String json = http.getString();
DynamicJsonDocument doc(1024);
deserializeJson(doc, json);
JsonArray nodes = doc["data"].as<JsonArray>();
return nodes;
}
displayError("Error getting data.");
return getNodeInfo();
}
JsonArray getContainerInfo(String node) {
HTTPClient http;
String apiAddress = PROXMOX_ADDRESS + "/api2/json/nodes/" + node + "/lxc";
String auth = "PVEAPIToken=" + PROXMOX_TOKEN_USER + "!" + PROXMOX_TOKEN_NAME + "=" + PROXMOX_TOKEN_SECRET;
char authc[auth.length() + 1];
auth.toCharArray(authc, auth.length() + 1);
http.begin(apiAddress);
http.setAuthorization(authc);
int httpCode = http.GET();
if (httpCode > 0) {
String json = http.getString();
DynamicJsonDocument doc(1024);
deserializeJson(doc, json);
JsonArray nodes = doc["data"].as<JsonArray>();
return nodes;
}
displayError("Error getting data.");
return getNodeInfo();
}
JsonArray getVMInfo(String node) {
HTTPClient http;
String apiAddress = PROXMOX_ADDRESS + "/api2/json/nodes/" + node + "/qemu";
String auth = "PVEAPIToken=" + PROXMOX_TOKEN_USER + "!" + PROXMOX_TOKEN_NAME + "=" + PROXMOX_TOKEN_SECRET;
char authc[auth.length() + 1];
auth.toCharArray(authc, auth.length() + 1);
http.begin(apiAddress);
http.setAuthorization(authc);
int httpCode = http.GET();
if (httpCode > 0) {
String json = http.getString();
DynamicJsonDocument doc(1024);
deserializeJson(doc, json);
JsonArray nodes = doc["data"].as<JsonArray>();
return nodes;
}
displayError("Error getting data.");
return getNodeInfo();
}

@ -0,0 +1,27 @@
#include <ArduinoJson.h>
#include <utils.h>
/**
Get a specific node from an array of nodes
*/
JsonObject getNode(String name, JsonArray nodes) {
for (JsonObject node : nodes) {
if (node["node"] == name) {
return node;
}
}
displayError("Node not found!");
}
JsonObject getContainer(int id, JsonArray containers) {
for (JsonObject container : containers) {
Serial.println(id);
Serial.println(container["vmid"].as<int>());
if (container["vmid"].as<int>() == id) {
return container;
}
}
displayError("Machine not found!");
}

@ -1,429 +1,11 @@
#include <Arduino.h>
#include <ArduinoJson.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include <odroid_go.h>
#include <server.hpp>
int selectedItem = 0;
String selectedNode;
// These ones are int as we use the ID instead of the name
int selectedVM;
int selectedLXC;
void listNodes(JsonArray nodes) {
GO.lcd.clearDisplay();
GO.lcd.setCursor(0, 0);
int numItems = nodes.size();
for (int i = 0; i < numItems; i++) {
if (selectedItem == i) {
GO.lcd.print("> ");
}
GO.lcd.println(nodes[i]["node"].as<String>());
}
switch (buttonListener(numItems)) {
case 1:
Serial.println("selected " + selectedItem);
selectedNode = nodes[selectedItem]["node"].as<String>();
break;
case 2:
Serial.println("back");
break;
default:
listNodes(nodes);
}
}
void listContainers(JsonArray containers) {
GO.lcd.clearDisplay();
GO.lcd.setCursor(0, 0);
int numItems = containers.size();
for (int i = 0; i < numItems; i++) {
if (selectedItem == i) {
GO.lcd.print("> ");
}
GO.lcd.println(containers[i]["vmid"].as<String>() + ": " + containers[i]["name"].as<String>());
}
switch (buttonListener(numItems)) {
case 1:
Serial.println("selected " + selectedItem);
selectedLXC = containers[selectedItem]["vmid"].as<int>();
break;
case 2:
Serial.println("back");
break;
default:
listContainers(containers);
}
}
void listVMs(JsonArray vms) {
GO.lcd.clearDisplay();
GO.lcd.setCursor(0, 0);
int numItems = vms.size();
for (int i = 0; i < numItems; i++) {
if (selectedItem == i) {
GO.lcd.print("> ");
}
GO.lcd.println(vms[i]["vmid"].as<String>() + ": " + vms[i]["name"].as<String>());
}
switch (buttonListener(numItems)) {
case 1:
Serial.println("selected " + selectedItem);
selectedVM = vms[selectedItem]["vmid"].as<int>();
break;
case 2:
Serial.println("back");
break;
default:
listVMs(vms);
}
}
void printNodeStats(JsonObject node) {
String name = node["node"].as<String>();
int cpu = round(node["cpu"].as<float>() * 100);
int threads = node["maxcpu"].as<int>();
String onlineStatus = node["status"].as<String>();
String mem = node["mem"].as<String>();
String maxmem = node["maxmem"].as<String>();
String disk = node["disk"].as<String>();
String maxdisk = node["maxdisk"].as<String>();
String uptime = node["uptime"].as<String>();
// these are strings for now because they could be way too big
GO.lcd.fillScreen(WHITE);
GO.lcd.setCursor(0, 0);
GO.lcd.setTextColor(BLACK);
GO.lcd.setTextSize(3);
GO.lcd.println(name);
GO.lcd.setTextSize(2);
GO.lcd.println("--------------------------");
GO.lcd.println("Status: " + onlineStatus);
GO.lcd.println("Uptime: " + uptime + "s");
GO.lcd.println("CPU: " + String(cpu) + "%");
GO.lcd.println("Threads: " + String(threads));
GO.lcd.println("RAM: " + mem);
GO.lcd.println("Max RAM: " + maxmem);
GO.lcd.println("Disk: " + disk);
GO.lcd.println("Max Disk: " + maxdisk);
}
void printContainerStats(JsonObject container) {
String name = container["name"].as<String>();
String id = container["vmid"].as<String>();
String onlineStatus = container["status"].as<String>();
String maxmem = container["maxmem"].as<String>();
String maxdisk = container["maxdisk"].as<String>();
String uptime = container["uptime"].as<String>();
// these are strings for now because they could be way too big
GO.lcd.fillScreen(WHITE);
GO.lcd.setCursor(0, 0);
GO.lcd.setTextColor(BLACK);
GO.lcd.setTextSize(3);
GO.lcd.println(id + ": " + name);
GO.lcd.setTextSize(2);
GO.lcd.println("--------------------------");
GO.lcd.println("Status: " + onlineStatus);
GO.lcd.println("Uptime: " + uptime + "s");
GO.lcd.println("Max RAM: " + maxmem);
GO.lcd.println("Max Disk: " + maxdisk);
}
void printVMStats(JsonObject vm) {
String name = vm["name"].as<String>();
String id = vm["vmid"].as<String>();
int cpu = round(vm["cpu"].as<float>() * 100);
int cores = vm["cpus"].as<int>();
String onlineStatus = vm["status"].as<String>();
String mem = vm["mem"].as<String>();
String maxmem = vm["maxmem"].as<String>();
String maxdisk = vm["maxdisk"].as<String>();
String uptime = vm["uptime"].as<String>();
String netin = vm["netin"].as<String>();
String netout = vm["netout"].as<String>();
// these are strings for now because they could be way too big
GO.lcd.fillScreen(WHITE);
GO.lcd.setCursor(0, 0);
GO.lcd.setTextColor(BLACK);
GO.lcd.setTextSize(3);
GO.lcd.println(id + ": " + name);
GO.lcd.setTextSize(2);
GO.lcd.println("--------------------------");
GO.lcd.println("Status: " + onlineStatus);
GO.lcd.println("Uptime: " + uptime + "s");
GO.lcd.println("CPU: " + String(cpu) + "%");
GO.lcd.println("Cores: " + String(cores));
GO.lcd.println("RAM: " + mem);
GO.lcd.println("Max RAM: " + maxmem);
GO.lcd.println("Max Disk: " + maxdisk);
GO.lcd.println("Net In: " + netin);
GO.lcd.println("Net Out: " + netout);
}
void connectWiFi() {
WiFi.begin(WIFI_SSID, WIFI_PASS);
GO.lcd.print("Connecting");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
GO.lcd.print(".");
}
}
// Struct for static menu items such as on the main menu. Has the name of the menu item and a function to run when it is selected.
typedef struct {
char *name;
void (*function)();
} MenuItem;
// Array of the main menu items
MenuItem mainMenuItems[] = {
{"Node Information", &nodeInfo},
{"Container Information", &containerInfo},
{"VM Information", &vmInfo}
};
void nodeInfo() {
Serial.println("nodeinfo");
while (true) {
printNodeStats(getNode(selectedNode, getNodeInfo()));
//printAllNodeCPU(getNodeInfo());
delay(2000);
}
}
void containerInfo() {
Serial.println("container info");
JsonArray containerArray = getContainerInfo(selectedNode);
selectedItem = 0;
listContainers(containerArray);
JsonObject container = getContainer(selectedLXC, containerArray);
printContainerStats(container);
delay(1000);
// only redraw screen if changed
while (true) {
if (getContainer(selectedLXC, containerArray) != container) {
containerInfo();
}
}
}
void vmInfo() {
Serial.println("vm info");
JsonArray vmArray = getVMInfo(selectedNode);
selectedItem = 0;
listVMs(vmArray);
while (true) {
printVMStats(getContainer(selectedVM, vmArray));
delay(2000);
}
}
void mainMenu() {
GO.lcd.clearDisplay();
GO.lcd.setCursor(0, 0);
int numItems = sizeof(mainMenuItems) / sizeof(MenuItem);
for (int i = 0; i < numItems; i++) {
if (selectedItem == i) {
GO.lcd.print("> ");
}
GO.lcd.println(mainMenuItems[i].name);
}
switch (buttonListener(numItems)) {
case 1:
Serial.println("selected " + selectedItem);
mainMenuItems[selectedItem].function();
break;
case 2:
Serial.println("back");
break;
default:
mainMenu();
}
}
int buttonListener(int numItems) {
delay(200);
while (true) {
GO.update();
if (GO.JOY_Y.isAxisPressed() == 1 && selectedItem < (numItems - 1)) {
selectedItem++;
break;
}
if (GO.JOY_Y.isAxisPressed() == 2 && selectedItem > 0) {
selectedItem--;
break;
}
if (GO.BtnA.isPressed() == 1) {
delay(300);
return 1;
}
if (GO.BtnB.isPressed() == 1) {
delay(300);
return 2;
}
}
return 0;
}
// todo make the bottom part of these into one function
// ######################################
// ######################################
// ######################################
// ######################################
// ######################################
JsonArray getNodeInfo() {
HTTPClient http;
String apiAddress = PROXMOX_ADDRESS + "/api2/json/nodes/";
String auth = "PVEAPIToken=" + PROXMOX_TOKEN_USER + "!" + PROXMOX_TOKEN_NAME + "=" + PROXMOX_TOKEN_SECRET;
char authc[auth.length() + 1];
auth.toCharArray(authc, auth.length() + 1);
http.begin(apiAddress);
http.setAuthorization(authc);
int httpCode = http.GET();
if (httpCode > 0) {
String json = http.getString();
DynamicJsonDocument doc(1024);
deserializeJson(doc, json);
JsonArray nodes = doc["data"].as<JsonArray>();
return nodes;
}
displayError("Error getting data.");
return getNodeInfo();
}
JsonArray getContainerInfo(String node) {
HTTPClient http;
String apiAddress = PROXMOX_ADDRESS + "/api2/json/nodes/" + node + "/lxc";
String auth = "PVEAPIToken=" + PROXMOX_TOKEN_USER + "!" + PROXMOX_TOKEN_NAME + "=" + PROXMOX_TOKEN_SECRET;
char authc[auth.length() + 1];
auth.toCharArray(authc, auth.length() + 1);
http.begin(apiAddress);
http.setAuthorization(authc);
int httpCode = http.GET();
if (httpCode > 0) {
String json = http.getString();
DynamicJsonDocument doc(1024);
deserializeJson(doc, json);
JsonArray nodes = doc["data"].as<JsonArray>();
return nodes;
}
displayError("Error getting data.");
return getNodeInfo();
}
JsonArray getVMInfo(String node) {
HTTPClient http;
String apiAddress = PROXMOX_ADDRESS + "/api2/json/nodes/" + node + "/qemu";
String auth = "PVEAPIToken=" + PROXMOX_TOKEN_USER + "!" + PROXMOX_TOKEN_NAME + "=" + PROXMOX_TOKEN_SECRET;
char authc[auth.length() + 1];
auth.toCharArray(authc, auth.length() + 1);
http.begin(apiAddress);
http.setAuthorization(authc);
int httpCode = http.GET();
if (httpCode > 0) {
String json = http.getString();
DynamicJsonDocument doc(1024);
deserializeJson(doc, json);
JsonArray nodes = doc["data"].as<JsonArray>();
return nodes;
}
displayError("Error getting data.");
return getNodeInfo();
}
/**
Get a specific node from an array of nodes
*/
JsonObject getNode(String name, JsonArray nodes) {
for (JsonObject node : nodes) {
if (node["node"] == name) {
return node;
}
}
displayError("Node not found!");
}
JsonObject getContainer(int id, JsonArray containers) {
for (JsonObject container : containers) {
Serial.println(id);
Serial.println(container["vmid"].as<int>());
if (container["vmid"].as<int>() == id) {
return container;
}
}
displayError("Machine not found!");
}
/**
Display an error on the screen
*/
void displayError(String message) {
GO.lcd.clearDisplay();
GO.lcd.setCursor(0, 0);
GO.lcd.setTextSize(2);
GO.lcd.setTextColor(RED);
GO.lcd.print(message);
delay(3000);
}
void printAllNodeCPU(JsonArray nodes) {
GO.lcd.fillScreen(WHITE);
GO.lcd.setCursor(0, 0);
for (JsonObject node : nodes) {
Serial.print("CPU Usage for node ");
Serial.print(node["node"].as<String>());
Serial.print(": ");
Serial.println(String(round(node["cpu"].as<float>() * 100)) + "%");
GO.lcd.setTextSize(2);
GO.lcd.setTextColor(BLACK);
GO.lcd.print("CPU Usage for node ");
GO.lcd.print(node["node"].as<String>());
GO.lcd.println(": ");
GO.lcd.println(String(round(node["cpu"].as<float>() * 100)) + "%");
}
}
#include <server.h>
#include <utils.h>
#include <menu.h>
#include <json/retrieve.h>
void setup() {
Serial.begin(115200);
@ -443,4 +25,4 @@ void loop() {
mainMenu();
}
}

@ -0,0 +1,141 @@
#include <json/retrieve.h>
#include <json/utils.h>
#include <global.h>
#include <menu.h>
#include <odroid_go.h>
void printNodeStats(JsonObject node) {
String name = node["node"].as<String>();
int cpu = round(node["cpu"].as<float>() * 100);
int threads = node["maxcpu"].as<int>();
String onlineStatus = node["status"].as<String>();
String mem = node["mem"].as<String>();
String maxmem = node["maxmem"].as<String>();
String disk = node["disk"].as<String>();
String maxdisk = node["maxdisk"].as<String>();
String uptime = node["uptime"].as<String>();
// these are strings for now because they could be way too big
GO.lcd.fillScreen(WHITE);
GO.lcd.setCursor(0, 0);
GO.lcd.setTextColor(BLACK);
GO.lcd.setTextSize(3);
GO.lcd.println(name);
GO.lcd.setTextSize(2);
GO.lcd.println("--------------------------");
GO.lcd.println("Status: " + onlineStatus);
GO.lcd.println("Uptime: " + uptime + "s");
GO.lcd.println("CPU: " + String(cpu) + "%");
GO.lcd.println("Threads: " + String(threads));
GO.lcd.println("RAM: " + mem);
GO.lcd.println("Max RAM: " + maxmem);
GO.lcd.println("Disk: " + disk);
GO.lcd.println("Max Disk: " + maxdisk);
}
void printContainerStats(JsonObject container) {
String name = container["name"].as<String>();
String id = container["vmid"].as<String>();
String onlineStatus = container["status"].as<String>();
String maxmem = container["maxmem"].as<String>();
String maxdisk = container["maxdisk"].as<String>();
String uptime = container["uptime"].as<String>();
// these are strings for now because they could be way too big
GO.lcd.fillScreen(WHITE);
GO.lcd.setCursor(0, 0);
GO.lcd.setTextColor(BLACK);
GO.lcd.setTextSize(3);
GO.lcd.println(id + ": " + name);
GO.lcd.setTextSize(2);
GO.lcd.println("--------------------------");
GO.lcd.println("Status: " + onlineStatus);
GO.lcd.println("Uptime: " + uptime + "s");
GO.lcd.println("Max RAM: " + maxmem);
GO.lcd.println("Max Disk: " + maxdisk);
}
void printVMStats(JsonObject vm) {
String name = vm["name"].as<String>();
String id = vm["vmid"].as<String>();
int cpu = round(vm["cpu"].as<float>() * 100);
int cores = vm["cpus"].as<int>();
String onlineStatus = vm["status"].as<String>();
String mem = vm["mem"].as<String>();
String maxmem = vm["maxmem"].as<String>();
String maxdisk = vm["maxdisk"].as<String>();
String uptime = vm["uptime"].as<String>();
String netin = vm["netin"].as<String>();
String netout = vm["netout"].as<String>();
// these are strings for now because they could be way too big
GO.lcd.fillScreen(WHITE);
GO.lcd.setCursor(0, 0);
GO.lcd.setTextColor(BLACK);
GO.lcd.setTextSize(3);
GO.lcd.println(id + ": " + name);
GO.lcd.setTextSize(2);
GO.lcd.println("--------------------------");
GO.lcd.println("Status: " + onlineStatus);
GO.lcd.println("Uptime: " + uptime + "s");
GO.lcd.println("CPU: " + String(cpu) + "%");
GO.lcd.println("Cores: " + String(cores));
GO.lcd.println("RAM: " + mem);
GO.lcd.println("Max RAM: " + maxmem);
GO.lcd.println("Max Disk: " + maxdisk);
GO.lcd.println("Net In: " + netin);
GO.lcd.println("Net Out: " + netout);
}
void nodeInfo() {
Serial.println("nodeinfo");
while (true) {
printNodeStats(getNode(selectedNode, getNodeInfo()));
delay(2000);
}
}
void containerInfo() {
Serial.println("container info");
JsonArray containerArray = getContainerInfo(selectedNode);
selectedItem = 0;
int selectedLXC = listContainers(containerArray);
JsonObject container = getContainer(selectedLXC, containerArray);
printContainerStats(container);
delay(1000);
// only redraw screen if changed
while (true) {
if (getContainer(selectedLXC, containerArray) != container) {
containerInfo();
}
}
}
void vmInfo() {
Serial.println("vm info");
JsonArray vmArray = getVMInfo(selectedNode);
selectedItem = 0;
int selectedVM = listContainers(vmArray);
Serial.println("vm");
Serial.println(selectedVM);
Serial.println(selectedVM);
Serial.println(selectedVM);
Serial.println(selectedVM);
while (true) {
printVMStats(getContainer(selectedVM, vmArray));
delay(2000);
}
}

@ -0,0 +1,26 @@
#include <odroid_go.h>
#include <wifi_info.h>
#include <WiFi.h>
/**
Display an error on the screen
*/
void displayError(String message) {
GO.lcd.clearDisplay();
GO.lcd.setCursor(0, 0);
GO.lcd.setTextSize(2);
GO.lcd.setTextColor(RED);
GO.lcd.print(message);
delay(3000);
}
void connectWiFi() {
WiFi.begin(WIFI_SSID, WIFI_PASS);
GO.lcd.print("Connecting");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
GO.lcd.print(".");
}
}
Loading…
Cancel
Save