Merge pull request #705 from crossan007/AddEnvironmentMessage

Changes to Environmental Measurement App
1.2-legacy
Jm Casler 2021-02-24 20:26:44 -08:00 zatwierdzone przez GitHub
commit 4f40128bbe
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
9 zmienionych plików z 246 dodań i 32 usunięć

2
proto

@ -1 +1 @@
Subproject commit 564292ee83bbd085d0c51a7f882d3a2aa305d6d6 Subproject commit d70f6f6f669df79c9423795caf34adbd28967e19

Wyświetl plik

@ -64,6 +64,10 @@ uint8_t imgBattery[16] = {0xFF, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
// Threshold values for the GPS lock accuracy bar display // Threshold values for the GPS lock accuracy bar display
uint32_t dopThresholds[5] = {2000, 1000, 500, 200, 100}; uint32_t dopThresholds[5] = {2000, 1000, 500, 200, 100};
// At some point, we're going to ask all of the plugins if they would like to display a screen frame
// we'll need to hold onto pointers for the plugins that can draw a frame.
std::vector<MeshPlugin *> pluginFrames;
// Stores the last 4 of our hardware ID, to make finding the device for pairing easier // Stores the last 4 of our hardware ID, to make finding the device for pairing easier
static char ourId[5]; static char ourId[5];
@ -144,6 +148,30 @@ static void drawSleepScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int
drawIconScreen("Sleeping...", display, state, x, y); drawIconScreen("Sleeping...", display, state, x, y);
} }
static void drawPluginFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{
uint8_t plugin_frame;
// there's a little but in the UI transition code
// where it invokes the function at the correct offset
// in the array of "drawScreen" functions; however,
// the passed-state doesn't quite reflect the "current"
// screen, so we have to detect it.
if (state->frameState == IN_TRANSITION && state->transitionFrameRelationship == INCOMING) {
// if we're transitioning from the end of the frame list back around to the first
// frame, then we want this to be `0`
plugin_frame = state->transitionFrameTarget;
}
else {
// otherwise, just display the plugin frame that's aligned with the current frame
plugin_frame = state->currentFrame;
//DEBUG_MSG("Screen is not in transition. Frame: %d\n\n", plugin_frame);
}
//DEBUG_MSG("Drawing Plugin Frame %d\n\n", plugin_frame);
MeshPlugin &pi = *pluginFrames.at(plugin_frame);
pi.drawFrame(display,state,x,y);
}
static void drawFrameBluetooth(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) static void drawFrameBluetooth(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{ {
display->setTextAlignment(TEXT_ALIGN_CENTER); display->setTextAlignment(TEXT_ALIGN_CENTER);
@ -887,6 +915,11 @@ void Screen::setFrames()
DEBUG_MSG("showing standard frames\n"); DEBUG_MSG("showing standard frames\n");
showingNormalScreen = true; showingNormalScreen = true;
pluginFrames = MeshPlugin::GetMeshPluginsWithUIFrames();
DEBUG_MSG("Showing %d plugin frames\n", pluginFrames.size());
int totalFrameCount = MAX_NUM_NODES + NUM_EXTRA_FRAMES + pluginFrames.size();
DEBUG_MSG("Total frame count: %d\n", totalFrameCount);
// We don't show the node info our our node (if we have it yet - we should) // We don't show the node info our our node (if we have it yet - we should)
size_t numnodes = nodeStatus->getNumTotal(); size_t numnodes = nodeStatus->getNumTotal();
if (numnodes > 0) if (numnodes > 0)
@ -894,6 +927,18 @@ void Screen::setFrames()
size_t numframes = 0; size_t numframes = 0;
// put all of the plugin frames first.
// this is a little bit of a dirty hack; since we're going to call
// the same drawPluginFrame handler here for all of these plugin frames
// and then we'll just assume that the state->currentFrame value
// is the same offset into the pluginFrames vector
// so that we can invoke the plugin's callback
for (auto i = pluginFrames.begin(); i != pluginFrames.end(); ++i) {
normalFrames[numframes++] = drawPluginFrame;
}
DEBUG_MSG("Added plugins. numframes: %d\n", numframes);
// If we have a critical fault, show it first // If we have a critical fault, show it first
if (myNodeInfo.error_code) if (myNodeInfo.error_code)
normalFrames[numframes++] = drawCriticalFaultFrame; normalFrames[numframes++] = drawCriticalFaultFrame;
@ -922,6 +967,8 @@ void Screen::setFrames()
} }
#endif #endif
DEBUG_MSG("Finished building frames. numframes: %d\n", numframes);
ui.setFrames(normalFrames, numframes); ui.setFrames(normalFrames, numframes);
ui.enableAllIndicators(); ui.enableAllIndicators();

Wyświetl plik

@ -76,3 +76,17 @@ void setReplyTo(MeshPacket *p, const MeshPacket &to) {
p->to = to.from; p->to = to.from;
p->want_ack = to.want_ack; p->want_ack = to.want_ack;
} }
std::vector<MeshPlugin *> MeshPlugin::GetMeshPluginsWithUIFrames() {
std::vector<MeshPlugin *> pluginsWithUIFrames;
for (auto i = plugins->begin(); i != plugins->end(); ++i) {
auto &pi = **i;
if ( pi.wantUIFrame()) {
DEBUG_MSG("Plugin wants a UI Frame\n");
pluginsWithUIFrames.push_back(&pi);
}
}
return pluginsWithUIFrames;
}

