Files
MeshCore/examples/companion_radio/AbstractUITask.h
T
mikecarperandR0ck f57dffa2be Add saved Companion sound and vibration controls
Default fresh settings to sound off and vibration on, and keep existing saved choices. Apply changes immediately across all three UIs and make custom notification patterns respect the same mute controls.

Keep the Wio Mini Companion within its existing flash boundary by storing its LED switch in a reserved preference byte and shortening CLI help without removing commands. Add coverage for live output changes, persistence, and storage failures.

Adapted from https://github.com/meshcore-dev/MeshCore/pull/3603.

Co-authored-by: R0ck <develop@hectospark.co.uk>
2026-10-20 09:33:43 -07:00

127 lines
4.7 KiB
C++

#pragma once
#include <MeshCore.h>
#include <helpers/ui/DisplayDriver.h>
#include <helpers/ui/UIScreen.h>
#include <helpers/SensorManager.h>
#include <helpers/MultiSerialInterface.h>
#include <Arduino.h>
#ifdef PIN_BUZZER
#include <helpers/ui/buzzer.h>
#endif
#include "NodePrefs.h"
enum class UIEventType {
none,
contactMessage,
channelMessage,
roomMessage,
newContactMessage,
ack
};
class UIShutdownGuard {
public:
virtual ~UIShutdownGuard() = default;
virtual bool prepareForUiShutdown() = 0;
};
class AbstractUITask {
protected:
mesh::MainBoard* _board;
MultiSerialInterface* _interfaceManager;
UIShutdownGuard* _shutdownGuard;
bool _connected;
bool _message_notification_override = false;
bool _message_notification_screen_override = false;
bool _notification_led_owned = false;
uint8_t _notification_outputs = 31;
AbstractUITask(mesh::MainBoard* board, MultiSerialInterface* interfaceManager)
: _board(board), _interfaceManager(interfaceManager),
_shutdownGuard(nullptr) {
_connected = false;
}
bool prepareForShutdown() {
return _shutdownGuard == nullptr
|| _shutdownGuard->prepareForUiShutdown();
}
bool shouldWakeDisplayForMessage() const {
return (_notification_outputs & 8) && !_message_notification_screen_override && !hasConnection();
}
public:
void setMessageNotificationOverride(bool managed, bool screen = false) {
_message_notification_override = managed;
_message_notification_screen_override = managed && screen;
}
void setNotificationLedOwnership(bool owned) { _notification_led_owned = owned; }
void setNotificationOutputs(uint8_t outputs) { _notification_outputs = outputs; }
virtual uint8_t notificationCapabilities() const { return 0; }
virtual void notificationVibration(bool on) { (void)on; }
virtual void notificationMelody(const char* text) { (void)text; }
virtual void notificationScreen(int8_t mode) { (void)mode; }
virtual void syncAlertPreferences() {}
void setShutdownGuard(UIShutdownGuard* guard) { _shutdownGuard = guard; }
void setHasConnection(bool connected) { _connected = connected; }
bool hasConnection() const { return _interfaceManager->isConnected(); }
bool hasBluetoothConnection() const { return _interfaceManager->isBluetoothConnected(); }
const char* connectedClientLabel() const {
const bool ble = hasBluetoothConnection();
const bool usb = _interfaceManager->isInterfaceConnected(InterfaceType::USB);
if (ble && usb) return "BLE + USB";
if (ble) return "BLUETOOTH";
if (usb) return "USB";
if (_interfaceManager->isInterfaceConnected(InterfaceType::WiFi)) return "TCP";
if (_interfaceManager->isInterfaceConnected(InterfaceType::Ethernet)) return "ETHERNET";
if (_interfaceManager->isInterfaceConnected(InterfaceType::HardwareSerial)) return "SERIAL";
return nullptr;
}
uint16_t getBattMilliVolts() const { return _board->getBattMilliVolts(); }
bool isBluetoothEnabled() const { return _interfaceManager->isBluetoothEnabled(); }
void enableBluetooth() { _interfaceManager->enableBluetooth(); }
void disableBluetooth() { _interfaceManager->disableBluetooth(); }
virtual void msgRead(int msgcount) = 0;
virtual void syncMessageQueue(int msgcount, int removed_index = -1) {
(void)removed_index;
msgRead(msgcount);
}
virtual bool supportsInboxModes() const { return false; }
virtual void inboxModeChanged() {}
virtual void newMsg(uint8_t path_len, const char* from_name,
const char* text, int msgcount,
int channel_idx = -1,
const char* channel_name = nullptr,
int queue_index = -1) = 0;
virtual void notify(UIEventType t = UIEventType::none) = 0;
virtual bool supportsDisplayRotation() const { return false; }
virtual bool setDisplayRotationDegrees(uint16_t degrees) {
(void)degrees;
return false;
}
// Optional, runtime-only touch diagnostics. Non-touch and legacy UIs
// explicitly report unsupported rather than accepting an invisible toggle.
virtual bool supportsTouchDebug() const { return false; }
virtual bool isTouchDebugEnabled() const { return false; }
virtual bool setTouchDebugEnabled(bool enabled) {
(void)enabled;
return false;
}
// Display implementations that surface an incoming BLE passkey request can
// override these hooks. The default keeps setup-screen routing compatible
// with older UIs that handle pairing only from their regular loop.
virtual void servicePairingState() {}
#ifdef MESH_BUTTON_AUDIO_HIL
virtual bool handleButtonAudioTest(const char*, char*, size_t) { return false; }
#endif
virtual bool isPairingPromptActive() const { return false; }
virtual void loop() = 0;
};