mirror of
https://github.com/MarekZegare4/MeshCore-Solo.git
synced 2026-11-01 10:21:59 +00:00
fix(l2): a dot per DM send, lists that notice every change, the LED lit only on TX
- A pending DM shows a dot per send, as on the L1. The thread is read from the SD archive, which a resend never updated: it does now, and the thread's signature and patch state count the attempt. - Nearby redraws when a node goes live, changes type or the units change; the scan popup when a name or the remote SNR arrives. - The user LED is active high: it was lit all the time and went dark while transmitting. - Sim hooks "dm" and "send" for testing a DM thread. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -460,6 +460,9 @@ public:
|
||||
e.ack_tag = expected_ack; // each attempt has a distinct ACK CRC
|
||||
e.ack_deadline_ms = now + est_timeout + 4000;
|
||||
e.resends_left--;
|
||||
#ifdef HIST_ARCHIVE
|
||||
if (_arc) _arc->dmUpdate(e); // the thread is read from it: a dot per send
|
||||
#endif
|
||||
} else {
|
||||
failDm(e); // couldn't compose/send — give up
|
||||
}
|
||||
|
||||
@@ -3177,8 +3177,9 @@ void UITask::refreshScanPopup() {
|
||||
uint32_t sig = (uint32_t)n + (_scanning ? 0x10000u : 0);
|
||||
for (int i = 0; i < n; i++) {
|
||||
const NearbyModel::Entry& e = _scan->at(i);
|
||||
sig = sig * 31 + e.rssi * 7 + e.snr_x4 + e.is_known;
|
||||
sig = sig * 31 + e.rssi * 7 + e.snr_x4 + e.remote_snr_x4 * 3 + e.type * 5 + e.is_known;
|
||||
for (int k = 0; k < 4; k++) sig = sig * 31 + e.pub_key[k];
|
||||
for (const char* p = e.name; *p; p++) sig = sig * 31 + (uint8_t)*p;
|
||||
}
|
||||
if (sig == _scan_sig || vlist::pressed(_scan_list)) return; // held: once it's let go
|
||||
_scan_sig = sig;
|
||||
@@ -3224,10 +3225,12 @@ void UITask::openScanNode(int row) {
|
||||
|
||||
// Changes whenever a rebuild would show something different.
|
||||
uint32_t UITask::nearbySignature() const {
|
||||
uint32_t sig = (uint32_t)_nearby->count() * 2654435761u + _nearby->sortMode() + (_scanning ? 7 : 0);
|
||||
uint32_t sig = (uint32_t)_nearby->count() * 2654435761u + _nearby->sortMode() + (_scanning ? 7 : 0)
|
||||
+ (_prefs && _prefs->units_imperial ? 13 : 0);
|
||||
for (int i = 0; i < _nearby->count(); i++) {
|
||||
const NearbyModel::Entry& e = _nearby->at(i);
|
||||
sig = sig * 31 + e.contact_idx + (uint32_t)e.lastmod + (uint32_t)(e.dist_km * 100) + e.rssi + e.fav;
|
||||
sig = sig * 31 + e.contact_idx + (uint32_t)e.lastmod + (uint32_t)(e.dist_km * 100) + e.rssi + e.fav
|
||||
+ e.type * 5 + (e.is_live ? 3 : 0);
|
||||
for (const char* p = e.name; *p; p++) sig = sig * 31 + (uint8_t)*p;
|
||||
}
|
||||
// Ages are shown in minutes, so let the list re-render once a minute anyway.
|
||||
@@ -3730,7 +3733,7 @@ uint32_t UITask::threadSignature() const {
|
||||
sig = n;
|
||||
for (int j = 0; j < n && j < 8; j++) {
|
||||
const DmHistEntry& e = h.dmAtPos(h.dmHistEntryForContact(_thread_key, j));
|
||||
sig = sig * 31 + e.timestamp + h.dmEffectiveStatus(e);
|
||||
sig = sig * 31 + e.timestamp + h.dmEffectiveStatus(e) + e.attempt * 7; // attempt: a dot per resend
|
||||
}
|
||||
}
|
||||
return sig;
|
||||
@@ -4053,7 +4056,7 @@ void UITask::refreshThread() {
|
||||
};
|
||||
auto stateOf = [&](int i) -> uint32_t {
|
||||
if (_thread_is_channel) return s_th_ch[i].relay_status | (uint32_t)s_th_ch[i].path_len << 8;
|
||||
return s_th_dm[i].outgoing ? 0x100u | h.dmEffectiveStatus(s_th_dm[i]) : 0;
|
||||
return s_th_dm[i].outgoing ? 0x100u | h.dmEffectiveStatus(s_th_dm[i]) | (uint32_t)s_th_dm[i].attempt << 16 : 0;
|
||||
};
|
||||
// Entry i's bubble (at the list's end) and its menu / position slots.
|
||||
auto build = [&](int i) {
|
||||
@@ -4091,7 +4094,13 @@ void UITask::refreshThread() {
|
||||
switch (h.dmEffectiveStatus(e)) {
|
||||
case ACK_OK: st = LV_SYMBOL_OK; col = theme::OK; break;
|
||||
case ACK_FAIL: st = LV_SYMBOL_CLOSE; col = theme::FAIL; break;
|
||||
case ACK_PENDING: st = "..."; break;
|
||||
case ACK_PENDING: { // a dot per send, as ui-new: grows with each auto-resend
|
||||
static char dots[9];
|
||||
int k = e.attempt + 1 < 8 ? e.attempt + 1 : 8;
|
||||
memset(dots, '.', k); dots[k] = '\0';
|
||||
st = dots;
|
||||
break;
|
||||
}
|
||||
default: st = ""; break;
|
||||
}
|
||||
}
|
||||
@@ -4657,6 +4666,13 @@ void UITask::simCompose(const char* text) {
|
||||
lv_textarea_set_text(_compose_ta, text);
|
||||
}
|
||||
|
||||
void UITask::simDm() {
|
||||
for (int i = 0; i < the_mesh.getNumContacts(); i++) {
|
||||
ContactInfo c;
|
||||
if (the_mesh.getContactByIdx(MAX_ANON_CONTACTS + i, c) && c.type == ADV_TYPE_CHAT) { openDM(c.id.pub_key); return; }
|
||||
}
|
||||
}
|
||||
|
||||
// Sim tests: straight to a screen by name.
|
||||
extern "C" EMSCRIPTEN_KEEPALIVE void sim_open(const char* name) {
|
||||
if (!s_ui) return;
|
||||
@@ -4679,6 +4695,8 @@ extern "C" EMSCRIPTEN_KEEPALIVE void sim_open(const char* name) {
|
||||
if (!strncmp(name, "map@", 4)) { s_ui->simMapAt(name + 4); return; } // "map@lat,lon,z"
|
||||
if (!strncmp(name, "channel@", 8)) { s_ui->openChannel(atoi(name + 8)); return; }
|
||||
if (!strncmp(name, "compose@", 8)) { s_ui->simCompose(name + 8); return; }
|
||||
if (!strcmp(name, "dm")) { s_ui->simDm(); return; }
|
||||
if (!strcmp(name, "send")) { s_ui->simSend(); return; }
|
||||
if (!strcmp(name, "vector")) { s_ui->setVectorMap(true); return; }
|
||||
if (!strcmp(name, "maptools")) { s_ui->navToolsPopup(); return; }
|
||||
if (!strcmp(name, "areasel")) { s_ui->areaSelectBegin(); return; }
|
||||
|
||||
@@ -129,6 +129,8 @@ public:
|
||||
void setVectorMap(bool on);
|
||||
void simMapAt(const char* spec); // Map tools > Live tiles
|
||||
void simCompose(const char* text); // the open thread's field: this text, keyboard up
|
||||
void simDm(); // the first chat contact's thread
|
||||
void simSend() { sendFromCompose(); } // the field, sent
|
||||
// Navigation map (NavMap.h)
|
||||
void navTargetsPopup();
|
||||
void navClosePopup();
|
||||
|
||||
@@ -77,8 +77,9 @@ bool WioTrackerL2Board::initExpander() {
|
||||
expSetOutput(EXP_PIN_GNSS_RST, HIGH);
|
||||
delay(10);
|
||||
expWritePin(EXP_PIN_GNSS_RST, LOW);
|
||||
// user LED is driven active-low through the expander; idle level HIGH = off
|
||||
expSetOutput(EXP_PIN_USER_LED, HIGH);
|
||||
// user LED: lit while the pin is HIGH (it read as active-low before, and
|
||||
// stayed lit except while transmitting); idle LOW = off
|
||||
expSetOutput(EXP_PIN_USER_LED, LOW);
|
||||
delay(10);
|
||||
expSetOutput(EXP_PIN_GROVE_EN, HIGH);
|
||||
delay(10);
|
||||
@@ -194,9 +195,8 @@ void WioTrackerL2Board::begin() {
|
||||
}
|
||||
|
||||
void WioTrackerL2Board::setLed(bool on) {
|
||||
// active low: HIGH = off
|
||||
if (expander_ok) {
|
||||
expWritePin(EXP_PIN_USER_LED, !on);
|
||||
expWritePin(EXP_PIN_USER_LED, on);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
#define EXP_PIN_GROVE_EN 7 // output - Grove port power
|
||||
#define EXP_PIN_TP_RST 8 // output - touch panel reset
|
||||
#define EXP_PIN_GNSS_RST 9 // output - GNSS reset (active HIGH)
|
||||
#define EXP_PIN_USER_LED 10 // output - mesh/user LED (active low)
|
||||
#define EXP_PIN_USER_LED 10 // output - mesh/user LED (active high; also GNSS wakeup)
|
||||
#define EXP_PIN_OTG_EN 11 // output - USB OTG power
|
||||
#define EXP_PIN_PA_EN 12 // output - speaker amp power
|
||||
#define EXP_PIN_GNSS_EN 13 // output - GNSS power
|
||||
|
||||
Reference in New Issue
Block a user