mirror of
https://github.com/meshtastic/firmware.git
synced 2025-04-28 18:47:40 +00:00
Implement interface for plugins to have custom UI Frames
This commit is contained in:
parent
087945d7cb
commit
ae76ce4024
@ -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,14 @@ 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)
|
||||||
|
{
|
||||||
|
DEBUG_MSG("Drawing Plugin Frame %d\n\n", state->currentFrame);
|
||||||
|
MeshPlugin &pi = *pluginFrames.at(state->currentFrame);
|
||||||
|
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 +899,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 +911,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", 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 +951,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();
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -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.
|
||||||
@ -14,7 +16,7 @@
|
|||||||
*/
|
*/
|
||||||
class MeshPlugin
|
class MeshPlugin
|
||||||
{
|
{
|
||||||
static std::vector<MeshPlugin *> *plugins;
|
static std::vector<MeshPlugin *> *plugins;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/** Constructor
|
/** Constructor
|
||||||
@ -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
|
||||||
|
@ -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;
|
||||||
@ -17,7 +19,7 @@ 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
|
//TODO: Make a related radioconfig preference to allow less-frequent reads
|
||||||
#define ENVIRONMENTAL_MEASUREMENT_APP_ENABLED false // DISABLED by default; set this to true if you want to use the plugin
|
#define ENVIRONMENTAL_MEASUREMENT_APP_ENABLED true // DISABLED by default; set this to true if you want to use the plugin
|
||||||
#define DHT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS 1000
|
#define DHT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS 1000
|
||||||
#define SENSOR_READ_ERROR_COUNT_THRESHOLD 5
|
#define SENSOR_READ_ERROR_COUNT_THRESHOLD 5
|
||||||
#define SENSOR_READ_MULTIPLIER 3
|
#define SENSOR_READ_MULTIPLIER 3
|
||||||
@ -26,6 +28,24 @@ uint32_t sensor_read_error_count = 0;
|
|||||||
|
|
||||||
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
|
||||||
if (!ENVIRONMENTAL_MEASUREMENT_APP_ENABLED){
|
if (!ENVIRONMENTAL_MEASUREMENT_APP_ENABLED){
|
||||||
@ -70,13 +90,17 @@ int32_t EnvironmentalMeasurementPlugin::runOnce() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EnvironmentalMeasurementPluginRadio::handleReceivedProtobuf(const MeshPacket &mp, const EnvironmentalMeasurement &p)
|
void EnvironmentalMeasurementPluginRadio::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||||
{
|
{
|
||||||
if (!ENVIRONMENTAL_MEASUREMENT_APP_ENABLED){
|
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||||
// If this plugin is not enabled, don't handle the packet, and allow other plugins to consume
|
display->setFont(FONT_MEDIUM);
|
||||||
return false;
|
display->drawString(x, y, "Environment");
|
||||||
}
|
display->setFont(FONT_SMALL);
|
||||||
bool wasBroadcast = mp.to == NODENUM_BROADCAST;
|
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;
|
String sender;
|
||||||
|
|
||||||
if (nodeDB.getNode(mp.from)){
|
if (nodeDB.getNode(mp.from)){
|
||||||
@ -85,18 +109,34 @@ bool EnvironmentalMeasurementPluginRadio::handleReceivedProtobuf(const MeshPacke
|
|||||||
else {
|
else {
|
||||||
sender = "UNK";
|
sender = "UNK";
|
||||||
}
|
}
|
||||||
|
return sender;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EnvironmentalMeasurementPluginRadio::handleReceivedProtobuf(const MeshPacket &mp, const EnvironmentalMeasurement &p)
|
||||||
|
{
|
||||||
|
if (!ENVIRONMENTAL_MEASUREMENT_APP_ENABLED){
|
||||||
|
// If this plugin is not enabled, 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
|
// Show new nodes on LCD screen
|
||||||
if (DISPLAY_RECEIVEID_MEASUREMENTS_ON_SCREEN && wasBroadcast) {
|
if (DISPLAY_RECEIVEID_MEASUREMENTS_ON_SCREEN && wasBroadcast) {
|
||||||
String lcd = String("Env Measured: ") + sender + "\n" +
|
String lcd = String("Env Measured: ") +sender + "\n" +
|
||||||
"T: " + p.temperature + "\n" +
|
"T: " + p.temperature + "\n" +
|
||||||
"H: " + p.relative_humidity + "\n";
|
"H: " + p.relative_humidity + "\n";
|
||||||
screen->print(lcd.c_str());
|
screen->print(lcd.c_str());
|
||||||
}
|
}
|
||||||
DEBUG_MSG("-----------------------------------------\n");
|
DEBUG_MSG("-----------------------------------------\n");
|
||||||
|
|
||||||
DEBUG_MSG("EnvironmentalMeasurement: Received data from %s\n",sender);
|
DEBUG_MSG("EnvironmentalMeasurement: Received data from %s\n", sender);
|
||||||
DEBUG_MSG("EnvironmentalMeasurement->relative_humidity: %f\n", p.relative_humidity);
|
DEBUG_MSG("EnvironmentalMeasurement->relative_humidity: %f\n", p.relative_humidity);
|
||||||
DEBUG_MSG("EnvironmentalMeasurement->temperature: %f\n", p.temperature);
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
@ -32,6 +34,8 @@ class EnvironmentalMeasurementPluginRadio : public ProtobufPlugin<EnvironmentalM
|
|||||||
*/
|
*/
|
||||||
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 +44,17 @@ 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() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
EnvironmentalMeasurement lastMeasurement;
|
||||||
|
|
||||||
|
String lastSender;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern EnvironmentalMeasurementPluginRadio *environmentalMeasurementPluginRadio;
|
extern EnvironmentalMeasurementPluginRadio *environmentalMeasurementPluginRadio;
|
Loading…
Reference in New Issue
Block a user