239 lines
6.9 KiB
C++
239 lines
6.9 KiB
C++
#include <Arduino.h>
|
|
#include <Adafruit_SSD1306.h>
|
|
#include <ESP8266HTTPClient.h>
|
|
#include <ArduinoJson.h>
|
|
#include "config.h"
|
|
#include "SmartCube/cubeSound.h"
|
|
#include "SmartCube/cubeButtons.h"
|
|
#include "SmartCube/cubeWifiManager.h"
|
|
|
|
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
|
|
cubeWifiManager cubeWifiManager(display);
|
|
|
|
unsigned long lastRefresh = 0;
|
|
const unsigned long refreshInterval = 60000; // 60 seconds
|
|
|
|
String lastEventId = "";
|
|
String problems[10];
|
|
String problemDescriptions;
|
|
int problemCount = 0;
|
|
int severityCounts[6] = {0};
|
|
bool newProblemsDetected = false;
|
|
int totalProblems = 0; // Variable to store the total number of active problems
|
|
|
|
// History buffer for the graph
|
|
const int maxHistorySize = 30;
|
|
int problemHistory[maxHistorySize] = {0}; // Array to store history
|
|
int historyIndex = 0; // Current index for the latest value
|
|
|
|
int scrollPos = SCREEN_WIDTH; // Global variable to keep track of the scroll position
|
|
unsigned long lastScrollTime = 0; // To control the scroll speed
|
|
const int scrollDelay = 120; // Delay in milliseconds between scroll updates
|
|
|
|
void initSystems() {
|
|
pinMode(PIN_BTN_L, INPUT);
|
|
pinMode(PIN_BTN_M, INPUT);
|
|
pinMode(PIN_BTN_R, INPUT);
|
|
pinMode(PIN_BUZZER, OUTPUT);
|
|
pinMode(LED_BUILTIN, OUTPUT);
|
|
digitalWrite(LED_BUILTIN, HIGH);
|
|
Wire.begin(); // Initialize I2C
|
|
Wire.setClock(400000L); // Set I2C to Fast Mode (400 kHz)
|
|
display.ssd1306_command(SSD1306_SETCONTRAST);
|
|
display.ssd1306_command(200); // Value between 0 and 255
|
|
|
|
// Initialize the SSD1306 display
|
|
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Adjust I2C address if needed
|
|
for (;;); // Don't proceed, loop forever
|
|
}
|
|
|
|
// Rotate the display 180 degrees
|
|
display.setRotation(2);
|
|
|
|
// Clear the display buffer
|
|
display.clearDisplay();
|
|
display.setTextSize(1);
|
|
display.setTextColor(WHITE);
|
|
display.setCursor(0, 0);
|
|
display.display();
|
|
}
|
|
|
|
void fetchActiveProblems() {
|
|
WiFiClient client;
|
|
HTTPClient http;
|
|
http.begin(client, zabbixServer);
|
|
http.setTimeout(5000); // 5-second timeout
|
|
http.addHeader("Content-Type", "application/json");
|
|
|
|
// JSON payload
|
|
DynamicJsonDocument doc(2048); // Increased to avoid memory issues
|
|
doc["jsonrpc"] = "2.0";
|
|
doc["method"] = "problem.get";
|
|
doc["id"] = 1;
|
|
doc["auth"] = zabbixToken;
|
|
JsonObject params = doc["params"].to<JsonObject>();
|
|
params["output"] = "extend";
|
|
params["recent"] = true;
|
|
params["sortfield"] = "eventid";
|
|
params["sortorder"] = "DESC";
|
|
|
|
String requestBody;
|
|
serializeJson(doc, requestBody);
|
|
|
|
// POST request
|
|
int httpResponseCode = http.POST(requestBody);
|
|
|
|
if (httpResponseCode > 0) {
|
|
String response = http.getString();
|
|
|
|
// Parse response
|
|
DynamicJsonDocument responseDoc(8192); // Increased size to fit more data
|
|
DeserializationError error = deserializeJson(responseDoc, response);
|
|
|
|
if (!error) {
|
|
JsonArray result = responseDoc["result"].as<JsonArray>();
|
|
|
|
// Clear descriptions and severity counts
|
|
memset(severityCounts, 0, sizeof(severityCounts));
|
|
problemDescriptions = ""; // Reset before appending
|
|
|
|
totalProblems = result.size(); // Set total problems count
|
|
|
|
// Store the current totalProblems in the history buffer
|
|
problemHistory[historyIndex] = totalProblems;
|
|
historyIndex = (historyIndex + 1) % maxHistorySize; // Circular buffer
|
|
|
|
int newProblemCount = 0;
|
|
for (JsonObject problem : result) {
|
|
String eventId = problem["eventid"].as<String>();
|
|
int severity = problem["severity"].as<int>();
|
|
String description = problem["name"].as<String>();
|
|
|
|
// Check for new problems by comparing event IDs
|
|
if (eventId.toInt() > lastEventId.toInt()) {
|
|
newProblemsDetected = true;
|
|
}
|
|
|
|
if (severity >= 0 && severity < 5) {
|
|
severityCounts[severity]++;
|
|
}
|
|
|
|
problemDescriptions += description + " "; // Append description with space for better display
|
|
newProblemCount++;
|
|
}
|
|
|
|
problemCount = newProblemCount;
|
|
|
|
if (problemCount > 0) {
|
|
lastEventId = result[0]["eventid"].as<String>();
|
|
}
|
|
} else {
|
|
beep(1000);
|
|
}
|
|
} else {
|
|
problemDescriptions="Zabbix API error";
|
|
}
|
|
|
|
http.end();
|
|
}
|
|
|
|
void playAlertMelody() {
|
|
int toneDuration = 60; // Each tone lasts 150ms
|
|
int pauseDuration = 20; // Pause between tones
|
|
|
|
// Play first tone
|
|
tone(PIN_BUZZER, 1500); // 1000 Hz
|
|
delay(toneDuration);
|
|
noTone(PIN_BUZZER);
|
|
delay(pauseDuration);
|
|
|
|
// Play second tone
|
|
tone(PIN_BUZZER, 1200); // 1200 Hz
|
|
delay(toneDuration);
|
|
noTone(PIN_BUZZER);
|
|
delay(pauseDuration);
|
|
|
|
// Play third tone
|
|
tone(PIN_BUZZER, 1500); // 1500 Hz
|
|
delay(toneDuration);
|
|
noTone(PIN_BUZZER);
|
|
}
|
|
|
|
void displayProblems() {
|
|
display.clearDisplay();
|
|
display.setTextSize(1);
|
|
display.setCursor(0, 0);
|
|
display.printf(" I:%d W:%d A:%d H:%d D:%d",
|
|
severityCounts[1],
|
|
severityCounts[2],
|
|
severityCounts[3],
|
|
severityCounts[4],
|
|
severityCounts[5]);
|
|
display.drawLine(0, 45, 127, 45, 1); // Line under the graph
|
|
display.drawLine(0, 10, 127, 10, 1); // Line under the graph
|
|
|
|
// Draw the history graph
|
|
int graphHeight = 30; // Height of the graph
|
|
int graphTop = 15; // Top position of the graph
|
|
int graphBottom = graphTop + graphHeight;
|
|
|
|
int maxProblems = *std::max_element(problemHistory, problemHistory + maxHistorySize); // Find max for scaling
|
|
if (maxProblems == 0) maxProblems = 1; // Avoid division by zero
|
|
|
|
for (int i = 0; i < maxHistorySize - 1; i++) {
|
|
int x1 = (i * SCREEN_WIDTH) / maxHistorySize;
|
|
int x2 = ((i + 1) * SCREEN_WIDTH) / maxHistorySize;
|
|
|
|
int y1 = graphBottom - (problemHistory[(historyIndex + i) % maxHistorySize] * graphHeight) / maxProblems;
|
|
int y2 = graphBottom - (problemHistory[(historyIndex + i + 1) % maxHistorySize] * graphHeight) / maxProblems;
|
|
|
|
display.drawLine(x1, y1, x2, y2, 1); // Draw line between points
|
|
}
|
|
|
|
// Scroll text below the graph
|
|
int stateWidth = strlen(problemDescriptions.c_str()) * 12;
|
|
|
|
if (!is_display_off) {
|
|
if (millis() - lastScrollTime > scrollDelay) {
|
|
scrollPos -= 11;
|
|
lastScrollTime = millis();
|
|
|
|
if (scrollPos < -stateWidth) {
|
|
scrollPos = SCREEN_WIDTH;
|
|
}
|
|
}
|
|
}
|
|
|
|
display.setTextSize(2);
|
|
display.setCursor(scrollPos, 48);
|
|
display.print(problemDescriptions);
|
|
display.setTextSize(1);
|
|
display.fillRect(117,35,10,10,0);
|
|
display.setCursor(118,36);
|
|
display.print(totalProblems);
|
|
display.display();
|
|
}
|
|
|
|
void setup() {
|
|
initSystems();
|
|
cubeWifiManager.start();
|
|
fetchActiveProblems();
|
|
}
|
|
|
|
void loop() {
|
|
unsigned long currentMillis = millis();
|
|
cubeButtonHandler();
|
|
|
|
if (!is_display_off && currentMillis - lastRefresh >= refreshInterval) {
|
|
lastRefresh = currentMillis;
|
|
fetchActiveProblems();
|
|
}
|
|
|
|
displayProblems();
|
|
|
|
if (newProblemsDetected) {
|
|
playAlertMelody();
|
|
newProblemsDetected = false;
|
|
}
|
|
}
|