Wyświetl plik

@ -2,6 +2,8 @@
#include "mesh/MeshTypes.h" #include "mesh/MeshTypes.h"
#include <vector> #include <vector>
#include <OLEDDisplay.h>
#include <OLEDDisplayUi.h>
/** A baseclass for any mesh "plugin". /** A baseclass for any mesh "plugin".
* *
* A plugin allows you to add new features to meshtastic device code, without needing to know messaging details. * A plugin allows you to add new features to meshtastic device code, without needing to know messaging details.
@ -28,6 +30,10 @@ class MeshPlugin
*/ */
static void callPlugins(const MeshPacket &mp); static void callPlugins(const MeshPacket &mp);
static std::vector<MeshPlugin *> GetMeshPluginsWithUIFrames();
virtual void drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) { return; }
protected: protected:
const char *name; const char *name;
@ -61,6 +67,13 @@ class MeshPlugin
* so that subclasses can (optionally) send a response back to the original sender. */ * so that subclasses can (optionally) send a response back to the original sender. */
virtual MeshPacket *allocReply() { return NULL; } virtual MeshPacket *allocReply() { return NULL; }
/***
* @return true if you want to be alloced a UI screen frame
*/
virtual bool wantUIFrame() { return false; }
private: private:
/** Messages can be received that have the want_response bit set. If set, this callback will be invoked /** Messages can be received that have the want_response bit set. If set, this callback will be invoked

Wyświetl plik

@ -80,7 +80,7 @@ extern const pb_msgdesc_t DeviceState_msg;
#define DeviceState_fields &DeviceState_msg #define DeviceState_fields &DeviceState_msg
/* Maximum encoded size of messages (where known) */ /* Maximum encoded size of messages (where known) */
#define DeviceState_size 6266 #define DeviceState_size 6293
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */

Wyświetl plik

