#include #include #include #include #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(); 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(); // 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(); int severity = problem["severity"].as(); String description = problem["name"].as(); // 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(); } } 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(112,35,10,10,0); display.setCursor(113,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; } }