buzzer and led queued offline message indicator

- buzzer was bugged when message received
- green led: hearthbeat, blue led: message received indicator (when not connected to app)
- if only one led blinks: hearthbeat 20msec, message received 200msec
This commit is contained in:
liquidraver
2026-04-02 21:06:28 +02:00
parent 97e13700ec
commit e115f24b31
2 changed files with 69 additions and 12 deletions
+19 -1
View File
@@ -16,6 +16,10 @@
#include <ZephyrSensorManager.h>
#include <adapters/sensors/SimpleLPP.h>
#include <adapters/ble/ZephyrBLE.h>
#if IS_ENABLED(CONFIG_ZEPHCORE_UI_BUTTONS) || IS_ENABLED(CONFIG_ZEPHCORE_UI_BUZZER) || IS_ENABLED(CONFIG_ZEPHCORE_UI_DISPLAY)
#include <ui_task.h>
#define ZEPHCORE_HAS_UI_TASK 1
#endif
LOG_MODULE_REGISTER(zephcore_companion, CONFIG_ZEPHCORE_MAIN_LOG_LEVEL);
/* Protocol commands (matches Arduino companion_radio) - sorted by opcode */
@@ -589,7 +593,6 @@ ContactInfo *CompanionMesh::processAck(const uint8_t *data)
uint32_t trip_time = now - sent_time;
put_le32(&ack_push[4], trip_time);
sendPush(PUSH_CODE_SEND_CONFIRMED, ack_push, 8);
return lookupContactByPubKey(ci.id.pub_key, PUB_KEY_SIZE);
}
}
@@ -611,6 +614,10 @@ void CompanionMesh::onMessageRecv(const ContactInfo &contact, mesh::Packet *pkt,
markConnectionActive(contact);
queueContactMessage(contact, pkt, TXT_TYPE_PLAIN, sender_timestamp, nullptr, 0, text);
sendPush(PUSH_CODE_MSG_WAITING);
#if ZEPHCORE_HAS_UI_TASK
ui_set_msg_count((uint16_t)_offline_queue_count);
ui_notify(UI_EVENT_CONTACT_MSG);
#endif
}
void CompanionMesh::queueContactMessage(const ContactInfo &contact, mesh::Packet *pkt,
@@ -685,6 +692,10 @@ void CompanionMesh::onSignedMessageRecv(const ContactInfo &contact, mesh::Packet
// sender_prefix is 4 bytes
queueContactMessage(contact, pkt, TXT_TYPE_SIGNED_PLAIN, sender_timestamp, sender_prefix, 4, text);
sendPush(PUSH_CODE_MSG_WAITING);
#if ZEPHCORE_HAS_UI_TASK
ui_set_msg_count((uint16_t)_offline_queue_count);
ui_notify(UI_EVENT_CONTACT_MSG);
#endif
}
uint32_t CompanionMesh::calcFloodTimeoutMillisFor(uint32_t pkt_airtime_millis) const
@@ -747,6 +758,10 @@ void CompanionMesh::onChannelMessageRecv(const mesh::GroupChannel &channel, mesh
LOG_DBG("onChannelMessageRecv: frame_len=%d channel_idx=%d", i, channel_idx);
queueOfflineMessage(frame, i);
sendPush(PUSH_CODE_MSG_WAITING);
#if ZEPHCORE_HAS_UI_TASK
ui_set_msg_count((uint16_t)_offline_queue_count);
ui_notify(UI_EVENT_CHANNEL_MSG);
#endif
}
void CompanionMesh::onChannelDataRecv(const mesh::GroupChannel &channel, mesh::Packet *pkt,
@@ -1766,6 +1781,9 @@ bool CompanionMesh::handleProtocolFrame(const uint8_t *data, size_t len)
if (_sync_pending) {
confirmOfflineMessage();
_sync_pending = false;
#if ZEPHCORE_HAS_UI_TASK
ui_set_msg_count((uint16_t)_offline_queue_count);
#endif
}
uint8_t buf[MAX_FRAME_SIZE];
+50 -11
View File
@@ -91,19 +91,28 @@ LOG_MODULE_REGISTER(ui_task, CONFIG_ZEPHCORE_BOARD_LOG_LEVEL);
* Works alongside displays; boards that want to disable it can
* remove the led0 alias or override this with a Kconfig guard. */
#if DT_NODE_HAS_PROP(DT_ALIAS(led0), gpios)
#define LED_NODE DT_ALIAS(led0)
static const struct gpio_dt_spec heartbeat_led =
GPIO_DT_SPEC_GET(LED_NODE, gpios);
GPIO_DT_SPEC_GET(DT_ALIAS(led0), gpios);
#define HAS_HEARTBEAT_LED 1
#elif DT_NODE_HAS_PROP(DT_ALIAS(led1), gpios)
#define LED_NODE DT_ALIAS(led1)
static const struct gpio_dt_spec heartbeat_led =
GPIO_DT_SPEC_GET(LED_NODE, gpios);
GPIO_DT_SPEC_GET(DT_ALIAS(led1), gpios);
#define HAS_HEARTBEAT_LED 1
#else
#define HAS_HEARTBEAT_LED 0
#endif
/* Message indicator LED — solid ON while offline queue is non-empty.
* Uses led1 only when led0 is already taken by the heartbeat. */
#if HAS_HEARTBEAT_LED && DT_NODE_HAS_PROP(DT_ALIAS(led0), gpios) && \
DT_NODE_HAS_PROP(DT_ALIAS(led1), gpios)
static const struct gpio_dt_spec msg_led =
GPIO_DT_SPEC_GET(DT_ALIAS(led1), gpios);
#define HAS_MSG_LED 1
#else
#define HAS_MSG_LED 0
#endif
#define LED_CYCLE_MS 4000 /* Total heartbeat period */
#define LED_ON_MS 20 /* Normal pulse width */
#define LED_ON_MSG_MS 200 /* Pulse width when unread messages */
@@ -183,6 +192,9 @@ static void led_off_work_handler(struct k_work *work)
{
ARG_UNUSED(work);
gpio_pin_set_dt(&heartbeat_led, 0);
#if HAS_MSG_LED
gpio_pin_set_dt(&msg_led, 0);
#endif
/* Schedule next ON after remainder of cycle */
struct ui_state *s = get_state();
@@ -195,10 +207,16 @@ static void led_on_work_handler(struct k_work *work)
{
ARG_UNUSED(work);
gpio_pin_set_dt(&heartbeat_led, 1);
/* Schedule OFF after pulse width */
#if HAS_MSG_LED
struct ui_state *s = get_state();
if (s->msg_count > 0) {
gpio_pin_set_dt(&msg_led, 1);
}
uint16_t on_ms = (s->msg_count > 0) ? LED_ON_MSG_MS : LED_ON_MS;
#else
struct ui_state *s = get_state();
uint16_t on_ms = (s->msg_count > 0) ? LED_ON_MSG_MS : LED_ON_MS;
#endif
k_work_reschedule(&led_off_work, K_MSEC(on_ms));
}
@@ -550,12 +568,15 @@ static void action_deep_sleep(void)
#ifdef CONFIG_POWEROFF
LOG_INF("deep sleep: shutting down...");
/* 1. Stop LED heartbeat */
/* 1. Stop LED heartbeat and msg indicator */
#if HAS_HEARTBEAT_LED
k_work_cancel_delayable(&led_on_work);
k_work_cancel_delayable(&led_off_work);
gpio_pin_set_dt(&heartbeat_led, 0);
#endif
#if HAS_MSG_LED
gpio_pin_set_dt(&msg_led, 0);
#endif
/* 2. Play shutdown melody (blocking wait) */
#ifdef CONFIG_ZEPHCORE_UI_BUZZER
@@ -860,6 +881,12 @@ int ui_init(void)
LOG_INF("LED heartbeat started");
}
#endif
#if HAS_MSG_LED
if (gpio_is_ready_dt(&msg_led)) {
gpio_pin_configure_dt(&msg_led, GPIO_OUTPUT_INACTIVE);
LOG_INF("msg LED ready");
}
#endif
/* NOTE: startup chime is NOT played here. It's played from main()
* after loadPrefs() so we can respect the persisted buzzer_quiet setting.
@@ -938,12 +965,24 @@ void ui_notify(enum ui_event event)
break;
}
/* Wake display on notifications.
* Repeater: never wake display on events only user button wakes it.
* Companion: wake unless phone is connected (phone handles its own). */
/* On message events: flash heartbeat LED immediately (if not BLE connected
* and LEDs are enabled). Cancel the current cycle, turn on now, let
* led_off_work resume the normal heartbeat after LED_ON_MSG_MS. */
#if HAS_HEARTBEAT_LED
if (is_msg_event && !get_state()->ble_connected && !get_state()->leds_disabled
&& gpio_is_ready_dt(&heartbeat_led)) {
k_work_cancel_delayable(&led_on_work);
k_work_cancel_delayable(&led_off_work);
gpio_pin_set_dt(&heartbeat_led, 1);
k_work_reschedule(&led_off_work, K_MSEC(LED_ON_MSG_MS));
}
#endif
/* Wake display on non-message notifications (BLE connect/disconnect etc).
* Message notifications use buzzer + LED flash instead of waking the display. */
#ifdef CONFIG_ZEPHCORE_UI_DISPLAY
#ifndef ZEPHCORE_REPEATER
if (!(is_msg_event && get_state()->ble_connected)) {
if (!is_msg_event) {
mc_display_on();
schedule_render();
}