diff --git a/examples/companion_radio/LocalSensors.h b/examples/companion_radio/LocalSensors.h new file mode 100644 index 00000000..351521f8 --- /dev/null +++ b/examples/companion_radio/LocalSensors.h @@ -0,0 +1,22 @@ +#pragma once +// This device's own readings, as the screens, the bot and message placeholders +// read them. + +#include +#include +#include + +// The sensors' readings, plus the chip's own temperature (NaN where a board has +// none) when no sensor reads one: the telemetry reply sends it too, so a board +// without a temperature sensor shows on screen and in {temp} what the app shows. +inline void queryLocalSensors(SensorManager& sm, float mcu_temp, CayenneLPP& lpp) { + sm.querySensors(0xFF, lpp); + if (isnan(mcu_temp)) return; + LPPReader r(lpp.getBuffer(), lpp.getSize()); + uint8_t ch, type; + while (r.readHeader(ch, type)) { + if (type == LPP_TEMPERATURE) return; + r.skipData(type); + } + lpp.addTemperature(TELEM_CHANNEL_SELF, mcu_temp); +} diff --git a/examples/companion_radio/MsgExpand.h b/examples/companion_radio/MsgExpand.h index f3dd7792..efa236ef 100644 --- a/examples/companion_radio/MsgExpand.h +++ b/examples/companion_radio/MsgExpand.h @@ -6,6 +6,7 @@ #include #include "NodePrefs.h" // localTm() #include +#include "LocalSensors.h" // Expands placeholders in tmpl into out (out_len bytes). // {loc} — GPS coordinates (lat/lon) or "no GPS" @@ -26,14 +27,15 @@ inline void expandMsg(const char* tmpl, char* out, int out_len, SensorManager* sm = nullptr, float batt_volts = -1.0f, const char* sender_name = nullptr, - int hops = -1) { + int hops = -1, + float mcu_temp = NAN) { // the chip's, for {temp} without a sensor // sv indices: 0=temp 1=hum 2=pres 3=batt 4=alt 5=lux 6=dist 7=co2 float sv[8] = {}; bool sv_ok[8] = {}; if (sm) { CayenneLPP lpp(100); - sm->querySensors(0xFF, lpp); + queryLocalSensors(*sm, mcu_temp, lpp); LPPReader r(lpp.getBuffer(), lpp.getSize()); uint8_t ch, type; while (r.readHeader(ch, type)) { diff --git a/examples/companion_radio/MyMeshBot.h b/examples/companion_radio/MyMeshBot.h index 0bccbe32..89446a15 100644 --- a/examples/companion_radio/MyMeshBot.h +++ b/examples/companion_radio/MyMeshBot.h @@ -143,7 +143,7 @@ void MyMesh::tryBotReplyDM(const ContactInfo& from, const char* text, uint8_t ho sensors.node_lat != 0.0 || sensors.node_lon != 0.0, ts, _prefs.tz_offset_hours, &sensors, (float)board.getBattMilliVolts() / 1000.0f, - from.name, hops); + from.name, hops, board.getMCUTemperature()); uint32_t expected_ack, est_timeout; if (sendMessage(from, ts, 0, expanded, expected_ack, est_timeout) != MSG_SEND_FAILED) { botDmRecord(from.id.pub_key); @@ -184,7 +184,7 @@ void MyMesh::tryBotReplyChannel(uint8_t channel_idx, const char* text, uint8_t h sensors.node_lat != 0.0 || sensors.node_lon != 0.0, ts, _prefs.tz_offset_hours, &sensors, (float)board.getBattMilliVolts() / 1000.0f, - sender_name, hops); + sender_name, hops, board.getMCUTemperature()); // Anti-loop: don't echo a message identical to our own reply (e.g. another bot // on the channel sending the same text), which would ping-pong forever. The // per-channel cooldown caps any residual back-and-forth between mismatched bots. @@ -228,7 +228,7 @@ void MyMesh::tryBotReplyRoom(const ContactInfo& from, const uint8_t* sender_pref sensors.node_lat != 0.0 || sensors.node_lon != 0.0, ts, _prefs.tz_offset_hours, &sensors, (float)board.getBattMilliVolts() / 1000.0f, - sender_name, hops); + sender_name, hops, board.getMCUTemperature()); // Anti-loop, mirrors the channel path: don't echo a message identical to // our own reply (e.g. re-synced back from the room server). if (strcmp(text, expanded) == 0) return; @@ -367,7 +367,7 @@ bool MyMesh::botCommandReply(const char* cmd, const char* arg, const char* arg2, sensors.node_lat != 0.0 || sensors.node_lon != 0.0, ts, _prefs.tz_offset_hours, &sensors, (float)board.getBattMilliVolts() / 1000.0f, - sender_name, hops); + sender_name, hops, board.getMCUTemperature()); if (strchr(out, '{')) strcpy(out, "n/a"); // requested sensor not present return true; } diff --git a/examples/companion_radio/ui-core/MessageText.h b/examples/companion_radio/ui-core/MessageText.h index c7dd2364..b7e74bd4 100644 --- a/examples/companion_radio/ui-core/MessageText.h +++ b/examples/companion_radio/ui-core/MessageText.h @@ -35,11 +35,11 @@ static void seedQuick(NodePrefs* p) { // ── Placeholders ────────────────────────────────────────────────────────────── // The sensor readings this device has right now, as placeholders ({temp}, -// {hum}, ...; {batt} only from a voltage sensor). -static void sensorPlaceholders(SensorManager* sm, void (*add)(const char* ph, void* ctx), void* ctx) { +// {hum}, ...; {batt} only from a voltage sensor; {temp} also from the chip, mcu_temp). +static void sensorPlaceholders(SensorManager* sm, float mcu_temp, void (*add)(const char* ph, void* ctx), void* ctx) { if (!sm) return; CayenneLPP lpp(100); - sm->querySensors(0xFF, lpp); + queryLocalSensors(*sm, mcu_temp, lpp); uint8_t present[16]; int pc = 0; LPPReader r(lpp.getBuffer(), lpp.getSize()); @@ -62,12 +62,12 @@ static void sensorPlaceholders(SensorManager* sm, void (*add)(const char* ph, vo // Everything a message can carry here: {loc}, {time}, {batt} (the board's // voltage), then the sensors'. -static void placeholders(SensorManager* sm, void (*add)(const char* ph, void* ctx), void* ctx) { +static void placeholders(SensorManager* sm, float mcu_temp, void (*add)(const char* ph, void* ctx), void* ctx) { add("{loc}", ctx); add("{time}", ctx); add("{batt}", ctx); struct Skip { void (*add)(const char*, void*); void* ctx; } skip = { add, ctx }; - sensorPlaceholders(sm, [](const char* ph, void* c) { + sensorPlaceholders(sm, mcu_temp, [](const char* ph, void* c) { Skip* s = (Skip*)c; if (strcmp(ph, "{batt}") != 0) s->add(ph, s->ctx); // already there }, &skip); @@ -89,7 +89,7 @@ static void expand(const char* tmpl, char* out, int n, const NodePrefs* p) { #endif float batt = (float)board.getBattMilliVolts() / 1000.0f; ::expandMsg(tmpl, out, n, lat, lon, gps_valid, rtc_clock.getCurrentTime(), - p ? p->tz_offset_hours : 0, &sensors, batt); + p ? p->tz_offset_hours : 0, &sensors, batt, nullptr, -1, board.getMCUTemperature()); } // A typed message: a reply's leading "@[nick] " stays as it is (a nick may diff --git a/examples/companion_radio/ui-core/Telemetry.h b/examples/companion_radio/ui-core/Telemetry.h index a6fd35f6..1a75473f 100644 --- a/examples/companion_radio/ui-core/Telemetry.h +++ b/examples/companion_radio/ui-core/Telemetry.h @@ -7,8 +7,6 @@ #include #include -#include -#include #include #include #include "Battery.h" @@ -66,21 +64,6 @@ static uint8_t lppType(uint8_t f) { // Read from the sensors, not the radio or GPS. static bool isSensor(uint8_t f) { return lppType(f) != 0; } -// The sensors' readings, plus the chip's own temperature (NaN where a board has -// none) when no sensor reads one: the telemetry reply sends it too, so a board -// without a temperature sensor shows on screen what the app shows. -static void querySensors(SensorManager& sm, float mcu_temp, CayenneLPP& lpp) { - sm.querySensors(0xFF, lpp); - if (isnan(mcu_temp)) return; - LPPReader r(lpp.getBuffer(), lpp.getSize()); - uint8_t ch, type; - while (r.readHeader(ch, type)) { - if (type == LPP_TEMPERATURE) return; - r.skipData(type); - } - lpp.addTemperature(TELEM_CHANNEL_SELF, mcu_temp); -} - // Altitude always in the small unit (never km / mi). static void altText(float m, bool imperial, const Style& st, char* v, int n) { snprintf(v, n, "%.0f%s%s", imperial ? m * 3.28084f : m, st.spaced ? " " : "", imperial ? "ft" : "m"); diff --git a/examples/companion_radio/ui-lvgl/BotScreen.h b/examples/companion_radio/ui-lvgl/BotScreen.h index 2838d0c6..ad589c47 100644 --- a/examples/companion_radio/ui-lvgl/BotScreen.h +++ b/examples/companion_radio/ui-lvgl/BotScreen.h @@ -175,7 +175,7 @@ void UITask::botRow(int row) { lv_obj_set_scrollbar_mode(chips, LV_SCROLLBAR_MODE_OFF); s_chip_ta = _nav_ta; for (int i = 0; i < botcfg::REPLY_PLACEHOLDER_COUNT; i++) botChip(botcfg::REPLY_PLACEHOLDERS[i], chips); - msgtext::sensorPlaceholders(&sensors, [](const char* ph, void* c) { + msgtext::sensorPlaceholders(&sensors, board.getMCUTemperature(), [](const char* ph, void* c) { if (strcmp(ph, "{batt}") != 0) botChip(ph, c); // already there }, chips); } diff --git a/examples/companion_radio/ui-lvgl/HomeScreen.h b/examples/companion_radio/ui-lvgl/HomeScreen.h index b0bdb737..f0cc4a99 100644 --- a/examples/companion_radio/ui-lvgl/HomeScreen.h +++ b/examples/companion_radio/ui-lvgl/HomeScreen.h @@ -621,7 +621,7 @@ void UITask::homeFieldText(uint8_t f, char* v, int n) { if (_sensors && (s_lpp_ms == 0 || millis() - s_lpp_ms > 5000)) { s_lpp_ms = millis() | 1; s_lpp.reset(); - telemetry::querySensors(*_sensors, board.getMCUTemperature(), s_lpp); + queryLocalSensors(*_sensors, board.getMCUTemperature(), s_lpp); } in.lpp = s_lpp.getBuffer(); in.lpp_len = s_lpp.getSize(); diff --git a/examples/companion_radio/ui-lvgl/QuickScreen.h b/examples/companion_radio/ui-lvgl/QuickScreen.h index 0640aae8..354d8b77 100644 --- a/examples/companion_radio/ui-lvgl/QuickScreen.h +++ b/examples/companion_radio/ui-lvgl/QuickScreen.h @@ -12,7 +12,7 @@ static int s_edit = -1; // quick message being edited static void collect() { s_ph_n = 0; - msgtext::placeholders(&sensors, [](const char* ph, void*) { if (s_ph_n < PH_MAX) s_ph[s_ph_n++] = ph; }, nullptr); + msgtext::placeholders(&sensors, board.getMCUTemperature(), [](const char* ph, void*) { if (s_ph_n < PH_MAX) s_ph[s_ph_n++] = ph; }, nullptr); } // The placeholders as small buttons; `cb` gets the index as user data. diff --git a/examples/companion_radio/ui-new/HomeScreen.h b/examples/companion_radio/ui-new/HomeScreen.h index 10379866..2becdd85 100644 --- a/examples/companion_radio/ui-new/HomeScreen.h +++ b/examples/companion_radio/ui-new/HomeScreen.h @@ -102,7 +102,7 @@ static void formatDashVal(uint8_t field, char* val, int val_len, uint16_t batt_m if (telemetry::isSensor(field)) { if (!lpp) { static CayenneLPP s_lpp(200); s_lpp.reset(); - { CardKBBusLock bus_lock; telemetry::querySensors(sensors, board.getMCUTemperature(), s_lpp); } + { CardKBBusLock bus_lock; queryLocalSensors(sensors, board.getMCUTemperature(), s_lpp); } lpp = &s_lpp; } in.lpp = lpp->getBuffer(); @@ -652,7 +652,7 @@ class HomeScreen : public UIScreen { sensors_lpp.reset(); sensors_nb = 0; sensors_lpp.addVoltage(TELEM_CHANNEL_SELF, (float)board.getBattMilliVolts() / 1000.0f); - { CardKBBusLock bus_lock; telemetry::querySensors(sensors, board.getMCUTemperature(), sensors_lpp); } + { CardKBBusLock bus_lock; queryLocalSensors(sensors, board.getMCUTemperature(), sensors_lpp); } LPPReader reader (sensors_lpp.getBuffer(), sensors_lpp.getSize()); uint8_t channel, type; while(reader.readHeader(channel, type)) { diff --git a/examples/companion_radio/ui-new/SensorPlaceholders.h b/examples/companion_radio/ui-new/SensorPlaceholders.h index 3e533f9e..a003b4a9 100644 --- a/examples/companion_radio/ui-new/SensorPlaceholders.h +++ b/examples/companion_radio/ui-new/SensorPlaceholders.h @@ -8,5 +8,5 @@ #include inline void kbAddSensorPlaceholders(KeyboardWidget& kb, SensorManager* sm) { // list: ui-core/MessageText.h - msgtext::sensorPlaceholders(sm, [](const char* ph, void* k) { ((KeyboardWidget*)k)->addPlaceholder(ph); }, &kb); + msgtext::sensorPlaceholders(sm, board.getMCUTemperature(), [](const char* ph, void* k) { ((KeyboardWidget*)k)->addPlaceholder(ph); }, &kb); } diff --git a/examples/companion_radio/ui-new/StatusScreen.h b/examples/companion_radio/ui-new/StatusScreen.h index 46035125..b6625827 100644 --- a/examples/companion_radio/ui-new/StatusScreen.h +++ b/examples/companion_radio/ui-new/StatusScreen.h @@ -237,7 +237,7 @@ private: // Sensors: every reading but the battery (above) and the position (GPS). if (!_lpp_at || millis() - _lpp_at > 5000) { // both passes (measure, draw) read one query _lpp.reset(); - { CardKBBusLock bus_lock; telemetry::querySensors(sensors, board.getMCUTemperature(), _lpp); } // shares the CardKB's bus + { CardKBBusLock bus_lock; queryLocalSensors(sensors, board.getMCUTemperature(), _lpp); } // shares the CardKB's bus _lpp_at = millis() | 1; } static const struct { uint8_t type; const char* name; } NAMES[] = {