Browse Source

feat(companion_radio): distinct buzzer notifications (#2626)

Give advert and toggleable settings (buzzer, GPS) their own short,
easily distinguishable buzzer tones so users of buzzer-only devices
(e.g. T1000E) can tell events apart by ear.

- genericBuzzer::playToggle(count, enabled): generic, opt-in helper
  for the count/direction convention (N notes ascending if enabled,
  descending if disabled). Lives next to play()/startup()/shutdown();
  any caller can use it, nothing forces it.
- AbstractUITask: virtual notifyToggle(count, enabled) with an empty
  default — subclasses that don't care don't override. UIEventType
  only gains one event-shaped entry (advertSent), so it doesn't grow
  one entry per toggleable setting.
- ui-orig / ui-new / ui-tiny: notify() handles fixed events;
  notifyToggle() is a one-line delegate to buzzer.playToggle().
  Button presses, home-page actions, toggleBuzzer (3 notes) and
  toggleGPS (4 notes) route through notifyToggle().
- Preserve existing silent-when-connected behavior for incoming
  contact messages: when the companion app is connected it handles
  user notification, so the device stays quiet.
- Fix mute-confirmation bug: hold mute until the off-tone finishes
  so the user actually hears it when disabling the buzzer.
pull/2665/head
Mark Jocas 2 months ago
parent
commit
f81f5a849a
No known key found for this signature in database GPG Key ID: F75EF1C43FC564B4
  1. 4
      examples/companion_radio/AbstractUITask.h
  2. 20
      examples/companion_radio/ui-new/UITask.cpp
  3. 1
      examples/companion_radio/ui-new/UITask.h
  4. 20
      examples/companion_radio/ui-orig/UITask.cpp
  5. 1
      examples/companion_radio/ui-orig/UITask.h
  6. 20
      examples/companion_radio/ui-tiny/UITask.cpp
  7. 1
      examples/companion_radio/ui-tiny/UITask.h
  8. 14
      src/helpers/ui/buzzer.cpp
  9. 1
      src/helpers/ui/buzzer.h

4
examples/companion_radio/AbstractUITask.h

@ -19,7 +19,8 @@ enum class UIEventType {
channelMessage,
roomMessage,
newContactMessage,
ack
ack,
advertSent
};
class AbstractUITask {
@ -42,5 +43,6 @@ public:
virtual void msgRead(int msgcount) = 0;
virtual void newMsg(uint8_t path_len, const char* from_name, const char* text, int msgcount) = 0;
virtual void notify(UIEventType t = UIEventType::none) = 0;
virtual void notifyToggle(int count, bool enabled) {}
virtual void loop() = 0;
};

20
examples/companion_radio/ui-new/UITask.cpp

@ -434,7 +434,7 @@ public:
return true;
}
if (c == KEY_ENTER && _page == HomePage::ADVERT) {
_task->notify(UIEventType::ack);
_task->notify(UIEventType::advertSent);
if (the_mesh.advert()) {
_task->showAlert("Advert sent!", 1000);
} else {
@ -609,6 +609,9 @@ switch(t){
case UIEventType::ack:
buzzer.play("ack:d=32,o=8,b=120:c");
break;
case UIEventType::advertSent:
buzzer.play("Advert:d=16,o=6,b=240:c,e,g,c7");
break;
case UIEventType::roomMessage:
case UIEventType::newContactMessage:
case UIEventType::none:
@ -625,6 +628,12 @@ switch(t){
#endif
}
void UITask::notifyToggle(int count, bool enabled) {
#if defined(PIN_BUZZER)
buzzer.playToggle(count, enabled);
#endif
}
void UITask::msgRead(int msgcount) {
_msgcount = msgcount;
@ -909,11 +918,11 @@ void UITask::toggleGPS() {
if (strcmp(_sensors->getSettingValue(i), "1") == 0) {
_sensors->setSettingValue("gps", "0");
_node_prefs->gps_enabled = 0;
notify(UIEventType::ack);
notifyToggle(4, false);
} else {
_sensors->setSettingValue("gps", "1");
_node_prefs->gps_enabled = 1;
notify(UIEventType::ack);
notifyToggle(4, true);
}
the_mesh.savePrefs();
showAlert(_node_prefs->gps_enabled ? "GPS: Enabled" : "GPS: Disabled", 800);
@ -929,8 +938,11 @@ void UITask::toggleBuzzer() {
#ifdef PIN_BUZZER
if (buzzer.isQuiet()) {
buzzer.quiet(false);
notify(UIEventType::ack);
notifyToggle(3, true);
} else {
// play the off-tone before muting so the user hears the confirmation
notifyToggle(3, false);
while (buzzer.isPlaying()) buzzer.loop();
buzzer.quiet(true);
}
_node_prefs->buzzer_quiet = buzzer.isQuiet();

1
examples/companion_radio/ui-new/UITask.h

@ -95,6 +95,7 @@ public:
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 notifyToggle(int count, bool enabled) override;
void loop() override;
void shutdown(bool restart = false);

20
examples/companion_radio/ui-orig/UITask.cpp

@ -103,6 +103,9 @@ switch(t){
case UIEventType::ack:
buzzer.play("ack:d=32,o=8,b=120:c");
break;
case UIEventType::advertSent:
buzzer.play("Advert:d=16,o=6,b=240:c,e,g,c7");
break;
case UIEventType::roomMessage:
case UIEventType::newContactMessage:
case UIEventType::none:
@ -114,6 +117,12 @@ switch(t){
// Serial.println((int) t);
}
void UITask::notifyToggle(int count, bool enabled) {
#if defined(PIN_BUZZER)
buzzer.playToggle(count, enabled);
#endif
}
void UITask::msgRead(int msgcount) {
_msgcount = msgcount;
if (msgcount == 0) {
@ -393,7 +402,7 @@ void UITask::handleButtonDoublePress() {
MESH_DEBUG_PRINTLN("UITask: double press triggered, sending advert");
// ADVERT
#ifdef PIN_BUZZER
notify(UIEventType::ack);
notify(UIEventType::advertSent);
#endif
if (the_mesh.advert()) {
MESH_DEBUG_PRINTLN("Advert sent!");
@ -411,9 +420,12 @@ void UITask::handleButtonTriplePress() {
#ifdef PIN_BUZZER
if (buzzer.isQuiet()) {
buzzer.quiet(false);
notify(UIEventType::ack);
notifyToggle(3, true);
sprintf(_alert, "Buzzer: ON");
} else {
// play the off-tone before muting so the user hears the confirmation
notifyToggle(3, false);
while (buzzer.isPlaying()) buzzer.loop();
buzzer.quiet(true);
sprintf(_alert, "Buzzer: OFF");
}
@ -432,11 +444,11 @@ void UITask::handleButtonQuadruplePress() {
if (strcmp(_sensors->getSettingName(i), "gps") == 0) {
if (strcmp(_sensors->getSettingValue(i), "1") == 0) {
_sensors->setSettingValue("gps", "0");
notify(UIEventType::ack);
notifyToggle(4, false);
sprintf(_alert, "GPS: Disabled");
} else {
_sensors->setSettingValue("gps", "1");
notify(UIEventType::ack);
notifyToggle(4, true);
sprintf(_alert, "GPS: Enabled");
}
break;

1
examples/companion_radio/ui-orig/UITask.h

@ -67,6 +67,7 @@ public:
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 notifyToggle(int count, bool enabled) override;
void loop() override;
void shutdown(bool restart = false);

20
examples/companion_radio/ui-tiny/UITask.cpp

@ -394,7 +394,7 @@ public:
return true;
}
if (c == KEY_ENTER && _page == HomePage::ADVERT) {
_task->notify(UIEventType::ack);
_task->notify(UIEventType::advertSent);
if (the_mesh.advert()) {
_task->showAlert("Advert sent!", 1000);
} else {
@ -481,6 +481,9 @@ switch(t){
case UIEventType::ack:
buzzer.play("ack:d=32,o=8,b=120:c");
break;
case UIEventType::advertSent:
buzzer.play("Advert:d=16,o=6,b=240:c,e,g,c7");
break;
case UIEventType::roomMessage:
case UIEventType::newContactMessage:
case UIEventType::none:
@ -497,6 +500,12 @@ switch(t){
#endif
}
void UITask::notifyToggle(int count, bool enabled) {
#if defined(PIN_BUZZER)
buzzer.playToggle(count, enabled);
#endif
}
void UITask::msgRead(int msgcount) {
_msgcount = msgcount;
@ -796,11 +805,11 @@ void UITask::toggleGPS() {
if (strcmp(_sensors->getSettingValue(i), "1") == 0) {
_sensors->setSettingValue("gps", "0");
_node_prefs->gps_enabled = 0;
notify(UIEventType::ack);
notifyToggle(4, false);
} else {
_sensors->setSettingValue("gps", "1");
_node_prefs->gps_enabled = 1;
notify(UIEventType::ack);
notifyToggle(4, true);
}
the_mesh.savePrefs();
showAlert(_node_prefs->gps_enabled ? "GPS: Enabled" : "GPS: Disabled", 800);
@ -816,8 +825,11 @@ void UITask::toggleBuzzer() {
#ifdef PIN_BUZZER
if (buzzer.isQuiet()) {
buzzer.quiet(false);
notify(UIEventType::ack);
notifyToggle(3, true);
} else {
// play the off-tone before muting so the user hears the confirmation
notifyToggle(3, false);
while (buzzer.isPlaying()) buzzer.loop();
buzzer.quiet(true);
}
_node_prefs->buzzer_quiet = buzzer.isQuiet();

1
examples/companion_radio/ui-tiny/UITask.h

@ -103,6 +103,7 @@ public:
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 notifyToggle(int count, bool enabled) override;
void loop() override;
void shutdown(bool restart = false);

14
src/helpers/ui/buzzer.cpp

@ -44,6 +44,20 @@ void genericBuzzer::shutdown() {
play(shutdown_song);
}
void genericBuzzer::playToggle(int count, bool enabled) {
static const char *notes[] = {"c", "e", "g", "c7", "e7", "g7"};
const int max_notes = (int)(sizeof(notes) / sizeof(notes[0]));
if (count < 1) count = 1;
if (count > max_notes) count = max_notes;
char melody[64];
int n = snprintf(melody, sizeof(melody), "Tg:d=16,o=6,b=200:");
for (int i = 0; i < count && n < (int)sizeof(melody); i++) {
int idx = enabled ? i : (count - 1 - i);
n += snprintf(melody + n, sizeof(melody) - n, "%s%s", i ? "," : "", notes[idx]);
}
play(melody);
}
void genericBuzzer::quiet(bool buzzer_state) {
_is_quiet = buzzer_state;
#ifdef PIN_BUZZER_EN

1
src/helpers/ui/buzzer.h

@ -21,6 +21,7 @@ class genericBuzzer
public:
void begin(); // set up buzzer port
void play(const char *melody); // Generic play function
void playToggle(int count, bool enabled); // play toggle tone
void loop(); // loop driven-nonblocking
void startup(); // play startup sound
void shutdown(); // play shutdown sound

Loading…
Cancel
Save