Files
MeshCore-Solo/examples/companion_radio/ui-new/UITask.h
T
JakubandClaude Sonnet 4.6 4e83e99316 Fix null pointer dereferences in SettingsScreen index helpers
lowBatIndex(), autoOffIndex(), gpsIntervalIndex() each called
getNodePrefs() independently without null check, while renderItem()
had its own guarded copy. Added null checks consistent with the rest
of the class. Also initialize _node_prefs to NULL in UITask constructor.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 21:09:47 +02:00

119 lines
3.1 KiB
C++

#pragma once
#include <MeshCore.h>
#include <helpers/ui/DisplayDriver.h>
#include <helpers/ui/UIScreen.h>
#include <helpers/SensorManager.h>
#include <helpers/BaseSerialInterface.h>
#include <Arduino.h>
#include <helpers/sensors/LPPDataHelpers.h>
#ifndef LED_STATE_ON
#define LED_STATE_ON 1
#endif
#ifdef PIN_BUZZER
#include <helpers/ui/buzzer.h>
#endif
#ifdef PIN_VIBRATION
#include <helpers/ui/GenericVibration.h>
#endif
#include "../AbstractUITask.h"
#include "../NodePrefs.h"
class UITask : public AbstractUITask {
DisplayDriver* _display;
SensorManager* _sensors;
#ifdef PIN_BUZZER
genericBuzzer buzzer;
#endif
#ifdef PIN_VIBRATION
GenericVibration vibration;
#endif
unsigned long _next_refresh, _auto_off;
NodePrefs* _node_prefs;
char _alert[80];
unsigned long _alert_expiry;
int _msgcount;
unsigned long ui_started_at, next_batt_chck;
uint16_t _batt_mv; // EMA-filtered battery voltage
int next_backlight_btn_check = 0;
#ifdef PIN_STATUS_LED
int led_state = 0;
int next_led_change = 0;
int last_led_increment = 0;
#endif
#ifdef PIN_USER_BTN_ANA
unsigned long _analogue_pin_read_millis = millis();
#endif
UIScreen* splash;
UIScreen* home;
UIScreen* msg_preview;
UIScreen* settings;
UIScreen* quick_msg;
UIScreen* curr;
void userLedHandler();
// Button action handlers
char checkDisplayOn(char c);
char handleLongPress(char c);
char handleDoubleClick(char c);
char handleTripleClick(char c);
void setCurrScreen(UIScreen* c);
public:
UITask(mesh::MainBoard* board, BaseSerialInterface* serial) : AbstractUITask(board, serial), _display(NULL), _sensors(NULL), _node_prefs(NULL) {
next_batt_chck = _next_refresh = 0;
ui_started_at = 0;
_batt_mv = 0;
curr = NULL;
}
void begin(DisplayDriver* display, SensorManager* sensors, NodePrefs* node_prefs);
NodePrefs* getNodePrefs() const { return _node_prefs; }
uint16_t getBattMilliVolts() const { return _batt_mv > 0 ? _batt_mv : AbstractUITask::getBattMilliVolts(); }
void gotoHomeScreen() { setCurrScreen(home); }
void gotoSettingsScreen() { setCurrScreen(settings); }
void gotoQuickMsgScreen();
void showAlert(const char* text, int duration_millis);
int getMsgCount() const { return _msgcount; }
bool hasDisplay() const { return _display != NULL; }
bool isButtonPressed() const;
bool isBuzzerQuiet() {
#ifdef PIN_BUZZER
return buzzer.isQuiet();
#else
return true;
#endif
}
void toggleBuzzer();
bool getGPSState();
void toggleGPS();
void applyBrightness();
void setBrightnessLevel(uint8_t level);
uint8_t getBrightnessLevel() const { return _node_prefs ? _node_prefs->display_brightness : 2; }
void applyTxPower();
void applyGPSInterval();
uint32_t autoOffMillis() const {
if (!_node_prefs || _node_prefs->auto_off_secs == 0) return 0;
return (uint32_t)_node_prefs->auto_off_secs * 1000UL;
}
// from AbstractUITask
void msgRead(int msgcount) override;
void newMsg(uint8_t path_len, const char* from_name, const char* text, int msgcount) override;
void notify(UIEventType t = UIEventType::none) override;
void loop() override;
void shutdown(bool restart = false);
};