diff --git a/src/mesh/MeshPlugin.cpp b/src/mesh/MeshPlugin.cpp index 985a7060f..180e1ebfd 100644 --- a/src/mesh/MeshPlugin.cpp +++ b/src/mesh/MeshPlugin.cpp @@ -179,7 +179,7 @@ void MeshPlugin::callPlugins(const MeshPacket &mp, RxSource src) if (!pluginFound) DEBUG_MSG("No plugins interested in portnum=%d, src=%s\n", - mp.decoded.portnum, + mp.decoded.portnum, (src == RX_SRC_LOCAL) ? "LOCAL":"REMOTE"); } @@ -226,11 +226,13 @@ std::vector MeshPlugin::GetMeshPluginsWithUIFrames() { std::vector 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); + if (plugins) { + 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; @@ -239,14 +241,42 @@ std::vector MeshPlugin::GetMeshPluginsWithUIFrames() void MeshPlugin::observeUIEvents( Observer *observer) { - std::vector pluginsWithUIFrames; - for (auto i = plugins->begin(); i != plugins->end(); ++i) { - auto &pi = **i; - Observable *observable = - pi.getUIFrameObservable(); - if (observable != NULL) { - DEBUG_MSG("Plugin wants a UI Frame\n"); - observer->observe(observable); + if (plugins) { + for (auto i = plugins->begin(); i != plugins->end(); ++i) { + auto &pi = **i; + Observable *observable = + pi.getUIFrameObservable(); + if (observable != NULL) { + DEBUG_MSG("Plugin wants a UI Frame\n"); + observer->observe(observable); + } } } } + +AdminMessageHandleResult MeshPlugin::handleAdminMessageForAllPlugins(const MeshPacket &mp, AdminMessage *request, AdminMessage *response) +{ + AdminMessageHandleResult handled = AdminMessageHandleResult::NOT_HANDLED; + if (plugins) { + for (auto i = plugins->begin(); i != plugins->end(); ++i) { + auto &pi = **i; + AdminMessageHandleResult h = pi.handleAdminMessageForPlugin(mp, request, response); + if (h == AdminMessageHandleResult::HANDLED_WITH_RESPONSE) + { + // In case we have a response it always has priority. + DEBUG_MSG("Reply prepared by plugin '%s' of variant: %d\n", + pi.name, + response->which_variant); + handled = h; + } + else if ((handled != AdminMessageHandleResult::HANDLED_WITH_RESPONSE) && + (h == AdminMessageHandleResult::HANDLED)) + { + // In case the message is handled it should be populated, but will not overwrite + // a result with response. + handled = h; + } + } + } + return handled; +} diff --git a/src/mesh/MeshPlugin.h b/src/mesh/MeshPlugin.h index 456769dc0..8d59aa508 100644 --- a/src/mesh/MeshPlugin.h +++ b/src/mesh/MeshPlugin.h @@ -21,6 +21,19 @@ enum class ProcessMessage STOP = 1, }; +/** + * Used by plugins to return the result of the AdminMessage handling. + * If request is handled, then plugin should return HANDLED, + * If response is also prepared for the request, then HANDLED_WITH_RESPONSE + * should be returned. + */ +enum class AdminMessageHandleResult +{ + NOT_HANDLED = 0, + HANDLED = 1, + HANDLED_WITH_RESPONSE = 2, +}; + /* * This struct is used by Screen to figure out whether screen frame should be updated. */ @@ -57,6 +70,8 @@ class MeshPlugin static std::vector GetMeshPluginsWithUIFrames(); static void observeUIEvents(Observer *observer); + static AdminMessageHandleResult handleAdminMessageForAllPlugins( + const MeshPacket &mp, AdminMessage *request, AdminMessage *response); #ifndef NO_SCREEN virtual void drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) { return; } #endif @@ -135,6 +150,19 @@ class MeshPlugin /// Send an error response for the specified packet. MeshPacket *allocErrorResponse(Routing_Error err, const MeshPacket *p); + /** + * @brief An admin message arrived to AdminPlugin. Plugin was asked whether it want to handle the request. + * + * @param mp The mesh packet arrived. + * @param request The AdminMessage request extracted from the packet. + * @param response The prepared response + * @return AdminMessageHandleResult + * HANDLED if message was handled + * HANDLED_WITH_RESPONSE if a response is also prepared and to be sent. + */ + virtual AdminMessageHandleResult handleAdminMessageForPlugin( + const MeshPacket &mp, AdminMessage *request, AdminMessage *response) { return AdminMessageHandleResult::NOT_HANDLED; }; + private: /** * If any of the current chain of plugins has already sent a reply, it will be here. This is useful to allow diff --git a/src/mesh/generated/admin.pb.h b/src/mesh/generated/admin.pb.h index 77518b60f..c313f9f55 100644 --- a/src/mesh/generated/admin.pb.h +++ b/src/mesh/generated/admin.pb.h @@ -4,7 +4,6 @@ #ifndef PB_ADMIN_PB_H_INCLUDED #define PB_ADMIN_PB_H_INCLUDED #include -#include "cannedmessages.pb.h" #include "channel.pb.h" #include "mesh.pb.h" #include "radioconfig.pb.h" @@ -31,20 +30,17 @@ typedef struct _AdminMessage { bool exit_simulator; int32_t reboot_seconds; bool get_canned_message_plugin_part1_request; - CannedMessagePluginMessagePart1 get_canned_message_plugin_part1_response; + char get_canned_message_plugin_part1_response[201]; bool get_canned_message_plugin_part2_request; - CannedMessagePluginMessagePart2 get_canned_message_plugin_part2_response; + char get_canned_message_plugin_part2_response[201]; bool get_canned_message_plugin_part3_request; - CannedMessagePluginMessagePart3 get_canned_message_plugin_part3_response; + char get_canned_message_plugin_part3_response[201]; bool get_canned_message_plugin_part4_request; - CannedMessagePluginMessagePart4 get_canned_message_plugin_part4_response; - bool get_canned_message_plugin_part5_request; - CannedMessagePluginMessagePart5 get_canned_message_plugin_part5_response; - CannedMessagePluginMessagePart1 set_canned_message_plugin_part1; - CannedMessagePluginMessagePart2 set_canned_message_plugin_part2; - CannedMessagePluginMessagePart3 set_canned_message_plugin_part3; - CannedMessagePluginMessagePart4 set_canned_message_plugin_part4; - CannedMessagePluginMessagePart5 set_canned_message_plugin_part5; + char get_canned_message_plugin_part4_response[201]; + char set_canned_message_plugin_part1[201]; + char set_canned_message_plugin_part2[201]; + char set_canned_message_plugin_part3[201]; + char set_canned_message_plugin_part4[201]; int32_t shutdown_seconds; }; } AdminMessage; @@ -80,13 +76,10 @@ extern "C" { #define AdminMessage_get_canned_message_plugin_part3_response_tag 41 #define AdminMessage_get_canned_message_plugin_part4_request_tag 42 #define AdminMessage_get_canned_message_plugin_part4_response_tag 43 -#define AdminMessage_get_canned_message_plugin_part5_request_tag 44 -#define AdminMessage_get_canned_message_plugin_part5_response_tag 45 -#define AdminMessage_set_canned_message_plugin_part1_tag 46 -#define AdminMessage_set_canned_message_plugin_part2_tag 47 -#define AdminMessage_set_canned_message_plugin_part3_tag 48 -#define AdminMessage_set_canned_message_plugin_part4_tag 49 -#define AdminMessage_set_canned_message_plugin_part5_tag 50 +#define AdminMessage_set_canned_message_plugin_part1_tag 44 +#define AdminMessage_set_canned_message_plugin_part2_tag 45 +#define AdminMessage_set_canned_message_plugin_part3_tag 46 +#define AdminMessage_set_canned_message_plugin_part4_tag 47 #define AdminMessage_shutdown_seconds_tag 51 /* Struct field encoding specification for nanopb */ @@ -105,20 +98,17 @@ X(a, STATIC, ONEOF, BOOL, (variant,confirm_set_radio,confirm_set_radio) X(a, STATIC, ONEOF, BOOL, (variant,exit_simulator,exit_simulator), 34) \ X(a, STATIC, ONEOF, INT32, (variant,reboot_seconds,reboot_seconds), 35) \ X(a, STATIC, ONEOF, BOOL, (variant,get_canned_message_plugin_part1_request,get_canned_message_plugin_part1_request), 36) \ -X(a, STATIC, ONEOF, MESSAGE, (variant,get_canned_message_plugin_part1_response,get_canned_message_plugin_part1_response), 37) \ +X(a, STATIC, ONEOF, STRING, (variant,get_canned_message_plugin_part1_response,get_canned_message_plugin_part1_response), 37) \ X(a, STATIC, ONEOF, BOOL, (variant,get_canned_message_plugin_part2_request,get_canned_message_plugin_part2_request), 38) \ -X(a, STATIC, ONEOF, MESSAGE, (variant,get_canned_message_plugin_part2_response,get_canned_message_plugin_part2_response), 39) \ +X(a, STATIC, ONEOF, STRING, (variant,get_canned_message_plugin_part2_response,get_canned_message_plugin_part2_response), 39) \ X(a, STATIC, ONEOF, BOOL, (variant,get_canned_message_plugin_part3_request,get_canned_message_plugin_part3_request), 40) \ -X(a, STATIC, ONEOF, MESSAGE, (variant,get_canned_message_plugin_part3_response,get_canned_message_plugin_part3_response), 41) \ +X(a, STATIC, ONEOF, STRING, (variant,get_canned_message_plugin_part3_response,get_canned_message_plugin_part3_response), 41) \ X(a, STATIC, ONEOF, BOOL, (variant,get_canned_message_plugin_part4_request,get_canned_message_plugin_part4_request), 42) \ -X(a, STATIC, ONEOF, MESSAGE, (variant,get_canned_message_plugin_part4_response,get_canned_message_plugin_part4_response), 43) \ -X(a, STATIC, ONEOF, BOOL, (variant,get_canned_message_plugin_part5_request,get_canned_message_plugin_part5_request), 44) \ -X(a, STATIC, ONEOF, MESSAGE, (variant,get_canned_message_plugin_part5_response,get_canned_message_plugin_part5_response), 45) \ -X(a, STATIC, ONEOF, MESSAGE, (variant,set_canned_message_plugin_part1,set_canned_message_plugin_part1), 46) \ -X(a, STATIC, ONEOF, MESSAGE, (variant,set_canned_message_plugin_part2,set_canned_message_plugin_part2), 47) \ -X(a, STATIC, ONEOF, MESSAGE, (variant,set_canned_message_plugin_part3,set_canned_message_plugin_part3), 48) \ -X(a, STATIC, ONEOF, MESSAGE, (variant,set_canned_message_plugin_part4,set_canned_message_plugin_part4), 49) \ -X(a, STATIC, ONEOF, MESSAGE, (variant,set_canned_message_plugin_part5,set_canned_message_plugin_part5), 50) \ +X(a, STATIC, ONEOF, STRING, (variant,get_canned_message_plugin_part4_response,get_canned_message_plugin_part4_response), 43) \ +X(a, STATIC, ONEOF, STRING, (variant,set_canned_message_plugin_part1,set_canned_message_plugin_part1), 44) \ +X(a, STATIC, ONEOF, STRING, (variant,set_canned_message_plugin_part2,set_canned_message_plugin_part2), 45) \ +X(a, STATIC, ONEOF, STRING, (variant,set_canned_message_plugin_part3,set_canned_message_plugin_part3), 46) \ +X(a, STATIC, ONEOF, STRING, (variant,set_canned_message_plugin_part4,set_canned_message_plugin_part4), 47) \ X(a, STATIC, ONEOF, INT32, (variant,shutdown_seconds,shutdown_seconds), 51) #define AdminMessage_CALLBACK NULL #define AdminMessage_DEFAULT NULL @@ -128,16 +118,6 @@ X(a, STATIC, ONEOF, INT32, (variant,shutdown_seconds,shutdown_seconds), #define AdminMessage_variant_get_radio_response_MSGTYPE RadioConfig #define AdminMessage_variant_get_channel_response_MSGTYPE Channel #define AdminMessage_variant_get_owner_response_MSGTYPE User -#define AdminMessage_variant_get_canned_message_plugin_part1_response_MSGTYPE CannedMessagePluginMessagePart1 -#define AdminMessage_variant_get_canned_message_plugin_part2_response_MSGTYPE CannedMessagePluginMessagePart2 -#define AdminMessage_variant_get_canned_message_plugin_part3_response_MSGTYPE CannedMessagePluginMessagePart3 -#define AdminMessage_variant_get_canned_message_plugin_part4_response_MSGTYPE CannedMessagePluginMessagePart4 -#define AdminMessage_variant_get_canned_message_plugin_part5_response_MSGTYPE CannedMessagePluginMessagePart5 -#define AdminMessage_variant_set_canned_message_plugin_part1_MSGTYPE CannedMessagePluginMessagePart1 -#define AdminMessage_variant_set_canned_message_plugin_part2_MSGTYPE CannedMessagePluginMessagePart2 -#define AdminMessage_variant_set_canned_message_plugin_part3_MSGTYPE CannedMessagePluginMessagePart3 -#define AdminMessage_variant_set_canned_message_plugin_part4_MSGTYPE CannedMessagePluginMessagePart4 -#define AdminMessage_variant_set_canned_message_plugin_part5_MSGTYPE CannedMessagePluginMessagePart5 extern const pb_msgdesc_t AdminMessage_msg; @@ -145,7 +125,7 @@ extern const pb_msgdesc_t AdminMessage_msg; #define AdminMessage_fields &AdminMessage_msg /* Maximum encoded size of messages (where known) */ -#define AdminMessage_size 804 +#define AdminMessage_size 601 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/mesh/generated/cannedmessages.pb.c b/src/mesh/generated/cannedmessages.pb.c index 16563446e..e36eff981 100644 --- a/src/mesh/generated/cannedmessages.pb.c +++ b/src/mesh/generated/cannedmessages.pb.c @@ -6,19 +6,7 @@ #error Regenerate this file with the current version of nanopb generator. #endif -PB_BIND(CannedMessagePluginMessagePart1, CannedMessagePluginMessagePart1, AUTO) - - -PB_BIND(CannedMessagePluginMessagePart2, CannedMessagePluginMessagePart2, AUTO) - - -PB_BIND(CannedMessagePluginMessagePart3, CannedMessagePluginMessagePart3, AUTO) - - -PB_BIND(CannedMessagePluginMessagePart4, CannedMessagePluginMessagePart4, AUTO) - - -PB_BIND(CannedMessagePluginMessagePart5, CannedMessagePluginMessagePart5, AUTO) +PB_BIND(CannedMessagePluginConfig, CannedMessagePluginConfig, 2) diff --git a/src/mesh/generated/cannedmessages.pb.h b/src/mesh/generated/cannedmessages.pb.h index 0f1b0786e..ec8a42123 100644 --- a/src/mesh/generated/cannedmessages.pb.h +++ b/src/mesh/generated/cannedmessages.pb.h @@ -10,25 +10,12 @@ #endif /* Struct definitions */ -typedef struct _CannedMessagePluginMessagePart1 { - char text[200]; -} CannedMessagePluginMessagePart1; - -typedef struct _CannedMessagePluginMessagePart2 { - char text[200]; -} CannedMessagePluginMessagePart2; - -typedef struct _CannedMessagePluginMessagePart3 { - char text[200]; -} CannedMessagePluginMessagePart3; - -typedef struct _CannedMessagePluginMessagePart4 { - char text[200]; -} CannedMessagePluginMessagePart4; - -typedef struct _CannedMessagePluginMessagePart5 { - char text[200]; -} CannedMessagePluginMessagePart5; +typedef struct _CannedMessagePluginConfig { + char messagesPart1[201]; + char messagesPart2[201]; + char messagesPart3[201]; + char messagesPart4[201]; +} CannedMessagePluginConfig; #ifdef __cplusplus @@ -36,69 +23,31 @@ extern "C" { #endif /* Initializer values for message structs */ -#define CannedMessagePluginMessagePart1_init_default {""} -#define CannedMessagePluginMessagePart2_init_default {""} -#define CannedMessagePluginMessagePart3_init_default {""} -#define CannedMessagePluginMessagePart4_init_default {""} -#define CannedMessagePluginMessagePart5_init_default {""} -#define CannedMessagePluginMessagePart1_init_zero {""} -#define CannedMessagePluginMessagePart2_init_zero {""} -#define CannedMessagePluginMessagePart3_init_zero {""} -#define CannedMessagePluginMessagePart4_init_zero {""} -#define CannedMessagePluginMessagePart5_init_zero {""} +#define CannedMessagePluginConfig_init_default {"", "", "", ""} +#define CannedMessagePluginConfig_init_zero {"", "", "", ""} /* Field tags (for use in manual encoding/decoding) */ -#define CannedMessagePluginMessagePart1_text_tag 1 -#define CannedMessagePluginMessagePart2_text_tag 1 -#define CannedMessagePluginMessagePart3_text_tag 1 -#define CannedMessagePluginMessagePart4_text_tag 1 -#define CannedMessagePluginMessagePart5_text_tag 1 +#define CannedMessagePluginConfig_messagesPart1_tag 11 +#define CannedMessagePluginConfig_messagesPart2_tag 12 +#define CannedMessagePluginConfig_messagesPart3_tag 13 +#define CannedMessagePluginConfig_messagesPart4_tag 14 /* Struct field encoding specification for nanopb */ -#define CannedMessagePluginMessagePart1_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, STRING, text, 1) -#define CannedMessagePluginMessagePart1_CALLBACK NULL -#define CannedMessagePluginMessagePart1_DEFAULT NULL +#define CannedMessagePluginConfig_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, STRING, messagesPart1, 11) \ +X(a, STATIC, SINGULAR, STRING, messagesPart2, 12) \ +X(a, STATIC, SINGULAR, STRING, messagesPart3, 13) \ +X(a, STATIC, SINGULAR, STRING, messagesPart4, 14) +#define CannedMessagePluginConfig_CALLBACK NULL +#define CannedMessagePluginConfig_DEFAULT NULL -#define CannedMessagePluginMessagePart2_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, STRING, text, 1) -#define CannedMessagePluginMessagePart2_CALLBACK NULL -#define CannedMessagePluginMessagePart2_DEFAULT NULL - -#define CannedMessagePluginMessagePart3_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, STRING, text, 1) -#define CannedMessagePluginMessagePart3_CALLBACK NULL -#define CannedMessagePluginMessagePart3_DEFAULT NULL - -#define CannedMessagePluginMessagePart4_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, STRING, text, 1) -#define CannedMessagePluginMessagePart4_CALLBACK NULL -#define CannedMessagePluginMessagePart4_DEFAULT NULL - -#define CannedMessagePluginMessagePart5_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, STRING, text, 1) -#define CannedMessagePluginMessagePart5_CALLBACK NULL -#define CannedMessagePluginMessagePart5_DEFAULT NULL - -extern const pb_msgdesc_t CannedMessagePluginMessagePart1_msg; -extern const pb_msgdesc_t CannedMessagePluginMessagePart2_msg; -extern const pb_msgdesc_t CannedMessagePluginMessagePart3_msg; -extern const pb_msgdesc_t CannedMessagePluginMessagePart4_msg; -extern const pb_msgdesc_t CannedMessagePluginMessagePart5_msg; +extern const pb_msgdesc_t CannedMessagePluginConfig_msg; /* Defines for backwards compatibility with code written before nanopb-0.4.0 */ -#define CannedMessagePluginMessagePart1_fields &CannedMessagePluginMessagePart1_msg -#define CannedMessagePluginMessagePart2_fields &CannedMessagePluginMessagePart2_msg -#define CannedMessagePluginMessagePart3_fields &CannedMessagePluginMessagePart3_msg -#define CannedMessagePluginMessagePart4_fields &CannedMessagePluginMessagePart4_msg -#define CannedMessagePluginMessagePart5_fields &CannedMessagePluginMessagePart5_msg +#define CannedMessagePluginConfig_fields &CannedMessagePluginConfig_msg /* Maximum encoded size of messages (where known) */ -#define CannedMessagePluginMessagePart1_size 202 -#define CannedMessagePluginMessagePart2_size 202 -#define CannedMessagePluginMessagePart3_size 202 -#define CannedMessagePluginMessagePart4_size 202 -#define CannedMessagePluginMessagePart5_size 202 +#define CannedMessagePluginConfig_size 812 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/mesh/generated/deviceonly.pb.h b/src/mesh/generated/deviceonly.pb.h index 14453a9ad..d384e7e57 100644 --- a/src/mesh/generated/deviceonly.pb.h +++ b/src/mesh/generated/deviceonly.pb.h @@ -34,11 +34,6 @@ typedef struct _DeviceState { uint32_t version; bool no_save; bool did_gps_reset; - char canned_message_plugin_message_part1[200]; - char canned_message_plugin_message_part2[200]; - char canned_message_plugin_message_part3[200]; - char canned_message_plugin_message_part4[200]; - char canned_message_plugin_message_part5[200]; } DeviceState; @@ -47,9 +42,9 @@ extern "C" { #endif /* Initializer values for message structs */ -#define DeviceState_init_default {false, MyNodeInfo_init_default, false, User_init_default, 0, {NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default}, 0, {MeshPacket_init_default}, false, GroupInfo_init_default, false, MeshPacket_init_default, 0, 0, 0, "", "", "", "", ""} +#define DeviceState_init_default {false, MyNodeInfo_init_default, false, User_init_default, 0, {NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default}, 0, {MeshPacket_init_default}, false, GroupInfo_init_default, false, MeshPacket_init_default, 0, 0, 0} #define ChannelFile_init_default {0, {Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default}} -#define DeviceState_init_zero {false, MyNodeInfo_init_zero, false, User_init_zero, 0, {NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero}, 0, {MeshPacket_init_zero}, false, GroupInfo_init_zero, false, MeshPacket_init_zero, 0, 0, 0, "", "", "", "", ""} +#define DeviceState_init_zero {false, MyNodeInfo_init_zero, false, User_init_zero, 0, {NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero}, 0, {MeshPacket_init_zero}, false, GroupInfo_init_zero, false, MeshPacket_init_zero, 0, 0, 0} #define ChannelFile_init_zero {0, {Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero}} /* Field tags (for use in manual encoding/decoding) */ @@ -63,11 +58,6 @@ extern "C" { #define DeviceState_version_tag 8 #define DeviceState_no_save_tag 9 #define DeviceState_did_gps_reset_tag 11 -#define DeviceState_canned_message_plugin_message_part1_tag 13 -#define DeviceState_canned_message_plugin_message_part2_tag 14 -#define DeviceState_canned_message_plugin_message_part3_tag 15 -#define DeviceState_canned_message_plugin_message_part4_tag 16 -#define DeviceState_canned_message_plugin_message_part5_tag 17 /* Struct field encoding specification for nanopb */ #define DeviceState_FIELDLIST(X, a) \ @@ -79,12 +69,7 @@ X(a, STATIC, OPTIONAL, MESSAGE, group_info, 6) \ X(a, STATIC, OPTIONAL, MESSAGE, rx_text_message, 7) \ X(a, STATIC, SINGULAR, UINT32, version, 8) \ X(a, STATIC, SINGULAR, BOOL, no_save, 9) \ -X(a, STATIC, SINGULAR, BOOL, did_gps_reset, 11) \ -X(a, STATIC, SINGULAR, STRING, canned_message_plugin_message_part1, 13) \ -X(a, STATIC, SINGULAR, STRING, canned_message_plugin_message_part2, 14) \ -X(a, STATIC, SINGULAR, STRING, canned_message_plugin_message_part3, 15) \ -X(a, STATIC, SINGULAR, STRING, canned_message_plugin_message_part4, 16) \ -X(a, STATIC, SINGULAR, STRING, canned_message_plugin_message_part5, 17) +X(a, STATIC, SINGULAR, BOOL, did_gps_reset, 11) #define DeviceState_CALLBACK NULL #define DeviceState_DEFAULT NULL #define DeviceState_my_node_MSGTYPE MyNodeInfo @@ -108,7 +93,7 @@ extern const pb_msgdesc_t ChannelFile_msg; #define ChannelFile_fields &ChannelFile_msg /* Maximum encoded size of messages (where known) */ -#define DeviceState_size 11174 +#define DeviceState_size 10162 #define ChannelFile_size 832 #ifdef __cplusplus diff --git a/src/mesh/generated/radioconfig.pb.h b/src/mesh/generated/radioconfig.pb.h index b8850d05c..af24b5184 100644 --- a/src/mesh/generated/radioconfig.pb.h +++ b/src/mesh/generated/radioconfig.pb.h @@ -186,7 +186,6 @@ typedef struct _RadioConfig_UserPreferences { InputEventChar rotary1_event_press; bool canned_message_plugin_enabled; char canned_message_plugin_allow_input_source[16]; - char canned_message_plugin_messages[200]; bool canned_message_plugin_send_bell; bool mqtt_encryption_enabled; float adc_multiplier_override; @@ -238,9 +237,9 @@ extern "C" { /* Initializer values for message structs */ #define RadioConfig_init_default {false, RadioConfig_UserPreferences_init_default} -#define RadioConfig_UserPreferences_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, _RegionCode_MIN, _ChargeCurrent_MIN, 0, _LocationSharing_MIN, _GpsOperation_MIN, 0, 0, 0, 0, 0, 0, 0, "", 0, _GpsCoordinateFormat_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, _RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_MIN, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, 0, 0, 0, 0, 0, _InputEventChar_MIN, _InputEventChar_MIN, _InputEventChar_MIN, 0, "", "", 0, 0, 0} +#define RadioConfig_UserPreferences_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, _RegionCode_MIN, _ChargeCurrent_MIN, 0, _LocationSharing_MIN, _GpsOperation_MIN, 0, 0, 0, 0, 0, 0, 0, "", 0, _GpsCoordinateFormat_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, _RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_MIN, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, 0, 0, 0, 0, 0, _InputEventChar_MIN, _InputEventChar_MIN, _InputEventChar_MIN, 0, "", 0, 0, 0} #define RadioConfig_init_zero {false, RadioConfig_UserPreferences_init_zero} -#define RadioConfig_UserPreferences_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, _RegionCode_MIN, _ChargeCurrent_MIN, 0, _LocationSharing_MIN, _GpsOperation_MIN, 0, 0, 0, 0, 0, 0, 0, "", 0, _GpsCoordinateFormat_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, _RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_MIN, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, 0, 0, 0, 0, 0, _InputEventChar_MIN, _InputEventChar_MIN, _InputEventChar_MIN, 0, "", "", 0, 0, 0} +#define RadioConfig_UserPreferences_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, _RegionCode_MIN, _ChargeCurrent_MIN, 0, _LocationSharing_MIN, _GpsOperation_MIN, 0, 0, 0, 0, 0, 0, 0, "", 0, _GpsCoordinateFormat_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, _RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_MIN, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, 0, 0, 0, 0, 0, _InputEventChar_MIN, _InputEventChar_MIN, _InputEventChar_MIN, 0, "", 0, 0, 0} /* Field tags (for use in manual encoding/decoding) */ #define RadioConfig_UserPreferences_position_broadcast_secs_tag 1 @@ -322,7 +321,6 @@ extern "C" { #define RadioConfig_UserPreferences_rotary1_event_press_tag 166 #define RadioConfig_UserPreferences_canned_message_plugin_enabled_tag 170 #define RadioConfig_UserPreferences_canned_message_plugin_allow_input_source_tag 171 -#define RadioConfig_UserPreferences_canned_message_plugin_messages_tag 172 #define RadioConfig_UserPreferences_canned_message_plugin_send_bell_tag 173 #define RadioConfig_UserPreferences_mqtt_encryption_enabled_tag 174 #define RadioConfig_UserPreferences_adc_multiplier_override_tag 175 @@ -415,7 +413,6 @@ X(a, STATIC, SINGULAR, UENUM, rotary1_event_ccw, 165) \ X(a, STATIC, SINGULAR, UENUM, rotary1_event_press, 166) \ X(a, STATIC, SINGULAR, BOOL, canned_message_plugin_enabled, 170) \ X(a, STATIC, SINGULAR, STRING, canned_message_plugin_allow_input_source, 171) \ -X(a, STATIC, SINGULAR, STRING, canned_message_plugin_messages, 172) \ X(a, STATIC, SINGULAR, BOOL, canned_message_plugin_send_bell, 173) \ X(a, STATIC, SINGULAR, BOOL, mqtt_encryption_enabled, 174) \ X(a, STATIC, SINGULAR, FLOAT, adc_multiplier_override, 175) @@ -430,8 +427,8 @@ extern const pb_msgdesc_t RadioConfig_UserPreferences_msg; #define RadioConfig_UserPreferences_fields &RadioConfig_UserPreferences_msg /* Maximum encoded size of messages (where known) */ -#define RadioConfig_size 801 -#define RadioConfig_UserPreferences_size 798 +#define RadioConfig_size 598 +#define RadioConfig_UserPreferences_size 595 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/plugins/AdminPlugin.cpp b/src/plugins/AdminPlugin.cpp index 3886cb232..2f1893a87 100644 --- a/src/plugins/AdminPlugin.cpp +++ b/src/plugins/AdminPlugin.cpp @@ -63,6 +63,9 @@ void AdminPlugin::handleGetRadio(const MeshPacket &req) bool AdminPlugin::handleReceivedProtobuf(const MeshPacket &mp, AdminMessage *r) { + // if handled == false, then let others look at this message also if they want + bool handled = false; + assert(r); switch (r->which_variant) { case AdminMessage_set_owner_tag: @@ -119,11 +122,25 @@ bool AdminPlugin::handleReceivedProtobuf(const MeshPacket &mp, AdminMessage *r) #endif default: - // Probably a message sent by us or sent to our local node. FIXME, we should avoid scanning these messages - DEBUG_MSG("Ignoring nonrelevant admin %d\n", r->which_variant); + AdminMessage response = AdminMessage_init_default; + AdminMessageHandleResult handleResult = MeshPlugin::handleAdminMessageForAllPlugins(mp, r, &response); + + if (handleResult == AdminMessageHandleResult::HANDLED_WITH_RESPONSE) + { + myReply = allocDataProtobuf(response); + } + else if (mp.decoded.want_response) + { + DEBUG_MSG("We did not responded to a request that wanted a respond. req.variant=%d\n", r->which_variant); + } + else if (handleResult != AdminMessageHandleResult::HANDLED) + { + // Probably a message sent by us or sent to our local node. FIXME, we should avoid scanning these messages + DEBUG_MSG("Ignoring nonrelevant admin %d\n", r->which_variant); + } break; } - return false; // Let others look at this message also if they want + return handled; } void AdminPlugin::handleSetOwner(const User &o) diff --git a/src/plugins/CannedMessagePlugin.cpp b/src/plugins/CannedMessagePlugin.cpp index b209187ad..a6b9a23f4 100644 --- a/src/plugins/CannedMessagePlugin.cpp +++ b/src/plugins/CannedMessagePlugin.cpp @@ -1,6 +1,8 @@ #include "configuration.h" #include "CannedMessagePlugin.h" #include "MeshService.h" +#include "FSCommon.h" +#include "mesh/generated/cannedmessages.pb.h" // TODO: reuse defined from Screen.cpp #define FONT_SMALL ArialMT_Plain_10 @@ -10,28 +12,40 @@ // Remove Canned message screen if no action is taken for some milliseconds #define INACTIVATE_AFTER_MS 20000 +static const char *cannedMessagesConfigFile = "/prefs/cannedConf.proto"; + +CannedMessagePluginConfig cannedMessagePluginConfig; + CannedMessagePlugin *cannedMessagePlugin; +// TODO: move it into NodeDB.h! +extern bool loadProto(const char *filename, size_t protoSize, size_t objSize, const pb_msgdesc_t *fields, void *dest_struct); +extern bool saveProto(const char *filename, size_t protoSize, size_t objSize, const pb_msgdesc_t *fields, const void *dest_struct); + CannedMessagePlugin::CannedMessagePlugin() : SinglePortPlugin("canned", PortNum_TEXT_MESSAGE_APP), concurrency::OSThread("CannedMessagePlugin") { if (radioConfig.preferences.canned_message_plugin_enabled) { + this->loadProtoForPlugin(); if(this->splitConfiguredMessages() <= 0) { - radioConfig.preferences.canned_message_plugin_enabled = false; DEBUG_MSG("CannedMessagePlugin: No messages are configured. Plugin is disabled\n"); - return; + this->runState = CANNED_MESSAGE_RUN_STATE_DISABLED; + } + else + { + DEBUG_MSG("CannedMessagePlugin is enabled\n"); + this->inputObserver.observe(inputBroker); } - this->inputObserver.observe(inputBroker); } } /** * @brief Items in array this->messages will be set to be pointing on the right * starting points of the string this->messageStore - * + * * @return int Returns the number of messages found. */ int CannedMessagePlugin::splitConfiguredMessages() @@ -39,11 +53,21 @@ int CannedMessagePlugin::splitConfiguredMessages() int messageIndex = 0; int i = 0; - strncpy( + // collect all the message parts + strcpy( this->messageStore, - radioConfig.preferences.canned_message_plugin_messages, - CANNED_MESSAGE_PLUGIN_MESSAGES_SIZE); + cannedMessagePluginConfig.messagesPart1); + strcat( + this->messageStore, + cannedMessagePluginConfig.messagesPart2); + strcat( + this->messageStore, + cannedMessagePluginConfig.messagesPart3); + strcat( + this->messageStore, + cannedMessagePluginConfig.messagesPart4); + // The first message points to the beginning of the store. this->messages[messageIndex++] = this->messageStore; int upTo = @@ -51,13 +75,14 @@ int CannedMessagePlugin::splitConfiguredMessages() while (i < upTo) { - if (this->messageStore[i] == '|') + if (this->messageStore[i] == '|') { // Message ending found, replace it with string-end character. this->messageStore[i] = '\0'; DEBUG_MSG("CannedMessage %d is: '%s'\n", messageIndex-1, this->messages[messageIndex-1]); + // hit our max messages, bail if (messageIndex >= CANNED_MESSAGE_PLUGIN_MESSAGE_MAX_COUNT) { this->messagesCount = messageIndex; @@ -72,6 +97,7 @@ int CannedMessagePlugin::splitConfiguredMessages() } if (strlen(this->messages[messageIndex-1]) > 0) { + // We have a last message. DEBUG_MSG("CannedMessage %d is: '%s'\n", messageIndex-1, this->messages[messageIndex-1]); this->messagesCount = messageIndex; @@ -92,6 +118,9 @@ int CannedMessagePlugin::handleInputEvent(const InputEvent *event) (strcmp(radioConfig.preferences.canned_message_plugin_allow_input_source, "_any") != 0)) { // Event source is not accepted. + // Event only accepted if source matches the configured one, or + // the configured one is "_any" (or if there is no configured + // source at all) return 0; } @@ -140,9 +169,6 @@ void CannedMessagePlugin::sendText(NodeNum dest, p->decoded.payload.size++; } - -// PacketId prevPacketId = p->id; // In case we need it later. - DEBUG_MSG("Sending message id=%d, msg=%.*s\n", p->id, p->decoded.payload.size, p->decoded.payload.bytes); @@ -152,6 +178,7 @@ void CannedMessagePlugin::sendText(NodeNum dest, int32_t CannedMessagePlugin::runOnce() { if ((!radioConfig.preferences.canned_message_plugin_enabled) + || (this->runState == CANNED_MESSAGE_RUN_STATE_DISABLED) || (this->runState == CANNED_MESSAGE_RUN_STATE_INACTIVE)) { return 30000; // TODO: should return MAX_VAL @@ -180,7 +207,7 @@ int32_t CannedMessagePlugin::runOnce() else if (this->currentMessageIndex == -1) { this->currentMessageIndex = 0; - DEBUG_MSG("First touch.\n"); + DEBUG_MSG("First touch (%d):%s\n", this->currentMessageIndex, this->getCurrentMessage()); e.frameChanged = true; this->runState = CANNED_MESSAGE_RUN_STATE_ACTIVE; } @@ -199,13 +226,13 @@ int32_t CannedMessagePlugin::runOnce() { this->currentMessageIndex = getPrevIndex(); this->runState = CANNED_MESSAGE_RUN_STATE_ACTIVE; - DEBUG_MSG("MOVE UP\n"); + DEBUG_MSG("MOVE UP (%d):%s\n", this->currentMessageIndex, this->getCurrentMessage()); } else if (this->runState == CANNED_MESSAGE_RUN_STATE_ACTION_DOWN) { this->currentMessageIndex = this->getNextIndex(); this->runState = CANNED_MESSAGE_RUN_STATE_ACTIVE; - DEBUG_MSG("MOVE DOWN\n"); + DEBUG_MSG("MOVE DOWN (%d):%s\n", this->currentMessageIndex, this->getCurrentMessage()); } if (this->runState == CANNED_MESSAGE_RUN_STATE_ACTIVE) @@ -286,3 +313,226 @@ void CannedMessagePlugin::drawFrame( } } +void CannedMessagePlugin::loadProtoForPlugin() +{ + if (!loadProto(cannedMessagesConfigFile, CannedMessagePluginConfig_size, sizeof(cannedMessagesConfigFile), CannedMessagePluginConfig_fields, &cannedMessagePluginConfig)) { + installDefaultCannedMessagePluginConfig(); + } +} + +/** + * @brief Save the plugin config to file. + * + * @return true On success. + * @return false On error. + */ +bool CannedMessagePlugin::saveProtoForPlugin() +{ + bool okay = true; + +#ifdef FS + FS.mkdir("/prefs"); +#endif + + okay &= saveProto(cannedMessagesConfigFile, CannedMessagePluginConfig_size, sizeof(CannedMessagePluginConfig), CannedMessagePluginConfig_fields, &cannedMessagePluginConfig); + + return okay; +} + +/** + * @brief Fill configuration with default values. + */ +void CannedMessagePlugin::installDefaultCannedMessagePluginConfig() +{ + memset(cannedMessagePluginConfig.messagesPart1, 0, sizeof(cannedMessagePluginConfig.messagesPart1)); + memset(cannedMessagePluginConfig.messagesPart2, 0, sizeof(cannedMessagePluginConfig.messagesPart2)); + memset(cannedMessagePluginConfig.messagesPart3, 0, sizeof(cannedMessagePluginConfig.messagesPart3)); + memset(cannedMessagePluginConfig.messagesPart4, 0, sizeof(cannedMessagePluginConfig.messagesPart4)); +} + +/** + * @brief An admin message arrived to AdminPlugin. We are asked whether we want to handle that. + * + * @param mp The mesh packet arrived. + * @param request The AdminMessage request extracted from the packet. + * @param response The prepared response + * @return AdminMessageHandleResult HANDLED if message was handled + * HANDLED_WITH_RESULT if a result is also prepared. + */ +AdminMessageHandleResult CannedMessagePlugin::handleAdminMessageForPlugin( + const MeshPacket &mp, AdminMessage *request, AdminMessage *response) +{ + AdminMessageHandleResult result; + + switch (request->which_variant) { + case AdminMessage_get_canned_message_plugin_part1_request_tag: + DEBUG_MSG("Client is getting radio canned message part1\n"); + this->handleGetCannedMessagePluginPart1(mp, response); + result = AdminMessageHandleResult::HANDLED_WITH_RESPONSE; + break; + + case AdminMessage_get_canned_message_plugin_part2_request_tag: + DEBUG_MSG("Client is getting radio canned message part2\n"); + this->handleGetCannedMessagePluginPart2(mp, response); + result = AdminMessageHandleResult::HANDLED_WITH_RESPONSE; + break; + + case AdminMessage_get_canned_message_plugin_part3_request_tag: + DEBUG_MSG("Client is getting radio canned message part3\n"); + this->handleGetCannedMessagePluginPart3(mp, response); + result = AdminMessageHandleResult::HANDLED_WITH_RESPONSE; + break; + + case AdminMessage_get_canned_message_plugin_part4_request_tag: + DEBUG_MSG("Client is getting radio canned message part4\n"); + this->handleGetCannedMessagePluginPart4(mp, response); + result = AdminMessageHandleResult::HANDLED_WITH_RESPONSE; + break; + + case AdminMessage_set_canned_message_plugin_part1_tag: + DEBUG_MSG("Client is setting radio canned message part 1\n"); + this->handleSetCannedMessagePluginPart1( + request->set_canned_message_plugin_part1); + result = AdminMessageHandleResult::HANDLED; + break; + + case AdminMessage_set_canned_message_plugin_part2_tag: + DEBUG_MSG("Client is setting radio canned message part 2\n"); + this->handleSetCannedMessagePluginPart2( + request->set_canned_message_plugin_part2); + result = AdminMessageHandleResult::HANDLED; + break; + + case AdminMessage_set_canned_message_plugin_part3_tag: + DEBUG_MSG("Client is setting radio canned message part 3\n"); + this->handleSetCannedMessagePluginPart3( + request->set_canned_message_plugin_part3); + result = AdminMessageHandleResult::HANDLED; + break; + + case AdminMessage_set_canned_message_plugin_part4_tag: + DEBUG_MSG("Client is setting radio canned message part 4\n"); + this->handleSetCannedMessagePluginPart4( + request->set_canned_message_plugin_part4); + result = AdminMessageHandleResult::HANDLED; + break; + + default: + result = AdminMessageHandleResult::NOT_HANDLED; + } + + return result; +} + +void CannedMessagePlugin::handleGetCannedMessagePluginPart1( + const MeshPacket &req, AdminMessage *response) +{ + DEBUG_MSG("*** handleGetCannedMessagePluginPart1\n"); + assert(req.decoded.want_response); + + response->which_variant = AdminMessage_get_canned_message_plugin_part1_response_tag; + strcpy( + response->get_canned_message_plugin_part1_response, + cannedMessagePluginConfig.messagesPart1); +} + +void CannedMessagePlugin::handleGetCannedMessagePluginPart2( + const MeshPacket &req, AdminMessage *response) +{ + DEBUG_MSG("*** handleGetCannedMessagePluginPart2\n"); + assert(req.decoded.want_response); + + response->which_variant = AdminMessage_get_canned_message_plugin_part2_response_tag; + strcpy( + response->get_canned_message_plugin_part2_response, + cannedMessagePluginConfig.messagesPart2); +} + +void CannedMessagePlugin::handleGetCannedMessagePluginPart3( + const MeshPacket &req, AdminMessage *response) +{ + DEBUG_MSG("*** handleGetCannedMessagePluginPart3\n"); + assert(req.decoded.want_response); + + response->which_variant = AdminMessage_get_canned_message_plugin_part3_response_tag; + strcpy( + response->get_canned_message_plugin_part3_response, + cannedMessagePluginConfig.messagesPart3); +} + +void CannedMessagePlugin::handleGetCannedMessagePluginPart4( + const MeshPacket &req, AdminMessage *response) +{ + DEBUG_MSG("*** handleGetCannedMessagePluginPart4\n"); + assert(req.decoded.want_response); + + response->which_variant = AdminMessage_get_canned_message_plugin_part4_response_tag; + strcpy( + response->get_canned_message_plugin_part4_response, + cannedMessagePluginConfig.messagesPart4); +} + +void CannedMessagePlugin::handleSetCannedMessagePluginPart1(const char *from_msg) +{ + int changed = 0; + + if (*from_msg) + { + changed |= strcmp(cannedMessagePluginConfig.messagesPart1, from_msg); + strcpy(cannedMessagePluginConfig.messagesPart1, from_msg); + DEBUG_MSG("*** from_msg.text:%s\n", from_msg); + } + + if (changed) + { + this->saveProtoForPlugin(); + } +} + +void CannedMessagePlugin::handleSetCannedMessagePluginPart2(const char *from_msg) +{ + int changed = 0; + + if (*from_msg) + { + changed |= strcmp(cannedMessagePluginConfig.messagesPart2, from_msg); + strcpy(cannedMessagePluginConfig.messagesPart2, from_msg); + } + + if (changed) + { + this->saveProtoForPlugin(); + } +} + +void CannedMessagePlugin::handleSetCannedMessagePluginPart3(const char *from_msg) +{ + int changed = 0; + + if (*from_msg) + { + changed |= strcmp(cannedMessagePluginConfig.messagesPart3, from_msg); + strcpy(cannedMessagePluginConfig.messagesPart3, from_msg); + } + + if (changed) + { + this->saveProtoForPlugin(); + } +} + +void CannedMessagePlugin::handleSetCannedMessagePluginPart4(const char *from_msg) +{ + int changed = 0; + + if (*from_msg) + { + changed |= strcmp(cannedMessagePluginConfig.messagesPart4, from_msg); + strcpy(cannedMessagePluginConfig.messagesPart4, from_msg); + } + + if (changed) + { + this->saveProtoForPlugin(); + } +} diff --git a/src/plugins/CannedMessagePlugin.h b/src/plugins/CannedMessagePlugin.h index 1f7dcf42e..2cb6e0730 100644 --- a/src/plugins/CannedMessagePlugin.h +++ b/src/plugins/CannedMessagePlugin.h @@ -1,24 +1,24 @@ #pragma once -#include "SinglePortPlugin.h" +#include "ProtobufPlugin.h" #include "input/InputBroker.h" enum cannedMessagePluginRunState { + CANNED_MESSAGE_RUN_STATE_DISABLED, CANNED_MESSAGE_RUN_STATE_INACTIVE, CANNED_MESSAGE_RUN_STATE_ACTIVE, CANNED_MESSAGE_RUN_STATE_SENDING_ACTIVE, CANNED_MESSAGE_RUN_STATE_ACTION_SELECT, CANNED_MESSAGE_RUN_STATE_ACTION_UP, - CANNED_MESSAGE_RUN_STATE_ACTION_DOWN + CANNED_MESSAGE_RUN_STATE_ACTION_DOWN, }; #define CANNED_MESSAGE_PLUGIN_MESSAGE_MAX_COUNT 50 /** - * Due to config-packet size restrictions we cannot have user configuration bigger - * than Constants_DATA_PAYLOAD_LEN bytes. + * Sum of CannedMessagePluginConfig part sizes. */ -#define CANNED_MESSAGE_PLUGIN_MESSAGES_SIZE 200 +#define CANNED_MESSAGE_PLUGIN_MESSAGES_SIZE 800 class CannedMessagePlugin : public SinglePortPlugin, @@ -38,6 +38,16 @@ class CannedMessagePlugin : void eventDown(); void eventSelect(); + void handleGetCannedMessagePluginPart1(const MeshPacket &req, AdminMessage *response); + void handleGetCannedMessagePluginPart2(const MeshPacket &req, AdminMessage *response); + void handleGetCannedMessagePluginPart3(const MeshPacket &req, AdminMessage *response); + void handleGetCannedMessagePluginPart4(const MeshPacket &req, AdminMessage *response); + + void handleSetCannedMessagePluginPart1(const char *from_msg); + void handleSetCannedMessagePluginPart2(const char *from_msg); + void handleSetCannedMessagePluginPart3(const char *from_msg); + void handleSetCannedMessagePluginPart4(const char *from_msg); + protected: virtual int32_t runOnce() override; @@ -56,11 +66,18 @@ class CannedMessagePlugin : virtual Observable* getUIFrameObservable() override { return this; } virtual void drawFrame( OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) override; + virtual AdminMessageHandleResult handleAdminMessageForPlugin( + const MeshPacket &mp, AdminMessage *request, AdminMessage *response) override; + + void loadProtoForPlugin(); + bool saveProtoForPlugin(); + + void installDefaultCannedMessagePluginConfig(); int currentMessageIndex = -1; cannedMessagePluginRunState runState = CANNED_MESSAGE_RUN_STATE_INACTIVE; - char messageStore[CANNED_MESSAGE_PLUGIN_MESSAGES_SIZE]; + char messageStore[CANNED_MESSAGE_PLUGIN_MESSAGES_SIZE+1]; char *messages[CANNED_MESSAGE_PLUGIN_MESSAGE_MAX_COUNT]; int messagesCount = 0; unsigned long lastTouchMillis = 0;