@ -208,6 +208,11 @@ typedef struct _RadioConfig_UserPreferences {
bool range_test_plugin_save; bool range_test_plugin_save;
bool store_forward_plugin_enabled; bool store_forward_plugin_enabled;
uint32_t store_forward_plugin_records; uint32_t store_forward_plugin_records;
bool environmental_measurement_plugin_measurement_enabled;
bool environmental_measurement_plugin_screen_enabled;
uint32_t environmental_measurement_plugin_read_error_count_threshold;
uint32_t environmental_measurement_plugin_update_interval;
uint32_t environmental_measurement_plugin_recovery_interval;
} RadioConfig_UserPreferences; } RadioConfig_UserPreferences;
typedef struct _RouteDiscovery { typedef struct _RouteDiscovery {
@ -360,7 +365,7 @@ extern "C" {
#define MeshPacket_init_default {0, 0, 0, {SubPacket_init_default}, 0, 0, 0, 0, 0, 0, _MeshPacket_Priority_MIN} #define MeshPacket_init_default {0, 0, 0, {SubPacket_init_default}, 0, 0, 0, 0, 0, 0, _MeshPacket_Priority_MIN}
#define ChannelSettings_init_default {0, _ChannelSettings_ModemConfig_MIN, {0, {0}}, "", 0, 0, 0, 0, 0, 0, 0} #define ChannelSettings_init_default {0, _ChannelSettings_ModemConfig_MIN, {0, {0}}, "", 0, 0, 0, 0, 0, 0, 0}
#define RadioConfig_init_default {false, RadioConfig_UserPreferences_init_default, false, ChannelSettings_init_default} #define RadioConfig_init_default {false, RadioConfig_UserPreferences_init_default, false, ChannelSettings_init_default}
#define RadioConfig_UserPreferences_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, _RegionCode_MIN, _ChargeCurrent_MIN, _LocationSharing_MIN, _GpsOperation_MIN, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define RadioConfig_UserPreferences_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, _RegionCode_MIN, _ChargeCurrent_MIN, _LocationSharing_MIN, _GpsOperation_MIN, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
#define NodeInfo_init_default {0, false, User_init_default, false, Position_init_default, 0, 0} #define NodeInfo_init_default {0, false, User_init_default, false, Position_init_default, 0, 0}
#define MyNodeInfo_init_default {0, 0, 0, "", "", "", _CriticalErrorCode_MIN, 0, 0, 0, 0, 0, 0, 0} #define MyNodeInfo_init_default {0, 0, 0, "", "", "", _CriticalErrorCode_MIN, 0, 0, 0, 0, 0, 0, 0}
#define LogRecord_init_default {"", 0, "", _LogRecord_Level_MIN} #define LogRecord_init_default {"", 0, "", _LogRecord_Level_MIN}
@ -374,7 +379,7 @@ extern "C" {
#define MeshPacket_init_zero {0, 0, 0, {SubPacket_init_zero}, 0, 0, 0, 0, 0, 0, _MeshPacket_Priority_MIN} #define MeshPacket_init_zero {0, 0, 0, {SubPacket_init_zero}, 0, 0, 0, 0, 0, 0, _MeshPacket_Priority_MIN}
#define ChannelSettings_init_zero {0, _ChannelSettings_ModemConfig_MIN, {0, {0}}, "", 0, 0, 0, 0, 0, 0, 0} #define ChannelSettings_init_zero {0, _ChannelSettings_ModemConfig_MIN, {0, {0}}, "", 0, 0, 0, 0, 0, 0, 0}
#define RadioConfig_init_zero {false, RadioConfig_UserPreferences_init_zero, false, ChannelSettings_init_zero} #define RadioConfig_init_zero {false, RadioConfig_UserPreferences_init_zero, false, ChannelSettings_init_zero}
#define RadioConfig_UserPreferences_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, _RegionCode_MIN, _ChargeCurrent_MIN, _LocationSharing_MIN, _GpsOperation_MIN, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define RadioConfig_UserPreferences_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, _RegionCode_MIN, _ChargeCurrent_MIN, _LocationSharing_MIN, _GpsOperation_MIN, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
#define NodeInfo_init_zero {0, false, User_init_zero, false, Position_init_zero, 0, 0} #define NodeInfo_init_zero {0, false, User_init_zero, false, Position_init_zero, 0, 0}
#define MyNodeInfo_init_zero {0, 0, 0, "", "", "", _CriticalErrorCode_MIN, 0, 0, 0, 0, 0, 0, 0} #define MyNodeInfo_init_zero {0, 0, 0, "", "", "", _CriticalErrorCode_MIN, 0, 0, 0, 0, 0, 0, 0}
#define LogRecord_init_zero {"", 0, "", _LogRecord_Level_MIN} #define LogRecord_init_zero {"", 0, "", _LogRecord_Level_MIN}
@ -460,6 +465,11 @@ extern "C" {
#define RadioConfig_UserPreferences_range_test_plugin_save_tag 134 #define RadioConfig_UserPreferences_range_test_plugin_save_tag 134
#define RadioConfig_UserPreferences_store_forward_plugin_enabled_tag 136 #define RadioConfig_UserPreferences_store_forward_plugin_enabled_tag 136
#define RadioConfig_UserPreferences_store_forward_plugin_records_tag 137 #define RadioConfig_UserPreferences_store_forward_plugin_records_tag 137
#define RadioConfig_UserPreferences_environmental_measurement_plugin_measurement_enabled_tag 140
#define RadioConfig_UserPreferences_environmental_measurement_plugin_screen_enabled_tag 141
#define RadioConfig_UserPreferences_environmental_measurement_plugin_read_error_count_threshold_tag 142
#define RadioConfig_UserPreferences_environmental_measurement_plugin_update_interval_tag 143
#define RadioConfig_UserPreferences_environmental_measurement_plugin_recovery_interval_tag 144
#define RouteDiscovery_route_tag 2 #define RouteDiscovery_route_tag 2
#define User_id_tag 1 #define User_id_tag 1
#define User_long_name_tag 2 #define User_long_name_tag 2
@ -641,7 +651,12 @@ X(a, STATIC, SINGULAR, BOOL, range_test_plugin_enabled, 132) \
X(a, STATIC, SINGULAR, UINT32, range_test_plugin_sender, 133) \ X(a, STATIC, SINGULAR, UINT32, range_test_plugin_sender, 133) \
X(a, STATIC, SINGULAR, BOOL, range_test_plugin_save, 134) \ X(a, STATIC, SINGULAR, BOOL, range_test_plugin_save, 134) \
X(a, STATIC, SINGULAR, BOOL, store_forward_plugin_enabled, 136) \ X(a, STATIC, SINGULAR, BOOL, store_forward_plugin_enabled, 136) \
X(a, STATIC, SINGULAR, UINT32, store_forward_plugin_records, 137) X(a, STATIC, SINGULAR, UINT32, store_forward_plugin_records, 137) \
X(a, STATIC, SINGULAR, BOOL, environmental_measurement_plugin_measurement_enabled, 140) \
X(a, STATIC, SINGULAR, BOOL, environmental_measurement_plugin_screen_enabled, 141) \
X(a, STATIC, SINGULAR, UINT32, environmental_measurement_plugin_read_error_count_threshold, 142) \
X(a, STATIC, SINGULAR, UINT32, environmental_measurement_plugin_update_interval, 143) \
X(a, STATIC, SINGULAR, UINT32, environmental_measurement_plugin_recovery_interval, 144)
#define RadioConfig_UserPreferences_CALLBACK NULL #define RadioConfig_UserPreferences_CALLBACK NULL
#define RadioConfig_UserPreferences_DEFAULT NULL #define RadioConfig_UserPreferences_DEFAULT NULL
@ -753,13 +768,13 @@ extern const pb_msgdesc_t ToRadio_msg;
#define SubPacket_size 275 #define SubPacket_size 275
#define MeshPacket_size 322 #define MeshPacket_size 322
#define ChannelSettings_size 95 #define ChannelSettings_size 95
#define RadioConfig_size 405 #define RadioConfig_size 432
#define RadioConfig_UserPreferences_size 305 #define RadioConfig_UserPreferences_size 332
#define NodeInfo_size 132 #define NodeInfo_size 132
#define MyNodeInfo_size 106 #define MyNodeInfo_size 106
#define LogRecord_size 81 #define LogRecord_size 81
#define FromRadio_size 414 #define FromRadio_size 441
#define ToRadio_size 409 #define ToRadio_size 436
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */

Wyświetl plik

@ -18,10 +18,10 @@ typedef enum _PortNum {
PortNum_NODEINFO_APP = 4, PortNum_NODEINFO_APP = 4,
PortNum_REPLY_APP = 32, PortNum_REPLY_APP = 32,
PortNum_IP_TUNNEL_APP = 33, PortNum_IP_TUNNEL_APP = 33,
PortNum_ENVIRONMENTAL_MEASUREMENT_APP = 34,
PortNum_SERIAL_APP = 64, PortNum_SERIAL_APP = 64,
PortNum_STORE_FORWARD_APP = 65, PortNum_STORE_FORWARD_APP = 65,
PortNum_RANGE_TEST_APP = 66, PortNum_RANGE_TEST_APP = 66,
PortNum_ENVIRONMENTAL_MEASUREMENT_APP = 67,
PortNum_PRIVATE_APP = 256, PortNum_PRIVATE_APP = 256,
PortNum_ATAK_FORWARDER = 257 PortNum_ATAK_FORWARDER = 257
} PortNum; } PortNum;

Wyświetl plik

@ -7,6 +7,8 @@
#include "main.h" #include "main.h"
#include "../mesh/generated/environmental_measurement.pb.h" #include "../mesh/generated/environmental_measurement.pb.h"
#include <DHT.h> #include <DHT.h>
#include <OLEDDisplay.h>
#include <OLEDDisplayUi.h>
EnvironmentalMeasurementPlugin *environmentalMeasurementPlugin; EnvironmentalMeasurementPlugin *environmentalMeasurementPlugin;
EnvironmentalMeasurementPluginRadio *environmentalMeasurementPluginRadio; EnvironmentalMeasurementPluginRadio *environmentalMeasurementPluginRadio;
@ -16,19 +18,51 @@ EnvironmentalMeasurementPlugin::EnvironmentalMeasurementPlugin() : concurrency::
uint32_t sensor_read_error_count = 0; uint32_t sensor_read_error_count = 0;
#define DHT_11_GPIO_PIN 13 #define DHT_11_GPIO_PIN 13
//TODO: Make a related radioconfig preference to allow less-frequent reads #define DHT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS 1000 // Some sensors (the DHT11) have a minimum required duration between read attempts
#define DHT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS 1000 #define FAILED_STATE_SENSOR_READ_MULTIPLIER 10
#define SENSOR_READ_ERROR_COUNT_THRESHOLD 5 #define DISPLAY_RECEIVEID_MEASUREMENTS_ON_SCREEN true
#define SENSOR_READ_MULTIPLIER 3
DHT dht(DHT_11_GPIO_PIN,DHT11); DHT dht(DHT_11_GPIO_PIN,DHT11);
#ifdef HAS_EINK
// The screen is bigger so use bigger fonts
#define FONT_SMALL ArialMT_Plain_16
#define FONT_MEDIUM ArialMT_Plain_24
#define FONT_LARGE ArialMT_Plain_24
#else
#define FONT_SMALL ArialMT_Plain_10
#define FONT_MEDIUM ArialMT_Plain_16
#define FONT_LARGE ArialMT_Plain_24
#endif
#define fontHeight(font) ((font)[1] + 1) // height is position 1
#define FONT_HEIGHT_SMALL fontHeight(FONT_SMALL)
#define FONT_HEIGHT_MEDIUM fontHeight(FONT_MEDIUM)
int32_t EnvironmentalMeasurementPlugin::runOnce() { int32_t EnvironmentalMeasurementPlugin::runOnce() {
#ifndef NO_ESP32 #ifndef NO_ESP32 // this only works on ESP32 devices
/*
Uncomment the preferences below if you want to use the plugin
without having to configure it from the PythonAPI or WebUI.
*/
/*radioConfig.preferences.environmental_measurement_plugin_measurement_enabled = 1;
radioConfig.preferences.environmental_measurement_plugin_screen_enabled = 1;
radioConfig.preferences.environmental_measurement_plugin_read_error_count_threshold = 5;
radioConfig.preferences.environmental_measurement_plugin_update_interval = 30;
radioConfig.preferences.environmental_measurement_plugin_recovery_interval = 600;*/
if (! (radioConfig.preferences.environmental_measurement_plugin_measurement_enabled || radioConfig.preferences.environmental_measurement_plugin_screen_enabled)){
// If this plugin is not enabled, and the user doesn't want the display screen don't waste any OSThread time on it
return (INT32_MAX);
}
if (firstTime) { if (firstTime) {
// This is the first time the OSThread library has called this function, so do some setup // This is the first time the OSThread library has called this function, so do some setup
DEBUG_MSG("Initializing Environmental Measurement Plugin -- Sender\n"); DEBUG_MSG("EnvironmentalMeasurement: Initializing\n");
environmentalMeasurementPluginRadio = new EnvironmentalMeasurementPluginRadio(); environmentalMeasurementPluginRadio = new EnvironmentalMeasurementPluginRadio();
firstTime = 0; firstTime = 0;
// begin reading measurements from the sensor // begin reading measurements from the sensor
@ -37,19 +71,44 @@ int32_t EnvironmentalMeasurementPlugin::runOnce() {
// returning the interval here means that the next time OSThread // returning the interval here means that the next time OSThread
// calls our plugin, we'll run the other branch of this if statement // calls our plugin, we'll run the other branch of this if statement
// and actually do a "sendOurEnvironmentalMeasurement()" // and actually do a "sendOurEnvironmentalMeasurement()"
if (radioConfig.preferences.environmental_measurement_plugin_measurement_enabled)
{
// it's possible to have this plugin enabled, only for displaying values on the screen.
// therefore, we should only enable the sensor loop if measurement is also enabled
dht.begin(); dht.begin();
return(DHT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS); return(DHT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS);
} }
return (INT32_MAX);
}
else { else {
if (!radioConfig.preferences.environmental_measurement_plugin_measurement_enabled)
{
// if we somehow got to a second run of this plugin with measurement disabled, then just wait forever
// I can't imagine we'd ever get here though.
return (INT32_MAX);
}
// this is not the first time OSThread library has called this function // this is not the first time OSThread library has called this function
// so just do what we intend to do on the interval // so just do what we intend to do on the interval
if(sensor_read_error_count > SENSOR_READ_ERROR_COUNT_THRESHOLD) if(sensor_read_error_count > radioConfig.preferences.environmental_measurement_plugin_read_error_count_threshold)
{ {
DEBUG_MSG("Environmental Measurement Plugin: DISABLED; The SENSOR_READ_ERROR_COUNT_THRESHOLD has been exceed: %d\n",SENSOR_READ_ERROR_COUNT_THRESHOLD); if (radioConfig.preferences.environmental_measurement_plugin_recovery_interval > 0 ) {
return(DHT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS); DEBUG_MSG(
"EnvironmentalMeasurement: TEMPORARILY DISABLED; The environmental_measurement_plugin_read_error_count_threshold has been exceed: %d. Will retry reads in %d seconds\n",
radioConfig.preferences.environmental_measurement_plugin_read_error_count_threshold,
radioConfig.preferences.environmental_measurement_plugin_recovery_interval);
return(radioConfig.preferences.environmental_measurement_plugin_recovery_interval*1000);
}
DEBUG_MSG(
"EnvironmentalMeasurement: DISABLED; The environmental_measurement_plugin_read_error_count_threshold has been exceed: %d. Reads will not be retried until after device reset\n",
radioConfig.preferences.environmental_measurement_plugin_read_error_count_threshold);
return(INT32_MAX);
} }
else if (sensor_read_error_count > 0){ else if (sensor_read_error_count > 0){
DEBUG_MSG("Environmental Measurement Plugin: There have been %d sensor read failures.\n",sensor_read_error_count); DEBUG_MSG("EnvironmentalMeasurement: There have been %d sensor read failures. Will retry %d more times\n",
sensor_read_error_count,
radioConfig.preferences.environmental_measurement_plugin_read_error_count_threshold-sensor_read_error_count);
} }
if (! environmentalMeasurementPluginRadio->sendOurEnvironmentalMeasurement() ){ if (! environmentalMeasurementPluginRadio->sendOurEnvironmentalMeasurement() ){
// if we failed to read the sensor, then try again // if we failed to read the sensor, then try again
@ -59,14 +118,62 @@ int32_t EnvironmentalMeasurementPlugin::runOnce() {
} }
// The return of runOnce is an int32 representing the desired number of // The return of runOnce is an int32 representing the desired number of
// miliseconds until the function should be called again by the // miliseconds until the function should be called again by the
// OSThread library. // OSThread library. Multiply the preference value by 1000 to convert seconds to miliseconds
return(SENSOR_READ_MULTIPLIER * DHT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS); return(radioConfig.preferences.environmental_measurement_plugin_update_interval * 1000);
#endif #endif
} }
bool EnvironmentalMeasurementPluginRadio::wantUIFrame() {
return radioConfig.preferences.environmental_measurement_plugin_screen_enabled;
}
void EnvironmentalMeasurementPluginRadio::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{
display->setTextAlignment(TEXT_ALIGN_LEFT);
display->setFont(FONT_MEDIUM);
display->drawString(x, y, "Environment");
display->setFont(FONT_SMALL);
display->drawString(x, y += fontHeight(FONT_MEDIUM), lastSender+": T:"+ String(lastMeasurement.temperature,2) + " H:" + String(lastMeasurement.relative_humidity,2));
}
String GetSenderName(const MeshPacket &mp) {
String sender;
if (nodeDB.getNode(mp.from)){
sender = nodeDB.getNode(mp.from)->user.short_name;
}
else {
sender = "UNK";
}
return sender;
}
bool EnvironmentalMeasurementPluginRadio::handleReceivedProtobuf(const MeshPacket &mp, const EnvironmentalMeasurement &p) bool EnvironmentalMeasurementPluginRadio::handleReceivedProtobuf(const MeshPacket &mp, const EnvironmentalMeasurement &p)
{ {
// This plugin doesn't really do anything with the messages it receives. if (!(radioConfig.preferences.environmental_measurement_plugin_measurement_enabled || radioConfig.preferences.environmental_measurement_plugin_screen_enabled)){
// If this plugin is not enabled in any capacity, don't handle the packet, and allow other plugins to consume
return false;
}
bool wasBroadcast = mp.to == NODENUM_BROADCAST;
String sender = GetSenderName(mp);
// Show new nodes on LCD screen
if (DISPLAY_RECEIVEID_MEASUREMENTS_ON_SCREEN && wasBroadcast) {
String lcd = String("Env Measured: ") +sender + "\n" +
"T: " + p.temperature + "\n" +
"H: " + p.relative_humidity + "\n";
screen->print(lcd.c_str());
}
DEBUG_MSG("-----------------------------------------\n");
DEBUG_MSG("EnvironmentalMeasurement: Received data from %s\n", sender);
DEBUG_MSG("EnvironmentalMeasurement->relative_humidity: %f\n", p.relative_humidity);
DEBUG_MSG("EnvironmentalMeasurement->temperature: %f\n", p.temperature);
lastMeasurement = p;
lastSender = sender;
return false; // Let others look at this message also if they want return false; // Let others look at this message also if they want
} }
@ -80,13 +187,13 @@ bool EnvironmentalMeasurementPluginRadio::sendOurEnvironmentalMeasurement(NodeNu
DEBUG_MSG("-----------------------------------------\n"); DEBUG_MSG("-----------------------------------------\n");
DEBUG_MSG("Environmental Measurement Plugin: Read data\n"); DEBUG_MSG("EnvironmentalMeasurement: Read data\n");
DEBUG_MSG("EnvironmentalMeasurement->relative_humidity: %f\n", m.relative_humidity); DEBUG_MSG("EnvironmentalMeasurement->relative_humidity: %f\n", m.relative_humidity);
DEBUG_MSG("EnvironmentalMeasurement->temperature: %f\n", m.temperature); DEBUG_MSG("EnvironmentalMeasurement->temperature: %f\n", m.temperature);
if (isnan(m.relative_humidity) || isnan(m.temperature) ){ if (isnan(m.relative_humidity) || isnan(m.temperature) ){
sensor_read_error_count++; sensor_read_error_count++;
DEBUG_MSG("Environmental Measurement Plugin: FAILED TO READ DATA\n"); DEBUG_MSG("EnvironmentalMeasurement: FAILED TO READ DATA\n");
return false; return false;
} }

Wyświetl plik

@ -1,6 +1,8 @@
#pragma once #pragma once
#include "ProtobufPlugin.h" #include "ProtobufPlugin.h"
#include "../mesh/generated/environmental_measurement.pb.h" #include "../mesh/generated/environmental_measurement.pb.h"
#include <OLEDDisplay.h>
#include <OLEDDisplayUi.h>
class EnvironmentalMeasurementPlugin : private concurrency::OSThread class EnvironmentalMeasurementPlugin : private concurrency::OSThread
@ -25,13 +27,20 @@ class EnvironmentalMeasurementPluginRadio : public ProtobufPlugin<EnvironmentalM
/** Constructor /** Constructor
* name is for debugging output * name is for debugging output
*/ */
EnvironmentalMeasurementPluginRadio() : ProtobufPlugin("EnvironmentalMeasurement", PortNum_ENVIRONMENTAL_MEASUREMENT_APP, &EnvironmentalMeasurement_msg) {} EnvironmentalMeasurementPluginRadio() : ProtobufPlugin("EnvironmentalMeasurement", PortNum_ENVIRONMENTAL_MEASUREMENT_APP, &EnvironmentalMeasurement_msg) {
lastMeasurement.barometric_pressure = nanf("");
lastMeasurement.relative_humidity = nanf("");
lastMeasurement.temperature = nanf("");
lastSender = "N/A";
}
/** /**
* Send our EnvironmentalMeasurement into the mesh * Send our EnvironmentalMeasurement into the mesh
*/ */
bool sendOurEnvironmentalMeasurement(NodeNum dest = NODENUM_BROADCAST, bool wantReplies = false); bool sendOurEnvironmentalMeasurement(NodeNum dest = NODENUM_BROADCAST, bool wantReplies = false);
virtual void drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
protected: protected:
/** Called to handle a particular incoming message /** Called to handle a particular incoming message
@ -40,6 +49,15 @@ class EnvironmentalMeasurementPluginRadio : public ProtobufPlugin<EnvironmentalM
*/ */
virtual bool handleReceivedProtobuf(const MeshPacket &mp, const EnvironmentalMeasurement &p); virtual bool handleReceivedProtobuf(const MeshPacket &mp, const EnvironmentalMeasurement &p);
virtual bool wantUIFrame();
private:
EnvironmentalMeasurement lastMeasurement;
String lastSender;
}; };
extern EnvironmentalMeasurementPluginRadio *environmentalMeasurementPluginRadio; extern EnvironmentalMeasurementPluginRadio *environmentalMeasurementPluginRadio;